flexdesk 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +93 -0
- package/LICENSE +0 -0
- package/README.md +2261 -42
- package/THIRD_PARTY_LICENSES.md +0 -0
- package/css/base.css +1834 -75
- package/css/flexdesk.css +3373 -238
- package/css/overrides.css +16 -0
- package/css/reset.css +0 -0
- package/css/tokens.css +0 -0
- package/dist/canvas.js +6 -239
- package/dist/canvas.js.map +3 -3
- package/dist/charts.js +709 -18
- package/dist/charts.js.map +4 -4
- package/dist/chunk-3PHCPZHT.js +0 -0
- package/dist/chunk-3PHCPZHT.js.map +0 -0
- package/dist/chunk-4A7SJC3T.js +503 -0
- package/dist/chunk-4A7SJC3T.js.map +7 -0
- package/dist/{chunk-6JSOVNID.js → chunk-CVMCZZX2.js} +635 -10
- package/dist/chunk-CVMCZZX2.js.map +7 -0
- package/dist/chunk-D3COLZZ2.js +1311 -0
- package/dist/chunk-D3COLZZ2.js.map +7 -0
- package/dist/chunk-FOOS3T5L.js +0 -0
- package/dist/chunk-FOOS3T5L.js.map +0 -0
- package/dist/{chunk-SN4LSOAR.js → chunk-GOQLR5WR.js} +452 -2
- package/dist/chunk-GOQLR5WR.js.map +7 -0
- package/dist/{chunk-FL5KFNQH.js → chunk-HNU6MM2B.js} +52 -17
- package/dist/chunk-HNU6MM2B.js.map +7 -0
- package/dist/chunk-HYJYYEPK.js +375 -0
- package/dist/chunk-HYJYYEPK.js.map +7 -0
- package/dist/chunk-JKZLNKG6.js +2041 -0
- package/dist/chunk-JKZLNKG6.js.map +7 -0
- package/dist/chunk-JYWURG5T.js +0 -0
- package/dist/chunk-JYWURG5T.js.map +0 -0
- package/dist/{chunk-RQM5Z2MU.js → chunk-MCIXFNVF.js} +633 -311
- package/dist/chunk-MCIXFNVF.js.map +7 -0
- package/dist/chunk-N7HC3ADV.js +30 -0
- package/dist/chunk-N7HC3ADV.js.map +7 -0
- package/dist/{chunk-FBGP5KN5.js → chunk-Q36EPT2R.js} +3268 -203
- package/dist/chunk-Q36EPT2R.js.map +7 -0
- package/dist/chunk-QWQJUDPD.js +610 -0
- package/dist/chunk-QWQJUDPD.js.map +7 -0
- package/dist/{chunk-NLTOY57M.js → chunk-UURZ37SD.js} +28 -48
- package/dist/chunk-UURZ37SD.js.map +7 -0
- package/dist/chunk-UWO43BZU.js +111 -0
- package/dist/chunk-UWO43BZU.js.map +7 -0
- package/dist/chunk-WVFGV5FT.js +0 -0
- package/dist/chunk-WVFGV5FT.js.map +0 -0
- package/dist/core.js +170 -118
- package/dist/core.js.map +2 -2
- package/dist/editor.js +156 -70
- package/dist/editor.js.map +2 -2
- package/dist/flexdesk.css +3373 -238
- package/dist/flow.js +2789 -306
- package/dist/flow.js.map +4 -4
- package/dist/host.js +109 -3
- package/dist/host.js.map +3 -3
- package/dist/reset.css +0 -0
- package/dist/tile_registry-6WZPTUZV.js +0 -0
- package/dist/tile_registry-6WZPTUZV.js.map +0 -0
- package/dist/tiles.js +1131 -253
- package/dist/tiles.js.map +4 -4
- package/dist/tokens.css +0 -0
- package/dist/widgets.js +3254 -2112
- package/dist/widgets.js.map +4 -4
- package/dist/wm.js +1227 -345
- package/dist/wm.js.map +4 -4
- package/package.json +3 -1
- package/src/canvas/canvas_adapter.js +5 -0
- package/src/canvas/edge_router.js +0 -0
- package/src/canvas/graph/connector_router.js +0 -0
- package/src/canvas/graph/history_service.js +0 -0
- package/src/canvas/graph/node_platform.js +0 -0
- package/src/canvas/index.js +1 -0
- package/src/canvas/layered_layout.js +244 -0
- package/src/charts/chart_types.js +0 -0
- package/src/charts/data_series_plot_window.js +0 -0
- package/src/charts/downsample.js +2 -2
- package/src/charts/plot_config.js +53 -29
- package/src/charts/plot_config_editor.js +627 -0
- package/src/charts/plot_grid.js +449 -0
- package/src/charts/plot_popout_window.js +103 -317
- package/src/charts/plotly_wrapper.js +22 -2
- package/src/charts/series_transforms.js +206 -0
- package/src/core/event_bus.js +0 -0
- package/src/core/logging.js +1 -1
- package/src/core/settings.js +105 -19
- package/src/core/state_guard.js +93 -51
- package/src/core/state_guard_config.js +85 -74
- package/src/core/state_machine.js +0 -0
- package/src/editor/editor_pane.js +3 -3
- package/src/editor/monaco_editor_factory.js +124 -60
- package/src/editor/monaco_loader.js +103 -28
- package/src/editor/notebook_search.js +0 -0
- package/src/editor/notebook_tab_bar.js +38 -52
- package/src/editor/notebook_undo_manager.js +0 -0
- package/src/editor/split_pane_container.js +6 -3
- package/src/flow/canvas_editor/connections.js +90 -0
- package/src/flow/canvas_editor/editor.js +2351 -153
- package/src/flow/canvas_editor/index.js +2 -1
- package/src/flow/canvas_editor/layout.js +119 -12
- package/src/flow/canvas_editor/strings.js +80 -0
- package/src/flow/kit/always_before.js +0 -0
- package/src/flow/kit/catalogue.js +97 -3
- package/src/flow/kit/chip_input.js +0 -0
- package/src/flow/kit/dom.js +0 -0
- package/src/flow/kit/findings.js +0 -0
- package/src/flow/kit/history.js +0 -0
- package/src/flow/kit/index.js +3 -3
- package/src/flow/kit/keys.js +7 -1
- package/src/flow/kit/logic_graph.js +97 -15
- package/src/flow/kit/references.js +0 -0
- package/src/flow/kit/settings_panel.js +0 -0
- package/src/flow/kit/settings_schema.js +2 -1
- package/src/flow/kit/step_picker.js +0 -0
- package/src/flow/kit/strings.js +3 -1
- package/src/flow/kit/value_picker.js +0 -0
- package/src/flow/kit/widgets.js +86 -109
- package/src/flow/lanes/editor.js +136 -14
- package/src/flow/lanes/index.js +3 -1
- package/src/flow/lanes/layout.js +0 -0
- package/src/flow/lanes/pipeline.js +44 -2
- package/src/flow/lanes/preview.js +0 -0
- package/src/flow/lanes/strings.js +1 -0
- package/src/flow/outline/editor.js +0 -0
- package/src/flow/outline/index.js +0 -0
- package/src/flow/outline/mapping.js +0 -0
- package/src/flow/outline/menu.js +0 -0
- package/src/flow/outline/operations.js +0 -0
- package/src/flow/outline/recognise.js +0 -0
- package/src/flow/outline/strings.js +0 -0
- package/src/help/help_modal.js +168 -42
- package/src/help/help_registry.js +12 -1
- package/src/host/external_links.js +0 -0
- package/src/host/file_picker.js +117 -0
- package/src/host/host.js +10 -2
- package/src/host/photino_host.js +9 -0
- package/src/host/photino_host.md +21 -3
- package/src/host/pywebview_host.js +10 -0
- package/src/tiles/chart_tiles.js +53 -245
- package/src/tiles/config_schema.js +8 -0
- package/src/tiles/figure_tile.js +322 -0
- package/src/tiles/layout_persistence.js +3 -3
- package/src/tiles/list_tiles.js +422 -0
- package/src/tiles/scope_picker.js +96 -0
- package/src/tiles/tile_base.js +12 -1
- package/src/tiles/tile_config_form.js +442 -0
- package/src/tiles/tile_grid.js +38 -1
- package/src/tiles/tile_registry.js +0 -0
- package/src/tiling/bottom_panel_tabs.js +67 -99
- package/src/tiling/command_palette.js +64 -19
- package/src/tiling/content_registry.js +4 -1
- package/src/tiling/desktops.js +11 -1
- package/src/tiling/entity_sources.js +0 -0
- package/src/tiling/keymap.js +403 -128
- package/src/tiling/kind_taxonomy.js +78 -0
- package/src/tiling/landing_table.js +0 -0
- package/src/tiling/loading_overlay.js +0 -0
- package/src/tiling/nav_panel.js +59 -10
- package/src/tiling/page_factory.js +5 -5
- package/src/tiling/panel_availability.js +49 -0
- package/src/tiling/panel_keys.js +0 -0
- package/src/tiling/shell.js +114 -12
- package/src/tiling/tab_strip.js +0 -0
- package/src/tiling/tile_breadcrumb.js +0 -0
- package/src/tiling/tile_renderer.js +105 -9
- package/src/tiling/tile_tab_menu.js +0 -0
- package/src/tiling/tile_tree.js +0 -0
- package/src/tiling/wm.js +562 -30
- package/src/tiling/zoom.js +0 -0
- package/src/ui/base/component_base.js +0 -0
- package/src/ui/base/controller_base.js +0 -0
- package/src/ui/base/page_base.js +0 -0
- package/src/ui/components/about_dialog.js +0 -0
- package/src/ui/components/action_dropdown.js +30 -2
- package/src/ui/components/alert_log.js +0 -0
- package/src/ui/components/alerts_pane.js +0 -0
- package/src/ui/components/attribute_list_editor.js +0 -0
- package/src/ui/components/autocomplete_field.js +0 -0
- package/src/ui/components/cell_editor_host.js +211 -0
- package/src/ui/components/cell_grid.js +648 -0
- package/src/ui/components/cell_selection.js +220 -0
- package/src/ui/components/choice_controls.js +351 -0
- package/src/ui/components/color_field.js +211 -0
- package/src/ui/components/color_list_field.js +210 -0
- package/src/ui/components/column_fit.js +0 -0
- package/src/ui/components/column_groups.js +314 -0
- package/src/ui/components/column_order.js +142 -0
- package/src/ui/components/computing_status_window.js +98 -25
- package/src/ui/components/confirm_dialog.js +81 -38
- package/src/ui/components/context_menu.js +2 -2
- package/src/ui/components/conversation_view.js +440 -0
- package/src/ui/components/crosstab.js +289 -0
- package/src/ui/components/data_table.js +601 -62
- package/src/ui/components/detail_header.js +22 -11
- package/src/ui/components/document_outline.js +397 -0
- package/src/ui/components/drag_reorder.js +0 -0
- package/src/ui/components/fact_table.js +0 -0
- package/src/ui/components/fill_handle.js +322 -0
- package/src/ui/components/gallery_picker.js +19 -8
- package/src/ui/components/header_actions.js +55 -0
- package/src/ui/components/inline_renamer.js +0 -0
- package/src/ui/components/job_progress.js +51 -0
- package/src/ui/components/managed_window.js +27 -4
- package/src/ui/components/menu_bar.js +745 -0
- package/src/ui/components/modal.js +449 -75
- package/src/ui/components/notification_history.js +3 -3
- package/src/ui/components/progress.js +483 -0
- package/src/ui/components/record_list.js +0 -0
- package/src/ui/components/row_activation.js +0 -0
- package/src/ui/components/section_stack.js +298 -0
- package/src/ui/components/series.js +173 -0
- package/src/ui/components/settings_view.js +634 -0
- package/src/ui/components/slide_out_panel.js +43 -6
- package/src/ui/components/slider_field.js +275 -18
- package/src/ui/components/sortable_list.js +26 -4
- package/src/ui/components/staged_edits.js +343 -0
- package/src/ui/components/staged_history.js +172 -0
- package/src/ui/components/table_filter_chips.js +0 -0
- package/src/ui/components/table_state_store.js +0 -0
- package/src/ui/components/table_structure.js +182 -0
- package/src/ui/components/table_values.js +0 -0
- package/src/ui/components/tabs.js +497 -0
- package/src/ui/components/tag_input.js +215 -0
- package/src/ui/components/toast.js +25 -8
- package/src/ui/components/toggle_field.js +175 -0
- package/src/ui/components/tree_view.js +55 -34
- package/src/ui/components/window_taskbar.js +0 -0
- package/src/ui/components/wizard.js +563 -0
- package/src/ui/controllers/window_chrome_controller.js +2 -2
- package/src/ui/notification_center.js +375 -119
- package/src/ui/utils/auto_scrollbars.js +0 -0
- package/src/ui/utils/markdown.js +709 -0
- package/src/ui/utils/native_context_menu.js +0 -0
- package/src/ui/utils/overlay_scrollbar.js +16 -12
- package/src/ui/utils/raf_resize_observer.js +0 -0
- package/src/ui/utils/scroll_lock.js +0 -0
- package/src/ui/utils/strip_scroll.js +55 -0
- package/src/ui/utils/tooltip_service.js +0 -8
- package/dist/chunk-6JSOVNID.js.map +0 -7
- package/dist/chunk-CWPMLX67.js +0 -475
- package/dist/chunk-CWPMLX67.js.map +0 -7
- package/dist/chunk-FBGP5KN5.js.map +0 -7
- package/dist/chunk-FL5KFNQH.js.map +0 -7
- package/dist/chunk-NLTOY57M.js.map +0 -7
- package/dist/chunk-NNFTETK3.js +0 -633
- package/dist/chunk-NNFTETK3.js.map +0 -7
- package/dist/chunk-O5OHMWBB.js +0 -284
- package/dist/chunk-O5OHMWBB.js.map +0 -7
- package/dist/chunk-RQM5Z2MU.js.map +0 -7
- package/dist/chunk-SN4LSOAR.js.map +0 -7
- package/src/ui/controllers/panel_state_machine.js +0 -634
package/dist/flexdesk.css
CHANGED
|
@@ -164,6 +164,10 @@
|
|
|
164
164
|
font-size: var(--font-size-sm);
|
|
165
165
|
line-height: 1.5;
|
|
166
166
|
}
|
|
167
|
+
/* Shown: the service adds `visible` once the tooltip is positioned, and removes it to fade out */
|
|
168
|
+
.twm-latex-tooltip.visible {
|
|
169
|
+
opacity: 1;
|
|
170
|
+
}
|
|
167
171
|
/* Tooltip header (first line) styling */
|
|
168
172
|
.twm-latex-tooltip strong {
|
|
169
173
|
display: block;
|
|
@@ -360,6 +364,46 @@
|
|
|
360
364
|
background: var(--accent);
|
|
361
365
|
border-color: var(--accent);
|
|
362
366
|
}
|
|
367
|
+
/* NotificationCenter progress toasts: a bar, a status line, a collapse toggle. */
|
|
368
|
+
.twm-notification__collapse {
|
|
369
|
+
width: 22px;
|
|
370
|
+
height: 22px;
|
|
371
|
+
border: none;
|
|
372
|
+
border-radius: var(--radius-sm);
|
|
373
|
+
background: rgba(255, 255, 255, 0.06);
|
|
374
|
+
color: #999;
|
|
375
|
+
cursor: pointer;
|
|
376
|
+
display: inline-flex;
|
|
377
|
+
align-items: center;
|
|
378
|
+
justify-content: center;
|
|
379
|
+
padding: 0;
|
|
380
|
+
flex-shrink: 0;
|
|
381
|
+
transition: background var(--transition-fast), color var(--transition-fast), transform var(--transition-fast);
|
|
382
|
+
}
|
|
383
|
+
.twm-notification__collapse:hover {
|
|
384
|
+
background: rgba(255, 255, 255, 0.14);
|
|
385
|
+
color: var(--text-bright);
|
|
386
|
+
}
|
|
387
|
+
.twm-notification--collapsed .twm-notification__collapse {
|
|
388
|
+
transform: rotate(-90deg);
|
|
389
|
+
}
|
|
390
|
+
.twm-notification__progress {
|
|
391
|
+
margin-top: var(--space-sm);
|
|
392
|
+
}
|
|
393
|
+
.twm-notification__status {
|
|
394
|
+
margin-top: var(--space-xs);
|
|
395
|
+
font-size: var(--font-size-xs);
|
|
396
|
+
color: var(--text-secondary);
|
|
397
|
+
overflow: hidden;
|
|
398
|
+
text-overflow: ellipsis;
|
|
399
|
+
white-space: nowrap;
|
|
400
|
+
}
|
|
401
|
+
.twm-notification--collapsed .twm-notification__body,
|
|
402
|
+
.twm-notification--collapsed .twm-notification__status,
|
|
403
|
+
.twm-notification--collapsed .twm-notification__description,
|
|
404
|
+
.twm-notification--collapsed .twm-notification__actions {
|
|
405
|
+
display: none;
|
|
406
|
+
}
|
|
363
407
|
/* Notification history (bottom bar bell + popover) */
|
|
364
408
|
.twm-notification-history__trigger {
|
|
365
409
|
display: flex;
|
|
@@ -461,6 +505,10 @@
|
|
|
461
505
|
padding: var(--space-md) 10px;
|
|
462
506
|
font-size: var(--font-size-sm);
|
|
463
507
|
}
|
|
508
|
+
.twm-notification-history__item--success { border-left-color: var(--color-success, #3fb950); }
|
|
509
|
+
.twm-notification-history__item--warn { border-left-color: var(--color-warning, #ff9800); }
|
|
510
|
+
.twm-notification-history__item--error,
|
|
511
|
+
.twm-notification-history__item--fatal { border-left-color: var(--color-danger, #c74e4e); }
|
|
464
512
|
.twm-notification-history__item-header {
|
|
465
513
|
display: flex;
|
|
466
514
|
align-items: center;
|
|
@@ -634,9 +682,14 @@ body.twm-dt-col-resizing {
|
|
|
634
682
|
width: auto;
|
|
635
683
|
min-width: 80px;
|
|
636
684
|
}
|
|
637
|
-
/* Alternating row backgrounds
|
|
685
|
+
/* Alternating row backgrounds. The stripe is the row's `--twm-dt-row-bg`, set
|
|
686
|
+
at no specificity so a consumer's row class can replace it; a crosstab
|
|
687
|
+
(STORY-0091) also lays it under its pinned cells. */
|
|
688
|
+
:where(.twm-preview-table tbody tr:nth-child(even)) {
|
|
689
|
+
--twm-dt-row-bg: rgba(255, 255, 255, 0.02);
|
|
690
|
+
}
|
|
638
691
|
.twm-preview-table tbody tr:nth-child(even) {
|
|
639
|
-
background:
|
|
692
|
+
background: var(--twm-dt-row-bg);
|
|
640
693
|
}
|
|
641
694
|
/* Hover state (disabled in wizard via modifier) */
|
|
642
695
|
.twm-preview-table:not(.twm-preview-table--readonly) tr:hover td {
|
|
@@ -780,6 +833,272 @@ body.twm-dt-col-resizing {
|
|
|
780
833
|
opacity: 1;
|
|
781
834
|
outline: 1px solid var(--accent-bright, #007acc);
|
|
782
835
|
}
|
|
836
|
+
/* STORY-0003 `selectionMode: 'cells'` — the range is a tint on its cells, the
|
|
837
|
+
* cursor a ring inside its cell (inset, so it moves no column by a pixel). A
|
|
838
|
+
* cell being edited gives its padding to the editor; a commit still out is
|
|
839
|
+
* dimmed, and a refused one carries a red ring and its message as the title. */
|
|
840
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--selected {
|
|
841
|
+
background: var(--state-selected, rgba(0, 122, 204, 0.15));
|
|
842
|
+
}
|
|
843
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--cursor {
|
|
844
|
+
box-shadow: inset 0 0 0 2px var(--accent-bright, #007acc);
|
|
845
|
+
}
|
|
846
|
+
.twm-preview-table.twm-dt--cells:focus {
|
|
847
|
+
outline: none;
|
|
848
|
+
}
|
|
849
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--editing {
|
|
850
|
+
padding: 0;
|
|
851
|
+
}
|
|
852
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--editing .twm-dt-editor {
|
|
853
|
+
display: block;
|
|
854
|
+
width: 100%;
|
|
855
|
+
box-sizing: border-box;
|
|
856
|
+
margin: 0;
|
|
857
|
+
padding: 2px 6px;
|
|
858
|
+
border: 0;
|
|
859
|
+
outline: 2px solid var(--accent-bright, #007acc);
|
|
860
|
+
outline-offset: -2px;
|
|
861
|
+
background: var(--surface-well, #1e1e1e);
|
|
862
|
+
color: inherit;
|
|
863
|
+
font: inherit;
|
|
864
|
+
}
|
|
865
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--pending {
|
|
866
|
+
opacity: 0.6;
|
|
867
|
+
font-style: italic;
|
|
868
|
+
}
|
|
869
|
+
/* STORY-0088 `staged`: a value typed and not yet committed. */
|
|
870
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--staged {
|
|
871
|
+
background: color-mix(in srgb, var(--accent-bright, #007acc) 16%, transparent);
|
|
872
|
+
}
|
|
873
|
+
/* STORY-0089 `fillHandle`: a square on the range's corner cell, the cells a
|
|
874
|
+
* drag covers dashed, and a cell the fill skipped (not editable) hatched. */
|
|
875
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--fill-corner {
|
|
876
|
+
position: relative;
|
|
877
|
+
}
|
|
878
|
+
.twm-preview-table.twm-dt--cells .twm-dt-fill-handle {
|
|
879
|
+
position: absolute;
|
|
880
|
+
right: 0;
|
|
881
|
+
bottom: 0;
|
|
882
|
+
width: 7px;
|
|
883
|
+
height: 7px;
|
|
884
|
+
box-sizing: border-box;
|
|
885
|
+
background: var(--accent-bright, #007acc);
|
|
886
|
+
border: 1px solid var(--surface-well, #1e1e1e);
|
|
887
|
+
cursor: crosshair;
|
|
888
|
+
z-index: 1;
|
|
889
|
+
touch-action: none;
|
|
890
|
+
}
|
|
891
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--fill-preview {
|
|
892
|
+
outline: 1px dashed var(--accent-bright, #007acc);
|
|
893
|
+
outline-offset: -1px;
|
|
894
|
+
}
|
|
895
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--fill-skipped {
|
|
896
|
+
background-image: repeating-linear-gradient(45deg,
|
|
897
|
+
color-mix(in srgb, var(--color-danger, #f14c4c) 22%, transparent) 0 4px, transparent 4px 8px);
|
|
898
|
+
}
|
|
899
|
+
/* While cells are staged, sort, filters and pages are held: the held control
|
|
900
|
+
* says why on itself (`data-refusal`). */
|
|
901
|
+
.twm-data-table-component.twm-dt--frozen th.sortable[data-refusal] {
|
|
902
|
+
cursor: not-allowed !important;
|
|
903
|
+
}
|
|
904
|
+
.twm-data-table-component.twm-dt--frozen [data-refusal]:disabled {
|
|
905
|
+
cursor: not-allowed;
|
|
906
|
+
opacity: 0.5;
|
|
907
|
+
}
|
|
908
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--error {
|
|
909
|
+
box-shadow: inset 0 0 0 1px var(--color-danger, #f14c4c);
|
|
910
|
+
}
|
|
911
|
+
.twm-preview-table.twm-dt--cells tbody td.twm-dt-cell--error.twm-dt-cell--cursor {
|
|
912
|
+
box-shadow: inset 0 0 0 2px var(--color-danger, #f14c4c);
|
|
913
|
+
}
|
|
914
|
+
/* STORY-0086 `reorderable` — the header being dragged is dimmed, and the one
|
|
915
|
+
* it would land on carries a bar on the side it lands (inset: no column moves
|
|
916
|
+
* by a pixel while the pointer passes). */
|
|
917
|
+
.twm-preview-table th.twm-dt-col--movable {
|
|
918
|
+
cursor: grab;
|
|
919
|
+
}
|
|
920
|
+
.twm-preview-table th.twm-dt-col--dragging {
|
|
921
|
+
opacity: 0.5;
|
|
922
|
+
}
|
|
923
|
+
.twm-preview-table th.twm-dt-col--drop {
|
|
924
|
+
box-shadow: inset 2px 0 0 0 var(--accent-bright, #007acc);
|
|
925
|
+
}
|
|
926
|
+
.twm-preview-table th.twm-dt-col--drop.twm-dt-col--drop-after {
|
|
927
|
+
box-shadow: inset -2px 0 0 0 var(--accent-bright, #007acc);
|
|
928
|
+
}
|
|
929
|
+
/* STORY-0066 `columnGroups` — the group row is a table of its own above the
|
|
930
|
+
* header table (`twm-dt-groups`), its `<col>`s copied from the header's widths;
|
|
931
|
+
* no first-column floor or cap of the header's applies to it. A crosstab's
|
|
932
|
+
* spanned header cells (STORY-0091) are the same group cells. A placeholder
|
|
933
|
+
* column (an empty group's) is drawn muted. The header action buttons are
|
|
934
|
+
* small icon buttons that keep to the cell. */
|
|
935
|
+
.twm-preview-table.twm-dt-groups th.twm-dt-group,
|
|
936
|
+
.twm-preview-table.twm-dt-crosstab th.twm-dt-group {
|
|
937
|
+
width: auto;
|
|
938
|
+
min-width: 0;
|
|
939
|
+
max-width: none;
|
|
940
|
+
text-align: center;
|
|
941
|
+
border-bottom: 1px solid var(--border-subtle, #333);
|
|
942
|
+
white-space: nowrap;
|
|
943
|
+
overflow: hidden;
|
|
944
|
+
text-overflow: ellipsis;
|
|
945
|
+
}
|
|
946
|
+
.twm-preview-table.twm-dt-groups th.twm-dt-group + th.twm-dt-group,
|
|
947
|
+
.twm-preview-table.twm-dt-crosstab th.twm-dt-group + th.twm-dt-group {
|
|
948
|
+
border-left: 1px solid var(--border-subtle, #333);
|
|
949
|
+
}
|
|
950
|
+
.twm-preview-table.twm-dt-groups th.twm-dt-group--empty .twm-dt-group__label {
|
|
951
|
+
opacity: 0.7;
|
|
952
|
+
}
|
|
953
|
+
.twm-preview-table .twm-dt-group__actions,
|
|
954
|
+
.twm-preview-table .twm-dt-col-actions {
|
|
955
|
+
display: inline-flex;
|
|
956
|
+
gap: 2px;
|
|
957
|
+
margin-left: 4px;
|
|
958
|
+
vertical-align: middle;
|
|
959
|
+
}
|
|
960
|
+
.twm-preview-table .twm-dt-group__add,
|
|
961
|
+
.twm-preview-table .twm-dt-group__action,
|
|
962
|
+
.twm-preview-table .twm-dt-col-action {
|
|
963
|
+
display: inline-flex;
|
|
964
|
+
align-items: center;
|
|
965
|
+
justify-content: center;
|
|
966
|
+
padding: 0 2px;
|
|
967
|
+
border: 0;
|
|
968
|
+
border-radius: 3px;
|
|
969
|
+
background: transparent;
|
|
970
|
+
color: inherit;
|
|
971
|
+
cursor: pointer;
|
|
972
|
+
opacity: 0.6;
|
|
973
|
+
font: inherit;
|
|
974
|
+
}
|
|
975
|
+
.twm-preview-table .twm-dt-group__add .material-symbols-outlined,
|
|
976
|
+
.twm-preview-table .twm-dt-group__action .material-symbols-outlined,
|
|
977
|
+
.twm-preview-table .twm-dt-col-action .material-symbols-outlined {
|
|
978
|
+
font-size: 16px;
|
|
979
|
+
}
|
|
980
|
+
.twm-preview-table .twm-dt-group__add:hover,
|
|
981
|
+
.twm-preview-table .twm-dt-group__action:hover,
|
|
982
|
+
.twm-preview-table .twm-dt-col-action:hover {
|
|
983
|
+
opacity: 1;
|
|
984
|
+
background: rgba(255, 255, 255, 0.08);
|
|
985
|
+
}
|
|
986
|
+
.twm-preview-table .twm-dt-group__add:focus-visible,
|
|
987
|
+
.twm-preview-table .twm-dt-group__action:focus-visible,
|
|
988
|
+
.twm-preview-table .twm-dt-col-action:focus-visible {
|
|
989
|
+
opacity: 1;
|
|
990
|
+
outline: 1px solid var(--accent-bright, #007acc);
|
|
991
|
+
}
|
|
992
|
+
.twm-preview-table th.twm-dt-col--placeholder,
|
|
993
|
+
.twm-preview-table td.twm-dt-cell--placeholder {
|
|
994
|
+
background: rgba(255, 255, 255, 0.015);
|
|
995
|
+
}
|
|
996
|
+
.twm-preview-table th .twm-dt-col-rename {
|
|
997
|
+
width: 100%;
|
|
998
|
+
box-sizing: border-box;
|
|
999
|
+
font: inherit;
|
|
1000
|
+
}
|
|
1001
|
+
/* STORY-0091 `crosstab` — one table in one scroller (`twm-dt-crosstab`).
|
|
1002
|
+
* Every header cell sticks to the top at the `top` crosstab.js measured for its
|
|
1003
|
+
* row; the pinned cells (select, row number and label columns) stick to the
|
|
1004
|
+
* left at the `left` it measured, and the corner — header cells over them — to
|
|
1005
|
+
* both, above everything else. Every crosstab row paints its `--twm-dt-row-bg`,
|
|
1006
|
+
* so a row coloured through it is one colour from the label cells to the last
|
|
1007
|
+
* column.
|
|
1008
|
+
*
|
|
1009
|
+
* A pinned body cell needs an OPAQUE background or the cells scrolling under it
|
|
1010
|
+
* show through, and every state FlexDesk paints on a `td` is translucent. So
|
|
1011
|
+
* the pinned cell's background is one `!important` stack nothing can replace —
|
|
1012
|
+
* not a stronger state rule, not an animation (an important declaration
|
|
1013
|
+
* outranks both) — and the states reach it as LAYERS instead:
|
|
1014
|
+
* --twm-dt-pin-mark a mark over everything (the fill's skipped hatch)
|
|
1015
|
+
* --twm-dt-pin-new the new-row flash (a registered colour, so it animates)
|
|
1016
|
+
* --twm-dt-pin-state the cell's state tint: hover, row and cell selection,
|
|
1017
|
+
* staged, placeholder, diff
|
|
1018
|
+
* --twm-dt-row-bg the row's background (the stripe or a consumer's colour)
|
|
1019
|
+
* --surface-0 the opaque surface under all of them.
|
|
1020
|
+
* Each state rule below is the unpinned rule it mirrors, with
|
|
1021
|
+
* `.twm-dt-crosstab` on the table and `.twm-dt-pin` on the cell — the same two
|
|
1022
|
+
* classes on every one, in the same order, so the state a pinned cell shows is
|
|
1023
|
+
* the one its unpinned neighbours show. */
|
|
1024
|
+
@property --twm-dt-pin-new {
|
|
1025
|
+
syntax: '<color>';
|
|
1026
|
+
inherits: false;
|
|
1027
|
+
initial-value: transparent;
|
|
1028
|
+
}
|
|
1029
|
+
.twm-preview-table.twm-dt-crosstab tbody tr {
|
|
1030
|
+
background: var(--twm-dt-row-bg, transparent);
|
|
1031
|
+
}
|
|
1032
|
+
.twm-preview-table.twm-dt-crosstab thead th {
|
|
1033
|
+
position: sticky;
|
|
1034
|
+
z-index: 3;
|
|
1035
|
+
}
|
|
1036
|
+
.twm-preview-table.twm-dt-crosstab thead th.twm-dt-pin {
|
|
1037
|
+
z-index: 4;
|
|
1038
|
+
}
|
|
1039
|
+
.twm-preview-table.twm-dt-crosstab tbody td.twm-dt-pin {
|
|
1040
|
+
position: sticky;
|
|
1041
|
+
z-index: 1;
|
|
1042
|
+
background:
|
|
1043
|
+
var(--twm-dt-pin-mark, none),
|
|
1044
|
+
linear-gradient(var(--twm-dt-pin-new, transparent), var(--twm-dt-pin-new, transparent)),
|
|
1045
|
+
var(--twm-dt-pin-state, none),
|
|
1046
|
+
linear-gradient(var(--twm-dt-row-bg, transparent), var(--twm-dt-row-bg, transparent)) var(--surface-0, #1e1e1e) !important;
|
|
1047
|
+
}
|
|
1048
|
+
.twm-preview-table.twm-dt-crosstab .twm-dt-pin--last {
|
|
1049
|
+
box-shadow: inset -1px 0 0 var(--border-strong, #3c3c3c);
|
|
1050
|
+
}
|
|
1051
|
+
.twm-preview-table.twm-dt-crosstab:not(.twm-preview-table--readonly) tr:hover td.twm-dt-pin {
|
|
1052
|
+
--twm-dt-pin-state: linear-gradient(rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.04));
|
|
1053
|
+
}
|
|
1054
|
+
.twm-preview-table.twm-dt-crosstab:not(.twm-preview-table--readonly) tbody tr.selected td.twm-dt-pin,
|
|
1055
|
+
.twm-preview-table.twm-dt-crosstab tbody tr.selected td.twm-dt-pin {
|
|
1056
|
+
--twm-dt-pin-state: linear-gradient(var(--state-selected, rgba(0, 122, 204, 0.15)), var(--state-selected, rgba(0, 122, 204, 0.15)));
|
|
1057
|
+
}
|
|
1058
|
+
.twm-preview-table.twm-dt-crosstab.twm-dt--clickable tbody tr:not(.twm-dt-spacer):not(.data-table__empty-row):not(.selected):hover td.twm-dt-pin {
|
|
1059
|
+
--twm-dt-pin-state: linear-gradient(var(--state-hover, rgba(255, 255, 255, 0.05)), var(--state-hover, rgba(255, 255, 255, 0.05)));
|
|
1060
|
+
}
|
|
1061
|
+
.twm-preview-table.twm-dt-crosstab.twm-dt--cells tbody td.twm-dt-pin.twm-dt-cell--selected {
|
|
1062
|
+
--twm-dt-pin-state: linear-gradient(var(--state-selected, rgba(0, 122, 204, 0.15)), var(--state-selected, rgba(0, 122, 204, 0.15)));
|
|
1063
|
+
}
|
|
1064
|
+
.twm-preview-table.twm-dt-crosstab.twm-dt--cells tbody td.twm-dt-pin.twm-dt-cell--staged {
|
|
1065
|
+
--twm-dt-pin-state: linear-gradient(color-mix(in srgb, var(--accent-bright, #007acc) 16%, transparent), color-mix(in srgb, var(--accent-bright, #007acc) 16%, transparent));
|
|
1066
|
+
}
|
|
1067
|
+
.twm-preview-table.twm-dt-crosstab.twm-dt--cells tbody td.twm-dt-pin.twm-dt-cell--fill-skipped {
|
|
1068
|
+
--twm-dt-pin-mark: repeating-linear-gradient(45deg,
|
|
1069
|
+
color-mix(in srgb, var(--color-danger, #f14c4c) 22%, transparent) 0 4px, transparent 4px 8px);
|
|
1070
|
+
}
|
|
1071
|
+
.twm-preview-table.twm-dt-crosstab td.twm-dt-pin.twm-dt-cell--placeholder {
|
|
1072
|
+
--twm-dt-pin-state: linear-gradient(rgba(255, 255, 255, 0.015), rgba(255, 255, 255, 0.015));
|
|
1073
|
+
}
|
|
1074
|
+
.twm-data-table-component .twm-preview-table.twm-dt-crosstab tbody tr.twm-dt-diff--added:not(.selected) > td.twm-dt-pin {
|
|
1075
|
+
--twm-dt-pin-state: linear-gradient(color-mix(in srgb, var(--color-success, #3fb950) 16%, transparent), color-mix(in srgb, var(--color-success, #3fb950) 16%, transparent));
|
|
1076
|
+
}
|
|
1077
|
+
.twm-data-table-component .twm-preview-table.twm-dt-crosstab tbody tr.twm-dt-diff--removed:not(.selected) > td.twm-dt-pin {
|
|
1078
|
+
--twm-dt-pin-state: linear-gradient(color-mix(in srgb, var(--color-danger, #c74e4e) 18%, transparent), color-mix(in srgb, var(--color-danger, #c74e4e) 18%, transparent));
|
|
1079
|
+
}
|
|
1080
|
+
.twm-data-table-component .twm-preview-table.twm-dt-crosstab tbody tr.twm-dt-diff:not(.selected) > td.twm-dt-pin.twm-dt-diff__cell--changed {
|
|
1081
|
+
--twm-dt-pin-state: linear-gradient(color-mix(in srgb, var(--color-warning, #ff9800) 22%, transparent), color-mix(in srgb, var(--color-warning, #ff9800) 22%, transparent));
|
|
1082
|
+
}
|
|
1083
|
+
.twm-data-table-component .twm-preview-table.twm-dt-crosstab tbody tr.twm-dt-diff--gap > td.twm-dt-pin.twm-dt-diff__gap {
|
|
1084
|
+
--twm-dt-pin-state: repeating-linear-gradient(135deg,
|
|
1085
|
+
transparent 0 6px,
|
|
1086
|
+
color-mix(in srgb, var(--text-muted, #888) 14%, transparent) 6px 7px);
|
|
1087
|
+
}
|
|
1088
|
+
.twm-preview-table.twm-dt-crosstab tr:hover td.twm-dt-pin {
|
|
1089
|
+
--twm-dt-pin-state: linear-gradient(rgba(255,255,255,0.04), rgba(255,255,255,0.04));
|
|
1090
|
+
}
|
|
1091
|
+
@keyframes twm-dt-pin-new {
|
|
1092
|
+
from { --twm-dt-pin-new: var(--twm-dt-new-bg, rgba(0, 122, 204, 0.22)); }
|
|
1093
|
+
to { --twm-dt-pin-new: transparent; }
|
|
1094
|
+
}
|
|
1095
|
+
.twm-preview-table.twm-dt-crosstab tbody tr.twm-dt-row--new > td.twm-dt-pin {
|
|
1096
|
+
animation: twm-dt-pin-new 1.6s ease-out;
|
|
1097
|
+
}
|
|
1098
|
+
.twm-preview-table.twm-dt-crosstab th.twm-dt-crosstab__none {
|
|
1099
|
+
font-style: italic;
|
|
1100
|
+
opacity: 0.7;
|
|
1101
|
+
}
|
|
783
1102
|
/* In the mode a click ticks: a pointer on every row, and the keyboard's row
|
|
784
1103
|
* (the arrows move it, Space ticks it) drawn as an outline. */
|
|
785
1104
|
.twm-preview-table.twm-dt--selecting tbody tr:not(.twm-dt-spacer):not(.data-table__empty-row) {
|
|
@@ -1107,6 +1426,82 @@ body.twm-dt-col-resizing {
|
|
|
1107
1426
|
cursor: grab;
|
|
1108
1427
|
border: 2px solid var(--surface-0);
|
|
1109
1428
|
}
|
|
1429
|
+
/* ══ SLIDER FIELD COMPANIONS ══ number box, readout, reset, enable toggle (STORY-0045) */
|
|
1430
|
+
.twm-slider-field__row {
|
|
1431
|
+
display: flex;
|
|
1432
|
+
align-items: center;
|
|
1433
|
+
gap: var(--space-sm);
|
|
1434
|
+
min-width: 0;
|
|
1435
|
+
}
|
|
1436
|
+
.twm-slider-field__row > .twm-slider-field__input {
|
|
1437
|
+
flex: 1 1 auto;
|
|
1438
|
+
min-width: 0;
|
|
1439
|
+
}
|
|
1440
|
+
.twm-slider-field__toggle {
|
|
1441
|
+
flex: 0 0 auto;
|
|
1442
|
+
margin: 0;
|
|
1443
|
+
cursor: pointer;
|
|
1444
|
+
}
|
|
1445
|
+
.twm-slider-field__readout {
|
|
1446
|
+
flex: 0 0 auto;
|
|
1447
|
+
min-width: 3em;
|
|
1448
|
+
text-align: right;
|
|
1449
|
+
font-size: var(--font-size-sm);
|
|
1450
|
+
font-variant-numeric: tabular-nums;
|
|
1451
|
+
color: var(--text-dim);
|
|
1452
|
+
}
|
|
1453
|
+
.twm-slider-field__number {
|
|
1454
|
+
flex: 0 0 auto;
|
|
1455
|
+
width: 6em;
|
|
1456
|
+
padding: var(--space-xxs) var(--space-xs);
|
|
1457
|
+
font: inherit;
|
|
1458
|
+
font-size: var(--font-size-sm);
|
|
1459
|
+
font-variant-numeric: tabular-nums;
|
|
1460
|
+
text-align: right;
|
|
1461
|
+
color: var(--text-body);
|
|
1462
|
+
background: var(--surface-well);
|
|
1463
|
+
border: 1px solid var(--border-default);
|
|
1464
|
+
border-radius: var(--radius-sm);
|
|
1465
|
+
}
|
|
1466
|
+
.twm-slider-field__number:focus {
|
|
1467
|
+
outline: none;
|
|
1468
|
+
border-color: var(--accent);
|
|
1469
|
+
}
|
|
1470
|
+
.twm-slider-field__reset {
|
|
1471
|
+
flex: 0 0 auto;
|
|
1472
|
+
display: inline-flex;
|
|
1473
|
+
align-items: center;
|
|
1474
|
+
justify-content: center;
|
|
1475
|
+
padding: 0;
|
|
1476
|
+
width: 22px;
|
|
1477
|
+
height: 22px;
|
|
1478
|
+
color: var(--text-dim);
|
|
1479
|
+
background: transparent;
|
|
1480
|
+
border: none;
|
|
1481
|
+
border-radius: var(--radius-sm);
|
|
1482
|
+
cursor: pointer;
|
|
1483
|
+
visibility: hidden;
|
|
1484
|
+
}
|
|
1485
|
+
.twm-slider-field__reset .material-symbols-outlined {
|
|
1486
|
+
font-size: 16px;
|
|
1487
|
+
}
|
|
1488
|
+
.twm-slider-field__reset:hover {
|
|
1489
|
+
color: var(--text-bright);
|
|
1490
|
+
background: var(--state-hover);
|
|
1491
|
+
}
|
|
1492
|
+
.twm-slider-field--modified .twm-slider-field__reset {
|
|
1493
|
+
visibility: visible;
|
|
1494
|
+
}
|
|
1495
|
+
.twm-slider-field--modified .twm-slider-field__number,
|
|
1496
|
+
.twm-slider-field--modified .twm-slider-field__readout {
|
|
1497
|
+
color: var(--accent-bright);
|
|
1498
|
+
}
|
|
1499
|
+
.twm-slider-field--off .twm-slider-field__input,
|
|
1500
|
+
.twm-slider-field--off .twm-slider-field__number,
|
|
1501
|
+
.twm-slider-field--off .twm-slider-field__readout {
|
|
1502
|
+
opacity: 0.45;
|
|
1503
|
+
}
|
|
1504
|
+
/* ══ end SLIDER FIELD COMPANIONS ══ */
|
|
1110
1505
|
/* ===== Sortable List Component ===== */
|
|
1111
1506
|
.twm-sortable-list {
|
|
1112
1507
|
display: flex;
|
|
@@ -2955,59 +3350,284 @@ body.twm-window-maximized .twm-resize-handle {
|
|
|
2955
3350
|
cursor: default;
|
|
2956
3351
|
}
|
|
2957
3352
|
|
|
2958
|
-
/*
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
THIS STYLESHEET HAD NEVER EXISTED. `src/tiles/` was extracted from
|
|
2962
|
-
EcoAgent's `ui/js/results/` with its JavaScript and without its CSS, so
|
|
2963
|
-
every consumer of `@flexdesk/tiles` got a `TileGrid` that ran, dragged,
|
|
2964
|
-
resized, saved layouts — and drew a column of unstyled `<div>`s.
|
|
2965
|
-
`TileGrid._init()` sets `--grid-columns`, `--grid-row-height` and
|
|
2966
|
-
`--grid-gap` on the grid element (`src/tiles/tile_grid.js`), and until
|
|
2967
|
-
these rules landed NOTHING IN ANY STYLESHEET READ THEM: no
|
|
2968
|
-
`display: grid`, no `grid-template-columns`, no `grid-auto-rows`. That is
|
|
2969
|
-
the CSS-side half of this repository's signature bug — not a class the JS
|
|
2970
|
-
sets and no rule defines, but the reverse, three custom properties written
|
|
2971
|
-
by the JS into a void.
|
|
2972
|
-
|
|
2973
|
-
THE CLASS NAMES ARE UNPREFIXED, deliberately and unusually. Everything
|
|
2974
|
-
else in this file is `twm-`; these are not, because the names are compiled
|
|
2975
|
-
into the JavaScript that was extracted (`className = 'tile-grid'`,
|
|
2976
|
-
`'tile-header'`, `classList.add('dragging')` …) and renaming them upstream
|
|
2977
|
-
would be a breaking change to every consumer for a cosmetic gain. The one
|
|
2978
|
-
place the prefix DOES appear — `.twm-tile-error`, below — is the exception
|
|
2979
|
-
that proves it: `showError()` emits the prefixed spelling, so the donor's
|
|
2980
|
-
`.tile-error` rule is NOT ported here. Porting it would have written a
|
|
2981
|
-
dead rule directly beside a live class, which is the mistake this comment
|
|
2982
|
-
exists to stop the next reader from repeating.
|
|
2983
|
-
|
|
2984
|
-
Values come from `tokens.css`, so swapping the tokens restyles the tiles
|
|
2985
|
-
with everything else. Two colour literals survive the port and each says at
|
|
2986
|
-
its own rule why: a light accent, for which there is no token (the nearest,
|
|
2987
|
-
`--accent-bright`, is a border colour on this background rather than a text
|
|
2988
|
-
one), and the error red already shipped in `.twm-tile-error`.
|
|
2989
|
-
Ported from EcoAgent `ui/css/results_widgets.css` (the donor still owns its
|
|
2990
|
-
own copy — it does not load this file).
|
|
2991
|
-
═══════════════════════════════════════════════════════════════════════ */
|
|
2992
|
-
|
|
2993
|
-
/* ── the grid container ──────────────────────────────────────────────── */
|
|
2994
|
-
/* The three custom properties are set by `TileGrid._init()` as inline style
|
|
2995
|
-
on this element; the fallbacks are the constructor's defaults, so a grid
|
|
2996
|
-
element built by hand still lays out. */
|
|
2997
|
-
.tile-grid {
|
|
2998
|
-
display: grid;
|
|
2999
|
-
grid-template-columns: repeat(var(--grid-columns, 12), 1fr);
|
|
3000
|
-
grid-auto-rows: var(--grid-row-height, 80px);
|
|
3001
|
-
gap: var(--grid-gap, 16px);
|
|
3002
|
-
padding: var(--grid-gap, 16px) 0 0 0;
|
|
3003
|
-
/* A floor rather than a height: the rows are what size the grid. It
|
|
3004
|
-
matters only when the board is empty, and an empty board that is zero
|
|
3005
|
-
pixels tall is a board you cannot drop the first tile onto. */
|
|
3006
|
-
min-height: 400px;
|
|
3007
|
-
position: relative;
|
|
3008
|
-
}
|
|
3353
|
+
/* ─── Progress: ProgressBar, ProgressList, StepProgress ──────────────
|
|
3354
|
+
`src/ui/components/progress.js`. Every width is the fill's inline
|
|
3355
|
+
`style.width`, changed in place; the states are modifier classes. */
|
|
3009
3356
|
|
|
3010
|
-
|
|
3357
|
+
.twm-progress {
|
|
3358
|
+
display: flex;
|
|
3359
|
+
flex-direction: column;
|
|
3360
|
+
gap: var(--space-xs);
|
|
3361
|
+
min-width: 0;
|
|
3362
|
+
}
|
|
3363
|
+
.twm-progress__head {
|
|
3364
|
+
display: flex;
|
|
3365
|
+
align-items: baseline;
|
|
3366
|
+
gap: var(--space-sm);
|
|
3367
|
+
font-size: var(--font-size-sm);
|
|
3368
|
+
color: var(--text-secondary);
|
|
3369
|
+
}
|
|
3370
|
+
.twm-progress__label {
|
|
3371
|
+
flex: 1 1 auto;
|
|
3372
|
+
min-width: 0;
|
|
3373
|
+
overflow: hidden;
|
|
3374
|
+
text-overflow: ellipsis;
|
|
3375
|
+
white-space: nowrap;
|
|
3376
|
+
color: var(--text-primary);
|
|
3377
|
+
}
|
|
3378
|
+
.twm-progress__readout,
|
|
3379
|
+
.twm-progress__elapsed {
|
|
3380
|
+
flex: 0 0 auto;
|
|
3381
|
+
font-variant-numeric: tabular-nums;
|
|
3382
|
+
}
|
|
3383
|
+
.twm-progress__elapsed {
|
|
3384
|
+
color: var(--text-muted);
|
|
3385
|
+
}
|
|
3386
|
+
.twm-progress__cancel {
|
|
3387
|
+
flex: 0 0 auto;
|
|
3388
|
+
background: transparent;
|
|
3389
|
+
border: 1px solid var(--border-default);
|
|
3390
|
+
border-radius: var(--radius-sm);
|
|
3391
|
+
color: var(--text-secondary);
|
|
3392
|
+
font-size: var(--font-size-xs);
|
|
3393
|
+
padding: 0 var(--space-sm);
|
|
3394
|
+
cursor: pointer;
|
|
3395
|
+
}
|
|
3396
|
+
.twm-progress__cancel:hover:not(:disabled) {
|
|
3397
|
+
border-color: var(--color-danger);
|
|
3398
|
+
color: var(--color-danger);
|
|
3399
|
+
}
|
|
3400
|
+
.twm-progress__cancel:disabled {
|
|
3401
|
+
opacity: 0.5;
|
|
3402
|
+
cursor: default;
|
|
3403
|
+
}
|
|
3404
|
+
.twm-progress__track,
|
|
3405
|
+
.twm-progress-list__track {
|
|
3406
|
+
position: relative;
|
|
3407
|
+
height: 6px;
|
|
3408
|
+
overflow: hidden;
|
|
3409
|
+
background: var(--surface-3);
|
|
3410
|
+
border-radius: var(--radius-pill);
|
|
3411
|
+
}
|
|
3412
|
+
.twm-progress__fill,
|
|
3413
|
+
.twm-progress-list__fill {
|
|
3414
|
+
height: 100%;
|
|
3415
|
+
width: 0;
|
|
3416
|
+
background: var(--accent);
|
|
3417
|
+
border-radius: inherit;
|
|
3418
|
+
transition: width var(--transition-normal);
|
|
3419
|
+
}
|
|
3420
|
+
.twm-progress--indeterminate .twm-progress__fill {
|
|
3421
|
+
position: absolute;
|
|
3422
|
+
left: 0;
|
|
3423
|
+
width: 30%;
|
|
3424
|
+
animation: twm-progress-sweep 1.2s ease-in-out infinite;
|
|
3425
|
+
}
|
|
3426
|
+
.twm-progress--done .twm-progress__fill {
|
|
3427
|
+
background: var(--color-success);
|
|
3428
|
+
}
|
|
3429
|
+
.twm-progress--error .twm-progress__fill {
|
|
3430
|
+
background: var(--color-danger);
|
|
3431
|
+
}
|
|
3432
|
+
.twm-progress--cancelled .twm-progress__fill {
|
|
3433
|
+
background: var(--text-dim);
|
|
3434
|
+
}
|
|
3435
|
+
@keyframes twm-progress-sweep {
|
|
3436
|
+
0% { transform: translateX(-100%); }
|
|
3437
|
+
100% { transform: translateX(340%); }
|
|
3438
|
+
}
|
|
3439
|
+
|
|
3440
|
+
.twm-progress-list {
|
|
3441
|
+
display: flex;
|
|
3442
|
+
flex-direction: column;
|
|
3443
|
+
gap: var(--space-sm);
|
|
3444
|
+
min-width: 0;
|
|
3445
|
+
}
|
|
3446
|
+
.twm-progress-list__rows {
|
|
3447
|
+
display: flex;
|
|
3448
|
+
flex-direction: column;
|
|
3449
|
+
gap: var(--space-xs);
|
|
3450
|
+
}
|
|
3451
|
+
.twm-progress-list__row {
|
|
3452
|
+
display: grid;
|
|
3453
|
+
grid-template-columns: auto minmax(6em, 1fr) minmax(4em, 2fr) auto;
|
|
3454
|
+
align-items: center;
|
|
3455
|
+
gap: var(--space-sm);
|
|
3456
|
+
font-size: var(--font-size-sm);
|
|
3457
|
+
color: var(--text-primary);
|
|
3458
|
+
}
|
|
3459
|
+
.twm-progress-list__name {
|
|
3460
|
+
overflow: hidden;
|
|
3461
|
+
text-overflow: ellipsis;
|
|
3462
|
+
white-space: nowrap;
|
|
3463
|
+
}
|
|
3464
|
+
.twm-progress-list__count {
|
|
3465
|
+
color: var(--text-secondary);
|
|
3466
|
+
font-variant-numeric: tabular-nums;
|
|
3467
|
+
white-space: nowrap;
|
|
3468
|
+
}
|
|
3469
|
+
.twm-progress-list__state {
|
|
3470
|
+
width: 8px;
|
|
3471
|
+
height: 8px;
|
|
3472
|
+
border-radius: var(--radius-circle);
|
|
3473
|
+
background: var(--text-dim);
|
|
3474
|
+
}
|
|
3475
|
+
.twm-progress-list__row--running .twm-progress-list__state {
|
|
3476
|
+
background: var(--accent);
|
|
3477
|
+
}
|
|
3478
|
+
.twm-progress-list--pulse .twm-progress-list__row--running .twm-progress-list__state {
|
|
3479
|
+
animation: twm-progress-pulse 1.2s ease-in-out infinite;
|
|
3480
|
+
}
|
|
3481
|
+
.twm-progress-list__row--done .twm-progress-list__state,
|
|
3482
|
+
.twm-progress-list__row--done .twm-progress-list__fill {
|
|
3483
|
+
background: var(--color-success);
|
|
3484
|
+
}
|
|
3485
|
+
.twm-progress-list__row--failed .twm-progress-list__state,
|
|
3486
|
+
.twm-progress-list__row--failed .twm-progress-list__fill {
|
|
3487
|
+
background: var(--color-danger);
|
|
3488
|
+
}
|
|
3489
|
+
.twm-progress-list__row--pending {
|
|
3490
|
+
color: var(--text-muted);
|
|
3491
|
+
}
|
|
3492
|
+
.twm-progress-list__empty,
|
|
3493
|
+
.twm-progress-list__stats {
|
|
3494
|
+
font-size: var(--font-size-xs);
|
|
3495
|
+
color: var(--text-muted);
|
|
3496
|
+
font-variant-numeric: tabular-nums;
|
|
3497
|
+
}
|
|
3498
|
+
@keyframes twm-progress-pulse {
|
|
3499
|
+
0%, 100% { opacity: 1; }
|
|
3500
|
+
50% { opacity: 0.35; }
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
.twm-steps {
|
|
3504
|
+
display: flex;
|
|
3505
|
+
flex-wrap: wrap;
|
|
3506
|
+
gap: var(--space-xs) var(--space-lg);
|
|
3507
|
+
margin: 0;
|
|
3508
|
+
padding: 0;
|
|
3509
|
+
list-style: none;
|
|
3510
|
+
font-size: var(--font-size-sm);
|
|
3511
|
+
}
|
|
3512
|
+
.twm-steps__step {
|
|
3513
|
+
display: inline-flex;
|
|
3514
|
+
align-items: center;
|
|
3515
|
+
gap: var(--space-xs);
|
|
3516
|
+
color: var(--text-muted);
|
|
3517
|
+
}
|
|
3518
|
+
.twm-steps__marker {
|
|
3519
|
+
width: 8px;
|
|
3520
|
+
height: 8px;
|
|
3521
|
+
border-radius: var(--radius-circle);
|
|
3522
|
+
border: 1px solid currentColor;
|
|
3523
|
+
}
|
|
3524
|
+
.twm-steps__step--done {
|
|
3525
|
+
color: var(--text-secondary);
|
|
3526
|
+
}
|
|
3527
|
+
.twm-steps__step--done .twm-steps__marker {
|
|
3528
|
+
background: var(--color-success);
|
|
3529
|
+
border-color: var(--color-success);
|
|
3530
|
+
}
|
|
3531
|
+
.twm-steps__step--active {
|
|
3532
|
+
color: var(--text-primary);
|
|
3533
|
+
font-weight: var(--font-weight-semibold);
|
|
3534
|
+
}
|
|
3535
|
+
.twm-steps__step--active .twm-steps__marker {
|
|
3536
|
+
background: var(--accent);
|
|
3537
|
+
border-color: var(--accent);
|
|
3538
|
+
}
|
|
3539
|
+
.twm-steps__step--error {
|
|
3540
|
+
color: var(--color-danger);
|
|
3541
|
+
}
|
|
3542
|
+
.twm-steps__step--error .twm-steps__marker {
|
|
3543
|
+
background: var(--color-danger);
|
|
3544
|
+
border-color: var(--color-danger);
|
|
3545
|
+
}
|
|
3546
|
+
.twm-steps__pass {
|
|
3547
|
+
font-weight: var(--font-weight-regular);
|
|
3548
|
+
color: var(--text-muted);
|
|
3549
|
+
font-variant-numeric: tabular-nums;
|
|
3550
|
+
}
|
|
3551
|
+
@media (prefers-reduced-motion: reduce) {
|
|
3552
|
+
.twm-progress__fill,
|
|
3553
|
+
.twm-progress-list__fill { transition: none; }
|
|
3554
|
+
.twm-progress--indeterminate .twm-progress__fill,
|
|
3555
|
+
.twm-progress-list--pulse .twm-progress-list__row--running .twm-progress-list__state { animation: none; }
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
/* The bar and phases inside showRunProgressDialog / showComputingWindow,
|
|
3559
|
+
and the message's final state. */
|
|
3560
|
+
.twm-job-progress__steps,
|
|
3561
|
+
.twm-job-progress__bar {
|
|
3562
|
+
align-self: stretch;
|
|
3563
|
+
margin: var(--space-xs) 0;
|
|
3564
|
+
}
|
|
3565
|
+
.twm-run-progress__message.is-ok,
|
|
3566
|
+
.twm-computing-status__message.is-ok {
|
|
3567
|
+
color: var(--color-success);
|
|
3568
|
+
}
|
|
3569
|
+
.twm-run-progress__message.is-err,
|
|
3570
|
+
.twm-computing-status__message.is-err {
|
|
3571
|
+
color: var(--color-danger);
|
|
3572
|
+
}
|
|
3573
|
+
.twm-run-progress__message.is-cancelled,
|
|
3574
|
+
.twm-computing-status__message.is-cancelled {
|
|
3575
|
+
color: var(--text-muted);
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3578
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
3579
|
+
@flexdesk/tiles — THE TILE GRID'S CHROME
|
|
3580
|
+
|
|
3581
|
+
THIS STYLESHEET HAD NEVER EXISTED. `src/tiles/` was extracted from
|
|
3582
|
+
EcoAgent's `ui/js/results/` with its JavaScript and without its CSS, so
|
|
3583
|
+
every consumer of `@flexdesk/tiles` got a `TileGrid` that ran, dragged,
|
|
3584
|
+
resized, saved layouts — and drew a column of unstyled `<div>`s.
|
|
3585
|
+
`TileGrid._init()` sets `--grid-columns`, `--grid-row-height` and
|
|
3586
|
+
`--grid-gap` on the grid element (`src/tiles/tile_grid.js`), and until
|
|
3587
|
+
these rules landed NOTHING IN ANY STYLESHEET READ THEM: no
|
|
3588
|
+
`display: grid`, no `grid-template-columns`, no `grid-auto-rows`. That is
|
|
3589
|
+
the CSS-side half of this repository's signature bug — not a class the JS
|
|
3590
|
+
sets and no rule defines, but the reverse, three custom properties written
|
|
3591
|
+
by the JS into a void.
|
|
3592
|
+
|
|
3593
|
+
THE CLASS NAMES ARE UNPREFIXED, deliberately and unusually. Everything
|
|
3594
|
+
else in this file is `twm-`; these are not, because the names are compiled
|
|
3595
|
+
into the JavaScript that was extracted (`className = 'tile-grid'`,
|
|
3596
|
+
`'tile-header'`, `classList.add('dragging')` …) and renaming them upstream
|
|
3597
|
+
would be a breaking change to every consumer for a cosmetic gain. The one
|
|
3598
|
+
place the prefix DOES appear — `.twm-tile-error`, below — is the exception
|
|
3599
|
+
that proves it: `showError()` emits the prefixed spelling, so the donor's
|
|
3600
|
+
`.tile-error` rule is NOT ported here. Porting it would have written a
|
|
3601
|
+
dead rule directly beside a live class, which is the mistake this comment
|
|
3602
|
+
exists to stop the next reader from repeating.
|
|
3603
|
+
|
|
3604
|
+
Values come from `tokens.css`, so swapping the tokens restyles the tiles
|
|
3605
|
+
with everything else. Two colour literals survive the port and each says at
|
|
3606
|
+
its own rule why: a light accent, for which there is no token (the nearest,
|
|
3607
|
+
`--accent-bright`, is a border colour on this background rather than a text
|
|
3608
|
+
one), and the error red already shipped in `.twm-tile-error`.
|
|
3609
|
+
Ported from EcoAgent `ui/css/results_widgets.css` (the donor still owns its
|
|
3610
|
+
own copy — it does not load this file).
|
|
3611
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
3612
|
+
|
|
3613
|
+
/* ── the grid container ──────────────────────────────────────────────── */
|
|
3614
|
+
/* The three custom properties are set by `TileGrid._init()` as inline style
|
|
3615
|
+
on this element; the fallbacks are the constructor's defaults, so a grid
|
|
3616
|
+
element built by hand still lays out. */
|
|
3617
|
+
.tile-grid {
|
|
3618
|
+
display: grid;
|
|
3619
|
+
grid-template-columns: repeat(var(--grid-columns, 12), 1fr);
|
|
3620
|
+
grid-auto-rows: var(--grid-row-height, 80px);
|
|
3621
|
+
gap: var(--grid-gap, 16px);
|
|
3622
|
+
padding: var(--grid-gap, 16px) 0 0 0;
|
|
3623
|
+
/* A floor rather than a height: the rows are what size the grid. It
|
|
3624
|
+
matters only when the board is empty, and an empty board that is zero
|
|
3625
|
+
pixels tall is a board you cannot drop the first tile onto. */
|
|
3626
|
+
min-height: 400px;
|
|
3627
|
+
position: relative;
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
/* ── the built-in toolbar ────────────────────────────────────────────── */
|
|
3011
3631
|
/* `_buildToolbar()` emits `tile-grid-toolbar tile-grid-toolbar--bottom` and no
|
|
3012
3632
|
other variant, so the divider lives on the modifier: a rule that put a
|
|
3013
3633
|
`border-bottom` on the base class — as the donor's did, when the toolbar sat
|
|
@@ -3489,10 +4109,12 @@ body.twm-window-maximized .twm-resize-handle {
|
|
|
3489
4109
|
font-size: 32px;
|
|
3490
4110
|
}
|
|
3491
4111
|
|
|
3492
|
-
/* ── the chart and KPI tiles (0.13.0, src/tiles/chart_tiles.js
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
4112
|
+
/* ── the figure, chart and KPI tiles (0.13.0, src/tiles/chart_tiles.js;
|
|
4113
|
+
0.17.0, src/tiles/figure_tile.js) ─────────────────────────────── */
|
|
4114
|
+
/* A figure tile's plot (a chart tile's too: it is one) flexes into what
|
|
4115
|
+
`.tile-content`'s column leaves; a chart's note takes its own line BELOW it,
|
|
4116
|
+
so the height chain above is untouched. */
|
|
4117
|
+
.fd-figure-tile {
|
|
3496
4118
|
display: flex;
|
|
3497
4119
|
flex-direction: column;
|
|
3498
4120
|
flex: 1 1 auto;
|
|
@@ -3504,7 +4126,7 @@ body.twm-window-maximized .twm-resize-handle {
|
|
|
3504
4126
|
/* Plotly puts `.js-plotly-plot` on the figure itself, and the rule above makes
|
|
3505
4127
|
that `height: 100% !important` — which, beside a note, pushes the note out of
|
|
3506
4128
|
the tile. Here the flex column sizes the figure instead. */
|
|
3507
|
-
.tile-content .fd-
|
|
4129
|
+
.tile-content .fd-figure-tile.js-plotly-plot {
|
|
3508
4130
|
height: auto !important;
|
|
3509
4131
|
}
|
|
3510
4132
|
|
|
@@ -3565,72 +4187,287 @@ body.twm-window-maximized .twm-resize-handle {
|
|
|
3565
4187
|
font-size: var(--font-size-xs);
|
|
3566
4188
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
|
|
3567
4189
|
}
|
|
3568
|
-
/*
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
.twm-action-dropdown-menu {
|
|
3574
|
-
/* position/top/left set by ActionDropdown.position() via inline style */
|
|
3575
|
-
position: fixed;
|
|
3576
|
-
min-width: 220px;
|
|
3577
|
-
padding: var(--space-md);
|
|
3578
|
-
background: linear-gradient(145deg, rgba(30, 32, 38, 0.98), rgba(24, 26, 32, 0.96));
|
|
3579
|
-
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
3580
|
-
border-radius: 10px;
|
|
3581
|
-
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
|
|
3582
|
-
z-index: var(--z-toast);
|
|
3583
|
-
opacity: 0;
|
|
3584
|
-
pointer-events: none;
|
|
3585
|
-
transition: opacity 0.16s ease;
|
|
3586
|
-
}
|
|
3587
|
-
.twm-action-dropdown-menu[hidden] {
|
|
3588
|
-
display: none !important;
|
|
3589
|
-
}
|
|
3590
|
-
/* THE OPEN STATE. `ActionDropdown.open()` un-hides the menu and then adds
|
|
3591
|
-
`.visible` on the next frame to fade it in (action_dropdown.js:172-180) —
|
|
3592
|
-
and no rule for that class existed, so the menu unhid itself into
|
|
3593
|
-
`opacity: 0; pointer-events: none` and stayed there. Every ActionDropdown in
|
|
3594
|
-
the library, "Add Widget" included, opened invisible and un-clickable.
|
|
3595
|
-
The same defect `.twm-collapsible-content.visible` had, in the same shape:
|
|
3596
|
-
the JS toggles a class the stylesheet never grew. */
|
|
3597
|
-
.twm-action-dropdown-menu.visible {
|
|
3598
|
-
opacity: 1;
|
|
3599
|
-
pointer-events: auto;
|
|
3600
|
-
}
|
|
3601
|
-
/* The option's text column. `_renderOptions` wraps the label and the
|
|
3602
|
-
description in `<span class="option-text">` (action_dropdown.js:125-128) and
|
|
3603
|
-
both children are inline, so a described option rendered as
|
|
3604
|
-
"Add Widget Put a widget on this desktop" on one run-together line. The
|
|
3605
|
-
description is a SECOND LINE by construction; this is what makes it one.
|
|
3606
|
-
`min-width: 0` so the ellipsis on the two children has something to bite on
|
|
3607
|
-
inside the flex row. */
|
|
3608
|
-
.twm-action-dropdown-option .option-text {
|
|
4190
|
+
/* ── the list and people tiles (0.16.1, list_tiles.js) ──────────────────
|
|
4191
|
+
A bar (count, button), the rows, a note. The rows scroll inside the tile;
|
|
4192
|
+
the bar and the note stay put. */
|
|
4193
|
+
.fd-list-tile {
|
|
4194
|
+
flex: 1 1 auto;
|
|
3609
4195
|
display: flex;
|
|
3610
4196
|
flex-direction: column;
|
|
3611
|
-
min-
|
|
4197
|
+
min-height: 0;
|
|
4198
|
+
gap: var(--space-xs);
|
|
4199
|
+
margin: calc(-1 * var(--space-sm)) 0;
|
|
3612
4200
|
}
|
|
3613
|
-
|
|
3614
|
-
|
|
4201
|
+
.fd-list-tile__bar {
|
|
4202
|
+
flex: 0 0 auto;
|
|
3615
4203
|
display: flex;
|
|
3616
4204
|
align-items: center;
|
|
3617
|
-
gap:
|
|
3618
|
-
|
|
3619
|
-
padding: 10px 12px;
|
|
3620
|
-
margin-bottom: var(--space-xs);
|
|
3621
|
-
background: rgba(255, 255, 255, 0.03);
|
|
3622
|
-
border: 1px solid transparent;
|
|
3623
|
-
border-radius: var(--radius-md);
|
|
3624
|
-
color: rgba(255, 255, 255, 0.85);
|
|
3625
|
-
font-family: inherit;
|
|
3626
|
-
font-size: var(--font-size-md);
|
|
3627
|
-
cursor: pointer;
|
|
3628
|
-
text-align: left;
|
|
3629
|
-
box-sizing: border-box;
|
|
3630
|
-
transition: background var(--transition-normal), border-color var(--transition-normal);
|
|
4205
|
+
gap: var(--space-sm);
|
|
4206
|
+
min-height: 24px;
|
|
3631
4207
|
}
|
|
3632
|
-
.
|
|
3633
|
-
|
|
4208
|
+
.fd-list-tile__count {
|
|
4209
|
+
color: var(--text-muted);
|
|
4210
|
+
font-size: var(--font-size-xs);
|
|
4211
|
+
font-variant-numeric: tabular-nums;
|
|
4212
|
+
}
|
|
4213
|
+
.fd-list-tile__spacer { flex: 1 1 auto; }
|
|
4214
|
+
.fd-list-tile__action {
|
|
4215
|
+
display: inline-flex;
|
|
4216
|
+
align-items: center;
|
|
4217
|
+
gap: 4px;
|
|
4218
|
+
padding: 2px 8px;
|
|
4219
|
+
border: 1px solid var(--border-subtle);
|
|
4220
|
+
border-radius: var(--radius-sm);
|
|
4221
|
+
background: transparent;
|
|
4222
|
+
color: var(--text-secondary);
|
|
4223
|
+
font: inherit;
|
|
4224
|
+
font-size: var(--font-size-xs);
|
|
4225
|
+
cursor: pointer;
|
|
4226
|
+
}
|
|
4227
|
+
.fd-list-tile__action:hover { color: var(--text-bright); border-color: var(--text-muted); }
|
|
4228
|
+
.fd-list-tile__action .material-symbols-outlined { font-size: 15px; }
|
|
4229
|
+
.fd-list-tile__rows {
|
|
4230
|
+
flex: 1 1 auto;
|
|
4231
|
+
min-height: 0;
|
|
4232
|
+
overflow-y: auto;
|
|
4233
|
+
overflow-x: hidden;
|
|
4234
|
+
}
|
|
4235
|
+
.fd-list-tile__empty {
|
|
4236
|
+
padding: var(--space-sm) 2px;
|
|
4237
|
+
color: var(--text-muted);
|
|
4238
|
+
font-size: var(--font-size-sm);
|
|
4239
|
+
}
|
|
4240
|
+
.fd-list-tile__row {
|
|
4241
|
+
display: flex;
|
|
4242
|
+
align-items: center;
|
|
4243
|
+
gap: var(--space-sm);
|
|
4244
|
+
min-width: 0;
|
|
4245
|
+
padding: 3px 4px;
|
|
4246
|
+
border-radius: var(--radius-sm);
|
|
4247
|
+
font-size: var(--font-size-sm);
|
|
4248
|
+
cursor: pointer;
|
|
4249
|
+
outline: none;
|
|
4250
|
+
}
|
|
4251
|
+
.fd-list-tile__row:hover { background: rgba(255, 255, 255, 0.05); }
|
|
4252
|
+
.fd-list-tile__row:focus-visible { box-shadow: inset 0 0 0 1px var(--accent-bright); }
|
|
4253
|
+
.fd-list-tile__icon { flex: 0 0 auto; font-size: 16px; color: var(--text-muted); }
|
|
4254
|
+
.fd-list-tile__lead {
|
|
4255
|
+
flex: 0 0 auto;
|
|
4256
|
+
color: var(--text-muted);
|
|
4257
|
+
font-variant-numeric: tabular-nums;
|
|
4258
|
+
white-space: nowrap;
|
|
4259
|
+
}
|
|
4260
|
+
.fd-list-tile__title {
|
|
4261
|
+
flex: 1 1 auto;
|
|
4262
|
+
min-width: 0;
|
|
4263
|
+
color: var(--text-bright);
|
|
4264
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
4265
|
+
}
|
|
4266
|
+
.fd-list-tile__cell {
|
|
4267
|
+
flex: 0 0 auto;
|
|
4268
|
+
display: inline-flex;
|
|
4269
|
+
align-items: center;
|
|
4270
|
+
gap: 2px;
|
|
4271
|
+
max-width: 40%;
|
|
4272
|
+
color: var(--text-secondary);
|
|
4273
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
4274
|
+
}
|
|
4275
|
+
.fd-list-tile__cell .material-symbols-outlined { font-size: 14px; }
|
|
4276
|
+
.fd-list-tile__cell--danger, .fd-people-tile__pill--danger { color: var(--color-danger); }
|
|
4277
|
+
.fd-list-tile__cell--warning, .fd-people-tile__pill--warning { color: var(--color-warning); }
|
|
4278
|
+
.fd-list-tile__cell--ok, .fd-people-tile__pill--ok { color: var(--color-success); }
|
|
4279
|
+
.fd-list-tile__cell--muted, .fd-people-tile__pill--muted { color: var(--text-muted); }
|
|
4280
|
+
.fd-list-tile__note {
|
|
4281
|
+
flex: 0 0 auto;
|
|
4282
|
+
font-size: var(--font-size-xs);
|
|
4283
|
+
color: var(--text-muted);
|
|
4284
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
4285
|
+
}
|
|
4286
|
+
.fd-people-tile__name {
|
|
4287
|
+
flex: 0 1 auto;
|
|
4288
|
+
min-width: 0;
|
|
4289
|
+
color: var(--text-bright);
|
|
4290
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
4291
|
+
}
|
|
4292
|
+
.fd-people-tile__name--muted { color: var(--text-muted); font-style: italic; }
|
|
4293
|
+
.fd-people-tile__pills {
|
|
4294
|
+
flex: 1 1 auto;
|
|
4295
|
+
display: flex;
|
|
4296
|
+
flex-wrap: nowrap;
|
|
4297
|
+
gap: 4px;
|
|
4298
|
+
min-width: 0;
|
|
4299
|
+
overflow: hidden;
|
|
4300
|
+
}
|
|
4301
|
+
.fd-people-tile__pill {
|
|
4302
|
+
flex: 0 0 auto;
|
|
4303
|
+
padding: 0 6px;
|
|
4304
|
+
border: 1px solid var(--border-subtle);
|
|
4305
|
+
border-radius: 9px;
|
|
4306
|
+
font-size: var(--font-size-xs);
|
|
4307
|
+
line-height: 16px;
|
|
4308
|
+
color: var(--text-secondary);
|
|
4309
|
+
white-space: nowrap;
|
|
4310
|
+
}
|
|
4311
|
+
.fd-people-tile__count {
|
|
4312
|
+
flex: 0 0 auto;
|
|
4313
|
+
color: var(--text-secondary);
|
|
4314
|
+
font-size: var(--font-size-xs);
|
|
4315
|
+
font-variant-numeric: tabular-nums;
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
/* ── the scope picker (0.16.1, scope_picker.js): one pressed button of a row */
|
|
4319
|
+
.fd-scope-picker {
|
|
4320
|
+
display: inline-flex;
|
|
4321
|
+
align-items: stretch;
|
|
4322
|
+
border: 1px solid var(--border-subtle);
|
|
4323
|
+
border-radius: var(--radius-sm);
|
|
4324
|
+
overflow: hidden;
|
|
4325
|
+
}
|
|
4326
|
+
.fd-scope-picker__btn {
|
|
4327
|
+
padding: 3px 10px;
|
|
4328
|
+
border: 0;
|
|
4329
|
+
border-left: 1px solid var(--border-subtle);
|
|
4330
|
+
background: transparent;
|
|
4331
|
+
color: var(--text-secondary);
|
|
4332
|
+
font: inherit;
|
|
4333
|
+
font-size: var(--font-size-sm);
|
|
4334
|
+
white-space: nowrap;
|
|
4335
|
+
cursor: pointer;
|
|
4336
|
+
}
|
|
4337
|
+
.fd-scope-picker__btn:first-child { border-left: 0; }
|
|
4338
|
+
.fd-scope-picker__btn:hover { color: var(--text-bright); background: rgba(255, 255, 255, 0.05); }
|
|
4339
|
+
.fd-scope-picker__btn--on,
|
|
4340
|
+
.fd-scope-picker__btn--on:hover { background: var(--accent); color: #fff; }
|
|
4341
|
+
.fd-scope-picker__btn:focus-visible { outline: 1px solid var(--accent-bright); outline-offset: -2px; }
|
|
4342
|
+
|
|
4343
|
+
/* ── the tile config form (0.17.0, tile_config_form.js) ──────────────────
|
|
4344
|
+
One row per schema field: the label, the control, the description, the
|
|
4345
|
+
inline error. A hidden row (visibleWhen) is `hidden`, never rebuilt. */
|
|
4346
|
+
.fd-tile-config {
|
|
4347
|
+
display: flex;
|
|
4348
|
+
flex-direction: column;
|
|
4349
|
+
gap: var(--space-sm);
|
|
4350
|
+
padding: var(--space-sm);
|
|
4351
|
+
font-size: var(--font-size-sm);
|
|
4352
|
+
}
|
|
4353
|
+
.fd-tile-config__row {
|
|
4354
|
+
display: flex;
|
|
4355
|
+
flex-direction: column;
|
|
4356
|
+
gap: 3px;
|
|
4357
|
+
min-width: 0;
|
|
4358
|
+
}
|
|
4359
|
+
.fd-tile-config__row[hidden] { display: none; }
|
|
4360
|
+
.fd-tile-config__row--checkbox {
|
|
4361
|
+
flex-direction: row;
|
|
4362
|
+
flex-wrap: wrap;
|
|
4363
|
+
align-items: center;
|
|
4364
|
+
gap: var(--space-xs);
|
|
4365
|
+
}
|
|
4366
|
+
.fd-tile-config__row--checkbox .fd-tile-config__help,
|
|
4367
|
+
.fd-tile-config__row--checkbox .fd-tile-config__error { flex-basis: 100%; }
|
|
4368
|
+
.fd-tile-config__label { color: var(--text-secondary); font-size: var(--font-size-xs); }
|
|
4369
|
+
.fd-tile-config__input,
|
|
4370
|
+
.fd-tile-config__select {
|
|
4371
|
+
width: 100%;
|
|
4372
|
+
box-sizing: border-box;
|
|
4373
|
+
padding: var(--ea-input-pad, 4px 6px);
|
|
4374
|
+
border: 1px solid var(--border-subtle);
|
|
4375
|
+
border-radius: var(--radius-sm);
|
|
4376
|
+
background: var(--ea-input-bg, transparent);
|
|
4377
|
+
color: var(--text-bright);
|
|
4378
|
+
font: inherit;
|
|
4379
|
+
}
|
|
4380
|
+
.fd-tile-config__input:focus,
|
|
4381
|
+
.fd-tile-config__select:focus { outline: none; border-color: var(--accent-bright); }
|
|
4382
|
+
.fd-tile-config__input:disabled,
|
|
4383
|
+
.fd-tile-config__select:disabled,
|
|
4384
|
+
.fd-tile-config__checkbox:disabled,
|
|
4385
|
+
.fd-tile-config__color:disabled,
|
|
4386
|
+
.fd-tile-config__range:disabled { opacity: 0.6; cursor: default; }
|
|
4387
|
+
.fd-tile-config__row--invalid .fd-tile-config__input,
|
|
4388
|
+
.fd-tile-config__row--invalid .fd-tile-config__select { border-color: var(--color-danger); }
|
|
4389
|
+
.fd-tile-config__range-wrap { display: flex; align-items: center; gap: var(--space-sm); }
|
|
4390
|
+
.fd-tile-config__range { flex: 1 1 auto; }
|
|
4391
|
+
.fd-tile-config__range-value { min-width: 3ch; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
|
|
4392
|
+
.fd-tile-config__color { width: 48px; height: 24px; padding: 0; border: 1px solid var(--border-subtle); background: transparent; }
|
|
4393
|
+
.fd-tile-config__help { color: var(--text-muted); font-size: var(--font-size-xs); line-height: 1.4; }
|
|
4394
|
+
.fd-tile-config__error { color: var(--color-danger); font-size: var(--font-size-xs); line-height: 1.4; }
|
|
4395
|
+
.fd-tile-config__error[hidden] { display: none; }
|
|
4396
|
+
|
|
4397
|
+
/* ===================================================================
|
|
4398
|
+
REUSABLE ACTION DROPDOWN COMPONENT
|
|
4399
|
+
Used by Add Scenario, Add Widget, and other action dropdowns
|
|
4400
|
+
=================================================================== */
|
|
4401
|
+
|
|
4402
|
+
.twm-action-dropdown-menu {
|
|
4403
|
+
/* position/top/left set by ActionDropdown.position() via inline style */
|
|
4404
|
+
position: fixed;
|
|
4405
|
+
min-width: 220px;
|
|
4406
|
+
padding: var(--space-md);
|
|
4407
|
+
background: linear-gradient(145deg, rgba(30, 32, 38, 0.98), rgba(24, 26, 32, 0.96));
|
|
4408
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
4409
|
+
border-radius: 10px;
|
|
4410
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
|
|
4411
|
+
z-index: var(--z-toast);
|
|
4412
|
+
opacity: 0;
|
|
4413
|
+
pointer-events: none;
|
|
4414
|
+
transition: opacity 0.16s ease;
|
|
4415
|
+
}
|
|
4416
|
+
.twm-action-dropdown-menu[hidden] {
|
|
4417
|
+
display: none !important;
|
|
4418
|
+
}
|
|
4419
|
+
/* THE OPEN STATE. `ActionDropdown.open()` un-hides the menu and then adds
|
|
4420
|
+
`.visible` on the next frame to fade it in (action_dropdown.js:172-180) —
|
|
4421
|
+
and no rule for that class existed, so the menu unhid itself into
|
|
4422
|
+
`opacity: 0; pointer-events: none` and stayed there. Every ActionDropdown in
|
|
4423
|
+
the library, "Add Widget" included, opened invisible and un-clickable.
|
|
4424
|
+
The same defect `.twm-collapsible-content.visible` had, in the same shape:
|
|
4425
|
+
the JS toggles a class the stylesheet never grew. */
|
|
4426
|
+
.twm-action-dropdown-menu.visible {
|
|
4427
|
+
opacity: 1;
|
|
4428
|
+
pointer-events: auto;
|
|
4429
|
+
}
|
|
4430
|
+
/* The option's text column. `_renderOptions` wraps the label and the
|
|
4431
|
+
description in `<span class="option-text">` (action_dropdown.js:125-128) and
|
|
4432
|
+
both children are inline, so a described option rendered as
|
|
4433
|
+
"Add Widget Put a widget on this desktop" on one run-together line. The
|
|
4434
|
+
description is a SECOND LINE by construction; this is what makes it one.
|
|
4435
|
+
`min-width: 0` so the ellipsis on the two children has something to bite on
|
|
4436
|
+
inside the flex row. */
|
|
4437
|
+
.twm-action-dropdown-option .option-text {
|
|
4438
|
+
display: flex;
|
|
4439
|
+
flex-direction: column;
|
|
4440
|
+
min-width: 0;
|
|
4441
|
+
}
|
|
4442
|
+
/* Dropdown options */
|
|
4443
|
+
.twm-action-dropdown-option {
|
|
4444
|
+
display: flex;
|
|
4445
|
+
align-items: center;
|
|
4446
|
+
gap: 10px;
|
|
4447
|
+
width: 100%;
|
|
4448
|
+
padding: 10px 12px;
|
|
4449
|
+
margin-bottom: var(--space-xs);
|
|
4450
|
+
background: rgba(255, 255, 255, 0.03);
|
|
4451
|
+
border: 1px solid transparent;
|
|
4452
|
+
border-radius: var(--radius-md);
|
|
4453
|
+
color: rgba(255, 255, 255, 0.85);
|
|
4454
|
+
font-family: inherit;
|
|
4455
|
+
font-size: var(--font-size-md);
|
|
4456
|
+
cursor: pointer;
|
|
4457
|
+
text-align: left;
|
|
4458
|
+
box-sizing: border-box;
|
|
4459
|
+
transition: background var(--transition-normal), border-color var(--transition-normal);
|
|
4460
|
+
}
|
|
4461
|
+
/* A `{ separator: true }` entry: a rule between two groups of options. It is
|
|
4462
|
+
not a button, so it takes no focus and the arrow keys pass over it. */
|
|
4463
|
+
.twm-action-dropdown-separator {
|
|
4464
|
+
height: 1px;
|
|
4465
|
+
/* the option above already leaves var(--space-xs) below itself */
|
|
4466
|
+
margin: 0 0 var(--space-xs);
|
|
4467
|
+
background: var(--border-subtle);
|
|
4468
|
+
}
|
|
4469
|
+
.twm-action-dropdown-option:last-child {
|
|
4470
|
+
margin-bottom: 0;
|
|
3634
4471
|
}
|
|
3635
4472
|
.twm-action-dropdown-option:hover,
|
|
3636
4473
|
.twm-action-dropdown-option:focus {
|
|
@@ -4421,7 +5258,36 @@ button.twm-about-dialog__btn--close:focus {
|
|
|
4421
5258
|
}
|
|
4422
5259
|
/* ─── Badges ──────────────────────────────────────────────────────────── */
|
|
4423
5260
|
|
|
4424
|
-
/*
|
|
5261
|
+
/* A badge beside the title (`createDetailHeader({badges})`, BUG-0015): a
|
|
5262
|
+
* neutral pill from tokens. A caller's own `className` sits on the same
|
|
5263
|
+
* element, after this rule's single class, to recolour it. */
|
|
5264
|
+
.twm-detail-header__badge {
|
|
5265
|
+
display: inline-flex;
|
|
5266
|
+
align-items: center;
|
|
5267
|
+
gap: var(--space-xs);
|
|
5268
|
+
padding: 2px var(--space-md);
|
|
5269
|
+
border-radius: var(--radius-pill);
|
|
5270
|
+
border: 1px solid var(--border-subtle);
|
|
5271
|
+
background: var(--surface-2);
|
|
5272
|
+
color: var(--text-muted);
|
|
5273
|
+
font-size: var(--font-size-xs);
|
|
5274
|
+
font-weight: var(--font-weight-medium);
|
|
5275
|
+
line-height: var(--line-height-tight);
|
|
5276
|
+
white-space: nowrap;
|
|
5277
|
+
flex-shrink: 0;
|
|
5278
|
+
}
|
|
5279
|
+
/* Compounded for the Material Symbols tie — see `.twm-leaf__icon`. */
|
|
5280
|
+
.twm-detail-header__badge-icon,
|
|
5281
|
+
.twm-detail-header__badge-icon.material-symbols-outlined {
|
|
5282
|
+
font-size: 14px;
|
|
5283
|
+
line-height: 1;
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5286
|
+
/* ─── Buttons ─────────────────────────────────────────────────────────── */
|
|
5287
|
+
|
|
5288
|
+
/* An action is a `.twm-btn` (BUG-0015): the shared button look, with
|
|
5289
|
+
* 'primary' wearing `.twm-btn--primary` and 'danger' `.twm-btn--danger`;
|
|
5290
|
+
* 'secondary' is the plain button. Its icon is a `.twm-btn__glyph`. */
|
|
4425
5291
|
|
|
4426
5292
|
/* ─── Subtitle ────────────────────────────────────────────────────────── */
|
|
4427
5293
|
|
|
@@ -4709,6 +5575,11 @@ button.twm-about-dialog__btn--close:focus {
|
|
|
4709
5575
|
margin-left: auto;
|
|
4710
5576
|
line-height: 1;
|
|
4711
5577
|
}
|
|
5578
|
+
/* The badge's variants: createTreeItem's badge.variant ('muted' when unset) */
|
|
5579
|
+
.twm-tree-item__badge--muted { background: color-mix(in srgb, var(--text-dim) 15%, transparent); color: var(--text-dim); }
|
|
5580
|
+
.twm-tree-item__badge--pass { background: color-mix(in srgb, var(--color-success) 15%, transparent); color: var(--color-success); }
|
|
5581
|
+
.twm-tree-item__badge--fail { background: color-mix(in srgb, var(--color-danger) 15%, transparent); color: var(--color-danger); }
|
|
5582
|
+
.twm-tree-item__badge--error { background: color-mix(in srgb, var(--color-danger) 15%, transparent); color: var(--color-danger); }
|
|
4712
5583
|
/* Status dot variant (smaller, no text) */
|
|
4713
5584
|
.twm-tree-item__status-dot {
|
|
4714
5585
|
width: 7px;
|
|
@@ -4716,7 +5587,12 @@ button.twm-about-dialog__btn--close:focus {
|
|
|
4716
5587
|
border-radius: 50%;
|
|
4717
5588
|
flex-shrink: 0;
|
|
4718
5589
|
margin-left: auto;
|
|
5590
|
+
background: var(--text-dim);
|
|
4719
5591
|
}
|
|
5592
|
+
.twm-tree-item__status-dot--muted { background: var(--text-dim); }
|
|
5593
|
+
.twm-tree-item__status-dot--pass { background: var(--color-success); }
|
|
5594
|
+
.twm-tree-item__status-dot--fail { background: var(--color-danger); }
|
|
5595
|
+
.twm-tree-item__status-dot--error { background: var(--color-danger); }
|
|
4720
5596
|
|
|
4721
5597
|
/* ── from slide_out_panel.css ───────────────────────── */
|
|
4722
5598
|
/* ─── SlideOutPanel ─────────────────────────────────────────────────────────
|
|
@@ -5314,55 +6190,197 @@ button.twm-about-dialog__btn--close:focus {
|
|
|
5314
6190
|
.twm-managed-window--modal .twm-picker__btn .material-symbols-outlined {
|
|
5315
6191
|
font-size: 15px;
|
|
5316
6192
|
}
|
|
5317
|
-
/*
|
|
5318
|
-
*
|
|
5319
|
-
|
|
5320
|
-
* on screen. */
|
|
5321
|
-
.twm-modal__row[hidden],
|
|
5322
|
-
.twm-modal__section[hidden] {
|
|
5323
|
-
display: none !important;
|
|
5324
|
-
}
|
|
5325
|
-
/* Action strip — true footer band, flush against the modal edges,
|
|
5326
|
-
* darker chrome bg, top border + 1px highlight above. Right-aligned
|
|
5327
|
-
* buttons, primary stays rightmost. */
|
|
5328
|
-
.twm-managed-window--modal .twm-modal__actions {
|
|
5329
|
-
margin-top: auto;
|
|
6193
|
+
/* Colour field: swatch (native picker) + hex box + optional preset strip.
|
|
6194
|
+
* The hex box takes the field-well styling of the text inputs above. */
|
|
6195
|
+
.twm-color-field {
|
|
5330
6196
|
display: flex;
|
|
5331
|
-
|
|
6197
|
+
flex-wrap: wrap;
|
|
5332
6198
|
align-items: center;
|
|
5333
|
-
gap:
|
|
5334
|
-
|
|
5335
|
-
border-top: 1px solid #4a4a4a;
|
|
5336
|
-
box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.03) inset;
|
|
5337
|
-
padding: 6px 14px;
|
|
5338
|
-
min-height: 32px;
|
|
6199
|
+
gap: 4px;
|
|
6200
|
+
min-width: 0;
|
|
5339
6201
|
}
|
|
5340
|
-
.twm-
|
|
6202
|
+
.twm-color-field__swatch {
|
|
6203
|
+
flex: 0 0 auto;
|
|
6204
|
+
width: 28px;
|
|
6205
|
+
height: 22px;
|
|
6206
|
+
padding: 0;
|
|
6207
|
+
border: 1px solid #3a3a3a;
|
|
5341
6208
|
border-radius: 0;
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
font-size: var(--ea-font-body);
|
|
5345
|
-
letter-spacing: 0.04em;
|
|
5346
|
-
text-transform: uppercase;
|
|
5347
|
-
}
|
|
5348
|
-
.twm-managed-window--modal .twm-modal__actions .twm-btn--primary {
|
|
5349
|
-
background: var(--ea-accent);
|
|
5350
|
-
border-color: var(--ea-accent);
|
|
5351
|
-
color: #fff;
|
|
5352
|
-
font-weight: 600;
|
|
6209
|
+
background: transparent;
|
|
6210
|
+
cursor: pointer;
|
|
5353
6211
|
}
|
|
5354
|
-
.twm-
|
|
5355
|
-
|
|
5356
|
-
|
|
6212
|
+
.twm-color-field__hex {
|
|
6213
|
+
flex: 1 1 90px;
|
|
6214
|
+
min-width: 0;
|
|
6215
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
5357
6216
|
}
|
|
5358
|
-
.twm-
|
|
5359
|
-
|
|
5360
|
-
border-color: #8b2a2a;
|
|
5361
|
-
color: #fff;
|
|
6217
|
+
.twm-color-field--invalid .twm-color-field__hex {
|
|
6218
|
+
border-color: #b03a3a;
|
|
5362
6219
|
}
|
|
5363
|
-
.twm-
|
|
5364
|
-
|
|
5365
|
-
|
|
6220
|
+
.twm-color-field__presets {
|
|
6221
|
+
flex: 1 0 100%;
|
|
6222
|
+
display: flex;
|
|
6223
|
+
flex-wrap: wrap;
|
|
6224
|
+
gap: 3px;
|
|
6225
|
+
}
|
|
6226
|
+
.twm-color-field__preset {
|
|
6227
|
+
width: 16px;
|
|
6228
|
+
height: 16px;
|
|
6229
|
+
padding: 0;
|
|
6230
|
+
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
6231
|
+
border-radius: 2px;
|
|
6232
|
+
cursor: pointer;
|
|
6233
|
+
}
|
|
6234
|
+
.twm-color-field__preset:hover,
|
|
6235
|
+
.twm-color-field__preset:focus-visible {
|
|
6236
|
+
outline: 1px solid var(--ea-accent, #569cd6);
|
|
6237
|
+
outline-offset: 1px;
|
|
6238
|
+
}
|
|
6239
|
+
/* Colour list: a SortableList whose rows are a colour field + move buttons. */
|
|
6240
|
+
.twm-color-list {
|
|
6241
|
+
min-width: 0;
|
|
6242
|
+
}
|
|
6243
|
+
.twm-color-list__row {
|
|
6244
|
+
display: flex;
|
|
6245
|
+
align-items: center;
|
|
6246
|
+
gap: 2px;
|
|
6247
|
+
min-width: 0;
|
|
6248
|
+
}
|
|
6249
|
+
.twm-color-list__row > .twm-color-field {
|
|
6250
|
+
flex: 1 1 auto;
|
|
6251
|
+
}
|
|
6252
|
+
.twm-color-list__move {
|
|
6253
|
+
display: flex;
|
|
6254
|
+
align-items: center;
|
|
6255
|
+
padding: 2px;
|
|
6256
|
+
background: transparent;
|
|
6257
|
+
border: none;
|
|
6258
|
+
color: #8c8c8c;
|
|
6259
|
+
cursor: pointer;
|
|
6260
|
+
}
|
|
6261
|
+
.twm-color-list__move:hover:not(:disabled) {
|
|
6262
|
+
color: var(--ea-accent, #569cd6);
|
|
6263
|
+
}
|
|
6264
|
+
.twm-color-list__move:disabled {
|
|
6265
|
+
opacity: 0.3;
|
|
6266
|
+
cursor: default;
|
|
6267
|
+
}
|
|
6268
|
+
.twm-color-list__move .material-symbols-outlined {
|
|
6269
|
+
font-size: 15px;
|
|
6270
|
+
}
|
|
6271
|
+
/* An option that cannot be chosen, and why — drawn by choice_controls.js
|
|
6272
|
+
* for openForm's select, checklist and radio (and the flow kit's widgets). */
|
|
6273
|
+
.twm-choice--disabled { cursor: default; opacity: 0.7; }
|
|
6274
|
+
.twm-choice__reason {
|
|
6275
|
+
font-size: var(--font-size-xs);
|
|
6276
|
+
font-style: italic;
|
|
6277
|
+
color: var(--ea-text-dim);
|
|
6278
|
+
}
|
|
6279
|
+
.twm-flow-togglechip > .twm-choice__reason { margin-left: 4px; }
|
|
6280
|
+
/* A group's heading over its chips or radio rows (a select's is its optgroup). */
|
|
6281
|
+
.twm-choice__group {
|
|
6282
|
+
flex-basis: 100%;
|
|
6283
|
+
font-size: var(--font-size-xs);
|
|
6284
|
+
font-weight: 600;
|
|
6285
|
+
text-transform: uppercase;
|
|
6286
|
+
letter-spacing: 0.04em;
|
|
6287
|
+
color: var(--ea-text-dim);
|
|
6288
|
+
}
|
|
6289
|
+
.twm-choice__group:not(:first-child) { margin-top: 4px; }
|
|
6290
|
+
.twm-flow-togglechip > .twm-choice__reason::before { content: '— '; }
|
|
6291
|
+
/* A row (or named section) hidden by openForm's `setVisible`. `[hidden]`
|
|
6292
|
+
* carries only the UA sheet's `display: none`, which the grid and flex rules
|
|
6293
|
+
* on `.twm-modal__row` / `.twm-modal__section` beat — so a hidden row stayed
|
|
6294
|
+
* on screen. */
|
|
6295
|
+
.twm-modal__row[hidden],
|
|
6296
|
+
.twm-modal__section[hidden] {
|
|
6297
|
+
display: none !important;
|
|
6298
|
+
}
|
|
6299
|
+
/* A `{ row: [...] }` entry of openForm: its fields side by side, each one an
|
|
6300
|
+
* ordinary `.twm-modal__row` with its own label, hint and error. The fields
|
|
6301
|
+
* after the first size their label to its text; the first keeps the form's
|
|
6302
|
+
* label column, so it lines up with the rows above and below, 10px from
|
|
6303
|
+
* each, as any two rows are. A form narrower than 360px stacks them — the
|
|
6304
|
+
* form is the query container, and only a form that has a row is made one,
|
|
6305
|
+
* so no other form's layout moves. */
|
|
6306
|
+
.twm-managed-window--modal .twm-modal__form:has(.twm-modal__field-group) {
|
|
6307
|
+
container: twm-form / inline-size;
|
|
6308
|
+
}
|
|
6309
|
+
.twm-modal__field-group {
|
|
6310
|
+
display: flex;
|
|
6311
|
+
align-items: flex-start;
|
|
6312
|
+
column-gap: 10px;
|
|
6313
|
+
}
|
|
6314
|
+
.twm-modal__field-group > .twm-modal__row {
|
|
6315
|
+
flex: 1 1 0;
|
|
6316
|
+
min-width: 0;
|
|
6317
|
+
}
|
|
6318
|
+
.twm-managed-window--modal .twm-modal__fields > .twm-modal__field-group {
|
|
6319
|
+
margin-left: 14px;
|
|
6320
|
+
margin-right: 14px;
|
|
6321
|
+
}
|
|
6322
|
+
.twm-managed-window--modal .twm-modal__fields > .twm-modal__field-group:first-child {
|
|
6323
|
+
margin-top: 14px;
|
|
6324
|
+
}
|
|
6325
|
+
/* A field after a leading row is still its label's first-of-type, so the
|
|
6326
|
+
* leading-row margin above would land on it a second time: it keeps the
|
|
6327
|
+
* normal 10px under the row (the row's own bottom margin) instead. */
|
|
6328
|
+
.twm-managed-window--modal .twm-modal__fields > .twm-modal__field-group ~ .twm-modal__row:first-of-type {
|
|
6329
|
+
margin-top: 0;
|
|
6330
|
+
}
|
|
6331
|
+
.twm-managed-window--modal .twm-modal__field-group > .twm-modal__row + .twm-modal__row {
|
|
6332
|
+
grid-template-columns: auto 1fr;
|
|
6333
|
+
}
|
|
6334
|
+
@container twm-form (max-width: 359px) {
|
|
6335
|
+
.twm-modal__field-group {
|
|
6336
|
+
flex-direction: column;
|
|
6337
|
+
align-items: stretch;
|
|
6338
|
+
}
|
|
6339
|
+
.twm-managed-window--modal .twm-modal__field-group > .twm-modal__row + .twm-modal__row {
|
|
6340
|
+
grid-template-columns: 130px 1fr;
|
|
6341
|
+
}
|
|
6342
|
+
}
|
|
6343
|
+
/* Action strip — true footer band, flush against the modal edges,
|
|
6344
|
+
* darker chrome bg, top border + 1px highlight above. Right-aligned
|
|
6345
|
+
* buttons, primary stays rightmost. */
|
|
6346
|
+
.twm-managed-window--modal .twm-modal__actions {
|
|
6347
|
+
margin-top: auto;
|
|
6348
|
+
display: flex;
|
|
6349
|
+
justify-content: flex-end;
|
|
6350
|
+
align-items: center;
|
|
6351
|
+
gap: 6px;
|
|
6352
|
+
background: var(--ea-bg-chrome);
|
|
6353
|
+
border-top: 1px solid #4a4a4a;
|
|
6354
|
+
box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.03) inset;
|
|
6355
|
+
padding: 6px 14px;
|
|
6356
|
+
min-height: 32px;
|
|
6357
|
+
}
|
|
6358
|
+
.twm-managed-window--modal .twm-modal__actions .twm-btn {
|
|
6359
|
+
border-radius: 0;
|
|
6360
|
+
min-height: 22px;
|
|
6361
|
+
padding: 0 14px;
|
|
6362
|
+
font-size: var(--ea-font-body);
|
|
6363
|
+
letter-spacing: 0.04em;
|
|
6364
|
+
text-transform: uppercase;
|
|
6365
|
+
}
|
|
6366
|
+
.twm-managed-window--modal .twm-modal__actions .twm-btn--primary {
|
|
6367
|
+
background: var(--ea-accent);
|
|
6368
|
+
border-color: var(--ea-accent);
|
|
6369
|
+
color: #fff;
|
|
6370
|
+
font-weight: 600;
|
|
6371
|
+
}
|
|
6372
|
+
.twm-managed-window--modal .twm-modal__actions .twm-btn--primary:hover:not(:disabled) {
|
|
6373
|
+
background: #1683c4;
|
|
6374
|
+
border-color: #1683c4;
|
|
6375
|
+
}
|
|
6376
|
+
.twm-managed-window--modal .twm-modal__actions .twm-btn--danger {
|
|
6377
|
+
background: #8b2a2a;
|
|
6378
|
+
border-color: #8b2a2a;
|
|
6379
|
+
color: #fff;
|
|
6380
|
+
}
|
|
6381
|
+
.twm-managed-window--modal .twm-modal__actions .twm-btn--danger:hover:not(:disabled) {
|
|
6382
|
+
background: #a13434;
|
|
6383
|
+
border-color: #a13434;
|
|
5366
6384
|
}
|
|
5367
6385
|
/* openConfirm uses .twm-modal__body for the message paragraph. */
|
|
5368
6386
|
.twm-managed-window--modal .twm-modal__body {
|
|
@@ -5373,6 +6391,12 @@ button.twm-about-dialog__btn--close:focus {
|
|
|
5373
6391
|
min-height: 0;
|
|
5374
6392
|
overflow-y: auto;
|
|
5375
6393
|
}
|
|
6394
|
+
/* openConfirm's message is text (BUG-0014): `\n` breaks the line, and a long
|
|
6395
|
+
* unbroken name wraps instead of widening the dialog. */
|
|
6396
|
+
.twm-managed-window--modal .twm-modal__body--text {
|
|
6397
|
+
white-space: pre-line;
|
|
6398
|
+
overflow-wrap: anywhere;
|
|
6399
|
+
}
|
|
5376
6400
|
/* Form-level error banner — left accent stripe, dim red panel. */
|
|
5377
6401
|
.twm-managed-window--modal .twm-modal__error {
|
|
5378
6402
|
margin-top: 8px;
|
|
@@ -6003,7 +7027,7 @@ body.twm-dragging * { user-select: none; }
|
|
|
6003
7027
|
* size (24) draws strokes too heavy to read as a small control. */
|
|
6004
7028
|
font-variation-settings: 'opsz' 20, 'wght' 400;
|
|
6005
7029
|
}
|
|
6006
|
-
.twm-leaf__btn:hover:not(:disabled) { background: var(--state-hover); color: var(--text-primary); }
|
|
7030
|
+
.twm-leaf__btn:hover:not(:disabled):not(.twm-leaf__btn--disabled) { background: var(--state-hover); color: var(--text-primary); }
|
|
6007
7031
|
/* C20. A verb that applies to this kind of pane but not right now — greyed and
|
|
6008
7032
|
* explained by its tooltip, rather than removed. `:disabled` alone would still
|
|
6009
7033
|
* take the hover highlight above, which reads as clickable. */
|
|
@@ -6012,6 +7036,34 @@ body.twm-dragging * { user-select: none; }
|
|
|
6012
7036
|
opacity: 0.35;
|
|
6013
7037
|
cursor: default;
|
|
6014
7038
|
}
|
|
7039
|
+
|
|
7040
|
+
/* C42. A content action that is a toggle, and on: `aria-pressed="true"`. The
|
|
7041
|
+
* selected tint the rest of the shell uses, so "on" reads the same everywhere. */
|
|
7042
|
+
.twm-leaf__btn--pressed {
|
|
7043
|
+
background: var(--state-selected);
|
|
7044
|
+
color: var(--text-primary);
|
|
7045
|
+
}
|
|
7046
|
+
|
|
7047
|
+
/* C42. A content action with a text label: the 18px square is for a glyph, so
|
|
7048
|
+
* a labelled button grows to its text. */
|
|
7049
|
+
.twm-leaf__btn--labelled {
|
|
7050
|
+
width: auto;
|
|
7051
|
+
gap: 2px;
|
|
7052
|
+
padding: 0 4px;
|
|
7053
|
+
}
|
|
7054
|
+
.twm-leaf__btn-label {
|
|
7055
|
+
font-size: 11px;
|
|
7056
|
+
line-height: 1;
|
|
7057
|
+
white-space: nowrap;
|
|
7058
|
+
}
|
|
7059
|
+
|
|
7060
|
+
/* C42. `{separator: true}` between groups of content actions. */
|
|
7061
|
+
.twm-leaf__sep {
|
|
7062
|
+
align-self: stretch;
|
|
7063
|
+
width: 1px;
|
|
7064
|
+
margin: 3px 2px;
|
|
7065
|
+
background: var(--border-subtle);
|
|
7066
|
+
}
|
|
6015
7067
|
.twm-leaf__body {
|
|
6016
7068
|
flex: 1 1 auto;
|
|
6017
7069
|
overflow: auto;
|
|
@@ -6556,6 +7608,199 @@ body.twm-dragging * { user-select: none; }
|
|
|
6556
7608
|
margin: var(--space-xxs) 0;
|
|
6557
7609
|
background: var(--border-subtle);
|
|
6558
7610
|
}
|
|
7611
|
+
|
|
7612
|
+
/* ══ EDITOR · PANES, SPLIT AND SEARCH (BUG-0025) ═════════════════════
|
|
7613
|
+
*
|
|
7614
|
+
* The same family as the tab bar above: `SplitPaneContainer`, `EditorPane`
|
|
7615
|
+
* and `NotebookSearchBar` set these classes and no FlexDesk stylesheet had a
|
|
7616
|
+
* rule for any of them, so with only FlexDesk CSS a split stacked its panes,
|
|
7617
|
+
* the divider was a zero-width div nobody could grab, and the search bar was
|
|
7618
|
+
* a row of bare inputs and icon names.
|
|
7619
|
+
*
|
|
7620
|
+
* `.split-pane-container*`, `.split-pane`, `.split-pane-divider*`
|
|
7621
|
+
* `editor/split_pane_container.js`
|
|
7622
|
+
* `.editor-pane*`, `.notebook-editor-container`
|
|
7623
|
+
* `editor/editor_pane.js`
|
|
7624
|
+
* `.nb-search-bar*` `editor/notebook_search.js`
|
|
7625
|
+
*
|
|
7626
|
+
* Layout first: the container is a row, each pane a column, and the divider
|
|
7627
|
+
* a fixed-width strip that never shrinks. The pane's flex is also written
|
|
7628
|
+
* inline by `SplitPaneContainer` (the ratio); the rule is the fallback. */
|
|
7629
|
+
.split-pane-container {
|
|
7630
|
+
display: flex;
|
|
7631
|
+
flex-direction: row;
|
|
7632
|
+
flex: 1 1 0;
|
|
7633
|
+
min-width: 0;
|
|
7634
|
+
min-height: 0;
|
|
7635
|
+
overflow: hidden;
|
|
7636
|
+
}
|
|
7637
|
+
.split-pane {
|
|
7638
|
+
display: flex;
|
|
7639
|
+
flex-direction: column;
|
|
7640
|
+
flex: 1 1 0;
|
|
7641
|
+
min-width: 0;
|
|
7642
|
+
min-height: 0;
|
|
7643
|
+
overflow: hidden;
|
|
7644
|
+
}
|
|
7645
|
+
/* 4px drawn, 10px grabbed: the `::before` widens the hit target 3px each side
|
|
7646
|
+
* without moving either pane. */
|
|
7647
|
+
.split-pane-divider {
|
|
7648
|
+
position: relative;
|
|
7649
|
+
z-index: 1;
|
|
7650
|
+
flex: 0 0 4px;
|
|
7651
|
+
width: 4px;
|
|
7652
|
+
background: var(--border-strong);
|
|
7653
|
+
cursor: col-resize;
|
|
7654
|
+
transition: background 0.15s;
|
|
7655
|
+
}
|
|
7656
|
+
.split-pane-divider::before {
|
|
7657
|
+
content: '';
|
|
7658
|
+
position: absolute;
|
|
7659
|
+
inset: 0 -3px;
|
|
7660
|
+
}
|
|
7661
|
+
.split-pane-divider:hover,
|
|
7662
|
+
.split-pane-divider--active {
|
|
7663
|
+
background: var(--accent-bright, #1683c4);
|
|
7664
|
+
}
|
|
7665
|
+
/* A pane is its tab bar over its body. The tab bar's own rule says
|
|
7666
|
+
* `height: 100%` (it fills a tile's strip); here it is a fixed 26px row, the
|
|
7667
|
+
* strip's height, and the body takes the rest. */
|
|
7668
|
+
.editor-pane {
|
|
7669
|
+
display: flex;
|
|
7670
|
+
flex-direction: column;
|
|
7671
|
+
flex: 1 1 0;
|
|
7672
|
+
min-width: 0;
|
|
7673
|
+
min-height: 0;
|
|
7674
|
+
overflow: hidden;
|
|
7675
|
+
}
|
|
7676
|
+
.editor-pane > .tabs.notebook-tabs {
|
|
7677
|
+
flex: 0 0 auto;
|
|
7678
|
+
height: 26px;
|
|
7679
|
+
}
|
|
7680
|
+
/* Which of two panes has focus — only drawn when there ARE two. An inset
|
|
7681
|
+
* shadow rather than a border, so focusing a pane does not move its body.
|
|
7682
|
+
* This and the tab-bar row above need `.editor-pane` to survive
|
|
7683
|
+
* `setPanes()`, which is why `SplitPaneContainer` ADDS `.split-pane` to a
|
|
7684
|
+
* pane instead of replacing its classes with it. */
|
|
7685
|
+
.split-pane-container--split .editor-pane--focused > .tabs.notebook-tabs {
|
|
7686
|
+
box-shadow: inset 0 -1px 0 var(--accent-bright, #1683c4);
|
|
7687
|
+
}
|
|
7688
|
+
/* The body is the positioning anchor; the editor container fills it
|
|
7689
|
+
* absolutely, so its height is the body's whatever its content is and the
|
|
7690
|
+
* scrollbar is its own. */
|
|
7691
|
+
.editor-pane__body {
|
|
7692
|
+
position: relative;
|
|
7693
|
+
flex: 1 1 0;
|
|
7694
|
+
min-height: 0;
|
|
7695
|
+
overflow: hidden;
|
|
7696
|
+
}
|
|
7697
|
+
.notebook-editor-container {
|
|
7698
|
+
position: absolute;
|
|
7699
|
+
inset: 0;
|
|
7700
|
+
overflow-x: hidden;
|
|
7701
|
+
overflow-y: auto;
|
|
7702
|
+
background: var(--surface-0);
|
|
7703
|
+
outline: none;
|
|
7704
|
+
}
|
|
7705
|
+
/* The search bar: mounted at the top of the editor container and sticky
|
|
7706
|
+
* there, hidden until `open()` adds `--open`. */
|
|
7707
|
+
.nb-search-bar {
|
|
7708
|
+
position: sticky;
|
|
7709
|
+
top: 0;
|
|
7710
|
+
z-index: 50;
|
|
7711
|
+
display: none;
|
|
7712
|
+
flex-direction: column;
|
|
7713
|
+
gap: var(--space-xs);
|
|
7714
|
+
padding: var(--space-sm) var(--space-md);
|
|
7715
|
+
background: var(--surface-1);
|
|
7716
|
+
border-bottom: 1px solid var(--border-strong);
|
|
7717
|
+
box-shadow: var(--shadow-md);
|
|
7718
|
+
color: var(--text-primary);
|
|
7719
|
+
font-size: var(--font-size-sm);
|
|
7720
|
+
}
|
|
7721
|
+
.nb-search-bar--open { display: flex; }
|
|
7722
|
+
.nb-search-bar__find-row,
|
|
7723
|
+
.nb-search-bar__replace-row {
|
|
7724
|
+
display: flex;
|
|
7725
|
+
align-items: center;
|
|
7726
|
+
gap: var(--space-xs);
|
|
7727
|
+
}
|
|
7728
|
+
/* Lines the replace input up under the find input: the toggle's width. */
|
|
7729
|
+
.nb-search-bar__spacer {
|
|
7730
|
+
flex: 0 0 26px;
|
|
7731
|
+
width: 26px;
|
|
7732
|
+
}
|
|
7733
|
+
.nb-search-bar__input-wrap {
|
|
7734
|
+
flex: 1 1 auto;
|
|
7735
|
+
min-width: 160px;
|
|
7736
|
+
max-width: 320px;
|
|
7737
|
+
}
|
|
7738
|
+
.nb-search-bar__input {
|
|
7739
|
+
box-sizing: border-box;
|
|
7740
|
+
width: 100%;
|
|
7741
|
+
padding: 3px var(--space-sm);
|
|
7742
|
+
background: var(--surface-3);
|
|
7743
|
+
border: 1px solid var(--border-strong);
|
|
7744
|
+
border-radius: var(--radius-sm);
|
|
7745
|
+
color: var(--text-primary);
|
|
7746
|
+
font: inherit;
|
|
7747
|
+
outline: none;
|
|
7748
|
+
}
|
|
7749
|
+
.nb-search-bar__input:focus { border-color: var(--accent-bright, #1683c4); }
|
|
7750
|
+
.nb-search-bar__match-info {
|
|
7751
|
+
min-width: 64px;
|
|
7752
|
+
color: var(--text-muted);
|
|
7753
|
+
font-size: var(--font-size-xs);
|
|
7754
|
+
text-align: center;
|
|
7755
|
+
white-space: nowrap;
|
|
7756
|
+
user-select: none;
|
|
7757
|
+
}
|
|
7758
|
+
.nb-search-bar__match-info--no-results { color: var(--color-danger, #c74e4e); }
|
|
7759
|
+
.nb-search-bar__btn {
|
|
7760
|
+
display: inline-flex;
|
|
7761
|
+
flex: 0 0 auto;
|
|
7762
|
+
align-items: center;
|
|
7763
|
+
justify-content: center;
|
|
7764
|
+
width: 26px;
|
|
7765
|
+
height: 26px;
|
|
7766
|
+
padding: 0;
|
|
7767
|
+
background: transparent;
|
|
7768
|
+
border: none;
|
|
7769
|
+
border-radius: var(--radius-sm);
|
|
7770
|
+
color: var(--text-secondary);
|
|
7771
|
+
cursor: pointer;
|
|
7772
|
+
font-size: var(--font-size-sm);
|
|
7773
|
+
font-weight: 600;
|
|
7774
|
+
}
|
|
7775
|
+
.nb-search-bar__btn:hover { background: var(--state-hover); }
|
|
7776
|
+
.nb-search-bar__btn:active { background: var(--state-active); }
|
|
7777
|
+
/* The case / word / regex toggles reserve the border `--active` colours. */
|
|
7778
|
+
.nb-search-bar__btn--toggle { border: 1px solid transparent; }
|
|
7779
|
+
.nb-search-bar__btn--active,
|
|
7780
|
+
.nb-search-bar__btn--active:hover {
|
|
7781
|
+
background: var(--state-selected);
|
|
7782
|
+
border-color: var(--accent-bright, #1683c4);
|
|
7783
|
+
color: var(--text-bright);
|
|
7784
|
+
}
|
|
7785
|
+
/* Two classes, for the Material Symbols tie — see `.twm-leaf__icon`. */
|
|
7786
|
+
.nb-search-bar__btn .material-symbols-outlined {
|
|
7787
|
+
font-size: 18px;
|
|
7788
|
+
line-height: 1;
|
|
7789
|
+
}
|
|
7790
|
+
.nb-search-bar__icon-word {
|
|
7791
|
+
font-size: var(--font-size-md);
|
|
7792
|
+
font-weight: 700;
|
|
7793
|
+
text-decoration: underline;
|
|
7794
|
+
text-underline-offset: 2px;
|
|
7795
|
+
}
|
|
7796
|
+
.nb-search-bar__separator {
|
|
7797
|
+
flex: 0 0 1px;
|
|
7798
|
+
width: 1px;
|
|
7799
|
+
height: 18px;
|
|
7800
|
+
margin: 0 2px;
|
|
7801
|
+
background: var(--border-strong);
|
|
7802
|
+
}
|
|
7803
|
+
/* ══ end EDITOR · PANES, SPLIT AND SEARCH ══ */
|
|
6559
7804
|
/* ── Tile tab menu (hamburger pop-out) ────────────────────────────
|
|
6560
7805
|
* Anchored above the hamburger button. Lists every entity that the
|
|
6561
7806
|
* tile's home page would show, grouped by source, with search +
|
|
@@ -6895,6 +8140,14 @@ body.twm-dragging * { user-select: none; }
|
|
|
6895
8140
|
border-color: var(--accent-bright);
|
|
6896
8141
|
color: var(--text-bright);
|
|
6897
8142
|
}
|
|
8143
|
+
.twm-chip[aria-disabled="true"] {
|
|
8144
|
+
color: var(--text-dim);
|
|
8145
|
+
cursor: not-allowed;
|
|
8146
|
+
}
|
|
8147
|
+
.twm-chip[aria-disabled="true"]:hover {
|
|
8148
|
+
background: var(--surface-2);
|
|
8149
|
+
color: var(--text-dim);
|
|
8150
|
+
}
|
|
6898
8151
|
.twm-cmdpal__list {
|
|
6899
8152
|
max-height: 40vh;
|
|
6900
8153
|
overflow: auto;
|
|
@@ -7043,6 +8296,8 @@ body.twm-dragging * { user-select: none; }
|
|
|
7043
8296
|
}
|
|
7044
8297
|
.twm-cmdpal__acts { display: none; gap: 10px; }
|
|
7045
8298
|
.twm-cmdpal__item--active .twm-cmdpal__acts { display: flex; }
|
|
8299
|
+
/* A copy verb a single kind refuses: drawn, greyed, with the reason as its title. */
|
|
8300
|
+
.twm-cmdpal__act--disabled { opacity: 0.45; }
|
|
7046
8301
|
.twm-cmdpal__item--active .twm-cmdpal__kind,
|
|
7047
8302
|
.twm-cmdpal__item--active .twm-cmdpal__shortcut { display: none; }
|
|
7048
8303
|
.twm-cmdpal__item--more { color: var(--text-muted); font-size: var(--font-size-sm); }
|
|
@@ -7853,11 +9108,119 @@ tr:hover .twm-row-action { opacity: 1; }
|
|
|
7853
9108
|
* status line sits at the foot. Only a pane holding the Alerts pane: other
|
|
7854
9109
|
* panes keep their padding and their own height. */
|
|
7855
9110
|
.twm-bp-pane:has(> .twm-alerts) { height: 100%; padding: 0; box-sizing: border-box; }
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
.twm-
|
|
9111
|
+
/* The public tab strip (`createTabs`, STORY-0048). It SCROLLS, never wraps or
|
|
9112
|
+
* shrinks its tabs, and hides the scrollbar; the wheel and the reveal of the
|
|
9113
|
+
* tab in front are `strip_scroll.js`'s. `--compact` is the dense variant. The
|
|
9114
|
+
* bottom panel draws the same component under its own `.twm-bp` block. */
|
|
9115
|
+
.twm-tabs {
|
|
9116
|
+
display: flex;
|
|
9117
|
+
flex-direction: column;
|
|
9118
|
+
min-width: 0;
|
|
9119
|
+
min-height: 0;
|
|
9120
|
+
background: var(--surface-0);
|
|
9121
|
+
color: var(--text-body);
|
|
9122
|
+
}
|
|
9123
|
+
.twm-tabs__tabs {
|
|
9124
|
+
flex: 0 0 auto;
|
|
9125
|
+
display: flex;
|
|
9126
|
+
align-items: stretch;
|
|
9127
|
+
height: 30px;
|
|
9128
|
+
min-width: 0;
|
|
9129
|
+
background: var(--surface-1);
|
|
9130
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
9131
|
+
overflow-x: auto;
|
|
9132
|
+
overflow-y: hidden;
|
|
9133
|
+
scrollbar-width: none;
|
|
9134
|
+
white-space: nowrap;
|
|
9135
|
+
user-select: none;
|
|
9136
|
+
}
|
|
9137
|
+
.twm-tabs__tabs::-webkit-scrollbar { width: 0; height: 0; display: none; }
|
|
9138
|
+
.twm-tabs__tab {
|
|
9139
|
+
position: relative;
|
|
9140
|
+
flex: 0 0 auto;
|
|
9141
|
+
display: inline-flex;
|
|
9142
|
+
align-items: center;
|
|
9143
|
+
gap: var(--space-xs);
|
|
9144
|
+
max-width: 220px;
|
|
9145
|
+
padding: 0 var(--space-sm);
|
|
9146
|
+
background: transparent;
|
|
9147
|
+
color: var(--text-muted);
|
|
9148
|
+
border: none;
|
|
9149
|
+
border-right: 1px solid var(--border-subtle);
|
|
9150
|
+
font: inherit;
|
|
9151
|
+
font-size: var(--font-size-xs);
|
|
9152
|
+
line-height: 1;
|
|
9153
|
+
cursor: pointer;
|
|
9154
|
+
}
|
|
9155
|
+
.twm-tabs__tab:hover { background: var(--surface-2); color: var(--text-primary); }
|
|
9156
|
+
.twm-tabs__tab:focus-visible { outline: 1px solid var(--accent-bright, #1683c4); outline-offset: -1px; }
|
|
9157
|
+
.twm-tabs__tab--on { background: var(--surface-0); color: var(--text-bright); }
|
|
9158
|
+
.twm-tabs__tab--on::before {
|
|
9159
|
+
content: '';
|
|
9160
|
+
position: absolute;
|
|
9161
|
+
inset: 0 0 auto 0;
|
|
9162
|
+
height: 2px;
|
|
9163
|
+
pointer-events: none;
|
|
9164
|
+
background: var(--accent-bright, #1683c4);
|
|
9165
|
+
}
|
|
9166
|
+
.twm-tabs__label { overflow: hidden; text-overflow: ellipsis; }
|
|
9167
|
+
/* Two classes: Google's `.material-symbols-outlined { font-size: 24px }` loads
|
|
9168
|
+
* after this sheet and would win a one-class tie. */
|
|
9169
|
+
.twm-tabs__icon,
|
|
9170
|
+
.twm-tabs__icon.material-symbols-outlined { flex: 0 0 auto; font-size: 14px; line-height: 1; }
|
|
9171
|
+
.twm-tabs__badge {
|
|
9172
|
+
display: inline-flex;
|
|
9173
|
+
align-items: center;
|
|
9174
|
+
justify-content: center;
|
|
9175
|
+
min-width: 16px;
|
|
9176
|
+
height: 16px;
|
|
9177
|
+
padding: 0 4px;
|
|
9178
|
+
box-sizing: border-box;
|
|
9179
|
+
border-radius: 8px;
|
|
9180
|
+
background: var(--accent);
|
|
9181
|
+
color: #fff;
|
|
9182
|
+
font-size: 10.5px;
|
|
9183
|
+
line-height: 16px;
|
|
9184
|
+
}
|
|
9185
|
+
.twm-tabs__badge--info { background: color-mix(in srgb, var(--color-info) 35%, var(--surface-0)); }
|
|
9186
|
+
.twm-tabs__badge--warning { background: color-mix(in srgb, var(--color-warning) 35%, var(--surface-0)); }
|
|
9187
|
+
.twm-tabs__badge--alert { background: color-mix(in srgb, var(--color-danger) 45%, var(--surface-0)); }
|
|
9188
|
+
.twm-tabs__indicator {
|
|
9189
|
+
flex: 0 0 auto;
|
|
9190
|
+
width: 6px;
|
|
9191
|
+
height: 6px;
|
|
9192
|
+
border-radius: 50%;
|
|
9193
|
+
background: var(--text-muted);
|
|
9194
|
+
}
|
|
9195
|
+
.twm-tabs__indicator--info { background: var(--color-info); }
|
|
9196
|
+
.twm-tabs__indicator--warning { background: var(--color-warning); }
|
|
9197
|
+
.twm-tabs__indicator--alert { background: var(--color-danger); }
|
|
9198
|
+
.twm-tabs__dirty { font-size: 10px; color: var(--text-primary); }
|
|
9199
|
+
.twm-tabs__close {
|
|
9200
|
+
padding: 0 2px;
|
|
9201
|
+
border-radius: var(--radius-sm);
|
|
9202
|
+
opacity: 0.6;
|
|
9203
|
+
font-size: 13px;
|
|
9204
|
+
}
|
|
9205
|
+
.twm-tabs__close:hover { opacity: 1; background: var(--surface-2); }
|
|
9206
|
+
/* A dirty, closable tab shows the dot until hovered, then the close mark.
|
|
9207
|
+
A dirty tab with no close mark keeps its dot. */
|
|
9208
|
+
.twm-tabs__tab--dirty:not(:hover) .twm-tabs__close { display: none; }
|
|
9209
|
+
.twm-tabs__tab--dirty.twm-tabs__tab--closable:hover .twm-tabs__dirty { display: none; }
|
|
9210
|
+
.twm-tabs__badge[hidden],
|
|
9211
|
+
.twm-tabs__indicator[hidden] { display: none; }
|
|
9212
|
+
.twm-tabs__body { flex: 1 1 auto; min-height: 0; overflow: auto; }
|
|
9213
|
+
.twm-tabs-pane { height: 100%; box-sizing: border-box; }
|
|
9214
|
+
.twm-tabs-pane[hidden] { display: none; }
|
|
9215
|
+
.twm-tabs--compact .twm-tabs__tabs { height: 22px; }
|
|
9216
|
+
.twm-tabs--compact .twm-tabs__tab { padding: 0 var(--space-xs); gap: 3px; }
|
|
9217
|
+
.twm-tabs--compact .twm-tabs__icon,
|
|
9218
|
+
.twm-tabs--compact .twm-tabs__icon.material-symbols-outlined { font-size: 12px; }
|
|
9219
|
+
.twm-alerts .material-symbols-outlined { font-size: 15px; }
|
|
9220
|
+
.twm-alerts__spacer { flex: 1 1 auto; }
|
|
9221
|
+
.twm-alerts__rules { flex: 0 0 280px; display: flex; flex-direction: column; min-width: 0; border-right: 1px solid var(--border-subtle); }
|
|
9222
|
+
.twm-alerts__head, .twm-alerts__bar { flex: none; display: flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 12px; border-bottom: 1px solid var(--border-subtle); }
|
|
9223
|
+
.twm-alerts__bar { flex-wrap: wrap; }
|
|
7861
9224
|
.twm-alerts__caps { color: var(--text-muted); font-size: 10.5px; letter-spacing: .08em; }
|
|
7862
9225
|
.twm-alerts__link { padding: 0; border: 0; background: none; color: var(--accent-bright); font: inherit; cursor: pointer; }
|
|
7863
9226
|
.twm-alerts__link:hover { text-decoration: underline; }
|
|
@@ -8273,78 +9636,1565 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
8273
9636
|
outline: 1px solid var(--accent-bright, #007acc);
|
|
8274
9637
|
outline-offset: -1px;
|
|
8275
9638
|
}
|
|
8276
|
-
.twm-record-list__empty {
|
|
8277
|
-
margin: 0;
|
|
8278
|
-
padding: 12px 6px;
|
|
8279
|
-
color: var(--text-muted, #888);
|
|
8280
|
-
font-size: var(--ea-font-body, 11px);
|
|
9639
|
+
.twm-record-list__empty {
|
|
9640
|
+
margin: 0;
|
|
9641
|
+
padding: 12px 6px;
|
|
9642
|
+
color: var(--text-muted, #888);
|
|
9643
|
+
font-size: var(--ea-font-body, 11px);
|
|
9644
|
+
}
|
|
9645
|
+
|
|
9646
|
+
/* ── the fact sheet ── */
|
|
9647
|
+
.twm-facts {
|
|
9648
|
+
width: 100%;
|
|
9649
|
+
border-collapse: collapse;
|
|
9650
|
+
table-layout: auto;
|
|
9651
|
+
font-size: var(--font-size-sm, 12px);
|
|
9652
|
+
}
|
|
9653
|
+
.twm-facts thead th {
|
|
9654
|
+
text-align: left;
|
|
9655
|
+
font-size: var(--ea-font-small, 10px);
|
|
9656
|
+
font-weight: 600;
|
|
9657
|
+
letter-spacing: 0.06em;
|
|
9658
|
+
text-transform: uppercase;
|
|
9659
|
+
color: var(--text-dim, #666);
|
|
9660
|
+
white-space: nowrap;
|
|
9661
|
+
border-bottom: 1px solid var(--border-default, #303030);
|
|
9662
|
+
padding: 0 12px 6px 0;
|
|
9663
|
+
}
|
|
9664
|
+
/* Every value WRAPS and keeps its own line breaks: nothing is cut off. */
|
|
9665
|
+
.twm-facts tbody td,
|
|
9666
|
+
.twm-facts tbody th {
|
|
9667
|
+
text-align: left;
|
|
9668
|
+
font-weight: normal;
|
|
9669
|
+
border-bottom: 1px solid var(--border-subtle, #2a2a2a);
|
|
9670
|
+
padding: 6px 12px 6px 0;
|
|
9671
|
+
color: var(--text-primary, #e0e0e0);
|
|
9672
|
+
vertical-align: top;
|
|
9673
|
+
white-space: pre-wrap;
|
|
9674
|
+
overflow-wrap: anywhere;
|
|
9675
|
+
}
|
|
9676
|
+
.twm-facts tbody tr:last-child > td,
|
|
9677
|
+
.twm-facts tbody tr:last-child > th { border-bottom: 0; }
|
|
9678
|
+
.twm-facts tbody th.twm-facts__label {
|
|
9679
|
+
color: var(--text-muted, #888);
|
|
9680
|
+
white-space: nowrap;
|
|
9681
|
+
}
|
|
9682
|
+
.twm-facts.twm-facts--wrap-labels tbody th.twm-facts__label { white-space: normal; }
|
|
9683
|
+
/* `wrap: 'words'` — a value wraps at spaces only, and a long word stays
|
|
9684
|
+
* whole: the sheet grows wider and a sideways scroller around it scrolls.
|
|
9685
|
+
* `wrap: 'none'` — a value keeps its own line breaks and no others. */
|
|
9686
|
+
.twm-facts.twm-facts--wrap-words tbody td,
|
|
9687
|
+
.twm-facts.twm-facts--wrap-words tbody th { overflow-wrap: normal; word-break: normal; }
|
|
9688
|
+
.twm-facts.twm-facts--wrap-none tbody td,
|
|
9689
|
+
.twm-facts.twm-facts--wrap-none tbody th { white-space: pre; overflow-wrap: normal; word-break: normal; }
|
|
9690
|
+
.twm-facts.twm-facts--mono tbody td.twm-facts__value,
|
|
9691
|
+
.twm-facts tbody td.twm-facts__mono { font-family: var(--font-family-mono, monospace); font-size: 0.95em; }
|
|
9692
|
+
.twm-facts .twm-facts__num { font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
9693
|
+
.twm-facts tbody td.twm-facts__null,
|
|
9694
|
+
.twm-facts tbody td.twm-facts__missing { color: var(--text-dim, #666); font-style: italic; }
|
|
9695
|
+
.twm-facts tbody td.twm-facts__arrow {
|
|
9696
|
+
color: var(--text-dim, #666);
|
|
9697
|
+
white-space: nowrap;
|
|
9698
|
+
width: 1%;
|
|
9699
|
+
}
|
|
9700
|
+
.twm-facts tbody tr.twm-facts__row--changed > td.twm-facts__before { color: var(--text-muted, #888); }
|
|
9701
|
+
.twm-facts tbody tr.twm-facts__row--changed > td.twm-facts__arrow { color: var(--color-warning, #ff9800); }
|
|
9702
|
+
.twm-facts tbody tr.twm-facts__row--same > td { color: var(--text-muted, #888); }
|
|
9703
|
+
.twm-facts tbody tr.twm-facts__row--added > td.twm-facts__after { color: var(--color-success, #3fb950); }
|
|
9704
|
+
.twm-facts tbody tr.twm-facts__row--removed > td.twm-facts__before { color: var(--color-danger, #c74e4e); }
|
|
9705
|
+
.twm-facts tbody td.twm-facts__empty {
|
|
9706
|
+
padding: 12px 0;
|
|
9707
|
+
color: var(--text-muted, #888);
|
|
9708
|
+
white-space: normal;
|
|
9709
|
+
}
|
|
9710
|
+
/* ══ end RECORD LIST & FACT SHEET ══ */
|
|
9711
|
+
|
|
9712
|
+
/* ══ HELP MODAL ══════════════════════════════════════════════════════
|
|
9713
|
+
*
|
|
9714
|
+
* `HelpModal` (src/help/help_modal.js): a centred dialog on a dimmed overlay,
|
|
9715
|
+
* a sidebar of categories, a search box and the content pane, which shows the
|
|
9716
|
+
* index, a topic, search results or an error. Its classes are `help-`, not
|
|
9717
|
+
* `twm-`, prefixed — they are older than this sheet, and an embedder styles
|
|
9718
|
+
* them by those names. `.help-article` holds the provider's rendered HTML, so
|
|
9719
|
+
* it styles plain elements. Every class the modal sets has a rule here, and
|
|
9720
|
+
* every class a rule here names is one it sets (tests/help_modal_css.test.mjs). */
|
|
9721
|
+
.help-modal-overlay {
|
|
9722
|
+
position: fixed;
|
|
9723
|
+
inset: 0;
|
|
9724
|
+
display: flex;
|
|
9725
|
+
align-items: center;
|
|
9726
|
+
justify-content: center;
|
|
9727
|
+
background: rgba(0, 0, 0, 0.7);
|
|
9728
|
+
backdrop-filter: blur(4px);
|
|
9729
|
+
z-index: var(--z-over-windows);
|
|
9730
|
+
}
|
|
9731
|
+
.help-modal {
|
|
9732
|
+
display: flex;
|
|
9733
|
+
flex-direction: column;
|
|
9734
|
+
width: 90%;
|
|
9735
|
+
max-width: 1000px;
|
|
9736
|
+
height: 80vh;
|
|
9737
|
+
max-height: 700px;
|
|
9738
|
+
background: var(--surface-0);
|
|
9739
|
+
color: var(--text-body);
|
|
9740
|
+
border: 1px solid var(--surface-3);
|
|
9741
|
+
border-radius: var(--radius-lg);
|
|
9742
|
+
box-shadow: var(--shadow-lg);
|
|
9743
|
+
overflow: hidden;
|
|
9744
|
+
user-select: text;
|
|
9745
|
+
}
|
|
9746
|
+
.help-modal__header {
|
|
9747
|
+
display: flex;
|
|
9748
|
+
align-items: center;
|
|
9749
|
+
justify-content: space-between;
|
|
9750
|
+
padding: var(--space-lg) var(--space-xl);
|
|
9751
|
+
background: var(--surface-1);
|
|
9752
|
+
border-bottom: 1px solid var(--surface-3);
|
|
9753
|
+
}
|
|
9754
|
+
.help-modal__title {
|
|
9755
|
+
display: flex;
|
|
9756
|
+
align-items: center;
|
|
9757
|
+
gap: var(--space-md);
|
|
9758
|
+
font-size: var(--font-size-xl);
|
|
9759
|
+
font-weight: var(--font-weight-semibold);
|
|
9760
|
+
color: var(--text-primary);
|
|
9761
|
+
}
|
|
9762
|
+
.help-modal__title .material-symbols-outlined {
|
|
9763
|
+
font-size: 20px;
|
|
9764
|
+
color: var(--accent-bright);
|
|
9765
|
+
}
|
|
9766
|
+
.help-modal__close {
|
|
9767
|
+
display: flex;
|
|
9768
|
+
align-items: center;
|
|
9769
|
+
justify-content: center;
|
|
9770
|
+
padding: var(--space-xs);
|
|
9771
|
+
background: transparent;
|
|
9772
|
+
border: none;
|
|
9773
|
+
border-radius: var(--radius-sm);
|
|
9774
|
+
color: var(--text-muted);
|
|
9775
|
+
cursor: pointer;
|
|
9776
|
+
}
|
|
9777
|
+
.help-modal__close:hover {
|
|
9778
|
+
background: var(--state-active);
|
|
9779
|
+
color: var(--text-primary);
|
|
9780
|
+
}
|
|
9781
|
+
.help-modal__search {
|
|
9782
|
+
display: flex;
|
|
9783
|
+
align-items: center;
|
|
9784
|
+
gap: var(--space-md);
|
|
9785
|
+
padding: var(--space-md) var(--space-xl);
|
|
9786
|
+
background: var(--surface-1);
|
|
9787
|
+
border-bottom: 1px solid var(--surface-3);
|
|
9788
|
+
}
|
|
9789
|
+
.help-modal__search .material-symbols-outlined {
|
|
9790
|
+
font-size: 18px;
|
|
9791
|
+
color: var(--text-dim);
|
|
9792
|
+
}
|
|
9793
|
+
.help-search-input {
|
|
9794
|
+
flex: 1;
|
|
9795
|
+
padding: var(--space-sm) 10px;
|
|
9796
|
+
background: var(--surface-0);
|
|
9797
|
+
border: 1px solid var(--surface-3);
|
|
9798
|
+
border-radius: var(--radius-sm);
|
|
9799
|
+
color: var(--text-body);
|
|
9800
|
+
font-size: var(--font-size-md);
|
|
9801
|
+
outline: none;
|
|
9802
|
+
}
|
|
9803
|
+
.help-search-input:focus { border-color: var(--accent-bright); }
|
|
9804
|
+
.help-search-input::placeholder { color: var(--text-dim); }
|
|
9805
|
+
.help-modal__body {
|
|
9806
|
+
display: flex;
|
|
9807
|
+
flex: 1;
|
|
9808
|
+
min-height: 0;
|
|
9809
|
+
overflow: hidden;
|
|
9810
|
+
}
|
|
9811
|
+
.help-modal__sidebar {
|
|
9812
|
+
flex: 0 0 220px;
|
|
9813
|
+
padding: var(--space-md) 0;
|
|
9814
|
+
background: var(--surface-1);
|
|
9815
|
+
border-right: 1px solid var(--surface-3);
|
|
9816
|
+
overflow-y: auto;
|
|
9817
|
+
}
|
|
9818
|
+
.help-sidebar__categories {
|
|
9819
|
+
display: flex;
|
|
9820
|
+
flex-direction: column;
|
|
9821
|
+
}
|
|
9822
|
+
.help-category { margin-bottom: var(--space-xs); }
|
|
9823
|
+
.help-category__header {
|
|
9824
|
+
display: flex;
|
|
9825
|
+
align-items: center;
|
|
9826
|
+
gap: var(--space-md);
|
|
9827
|
+
padding: var(--space-md) var(--space-lg);
|
|
9828
|
+
color: var(--text-muted);
|
|
9829
|
+
font-size: var(--font-size-sm);
|
|
9830
|
+
font-weight: var(--font-weight-semibold);
|
|
9831
|
+
text-transform: uppercase;
|
|
9832
|
+
letter-spacing: 0.5px;
|
|
9833
|
+
cursor: pointer;
|
|
9834
|
+
user-select: none;
|
|
9835
|
+
}
|
|
9836
|
+
.help-category__header:hover { color: var(--text-secondary); }
|
|
9837
|
+
.help-category__header .material-symbols-outlined { font-size: 16px; }
|
|
9838
|
+
.help-category__topics {
|
|
9839
|
+
list-style: none;
|
|
9840
|
+
margin: 0;
|
|
9841
|
+
padding: 0;
|
|
9842
|
+
}
|
|
9843
|
+
.help-category.collapsed .help-category__topics { display: none; }
|
|
9844
|
+
.help-topic-item {
|
|
9845
|
+
padding: var(--space-sm) var(--space-lg) var(--space-sm) 36px;
|
|
9846
|
+
border-left: 2px solid transparent;
|
|
9847
|
+
color: var(--text-secondary);
|
|
9848
|
+
font-size: var(--font-size-md);
|
|
9849
|
+
cursor: pointer;
|
|
9850
|
+
}
|
|
9851
|
+
.help-topic-item:hover {
|
|
9852
|
+
background: var(--state-hover);
|
|
9853
|
+
color: var(--text-primary);
|
|
9854
|
+
}
|
|
9855
|
+
.help-topic-item.active {
|
|
9856
|
+
background: var(--state-selected);
|
|
9857
|
+
border-left-color: var(--accent-bright);
|
|
9858
|
+
color: var(--text-bright);
|
|
9859
|
+
}
|
|
9860
|
+
.help-modal__content {
|
|
9861
|
+
flex: 1;
|
|
9862
|
+
min-width: 0;
|
|
9863
|
+
padding: 20px var(--space-2xl);
|
|
9864
|
+
background: var(--surface-0);
|
|
9865
|
+
overflow-y: auto;
|
|
9866
|
+
}
|
|
9867
|
+
.help-content__loading,
|
|
9868
|
+
.help-content__error {
|
|
9869
|
+
display: flex;
|
|
9870
|
+
flex-direction: column;
|
|
9871
|
+
align-items: center;
|
|
9872
|
+
justify-content: center;
|
|
9873
|
+
gap: var(--space-lg);
|
|
9874
|
+
height: 200px;
|
|
9875
|
+
color: var(--text-muted);
|
|
9876
|
+
font-size: var(--font-size-lg);
|
|
9877
|
+
}
|
|
9878
|
+
.help-content__error { color: var(--color-danger-hover); }
|
|
9879
|
+
.help-content__error .material-symbols-outlined {
|
|
9880
|
+
font-size: 48px;
|
|
9881
|
+
opacity: 0.5;
|
|
9882
|
+
}
|
|
9883
|
+
.help-content__article { max-width: 860px; }
|
|
9884
|
+
.help-content__breadcrumb {
|
|
9885
|
+
display: flex;
|
|
9886
|
+
align-items: center;
|
|
9887
|
+
gap: var(--space-md);
|
|
9888
|
+
margin-bottom: var(--space-xl);
|
|
9889
|
+
padding-bottom: var(--space-lg);
|
|
9890
|
+
border-bottom: 1px solid var(--surface-3);
|
|
9891
|
+
}
|
|
9892
|
+
.help-breadcrumb__home {
|
|
9893
|
+
display: flex;
|
|
9894
|
+
align-items: center;
|
|
9895
|
+
color: var(--text-muted);
|
|
9896
|
+
text-decoration: none;
|
|
9897
|
+
}
|
|
9898
|
+
.help-breadcrumb__home:hover { color: var(--accent-bright); }
|
|
9899
|
+
.help-breadcrumb__home .material-symbols-outlined { font-size: 18px; }
|
|
9900
|
+
.help-breadcrumb__separator { color: var(--text-dim); }
|
|
9901
|
+
.help-breadcrumb__title {
|
|
9902
|
+
color: var(--text-secondary);
|
|
9903
|
+
font-size: var(--font-size-md);
|
|
9904
|
+
}
|
|
9905
|
+
/* A topic's table of contents (a `createDocumentOutline`), between the
|
|
9906
|
+
* breadcrumb and the article; drawn only for two headings or more. */
|
|
9907
|
+
.help-content__toc {
|
|
9908
|
+
margin-bottom: var(--space-xl);
|
|
9909
|
+
padding: var(--space-md) 0;
|
|
9910
|
+
border-left: 2px solid var(--surface-3);
|
|
9911
|
+
font-size: var(--font-size-md);
|
|
9912
|
+
}
|
|
9913
|
+
.help-content__toc[hidden] { display: none; }
|
|
9914
|
+
.help-index h1 {
|
|
9915
|
+
margin: 0 0 var(--space-md);
|
|
9916
|
+
color: var(--text-primary);
|
|
9917
|
+
font-size: 24px;
|
|
9918
|
+
}
|
|
9919
|
+
.help-index > p {
|
|
9920
|
+
margin-bottom: var(--space-2xl);
|
|
9921
|
+
color: var(--text-muted);
|
|
9922
|
+
}
|
|
9923
|
+
.help-index__grid {
|
|
9924
|
+
display: grid;
|
|
9925
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
9926
|
+
gap: var(--space-xl);
|
|
9927
|
+
}
|
|
9928
|
+
.help-index__category {
|
|
9929
|
+
padding: var(--space-lg);
|
|
9930
|
+
background: var(--surface-1);
|
|
9931
|
+
border: 1px solid var(--surface-3);
|
|
9932
|
+
border-radius: var(--radius-md);
|
|
9933
|
+
}
|
|
9934
|
+
.help-index__category:hover { border-color: var(--accent-bright); }
|
|
9935
|
+
.help-index__category-header {
|
|
9936
|
+
display: flex;
|
|
9937
|
+
align-items: center;
|
|
9938
|
+
gap: var(--space-md);
|
|
9939
|
+
margin-bottom: var(--space-md);
|
|
9940
|
+
color: var(--accent-bright);
|
|
9941
|
+
font-weight: var(--font-weight-semibold);
|
|
9942
|
+
}
|
|
9943
|
+
.help-index__category-header .material-symbols-outlined { font-size: 18px; }
|
|
9944
|
+
.help-index__topics {
|
|
9945
|
+
list-style: none;
|
|
9946
|
+
margin: 0;
|
|
9947
|
+
padding: 0;
|
|
9948
|
+
}
|
|
9949
|
+
.help-index__topic,
|
|
9950
|
+
.help-index__more {
|
|
9951
|
+
padding: var(--space-xs) 0;
|
|
9952
|
+
color: var(--text-secondary);
|
|
9953
|
+
font-size: var(--font-size-md);
|
|
9954
|
+
}
|
|
9955
|
+
.help-index__topic { cursor: pointer; }
|
|
9956
|
+
.help-index__topic:hover { color: var(--text-primary); }
|
|
9957
|
+
.help-index__more {
|
|
9958
|
+
color: var(--text-dim);
|
|
9959
|
+
font-size: var(--font-size-sm);
|
|
9960
|
+
font-style: italic;
|
|
9961
|
+
}
|
|
9962
|
+
.help-search-results h2 {
|
|
9963
|
+
margin: 0 0 var(--space-md);
|
|
9964
|
+
color: var(--text-primary);
|
|
9965
|
+
font-size: var(--font-size-2xl);
|
|
9966
|
+
}
|
|
9967
|
+
.help-search-count {
|
|
9968
|
+
margin-bottom: var(--space-xl);
|
|
9969
|
+
color: var(--text-muted);
|
|
9970
|
+
font-size: var(--font-size-md);
|
|
9971
|
+
}
|
|
9972
|
+
.help-search-empty {
|
|
9973
|
+
color: var(--text-muted);
|
|
9974
|
+
font-style: italic;
|
|
9975
|
+
}
|
|
9976
|
+
.help-search-list {
|
|
9977
|
+
list-style: none;
|
|
9978
|
+
margin: 0;
|
|
9979
|
+
padding: 0;
|
|
9980
|
+
}
|
|
9981
|
+
.help-search-item {
|
|
9982
|
+
display: flex;
|
|
9983
|
+
justify-content: space-between;
|
|
9984
|
+
align-items: center;
|
|
9985
|
+
gap: var(--space-lg);
|
|
9986
|
+
margin-bottom: var(--space-md);
|
|
9987
|
+
padding: 10px var(--space-lg);
|
|
9988
|
+
background: var(--surface-1);
|
|
9989
|
+
border: 1px solid var(--surface-3);
|
|
9990
|
+
border-radius: var(--radius-sm);
|
|
9991
|
+
cursor: pointer;
|
|
9992
|
+
}
|
|
9993
|
+
.help-search-item:hover { border-color: var(--accent-bright); }
|
|
9994
|
+
.help-search-item__title {
|
|
9995
|
+
color: var(--text-primary);
|
|
9996
|
+
font-size: var(--font-size-lg);
|
|
9997
|
+
}
|
|
9998
|
+
.help-search-item__category {
|
|
9999
|
+
color: var(--text-dim);
|
|
10000
|
+
font-size: var(--font-size-sm);
|
|
10001
|
+
}
|
|
10002
|
+
.help-article {
|
|
10003
|
+
color: var(--text-body);
|
|
10004
|
+
font-size: var(--font-size-lg);
|
|
10005
|
+
line-height: 1.6;
|
|
10006
|
+
}
|
|
10007
|
+
.help-article h1,
|
|
10008
|
+
.help-article h2,
|
|
10009
|
+
.help-article h3 { color: var(--text-primary); }
|
|
10010
|
+
.help-article h1 {
|
|
10011
|
+
margin: 0 0 var(--space-xl);
|
|
10012
|
+
padding-bottom: var(--space-md);
|
|
10013
|
+
border-bottom: 1px solid var(--surface-3);
|
|
10014
|
+
font-size: 24px;
|
|
10015
|
+
}
|
|
10016
|
+
.help-article h2 { margin: var(--space-2xl) 0 var(--space-lg); font-size: 20px; }
|
|
10017
|
+
.help-article h3 { margin: 20px 0 var(--space-md); font-size: var(--font-size-xl); }
|
|
10018
|
+
.help-article h4,
|
|
10019
|
+
.help-article h5,
|
|
10020
|
+
.help-article h6 {
|
|
10021
|
+
margin: var(--space-xl) 0 var(--space-md);
|
|
10022
|
+
color: var(--text-secondary);
|
|
10023
|
+
}
|
|
10024
|
+
.help-article p { margin: 0 0 var(--space-lg); }
|
|
10025
|
+
.help-article a { color: var(--accent-bright); text-decoration: none; }
|
|
10026
|
+
.help-article a:hover { text-decoration: underline; }
|
|
10027
|
+
.help-article strong { color: var(--text-primary); font-weight: var(--font-weight-semibold); }
|
|
10028
|
+
.help-article em { font-style: italic; }
|
|
10029
|
+
.help-article code {
|
|
10030
|
+
padding: 2px 6px;
|
|
10031
|
+
background: var(--surface-2);
|
|
10032
|
+
border-radius: 3px;
|
|
10033
|
+
font-family: var(--font-family-mono);
|
|
10034
|
+
font-size: var(--font-size-md);
|
|
10035
|
+
}
|
|
10036
|
+
.help-article pre {
|
|
10037
|
+
margin: 0 0 var(--space-xl);
|
|
10038
|
+
padding: var(--space-lg) var(--space-xl);
|
|
10039
|
+
background: var(--surface-well);
|
|
10040
|
+
border: 1px solid var(--surface-3);
|
|
10041
|
+
border-radius: var(--radius-sm);
|
|
10042
|
+
overflow-x: auto;
|
|
10043
|
+
}
|
|
10044
|
+
.help-article pre code { padding: 0; background: transparent; }
|
|
10045
|
+
.help-article blockquote {
|
|
10046
|
+
margin: 0 0 var(--space-lg);
|
|
10047
|
+
padding: var(--space-md) var(--space-xl);
|
|
10048
|
+
background: var(--state-selected);
|
|
10049
|
+
border-left: 3px solid var(--accent-bright);
|
|
10050
|
+
color: var(--text-secondary);
|
|
10051
|
+
}
|
|
10052
|
+
.help-article hr {
|
|
10053
|
+
margin: var(--space-2xl) 0;
|
|
10054
|
+
border: none;
|
|
10055
|
+
border-top: 1px solid var(--surface-3);
|
|
10056
|
+
}
|
|
10057
|
+
.help-article img {
|
|
10058
|
+
max-width: 100%;
|
|
10059
|
+
margin: var(--space-lg) 0;
|
|
10060
|
+
border-radius: var(--radius-sm);
|
|
10061
|
+
}
|
|
10062
|
+
.help-article table {
|
|
10063
|
+
width: 100%;
|
|
10064
|
+
margin: var(--space-xl) 0;
|
|
10065
|
+
border-collapse: collapse;
|
|
10066
|
+
font-size: var(--font-size-md);
|
|
10067
|
+
}
|
|
10068
|
+
.help-article th,
|
|
10069
|
+
.help-article td {
|
|
10070
|
+
padding: var(--space-md) var(--space-lg);
|
|
10071
|
+
border: 1px solid var(--surface-3);
|
|
10072
|
+
text-align: left;
|
|
10073
|
+
}
|
|
10074
|
+
.help-article th {
|
|
10075
|
+
background: var(--surface-2);
|
|
10076
|
+
color: var(--text-primary);
|
|
10077
|
+
font-weight: var(--font-weight-semibold);
|
|
10078
|
+
}
|
|
10079
|
+
.help-article tr:nth-child(even) { background: rgba(255, 255, 255, 0.02); }
|
|
10080
|
+
.help-article ul,
|
|
10081
|
+
.help-article ol {
|
|
10082
|
+
margin: var(--space-md) 0 var(--space-xl);
|
|
10083
|
+
padding-left: var(--space-2xl);
|
|
10084
|
+
}
|
|
10085
|
+
.help-article li { margin-bottom: var(--space-xs); line-height: 1.5; }
|
|
10086
|
+
.help-article li p { margin: 0; }
|
|
10087
|
+
.help-article li > ul,
|
|
10088
|
+
.help-article li > ol { margin: var(--space-xs) 0; }
|
|
10089
|
+
@media (max-width: 600px) {
|
|
10090
|
+
.help-modal { width: 95%; height: 90vh; }
|
|
10091
|
+
.help-modal__sidebar { display: none; }
|
|
10092
|
+
.help-modal__content { padding: var(--space-xl); }
|
|
10093
|
+
}
|
|
10094
|
+
/* ══ end HELP MODAL ══ */
|
|
10095
|
+
|
|
10096
|
+
/* ══ MENU BAR ════════════════════════════════════════════════════════
|
|
10097
|
+
*
|
|
10098
|
+
* `MenuBar` (src/ui/components/menu_bar.js, STORY-0030): a row of titles,
|
|
10099
|
+
* each opening a menu that may fly out submenus. Not `.twm-menu-bar`, which
|
|
10100
|
+
* is the older strip of 25px icon buttons and keeps its meaning. A menu is
|
|
10101
|
+
* `position: fixed` (the JS places it), so a bar inside a clipped chrome strip
|
|
10102
|
+
* still drops its menus over the page. Same surface, border and shadow as
|
|
10103
|
+
* `.twm-context-menu`: two menus that look different read as two systems.
|
|
10104
|
+
* tests/menu_bar_css.test.mjs holds every class the bar sets to a rule here,
|
|
10105
|
+
* both ways, and base.css to the same text. */
|
|
10106
|
+
.twm-menubar {
|
|
10107
|
+
display: flex;
|
|
10108
|
+
align-items: stretch;
|
|
10109
|
+
gap: 1px;
|
|
10110
|
+
min-height: 24px;
|
|
10111
|
+
font-size: var(--font-size-md);
|
|
10112
|
+
color: var(--text-body);
|
|
10113
|
+
user-select: none;
|
|
10114
|
+
}
|
|
10115
|
+
.twm-menubar__entry {
|
|
10116
|
+
position: relative;
|
|
10117
|
+
display: flex;
|
|
10118
|
+
}
|
|
10119
|
+
.twm-menubar__title {
|
|
10120
|
+
appearance: none;
|
|
10121
|
+
background: none;
|
|
10122
|
+
border: 0;
|
|
10123
|
+
border-radius: var(--radius-sm);
|
|
10124
|
+
color: inherit;
|
|
10125
|
+
font: inherit;
|
|
10126
|
+
padding: var(--space-xxs) var(--space-md);
|
|
10127
|
+
cursor: default;
|
|
10128
|
+
}
|
|
10129
|
+
.twm-menubar__title:hover,
|
|
10130
|
+
.twm-menubar__title:focus-visible,
|
|
10131
|
+
.twm-menubar__title[aria-expanded="true"] {
|
|
10132
|
+
background: var(--state-active);
|
|
10133
|
+
color: var(--text-bright);
|
|
10134
|
+
outline: none;
|
|
10135
|
+
}
|
|
10136
|
+
.twm-menubar__menu {
|
|
10137
|
+
position: fixed;
|
|
10138
|
+
z-index: var(--z-over-windows);
|
|
10139
|
+
display: flex;
|
|
10140
|
+
flex-direction: column;
|
|
10141
|
+
min-width: 200px;
|
|
10142
|
+
max-height: calc(100vh - 8px);
|
|
10143
|
+
overflow-y: auto;
|
|
10144
|
+
padding: var(--space-xs) 0;
|
|
10145
|
+
background: var(--surface-0);
|
|
10146
|
+
color: var(--text-body);
|
|
10147
|
+
border: 1px solid var(--surface-3);
|
|
10148
|
+
border-radius: var(--radius-md);
|
|
10149
|
+
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
|
|
10150
|
+
}
|
|
10151
|
+
.twm-menubar__cell {
|
|
10152
|
+
display: flex;
|
|
10153
|
+
}
|
|
10154
|
+
.twm-menubar__item {
|
|
10155
|
+
appearance: none;
|
|
10156
|
+
background: none;
|
|
10157
|
+
border: 0;
|
|
10158
|
+
width: 100%;
|
|
10159
|
+
text-align: left;
|
|
10160
|
+
color: inherit;
|
|
10161
|
+
font: inherit;
|
|
10162
|
+
display: flex;
|
|
10163
|
+
align-items: center;
|
|
10164
|
+
gap: var(--space-md);
|
|
10165
|
+
padding: var(--space-xs) var(--space-lg) var(--space-xs) var(--space-xs);
|
|
10166
|
+
cursor: default;
|
|
10167
|
+
white-space: nowrap;
|
|
10168
|
+
}
|
|
10169
|
+
.twm-menubar__item:focus,
|
|
10170
|
+
.twm-menubar__item:hover:not(.twm-menubar__item--disabled),
|
|
10171
|
+
.twm-menubar__item[aria-expanded="true"] {
|
|
10172
|
+
background: var(--state-selected);
|
|
10173
|
+
outline: none;
|
|
10174
|
+
}
|
|
10175
|
+
.twm-menubar__item--submenu {
|
|
10176
|
+
padding-right: var(--space-md);
|
|
10177
|
+
}
|
|
10178
|
+
.twm-menubar__item--disabled {
|
|
10179
|
+
opacity: 0.4;
|
|
10180
|
+
color: var(--text-muted);
|
|
10181
|
+
}
|
|
10182
|
+
.twm-menubar__check {
|
|
10183
|
+
flex: 0 0 16px;
|
|
10184
|
+
text-align: center;
|
|
10185
|
+
}
|
|
10186
|
+
.twm-menubar__item--check[aria-checked="true"] .twm-menubar__check::before { content: "\2713"; }
|
|
10187
|
+
.twm-menubar__item--radio[aria-checked="true"] .twm-menubar__check::before { content: "\2022"; }
|
|
10188
|
+
.twm-menubar__label {
|
|
10189
|
+
flex: 1 1 auto;
|
|
10190
|
+
}
|
|
10191
|
+
.twm-menubar__shortcut {
|
|
10192
|
+
margin-left: var(--space-2xl);
|
|
10193
|
+
color: var(--text-muted);
|
|
10194
|
+
font-size: var(--font-size-sm);
|
|
10195
|
+
}
|
|
10196
|
+
.twm-menubar__arrow::before {
|
|
10197
|
+
content: "\25B8";
|
|
10198
|
+
color: var(--text-muted);
|
|
10199
|
+
}
|
|
10200
|
+
.twm-menubar__separator {
|
|
10201
|
+
height: 1px;
|
|
10202
|
+
margin: var(--space-xs) var(--space-md);
|
|
10203
|
+
background: var(--surface-3);
|
|
10204
|
+
}
|
|
10205
|
+
/* ══ end MENU BAR ══ */
|
|
10206
|
+
|
|
10207
|
+
/* ══ TOGGLE ══════════════════════════════════════════════════════════
|
|
10208
|
+
* ToggleField: a track and a knob drawn over a real checkbox with
|
|
10209
|
+
* role="switch". The input sits on top of the track, transparent, so the
|
|
10210
|
+
* pointer and the keyboard reach a native control. Tokens only: swap
|
|
10211
|
+
* tokens.css and the switch follows.
|
|
10212
|
+
*/
|
|
10213
|
+
.twm-toggle {
|
|
10214
|
+
--twm-toggle-w: 34px;
|
|
10215
|
+
--twm-toggle-h: 18px;
|
|
10216
|
+
--twm-toggle-pad: 2px;
|
|
10217
|
+
display: inline-flex;
|
|
10218
|
+
align-items: center;
|
|
10219
|
+
gap: var(--space-sm);
|
|
10220
|
+
color: var(--text-body);
|
|
10221
|
+
font-size: var(--font-size-sm);
|
|
10222
|
+
line-height: var(--line-height-tight);
|
|
10223
|
+
cursor: pointer;
|
|
10224
|
+
user-select: none;
|
|
10225
|
+
vertical-align: middle;
|
|
10226
|
+
}
|
|
10227
|
+
.twm-toggle--compact {
|
|
10228
|
+
--twm-toggle-w: 26px;
|
|
10229
|
+
--twm-toggle-h: 14px;
|
|
10230
|
+
gap: var(--space-xs);
|
|
10231
|
+
font-size: var(--font-size-xs);
|
|
10232
|
+
}
|
|
10233
|
+
.twm-toggle__control {
|
|
10234
|
+
position: relative;
|
|
10235
|
+
display: inline-flex;
|
|
10236
|
+
flex: none;
|
|
10237
|
+
width: var(--twm-toggle-w);
|
|
10238
|
+
height: var(--twm-toggle-h);
|
|
10239
|
+
}
|
|
10240
|
+
.twm-toggle__input {
|
|
10241
|
+
position: absolute;
|
|
10242
|
+
inset: 0;
|
|
10243
|
+
width: 100%;
|
|
10244
|
+
height: 100%;
|
|
10245
|
+
margin: 0;
|
|
10246
|
+
opacity: 0;
|
|
10247
|
+
cursor: inherit;
|
|
10248
|
+
z-index: 1;
|
|
10249
|
+
}
|
|
10250
|
+
.twm-toggle__track {
|
|
10251
|
+
position: relative;
|
|
10252
|
+
display: block;
|
|
10253
|
+
width: 100%;
|
|
10254
|
+
height: 100%;
|
|
10255
|
+
box-sizing: border-box;
|
|
10256
|
+
border: 1px solid var(--border-strong);
|
|
10257
|
+
border-radius: var(--radius-pill);
|
|
10258
|
+
background: var(--surface-3);
|
|
10259
|
+
transition: background-color var(--transition-fast), border-color var(--transition-fast);
|
|
10260
|
+
}
|
|
10261
|
+
.twm-toggle__knob {
|
|
10262
|
+
position: absolute;
|
|
10263
|
+
top: var(--twm-toggle-pad);
|
|
10264
|
+
left: var(--twm-toggle-pad);
|
|
10265
|
+
width: calc(var(--twm-toggle-h) - 2 * var(--twm-toggle-pad) - 2px);
|
|
10266
|
+
height: calc(var(--twm-toggle-h) - 2 * var(--twm-toggle-pad) - 2px);
|
|
10267
|
+
border-radius: var(--radius-circle);
|
|
10268
|
+
background: var(--text-muted);
|
|
10269
|
+
box-shadow: var(--shadow-sm);
|
|
10270
|
+
transition: transform var(--transition-fast), background-color var(--transition-fast);
|
|
10271
|
+
}
|
|
10272
|
+
.twm-toggle__input:checked + .twm-toggle__track {
|
|
10273
|
+
background: var(--accent);
|
|
10274
|
+
border-color: var(--accent);
|
|
10275
|
+
}
|
|
10276
|
+
.twm-toggle__input:checked + .twm-toggle__track .twm-toggle__knob {
|
|
10277
|
+
transform: translateX(calc(var(--twm-toggle-w) - var(--twm-toggle-h)));
|
|
10278
|
+
background: var(--text-bright);
|
|
10279
|
+
}
|
|
10280
|
+
.twm-toggle:hover .twm-toggle__input:not(:disabled) + .twm-toggle__track {
|
|
10281
|
+
border-color: var(--accent-hover);
|
|
10282
|
+
}
|
|
10283
|
+
.twm-toggle__input:focus-visible + .twm-toggle__track {
|
|
10284
|
+
outline: 2px solid var(--accent-bright);
|
|
10285
|
+
outline-offset: 2px;
|
|
10286
|
+
}
|
|
10287
|
+
.twm-toggle__state {
|
|
10288
|
+
min-width: 2.5em;
|
|
10289
|
+
color: var(--text-muted);
|
|
10290
|
+
}
|
|
10291
|
+
.twm-toggle__label {
|
|
10292
|
+
color: var(--text-body);
|
|
10293
|
+
}
|
|
10294
|
+
.twm-toggle--disabled {
|
|
10295
|
+
cursor: not-allowed;
|
|
10296
|
+
opacity: 0.5;
|
|
10297
|
+
}
|
|
10298
|
+
.twm-modal__toggle {
|
|
10299
|
+
display: flex;
|
|
10300
|
+
align-items: center;
|
|
10301
|
+
min-height: var(--ea-row-h);
|
|
10302
|
+
}
|
|
10303
|
+
/* ══ end TOGGLE ══ */
|
|
10304
|
+
|
|
10305
|
+
/* ══ SETTINGS VIEW (STORY-0050) ══════════════════════════════════════
|
|
10306
|
+
* SettingsView: a sidebar of categories with a filter box, beside the
|
|
10307
|
+
* chosen category's settings in groups. Tokens only.
|
|
10308
|
+
*/
|
|
10309
|
+
.twm-settings {
|
|
10310
|
+
display: flex;
|
|
10311
|
+
height: 100%;
|
|
10312
|
+
min-height: 0;
|
|
10313
|
+
background: var(--surface-1);
|
|
10314
|
+
color: var(--text-body);
|
|
10315
|
+
font-size: var(--font-size-sm);
|
|
10316
|
+
}
|
|
10317
|
+
.twm-settings__sidebar {
|
|
10318
|
+
display: flex;
|
|
10319
|
+
flex-direction: column;
|
|
10320
|
+
flex: 0 0 220px;
|
|
10321
|
+
min-width: 0;
|
|
10322
|
+
gap: var(--space-sm);
|
|
10323
|
+
padding: var(--space-md);
|
|
10324
|
+
border-right: 1px solid var(--border-subtle);
|
|
10325
|
+
background: var(--surface-0);
|
|
10326
|
+
}
|
|
10327
|
+
.twm-settings__sidebar-title {
|
|
10328
|
+
display: flex;
|
|
10329
|
+
align-items: center;
|
|
10330
|
+
gap: var(--space-sm);
|
|
10331
|
+
color: var(--text-bright);
|
|
10332
|
+
font-weight: var(--font-weight-semibold);
|
|
10333
|
+
}
|
|
10334
|
+
.twm-settings__search {
|
|
10335
|
+
display: flex;
|
|
10336
|
+
align-items: center;
|
|
10337
|
+
gap: var(--space-xs);
|
|
10338
|
+
padding: 0 var(--space-sm);
|
|
10339
|
+
min-height: var(--ea-row-h);
|
|
10340
|
+
background: var(--ea-input-bg);
|
|
10341
|
+
border: 1px solid var(--border-strong);
|
|
10342
|
+
border-radius: var(--radius-sm);
|
|
10343
|
+
color: var(--text-muted);
|
|
10344
|
+
}
|
|
10345
|
+
.twm-settings__search:focus-within { border-color: var(--accent-bright); }
|
|
10346
|
+
.twm-settings__search-input {
|
|
10347
|
+
flex: 1 1 auto;
|
|
10348
|
+
min-width: 0;
|
|
10349
|
+
background: transparent;
|
|
10350
|
+
border: none;
|
|
10351
|
+
outline: none;
|
|
10352
|
+
color: var(--text-body);
|
|
10353
|
+
font: inherit;
|
|
10354
|
+
}
|
|
10355
|
+
.twm-settings__nav {
|
|
10356
|
+
display: flex;
|
|
10357
|
+
flex-direction: column;
|
|
10358
|
+
flex: 1 1 auto;
|
|
10359
|
+
min-height: 0;
|
|
10360
|
+
overflow-y: auto;
|
|
10361
|
+
gap: var(--space-xxs);
|
|
10362
|
+
}
|
|
10363
|
+
.twm-settings__cat {
|
|
10364
|
+
display: flex;
|
|
10365
|
+
align-items: center;
|
|
10366
|
+
gap: var(--space-sm);
|
|
10367
|
+
min-height: var(--ea-row-h);
|
|
10368
|
+
padding: 0 var(--space-sm);
|
|
10369
|
+
background: transparent;
|
|
10370
|
+
border: none;
|
|
10371
|
+
border-radius: var(--radius-sm);
|
|
10372
|
+
color: var(--text-secondary);
|
|
10373
|
+
font: inherit;
|
|
10374
|
+
text-align: left;
|
|
10375
|
+
cursor: pointer;
|
|
10376
|
+
}
|
|
10377
|
+
.twm-settings__cat:hover { background: var(--state-hover); }
|
|
10378
|
+
.twm-settings__cat:focus-visible { outline: 1px solid var(--accent-bright); }
|
|
10379
|
+
.twm-settings__cat--active {
|
|
10380
|
+
background: var(--state-selected);
|
|
10381
|
+
color: var(--text-bright);
|
|
10382
|
+
}
|
|
10383
|
+
.twm-settings__cat .material-symbols-outlined,
|
|
10384
|
+
.twm-settings__reset-all .material-symbols-outlined,
|
|
10385
|
+
.twm-settings__reset-category .material-symbols-outlined {
|
|
10386
|
+
font-size: var(--font-size-lg);
|
|
10387
|
+
}
|
|
10388
|
+
.twm-settings__cat-label {
|
|
10389
|
+
overflow: hidden;
|
|
10390
|
+
text-overflow: ellipsis;
|
|
10391
|
+
white-space: nowrap;
|
|
10392
|
+
}
|
|
10393
|
+
.twm-settings__content {
|
|
10394
|
+
flex: 1 1 auto;
|
|
10395
|
+
min-width: 0;
|
|
10396
|
+
overflow-y: auto;
|
|
10397
|
+
padding: var(--space-lg) var(--space-xl);
|
|
10398
|
+
}
|
|
10399
|
+
.twm-settings__header {
|
|
10400
|
+
display: flex;
|
|
10401
|
+
align-items: flex-start;
|
|
10402
|
+
justify-content: space-between;
|
|
10403
|
+
gap: var(--space-lg);
|
|
10404
|
+
margin-bottom: var(--space-lg);
|
|
10405
|
+
}
|
|
10406
|
+
.twm-settings__header-info {
|
|
10407
|
+
flex: 1 1 auto;
|
|
10408
|
+
min-width: 0;
|
|
10409
|
+
}
|
|
10410
|
+
.twm-settings__title {
|
|
10411
|
+
margin: 0;
|
|
10412
|
+
color: var(--text-bright);
|
|
10413
|
+
font-size: var(--font-size-xl);
|
|
10414
|
+
font-weight: var(--font-weight-semibold);
|
|
10415
|
+
}
|
|
10416
|
+
.twm-settings__description {
|
|
10417
|
+
margin: var(--space-xs) 0 0;
|
|
10418
|
+
color: var(--text-muted);
|
|
10419
|
+
}
|
|
10420
|
+
.twm-settings__group { margin-bottom: var(--space-xl); }
|
|
10421
|
+
.twm-settings__group-title {
|
|
10422
|
+
margin: 0 0 var(--space-sm);
|
|
10423
|
+
padding-bottom: var(--space-xs);
|
|
10424
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
10425
|
+
color: var(--text-secondary);
|
|
10426
|
+
font-size: var(--font-size-xs);
|
|
10427
|
+
font-weight: var(--font-weight-semibold);
|
|
10428
|
+
text-transform: uppercase;
|
|
10429
|
+
letter-spacing: 0.04em;
|
|
10430
|
+
}
|
|
10431
|
+
.twm-settings__row {
|
|
10432
|
+
display: flex;
|
|
10433
|
+
align-items: center;
|
|
10434
|
+
gap: var(--space-md);
|
|
10435
|
+
padding: var(--space-sm) var(--space-sm);
|
|
10436
|
+
border-left: 2px solid transparent;
|
|
10437
|
+
border-radius: var(--radius-sm);
|
|
10438
|
+
}
|
|
10439
|
+
.twm-settings__row:hover { background: var(--state-hover); }
|
|
10440
|
+
.twm-settings__row--modified { border-left-color: var(--accent-bright); }
|
|
10441
|
+
.twm-settings__info {
|
|
10442
|
+
flex: 1 1 auto;
|
|
10443
|
+
min-width: 0;
|
|
10444
|
+
}
|
|
10445
|
+
.twm-settings__label-line {
|
|
10446
|
+
display: flex;
|
|
10447
|
+
align-items: center;
|
|
10448
|
+
gap: var(--space-sm);
|
|
10449
|
+
}
|
|
10450
|
+
.twm-settings__label { color: var(--text-primary); }
|
|
10451
|
+
.twm-settings__marker {
|
|
10452
|
+
padding: 0 var(--space-xs);
|
|
10453
|
+
border-radius: var(--radius-pill);
|
|
10454
|
+
background: var(--surface-3);
|
|
10455
|
+
color: var(--accent-bright);
|
|
10456
|
+
font-size: var(--font-size-xs);
|
|
10457
|
+
}
|
|
10458
|
+
.twm-settings__marker[hidden],
|
|
10459
|
+
.twm-settings__reset[hidden] { display: none; }
|
|
10460
|
+
.twm-settings__row .twm-settings__description {
|
|
10461
|
+
margin-top: var(--space-xxs);
|
|
10462
|
+
font-size: var(--font-size-xs);
|
|
10463
|
+
}
|
|
10464
|
+
.twm-settings__path {
|
|
10465
|
+
display: block;
|
|
10466
|
+
margin-top: var(--space-xxs);
|
|
10467
|
+
color: var(--text-dim);
|
|
10468
|
+
font-family: var(--font-family-mono);
|
|
10469
|
+
font-size: var(--font-size-xs);
|
|
10470
|
+
}
|
|
10471
|
+
.twm-settings__control {
|
|
10472
|
+
flex: 0 0 auto;
|
|
10473
|
+
display: flex;
|
|
10474
|
+
align-items: center;
|
|
10475
|
+
max-width: 50%;
|
|
10476
|
+
}
|
|
10477
|
+
.twm-settings__select,
|
|
10478
|
+
.twm-settings__number,
|
|
10479
|
+
.twm-settings__text {
|
|
10480
|
+
min-height: var(--ea-row-h);
|
|
10481
|
+
padding: 0 var(--space-sm);
|
|
10482
|
+
background: var(--ea-input-bg);
|
|
10483
|
+
border: 1px solid var(--border-strong);
|
|
10484
|
+
border-radius: var(--radius-sm);
|
|
10485
|
+
color: var(--text-body);
|
|
10486
|
+
font: inherit;
|
|
10487
|
+
}
|
|
10488
|
+
.twm-settings__select:focus,
|
|
10489
|
+
.twm-settings__number:focus,
|
|
10490
|
+
.twm-settings__text:focus {
|
|
10491
|
+
outline: none;
|
|
10492
|
+
border-color: var(--accent-bright);
|
|
10493
|
+
}
|
|
10494
|
+
.twm-settings__number { width: 110px; }
|
|
10495
|
+
.twm-settings__text { width: 240px; }
|
|
10496
|
+
.twm-settings__readonly {
|
|
10497
|
+
color: var(--text-muted);
|
|
10498
|
+
font-family: var(--font-family-mono);
|
|
10499
|
+
}
|
|
10500
|
+
.twm-settings__reset {
|
|
10501
|
+
flex: 0 0 auto;
|
|
10502
|
+
display: inline-flex;
|
|
10503
|
+
align-items: center;
|
|
10504
|
+
justify-content: center;
|
|
10505
|
+
width: var(--ea-row-h);
|
|
10506
|
+
height: var(--ea-row-h);
|
|
10507
|
+
padding: 0;
|
|
10508
|
+
background: transparent;
|
|
10509
|
+
border: none;
|
|
10510
|
+
border-radius: var(--radius-sm);
|
|
10511
|
+
color: var(--text-muted);
|
|
10512
|
+
cursor: pointer;
|
|
10513
|
+
}
|
|
10514
|
+
.twm-settings__reset:hover { background: var(--state-hover); color: var(--text-bright); }
|
|
10515
|
+
.twm-settings__reset .material-symbols-outlined { font-size: var(--font-size-lg); }
|
|
10516
|
+
.twm-settings__empty {
|
|
10517
|
+
padding: var(--space-xl) 0;
|
|
10518
|
+
color: var(--text-muted);
|
|
10519
|
+
}
|
|
10520
|
+
/* ══ end SETTINGS VIEW ══ */
|
|
10521
|
+
|
|
10522
|
+
/* ══ DOCUMENT OUTLINE (0.17.0) ═══════════════════════════════════════
|
|
10523
|
+
* `createDocumentOutline` (src/ui/components/document_outline.js). No height
|
|
10524
|
+
* of its own: the host that holds it scrolls, if anything does. */
|
|
10525
|
+
.twm-doc-outline { display: block; min-width: 0; }
|
|
10526
|
+
.twm-doc-outline__items {
|
|
10527
|
+
list-style: none;
|
|
10528
|
+
margin: 0;
|
|
10529
|
+
padding: 2px 0;
|
|
10530
|
+
}
|
|
10531
|
+
.twm-doc-outline__item { margin: 0; padding: 0; min-width: 0; }
|
|
10532
|
+
/* One step of indentation per level below the first, set inline per item as
|
|
10533
|
+
* `--twm-doc-outline-depth` (0 for depth 1). */
|
|
10534
|
+
.twm-doc-outline__link {
|
|
10535
|
+
display: flex;
|
|
10536
|
+
align-items: baseline;
|
|
10537
|
+
gap: 6px;
|
|
10538
|
+
width: 100%;
|
|
10539
|
+
min-width: 0;
|
|
10540
|
+
margin: 0;
|
|
10541
|
+
padding: 3px 8px 3px calc(8px + var(--twm-doc-outline-depth, 0) * var(--twm-doc-outline-indent, 12px));
|
|
10542
|
+
border: none;
|
|
10543
|
+
border-left: 2px solid transparent;
|
|
10544
|
+
background: transparent;
|
|
10545
|
+
color: var(--text-secondary, #cccccc);
|
|
10546
|
+
font: inherit;
|
|
10547
|
+
text-align: left;
|
|
10548
|
+
cursor: pointer;
|
|
10549
|
+
}
|
|
10550
|
+
.twm-doc-outline__link:hover { background: var(--state-hover, rgba(255, 255, 255, 0.05)); color: var(--text-primary, #e0e0e0); }
|
|
10551
|
+
.twm-doc-outline__link:focus-visible { outline: 1px solid var(--accent-bright, #007acc); outline-offset: -1px; }
|
|
10552
|
+
.twm-doc-outline__item--level-1 > .twm-doc-outline__link { color: var(--text-primary, #e0e0e0); }
|
|
10553
|
+
.twm-doc-outline__number {
|
|
10554
|
+
flex: 0 0 auto;
|
|
10555
|
+
color: var(--text-muted, #888888);
|
|
10556
|
+
font-variant-numeric: tabular-nums;
|
|
10557
|
+
}
|
|
10558
|
+
.twm-doc-outline__label {
|
|
10559
|
+
flex: 1 1 auto;
|
|
10560
|
+
min-width: 0;
|
|
10561
|
+
overflow: hidden;
|
|
10562
|
+
text-overflow: ellipsis;
|
|
10563
|
+
white-space: nowrap;
|
|
10564
|
+
}
|
|
10565
|
+
.twm-doc-outline__item.twm-doc-outline__item--active > .twm-doc-outline__link {
|
|
10566
|
+
border-left-color: var(--accent-bright, #007acc);
|
|
10567
|
+
background: rgba(0, 122, 204, 0.15);
|
|
10568
|
+
color: var(--text-primary, #e0e0e0);
|
|
10569
|
+
}
|
|
10570
|
+
/* Listed, but nothing in the document answers to it. */
|
|
10571
|
+
.twm-doc-outline__item--unresolved > .twm-doc-outline__link { opacity: 0.6; }
|
|
10572
|
+
.twm-doc-outline__empty {
|
|
10573
|
+
margin: 0;
|
|
10574
|
+
padding: 8px;
|
|
10575
|
+
color: var(--text-muted, #888888);
|
|
10576
|
+
font-style: italic;
|
|
10577
|
+
}
|
|
10578
|
+
/* ══ end DOCUMENT OUTLINE ══ */
|
|
10579
|
+
|
|
10580
|
+
/* ══ TAG INPUT (0.17.0) ═══════════════════════════════════════════════
|
|
10581
|
+
* `createTagInput` (src/ui/components/tag_input.js): removable chips and a
|
|
10582
|
+
* text box on one wrapping line. No height of its own. */
|
|
10583
|
+
.twm-tag-input {
|
|
10584
|
+
display: flex;
|
|
10585
|
+
flex-wrap: wrap;
|
|
10586
|
+
align-items: center;
|
|
10587
|
+
gap: var(--space-xs, 4px);
|
|
10588
|
+
min-width: 0;
|
|
10589
|
+
padding: 3px var(--space-xs, 4px);
|
|
10590
|
+
background: var(--surface-3, #3c3c3c);
|
|
10591
|
+
border: 1px solid var(--border-strong, #383838);
|
|
10592
|
+
border-radius: var(--radius-sm, 4px);
|
|
10593
|
+
cursor: text;
|
|
10594
|
+
}
|
|
10595
|
+
.twm-tag-input:focus-within { border-color: var(--accent-bright, #007acc); }
|
|
10596
|
+
.twm-tag-input--readonly {
|
|
10597
|
+
background: transparent;
|
|
10598
|
+
border-color: transparent;
|
|
10599
|
+
padding-left: 0;
|
|
10600
|
+
padding-right: 0;
|
|
10601
|
+
cursor: default;
|
|
10602
|
+
}
|
|
10603
|
+
.twm-tag-input__chips {
|
|
10604
|
+
display: contents;
|
|
10605
|
+
list-style: none;
|
|
10606
|
+
margin: 0;
|
|
10607
|
+
padding: 0;
|
|
10608
|
+
}
|
|
10609
|
+
.twm-tag-input__chip {
|
|
10610
|
+
display: inline-flex;
|
|
10611
|
+
align-items: center;
|
|
10612
|
+
gap: 2px;
|
|
10613
|
+
max-width: 100%;
|
|
10614
|
+
min-width: 0;
|
|
10615
|
+
padding: 1px var(--space-xs, 4px) 1px var(--space-sm, 6px);
|
|
10616
|
+
background: var(--surface-2, #2d2d2d);
|
|
10617
|
+
border: 1px solid var(--border-strong, #383838);
|
|
10618
|
+
border-radius: var(--radius-pill, 999px);
|
|
10619
|
+
color: var(--text-primary, #e0e0e0);
|
|
10620
|
+
font-size: var(--font-size-sm, 12px);
|
|
10621
|
+
line-height: 18px;
|
|
10622
|
+
}
|
|
10623
|
+
.twm-tag-input--readonly .twm-tag-input__chip { padding-right: var(--space-sm, 6px); }
|
|
10624
|
+
.twm-tag-input__text {
|
|
10625
|
+
min-width: 0;
|
|
10626
|
+
overflow: hidden;
|
|
10627
|
+
text-overflow: ellipsis;
|
|
10628
|
+
white-space: nowrap;
|
|
10629
|
+
}
|
|
10630
|
+
.twm-tag-input__remove {
|
|
10631
|
+
display: inline-flex;
|
|
10632
|
+
align-items: center;
|
|
10633
|
+
justify-content: center;
|
|
10634
|
+
width: 16px;
|
|
10635
|
+
height: 16px;
|
|
10636
|
+
padding: 0;
|
|
10637
|
+
border: none;
|
|
10638
|
+
border-radius: var(--radius-circle, 50%);
|
|
10639
|
+
background: transparent;
|
|
10640
|
+
color: var(--text-muted, #888);
|
|
10641
|
+
font: inherit;
|
|
10642
|
+
line-height: 1;
|
|
10643
|
+
cursor: pointer;
|
|
10644
|
+
}
|
|
10645
|
+
.twm-tag-input__remove:hover,
|
|
10646
|
+
.twm-tag-input__remove:focus-visible {
|
|
10647
|
+
background: var(--state-active, rgba(255, 255, 255, 0.08));
|
|
10648
|
+
color: var(--text-bright, #fff);
|
|
10649
|
+
}
|
|
10650
|
+
.twm-tag-input__input {
|
|
10651
|
+
flex: 1 1 6em;
|
|
10652
|
+
min-width: 4em;
|
|
10653
|
+
padding: 1px 2px;
|
|
10654
|
+
border: none;
|
|
10655
|
+
outline: none;
|
|
10656
|
+
background: transparent;
|
|
10657
|
+
color: var(--text-primary, #e0e0e0);
|
|
10658
|
+
font: inherit;
|
|
10659
|
+
font-size: var(--font-size-sm, 12px);
|
|
10660
|
+
}
|
|
10661
|
+
/* ══ end TAG INPUT ══ */
|
|
10662
|
+
|
|
10663
|
+
/* ══ SERIES TRANSFORMS ═══════════════════════════════════════════════
|
|
10664
|
+
*
|
|
10665
|
+
* `renderSeriesTransformControls` (src/charts/series_transforms.js): per
|
|
10666
|
+
* injected transform, a group with a toggle per output and a number field per
|
|
10667
|
+
* parameter, in a subplot's config. */
|
|
10668
|
+
.twm-series-transforms {
|
|
10669
|
+
display: flex;
|
|
10670
|
+
flex-direction: column;
|
|
10671
|
+
gap: var(--space-md);
|
|
10672
|
+
}
|
|
10673
|
+
.twm-series-transforms__group {
|
|
10674
|
+
display: flex;
|
|
10675
|
+
flex-direction: column;
|
|
10676
|
+
gap: var(--space-xs);
|
|
10677
|
+
margin: 0;
|
|
10678
|
+
padding: var(--space-sm) var(--space-md);
|
|
10679
|
+
border: 1px solid var(--border-subtle);
|
|
10680
|
+
border-radius: var(--radius-sm);
|
|
10681
|
+
}
|
|
10682
|
+
.twm-series-transforms__label {
|
|
10683
|
+
padding: 0 var(--space-xs);
|
|
10684
|
+
font-size: var(--font-size-sm);
|
|
10685
|
+
font-weight: var(--font-weight-semibold);
|
|
10686
|
+
color: var(--text-muted);
|
|
10687
|
+
}
|
|
10688
|
+
.twm-series-transforms__row {
|
|
10689
|
+
display: flex;
|
|
10690
|
+
align-items: center;
|
|
10691
|
+
gap: var(--space-sm);
|
|
10692
|
+
font-size: var(--font-size-sm);
|
|
10693
|
+
color: var(--text-primary);
|
|
10694
|
+
}
|
|
10695
|
+
.twm-series-transforms__param {
|
|
10696
|
+
width: 96px;
|
|
10697
|
+
margin-left: auto;
|
|
10698
|
+
padding: var(--space-xxs) var(--space-xs);
|
|
10699
|
+
background: var(--surface-3);
|
|
10700
|
+
color: var(--text-primary);
|
|
10701
|
+
border: 1px solid var(--border-strong);
|
|
10702
|
+
border-radius: var(--radius-sm);
|
|
10703
|
+
}
|
|
10704
|
+
.twm-series-transforms__param:disabled {
|
|
10705
|
+
opacity: 0.5;
|
|
10706
|
+
}
|
|
10707
|
+
/* ══ end SERIES TRANSFORMS ══ */
|
|
10708
|
+
|
|
10709
|
+
/* ══ PLOT GRID ════════════════════════════════════════════════════════
|
|
10710
|
+
*
|
|
10711
|
+
* `renderPlotGrid` (src/charts/plot_grid.js): a CSS grid of one Plotly figure
|
|
10712
|
+
* per subplot. The template columns/rows and each cell's grid-area are inline,
|
|
10713
|
+
* from PLOT_LAYOUTS. */
|
|
10714
|
+
.twm-plot-grid {
|
|
10715
|
+
display: grid;
|
|
10716
|
+
gap: 4px;
|
|
10717
|
+
width: 100%;
|
|
10718
|
+
height: 100%;
|
|
10719
|
+
min-height: 0;
|
|
10720
|
+
}
|
|
10721
|
+
.twm-plot-grid__cell {
|
|
10722
|
+
position: relative; /* Anchor for Plotly's positioning */
|
|
10723
|
+
min-width: 0;
|
|
10724
|
+
min-height: 0;
|
|
10725
|
+
}
|
|
10726
|
+
.twm-plot-grid__cell > .twm-plot-no-data {
|
|
10727
|
+
padding: var(--space-lg);
|
|
10728
|
+
font-size: var(--font-size-xs);
|
|
10729
|
+
}
|
|
10730
|
+
/* ══ end PLOT GRID ══ */
|
|
10731
|
+
|
|
10732
|
+
/* ══ PLOT CONFIG EDITOR ═══════════════════════════════════════════════
|
|
10733
|
+
*
|
|
10734
|
+
* `renderPlotConfigEditor` (src/charts/plot_config_editor.js): a layout
|
|
10735
|
+
* picker, a tab per subplot slot and the fields of the subplot in front. */
|
|
10736
|
+
.twm-plot-config {
|
|
10737
|
+
display: flex;
|
|
10738
|
+
flex-direction: column;
|
|
10739
|
+
gap: var(--space-md);
|
|
10740
|
+
min-width: 0;
|
|
10741
|
+
font-size: var(--font-size-sm);
|
|
10742
|
+
color: var(--text-primary);
|
|
10743
|
+
}
|
|
10744
|
+
.twm-plot-config__section {
|
|
10745
|
+
display: flex;
|
|
10746
|
+
flex-direction: column;
|
|
10747
|
+
gap: var(--space-xs);
|
|
10748
|
+
}
|
|
10749
|
+
.twm-plot-config__heading {
|
|
10750
|
+
margin: 0;
|
|
10751
|
+
font-size: var(--font-size-sm);
|
|
10752
|
+
font-weight: var(--font-weight-semibold);
|
|
10753
|
+
color: var(--text-muted);
|
|
10754
|
+
}
|
|
10755
|
+
.twm-plot-config__layouts {
|
|
10756
|
+
display: flex;
|
|
10757
|
+
flex-wrap: wrap;
|
|
10758
|
+
gap: var(--space-xs);
|
|
10759
|
+
}
|
|
10760
|
+
.twm-plot-config__layout {
|
|
10761
|
+
min-width: 0;
|
|
10762
|
+
}
|
|
10763
|
+
.twm-plot-config__layout--on {
|
|
10764
|
+
border-color: var(--accent);
|
|
10765
|
+
color: var(--text-bright);
|
|
10766
|
+
}
|
|
10767
|
+
.twm-plot-config__tabs[hidden] {
|
|
10768
|
+
display: none;
|
|
10769
|
+
}
|
|
10770
|
+
.twm-plot-config__body {
|
|
10771
|
+
display: flex;
|
|
10772
|
+
flex-direction: column;
|
|
10773
|
+
gap: var(--space-md);
|
|
10774
|
+
}
|
|
10775
|
+
.twm-plot-config__field {
|
|
10776
|
+
display: flex;
|
|
10777
|
+
align-items: center;
|
|
10778
|
+
gap: var(--space-sm);
|
|
10779
|
+
min-width: 0;
|
|
10780
|
+
}
|
|
10781
|
+
.twm-plot-config__label {
|
|
10782
|
+
flex: 0 0 96px;
|
|
10783
|
+
color: var(--text-muted);
|
|
10784
|
+
}
|
|
10785
|
+
.twm-plot-config__input {
|
|
10786
|
+
box-sizing: border-box;
|
|
10787
|
+
min-width: 0;
|
|
10788
|
+
flex: 1 1 auto;
|
|
10789
|
+
padding: var(--space-xxs) var(--space-xs);
|
|
10790
|
+
font: inherit;
|
|
10791
|
+
background: var(--surface-3);
|
|
10792
|
+
color: var(--text-primary);
|
|
10793
|
+
border: 1px solid var(--border-strong);
|
|
10794
|
+
border-radius: var(--radius-sm);
|
|
10795
|
+
}
|
|
10796
|
+
.twm-plot-config__input--number {
|
|
10797
|
+
flex: 0 1 80px;
|
|
10798
|
+
width: 80px;
|
|
10799
|
+
}
|
|
10800
|
+
.twm-plot-config__input:disabled {
|
|
10801
|
+
opacity: 0.5;
|
|
10802
|
+
}
|
|
10803
|
+
.twm-plot-config__picker {
|
|
10804
|
+
flex: 1 1 140px;
|
|
10805
|
+
min-width: 0;
|
|
10806
|
+
}
|
|
10807
|
+
.twm-plot-config__axes,
|
|
10808
|
+
.twm-plot-config__list,
|
|
10809
|
+
.twm-plot-config__series-list {
|
|
10810
|
+
display: flex;
|
|
10811
|
+
flex-direction: column;
|
|
10812
|
+
gap: var(--space-xs);
|
|
10813
|
+
}
|
|
10814
|
+
.twm-plot-config__axis {
|
|
10815
|
+
display: flex;
|
|
10816
|
+
flex-direction: column;
|
|
10817
|
+
gap: var(--space-xs);
|
|
10818
|
+
margin: 0;
|
|
10819
|
+
padding: var(--space-sm) var(--space-md);
|
|
10820
|
+
border: 1px solid var(--border-subtle);
|
|
10821
|
+
border-radius: var(--radius-sm);
|
|
10822
|
+
min-width: 0;
|
|
10823
|
+
}
|
|
10824
|
+
.twm-plot-config__axis--disabled {
|
|
10825
|
+
opacity: 0.5;
|
|
10826
|
+
}
|
|
10827
|
+
.twm-plot-config__axis-title {
|
|
10828
|
+
display: flex;
|
|
10829
|
+
align-items: center;
|
|
10830
|
+
gap: var(--space-xs);
|
|
10831
|
+
padding: 0 var(--space-xs);
|
|
10832
|
+
font-weight: var(--font-weight-semibold);
|
|
10833
|
+
color: var(--text-muted);
|
|
10834
|
+
}
|
|
10835
|
+
.twm-plot-config__axis-fields {
|
|
10836
|
+
display: grid;
|
|
10837
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
10838
|
+
gap: var(--space-xs) var(--space-md);
|
|
10839
|
+
}
|
|
10840
|
+
.twm-plot-config__series {
|
|
10841
|
+
display: flex;
|
|
10842
|
+
flex-direction: column;
|
|
10843
|
+
gap: var(--space-xxs);
|
|
10844
|
+
padding: var(--space-xs) 0;
|
|
10845
|
+
border-top: 1px solid var(--border-subtle);
|
|
10846
|
+
}
|
|
10847
|
+
.twm-plot-config__series-main,
|
|
10848
|
+
.twm-plot-config__row {
|
|
10849
|
+
display: flex;
|
|
10850
|
+
flex-wrap: wrap;
|
|
10851
|
+
align-items: center;
|
|
10852
|
+
gap: var(--space-xs);
|
|
10853
|
+
}
|
|
10854
|
+
.twm-plot-config__series-main > .twm-plot-config__input:not(.twm-plot-config__input--number):not(.twm-plot-config__input--select),
|
|
10855
|
+
.twm-plot-config__row > .twm-plot-config__input:not(.twm-plot-config__input--number):not(.twm-plot-config__input--select) {
|
|
10856
|
+
flex: 1 1 100px;
|
|
10857
|
+
}
|
|
10858
|
+
.twm-plot-config__series-main > .twm-plot-config__input--select,
|
|
10859
|
+
.twm-plot-config__row > .twm-plot-config__input--select {
|
|
10860
|
+
flex: 0 1 auto;
|
|
10861
|
+
}
|
|
10862
|
+
.twm-plot-config__series-extra:empty {
|
|
10863
|
+
display: none;
|
|
10864
|
+
}
|
|
10865
|
+
.twm-plot-config__overlay,
|
|
10866
|
+
.twm-plot-config__overlay-fields {
|
|
10867
|
+
display: flex;
|
|
10868
|
+
flex-direction: column;
|
|
10869
|
+
gap: var(--space-xxs);
|
|
10870
|
+
padding-left: var(--space-md);
|
|
10871
|
+
}
|
|
10872
|
+
.twm-plot-config__overlay-source {
|
|
10873
|
+
color: var(--text-muted);
|
|
10874
|
+
}
|
|
10875
|
+
.twm-plot-config__overlay-source--error {
|
|
10876
|
+
color: var(--color-danger);
|
|
10877
|
+
}
|
|
10878
|
+
.twm-plot-config__empty {
|
|
10879
|
+
color: var(--text-muted);
|
|
10880
|
+
font-style: italic;
|
|
10881
|
+
}
|
|
10882
|
+
.twm-plot-config__add {
|
|
10883
|
+
align-self: flex-start;
|
|
10884
|
+
}
|
|
10885
|
+
.twm-plot-config__remove {
|
|
10886
|
+
flex: 0 0 auto;
|
|
10887
|
+
margin-left: auto;
|
|
10888
|
+
}
|
|
10889
|
+
.twm-plot-config__remove > .material-symbols-outlined {
|
|
10890
|
+
font-size: 16px;
|
|
10891
|
+
}
|
|
10892
|
+
/* ══ end PLOT CONFIG EDITOR ══ */
|
|
10893
|
+
|
|
10894
|
+
/* ══ WIZARD (STORY-0047) ══════════════════════════════════════════════════
|
|
10895
|
+
* A step indicator, a body slot and a footer. Steps are drawn done / current /
|
|
10896
|
+
* upcoming / error and joined by a connector that fills once the step after it
|
|
10897
|
+
* has been reached. Only a done (or errored) step before the current one is an
|
|
10898
|
+
* enabled button; the rest are disabled and look inert. */
|
|
10899
|
+
.twm-wizard {
|
|
10900
|
+
display: flex;
|
|
10901
|
+
flex-direction: column;
|
|
10902
|
+
height: 100%;
|
|
10903
|
+
min-height: 0;
|
|
10904
|
+
color: var(--text-body);
|
|
10905
|
+
font-size: var(--font-size-sm);
|
|
10906
|
+
}
|
|
10907
|
+
.twm-wizard__steps {
|
|
10908
|
+
display: flex;
|
|
10909
|
+
align-items: center;
|
|
10910
|
+
gap: var(--space-xs);
|
|
10911
|
+
margin: 0;
|
|
10912
|
+
padding: var(--space-md) var(--space-lg);
|
|
10913
|
+
list-style: none;
|
|
10914
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
10915
|
+
}
|
|
10916
|
+
.twm-wizard__step {
|
|
10917
|
+
flex: 0 0 auto;
|
|
10918
|
+
min-width: 0;
|
|
10919
|
+
}
|
|
10920
|
+
.twm-wizard__step-btn {
|
|
10921
|
+
display: inline-flex;
|
|
10922
|
+
align-items: center;
|
|
10923
|
+
gap: var(--space-xs);
|
|
10924
|
+
padding: var(--space-xxs) var(--space-xs);
|
|
10925
|
+
border: 0;
|
|
10926
|
+
border-radius: var(--radius-sm);
|
|
10927
|
+
background: transparent;
|
|
10928
|
+
color: var(--text-muted);
|
|
10929
|
+
font: inherit;
|
|
10930
|
+
cursor: pointer;
|
|
10931
|
+
}
|
|
10932
|
+
.twm-wizard__step-btn:hover:not(:disabled) {
|
|
10933
|
+
background: var(--state-hover);
|
|
10934
|
+
}
|
|
10935
|
+
.twm-wizard__step-btn:focus-visible {
|
|
10936
|
+
outline: 1px solid var(--accent);
|
|
10937
|
+
outline-offset: 1px;
|
|
10938
|
+
}
|
|
10939
|
+
.twm-wizard__step-btn:disabled {
|
|
10940
|
+
cursor: default;
|
|
10941
|
+
}
|
|
10942
|
+
.twm-wizard__step-marker {
|
|
10943
|
+
display: inline-flex;
|
|
10944
|
+
align-items: center;
|
|
10945
|
+
justify-content: center;
|
|
10946
|
+
flex: 0 0 auto;
|
|
10947
|
+
width: 20px;
|
|
10948
|
+
height: 20px;
|
|
10949
|
+
border: 1px solid var(--border-strong);
|
|
10950
|
+
border-radius: var(--radius-circle);
|
|
10951
|
+
font-size: var(--font-size-xs);
|
|
10952
|
+
line-height: 1;
|
|
10953
|
+
}
|
|
10954
|
+
.twm-wizard__step-marker.material-symbols-outlined {
|
|
10955
|
+
font-size: 14px;
|
|
10956
|
+
}
|
|
10957
|
+
.twm-wizard__step-label {
|
|
10958
|
+
overflow: hidden;
|
|
10959
|
+
text-overflow: ellipsis;
|
|
10960
|
+
white-space: nowrap;
|
|
10961
|
+
}
|
|
10962
|
+
.twm-wizard__step--done .twm-wizard__step-btn {
|
|
10963
|
+
color: var(--text-body);
|
|
10964
|
+
}
|
|
10965
|
+
.twm-wizard__step--done .twm-wizard__step-marker {
|
|
10966
|
+
border-color: var(--color-success);
|
|
10967
|
+
color: var(--color-success);
|
|
10968
|
+
}
|
|
10969
|
+
.twm-wizard__step--current .twm-wizard__step-btn {
|
|
10970
|
+
color: var(--text-bright);
|
|
10971
|
+
font-weight: var(--font-weight-semibold);
|
|
10972
|
+
}
|
|
10973
|
+
.twm-wizard__step--current .twm-wizard__step-marker {
|
|
10974
|
+
border-color: var(--accent);
|
|
10975
|
+
background: var(--accent);
|
|
10976
|
+
color: var(--text-bright);
|
|
10977
|
+
}
|
|
10978
|
+
.twm-wizard__step--upcoming .twm-wizard__step-btn {
|
|
10979
|
+
color: var(--text-dim);
|
|
10980
|
+
}
|
|
10981
|
+
.twm-wizard__step--error .twm-wizard__step-btn {
|
|
10982
|
+
color: var(--color-danger);
|
|
10983
|
+
}
|
|
10984
|
+
.twm-wizard__step--error .twm-wizard__step-marker {
|
|
10985
|
+
border-color: var(--color-danger);
|
|
10986
|
+
color: var(--color-danger);
|
|
10987
|
+
}
|
|
10988
|
+
.twm-wizard__step--active .twm-wizard__step-label {
|
|
10989
|
+
text-decoration: underline;
|
|
10990
|
+
text-underline-offset: 3px;
|
|
10991
|
+
}
|
|
10992
|
+
.twm-wizard__connector {
|
|
10993
|
+
flex: 1 1 16px;
|
|
10994
|
+
min-width: 16px;
|
|
10995
|
+
height: 1px;
|
|
10996
|
+
background: var(--border-default);
|
|
10997
|
+
}
|
|
10998
|
+
.twm-wizard__connector--done {
|
|
10999
|
+
background: var(--color-success);
|
|
11000
|
+
}
|
|
11001
|
+
.twm-wizard__body {
|
|
11002
|
+
flex: 1 1 auto;
|
|
11003
|
+
min-height: 0;
|
|
11004
|
+
overflow: auto;
|
|
11005
|
+
padding: var(--space-lg);
|
|
11006
|
+
}
|
|
11007
|
+
.twm-wizard__footer {
|
|
11008
|
+
display: flex;
|
|
11009
|
+
align-items: center;
|
|
11010
|
+
gap: var(--space-md);
|
|
11011
|
+
padding: var(--space-sm) var(--space-lg);
|
|
11012
|
+
border-top: 1px solid var(--border-subtle);
|
|
11013
|
+
}
|
|
11014
|
+
.twm-wizard__message {
|
|
11015
|
+
flex: 1 1 auto;
|
|
11016
|
+
min-width: 0;
|
|
11017
|
+
color: var(--text-muted);
|
|
11018
|
+
}
|
|
11019
|
+
.twm-wizard__message--hint {
|
|
11020
|
+
color: var(--color-warning);
|
|
11021
|
+
}
|
|
11022
|
+
.twm-wizard__message--error {
|
|
11023
|
+
color: var(--color-danger);
|
|
11024
|
+
}
|
|
11025
|
+
.twm-wizard__actions {
|
|
11026
|
+
display: flex;
|
|
11027
|
+
flex: 0 0 auto;
|
|
11028
|
+
gap: var(--space-xs);
|
|
11029
|
+
}
|
|
11030
|
+
.twm-wizard--busy {
|
|
11031
|
+
cursor: progress;
|
|
11032
|
+
}
|
|
11033
|
+
.twm-wizard--busy .twm-wizard__body {
|
|
11034
|
+
opacity: 0.6;
|
|
11035
|
+
pointer-events: none;
|
|
11036
|
+
}
|
|
11037
|
+
/* ══ end WIZARD ══ */
|
|
11038
|
+
|
|
11039
|
+
/* ══ SECTION STACK ═══════════════════════════════════════════════════════
|
|
11040
|
+
* `createSectionStack` (ui/components/section_stack.js, STORY-0036): titled
|
|
11041
|
+
* sections in a column, built on the tree's `.twm-collapsible-*` primitive.
|
|
11042
|
+
*
|
|
11043
|
+
* THE STACK IS A COLUMN AS TALL AS ITS CONTAINER. A section is as tall as its
|
|
11044
|
+
* content, except the FILL section, which takes what the others leave
|
|
11045
|
+
* (`flex: 1 1 0`) — and only while it is open, so a closed one is a header.
|
|
11046
|
+
* Its body is the one that scrolls: `min-height: 0` on the box and the body is
|
|
11047
|
+
* what lets a flex child shrink below its content, without which a long
|
|
11048
|
+
* conversation grows the section, and the panel, past the window. If the
|
|
11049
|
+
* fixed sections alone outgrow the stack, the stack itself scrolls; the open
|
|
11050
|
+
* fill box then stops at its header's height (`min-height: 26px`, the header
|
|
11051
|
+
* rule's `height`) so its header never lands on the next section's, and only
|
|
11052
|
+
* its body shrinks away.
|
|
11053
|
+
*
|
|
11054
|
+
* `[hidden]` needs its own rule: the box is `display: flex`, and an author
|
|
11055
|
+
* `display` beats the UA's `[hidden] { display: none }`. */
|
|
11056
|
+
.twm-section-stack {
|
|
11057
|
+
display: flex;
|
|
11058
|
+
flex-direction: column;
|
|
11059
|
+
height: 100%;
|
|
11060
|
+
min-height: 0;
|
|
11061
|
+
overflow-x: hidden;
|
|
11062
|
+
overflow-y: auto;
|
|
11063
|
+
}
|
|
11064
|
+
.twm-section-stack > .twm-section-stack__section {
|
|
11065
|
+
display: flex;
|
|
11066
|
+
flex-direction: column;
|
|
11067
|
+
flex: 0 0 auto;
|
|
11068
|
+
min-height: 0;
|
|
11069
|
+
}
|
|
11070
|
+
.twm-section-stack > .twm-section-stack__section[hidden] {
|
|
11071
|
+
display: none;
|
|
11072
|
+
}
|
|
11073
|
+
.twm-section-stack > .twm-section-stack__section--fill.twm-section-stack__section--expanded {
|
|
11074
|
+
flex: 1 1 0;
|
|
11075
|
+
min-height: 26px;
|
|
11076
|
+
}
|
|
11077
|
+
.twm-section-stack__section--fill > .twm-collapsible-content.visible {
|
|
11078
|
+
flex: 1 1 0;
|
|
11079
|
+
min-height: 0;
|
|
11080
|
+
overflow-y: auto;
|
|
11081
|
+
}
|
|
11082
|
+
.twm-section-stack__header {
|
|
11083
|
+
gap: var(--space-xxs);
|
|
11084
|
+
height: 26px;
|
|
11085
|
+
padding: 0 var(--space-xs) 0 0;
|
|
11086
|
+
box-sizing: border-box;
|
|
11087
|
+
flex-shrink: 0;
|
|
11088
|
+
color: var(--text-secondary);
|
|
11089
|
+
}
|
|
11090
|
+
.twm-section-stack__header:hover {
|
|
11091
|
+
background: var(--state-hover);
|
|
11092
|
+
}
|
|
11093
|
+
/* A real button, so Enter and Space toggle without re-implementing them; the
|
|
11094
|
+
* first declarations are the reset that keeps the UA's own button off it. */
|
|
11095
|
+
.twm-section-stack__toggle {
|
|
11096
|
+
appearance: none;
|
|
11097
|
+
background: none;
|
|
11098
|
+
border: 0;
|
|
11099
|
+
color: inherit;
|
|
11100
|
+
font: inherit;
|
|
11101
|
+
text-transform: inherit;
|
|
11102
|
+
text-align: left;
|
|
11103
|
+
cursor: pointer;
|
|
11104
|
+
display: flex;
|
|
11105
|
+
align-items: center;
|
|
11106
|
+
gap: var(--space-xs);
|
|
11107
|
+
flex: 1 1 auto;
|
|
11108
|
+
min-width: 0;
|
|
11109
|
+
height: 100%;
|
|
11110
|
+
padding: 0 0 0 var(--space-xs);
|
|
11111
|
+
}
|
|
11112
|
+
.twm-section-stack__toggle:focus-visible,
|
|
11113
|
+
.twm-section-stack__action:focus-visible {
|
|
11114
|
+
outline: 2px solid var(--accent-bright);
|
|
11115
|
+
outline-offset: -2px;
|
|
8281
11116
|
}
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
11117
|
+
/* The arrow points down while open (`.twm-collapsible-arrow`) and right while
|
|
11118
|
+
* closed — the class `paint()` sets on it. A fixed, clipped box: without the
|
|
11119
|
+
* icon font the glyph is the word `expand_more`, and that word turned on its
|
|
11120
|
+
* side stood taller than the header and made the whole stack scroll. */
|
|
11121
|
+
.twm-section-stack .twm-collapsible-arrow {
|
|
11122
|
+
flex-shrink: 0;
|
|
11123
|
+
width: 12px;
|
|
11124
|
+
height: 12px;
|
|
11125
|
+
line-height: 12px;
|
|
11126
|
+
overflow: hidden;
|
|
8289
11127
|
}
|
|
8290
|
-
.twm-
|
|
8291
|
-
|
|
8292
|
-
font-size: var(--ea-font-small, 10px);
|
|
8293
|
-
font-weight: 600;
|
|
8294
|
-
letter-spacing: 0.06em;
|
|
8295
|
-
text-transform: uppercase;
|
|
8296
|
-
color: var(--text-dim, #666);
|
|
8297
|
-
white-space: nowrap;
|
|
8298
|
-
border-bottom: 1px solid var(--border-default, #303030);
|
|
8299
|
-
padding: 0 12px 6px 0;
|
|
11128
|
+
.twm-section-stack .twm-collapsible-arrow.collapsed {
|
|
11129
|
+
transform: rotate(-90deg);
|
|
8300
11130
|
}
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
text-align: left;
|
|
8305
|
-
font-weight: normal;
|
|
8306
|
-
border-bottom: 1px solid var(--border-subtle, #2a2a2a);
|
|
8307
|
-
padding: 6px 12px 6px 0;
|
|
8308
|
-
color: var(--text-primary, #e0e0e0);
|
|
8309
|
-
vertical-align: top;
|
|
8310
|
-
white-space: pre-wrap;
|
|
8311
|
-
overflow-wrap: anywhere;
|
|
11131
|
+
.twm-section-stack__icon.material-symbols-outlined {
|
|
11132
|
+
font-size: var(--font-size-md);
|
|
11133
|
+
line-height: 1;
|
|
8312
11134
|
}
|
|
8313
|
-
.twm-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
color: var(--text-muted, #888);
|
|
11135
|
+
.twm-section-stack__title {
|
|
11136
|
+
flex: 1 1 auto;
|
|
11137
|
+
min-width: 0;
|
|
8317
11138
|
white-space: nowrap;
|
|
11139
|
+
overflow: hidden;
|
|
11140
|
+
text-overflow: ellipsis;
|
|
8318
11141
|
}
|
|
8319
|
-
.twm-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
.twm-facts.twm-facts--wrap-words tbody th { overflow-wrap: normal; word-break: normal; }
|
|
8325
|
-
.twm-facts.twm-facts--wrap-none tbody td,
|
|
8326
|
-
.twm-facts.twm-facts--wrap-none tbody th { white-space: pre; overflow-wrap: normal; word-break: normal; }
|
|
8327
|
-
.twm-facts.twm-facts--mono tbody td.twm-facts__value,
|
|
8328
|
-
.twm-facts tbody td.twm-facts__mono { font-family: var(--font-family-mono, monospace); font-size: 0.95em; }
|
|
8329
|
-
.twm-facts .twm-facts__num { font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
8330
|
-
.twm-facts tbody td.twm-facts__null,
|
|
8331
|
-
.twm-facts tbody td.twm-facts__missing { color: var(--text-dim, #666); font-style: italic; }
|
|
8332
|
-
.twm-facts tbody td.twm-facts__arrow {
|
|
8333
|
-
color: var(--text-dim, #666);
|
|
8334
|
-
white-space: nowrap;
|
|
8335
|
-
width: 1%;
|
|
11142
|
+
.twm-section-stack__actions {
|
|
11143
|
+
display: flex;
|
|
11144
|
+
align-items: center;
|
|
11145
|
+
gap: var(--space-xxs);
|
|
11146
|
+
flex-shrink: 0;
|
|
8336
11147
|
}
|
|
8337
|
-
.twm-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
11148
|
+
.twm-section-stack__action {
|
|
11149
|
+
appearance: none;
|
|
11150
|
+
background: none;
|
|
11151
|
+
border: 0;
|
|
11152
|
+
color: var(--text-muted);
|
|
11153
|
+
cursor: pointer;
|
|
11154
|
+
display: flex;
|
|
11155
|
+
align-items: center;
|
|
11156
|
+
justify-content: center;
|
|
11157
|
+
width: 20px;
|
|
11158
|
+
height: 20px;
|
|
11159
|
+
padding: 0;
|
|
11160
|
+
border-radius: var(--radius-sm);
|
|
8346
11161
|
}
|
|
8347
|
-
|
|
11162
|
+
.twm-section-stack__action:hover {
|
|
11163
|
+
color: var(--text-primary);
|
|
11164
|
+
background: var(--state-active);
|
|
11165
|
+
}
|
|
11166
|
+
.twm-section-stack__action .material-symbols-outlined {
|
|
11167
|
+
font-size: var(--font-size-md);
|
|
11168
|
+
line-height: 1;
|
|
11169
|
+
}
|
|
11170
|
+
/* ══ end SECTION STACK ══ */
|
|
11171
|
+
|
|
11172
|
+
/* ── The conversation view (conversation_view.js, STORY-0057) ─────────────
|
|
11173
|
+
* A transcript of role-tagged messages above a growing composer. The view
|
|
11174
|
+
* fills its host; the transcript scrolls, the composer stays at the foot. */
|
|
11175
|
+
.twm-chat { display: flex; flex-direction: column; height: 100%; min-height: 0; font-size: var(--font-size-sm); color: var(--text-body); }
|
|
11176
|
+
.twm-chat .material-symbols-outlined { font-size: 18px; line-height: 1; }
|
|
11177
|
+
.twm-chat__viewport { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
|
|
11178
|
+
.twm-chat__log { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--space-md); display: flex; flex-direction: column; gap: var(--space-sm); }
|
|
11179
|
+
.twm-chat__msg { max-width: 85%; padding: var(--space-sm) var(--space-md); border-radius: var(--radius-md); background: var(--surface-1); line-height: var(--line-height-relaxed); overflow-wrap: anywhere; }
|
|
11180
|
+
.twm-chat__msg--user { align-self: flex-end; background: var(--state-selected); }
|
|
11181
|
+
.twm-chat__msg--assistant { align-self: flex-start; }
|
|
11182
|
+
.twm-chat__msg--system { align-self: center; background: none; color: var(--text-muted); font-size: var(--font-size-xs); }
|
|
11183
|
+
.twm-chat__msg--streaming .twm-chat__body::after { content: '\258D'; margin-left: 1px; color: var(--text-muted); }
|
|
11184
|
+
.twm-chat__body--plain { white-space: pre-wrap; }
|
|
11185
|
+
.twm-chat__extra:empty { display: none; }
|
|
11186
|
+
.twm-chat__extra { margin-top: var(--space-sm); }
|
|
11187
|
+
.twm-chat__jump { position: absolute; left: 50%; bottom: var(--space-md); transform: translateX(-50%); display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 12px; border: 1px solid var(--border-default); border-radius: var(--radius-pill); background: var(--surface-2); color: var(--text-body); font: inherit; font-size: var(--font-size-xs); box-shadow: var(--shadow-md); cursor: pointer; }
|
|
11188
|
+
.twm-chat__jump:hover { background: var(--state-hover); }
|
|
11189
|
+
.twm-chat__jump[hidden] { display: none; }
|
|
11190
|
+
.twm-chat__composer { flex: 0 0 auto; display: flex; align-items: flex-end; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); border-top: 1px solid var(--border-subtle); }
|
|
11191
|
+
.twm-chat__input { flex: 1 1 auto; min-height: 30px; box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--surface-3); border-radius: var(--radius-sm); background: var(--surface-1); color: var(--text-body); font: inherit; line-height: var(--line-height-normal); resize: none; overflow-y: hidden; }
|
|
11192
|
+
.twm-chat__input:focus { outline: none; border-color: var(--accent-bright); }
|
|
11193
|
+
.twm-chat__send { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border: 0; border-radius: var(--radius-sm); background: var(--accent); color: var(--text-bright); cursor: pointer; }
|
|
11194
|
+
.twm-chat__send:hover { background: var(--accent-hover); }
|
|
11195
|
+
.twm-chat__send--cancel { background: var(--color-danger); }
|
|
11196
|
+
.twm-chat__send--cancel:hover { background: var(--color-danger-hover); }
|
|
11197
|
+
.twm-chat--busy .twm-chat__input { border-color: var(--border-default); }
|
|
8348
11198
|
|
|
8349
11199
|
/* ══ FLOW · KIT ═══════════════════════════════════════════════════════ */
|
|
8350
11200
|
/* The shared flow-editor kit (36 §3, §3.12): the settings panel and its
|
|
@@ -8572,10 +11422,6 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
8572
11422
|
font-size: var(--font-size-xs);
|
|
8573
11423
|
color: var(--twm-flow-muted);
|
|
8574
11424
|
}
|
|
8575
|
-
.twm-flow-field__kept {
|
|
8576
|
-
font-family: var(--font-family-mono);
|
|
8577
|
-
color: var(--text-secondary);
|
|
8578
|
-
}
|
|
8579
11425
|
.twm-flow-field__refusal {
|
|
8580
11426
|
margin: 0;
|
|
8581
11427
|
padding: 6px 8px;
|
|
@@ -8808,6 +11654,30 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
8808
11654
|
outline-offset: 1px;
|
|
8809
11655
|
}
|
|
8810
11656
|
|
|
11657
|
+
/* ── a column typed by name, while the columns are not known ─────────── */
|
|
11658
|
+
.twm-flow-field__typed {
|
|
11659
|
+
display: flex;
|
|
11660
|
+
flex-direction: column;
|
|
11661
|
+
min-width: 0;
|
|
11662
|
+
}
|
|
11663
|
+
.twm-flow-typedchips:focus-within {
|
|
11664
|
+
border-color: var(--twm-flow-focus);
|
|
11665
|
+
}
|
|
11666
|
+
.twm-flow-input.twm-flow-typedchips__input {
|
|
11667
|
+
flex: 1 1 8em;
|
|
11668
|
+
width: auto;
|
|
11669
|
+
min-width: 6em;
|
|
11670
|
+
height: 18px;
|
|
11671
|
+
padding: 0 2px;
|
|
11672
|
+
border: 0;
|
|
11673
|
+
background: transparent;
|
|
11674
|
+
font-size: var(--font-size-xs);
|
|
11675
|
+
}
|
|
11676
|
+
.twm-flow-input.twm-flow-typedchips__input:focus {
|
|
11677
|
+
outline: none;
|
|
11678
|
+
box-shadow: none;
|
|
11679
|
+
}
|
|
11680
|
+
|
|
8811
11681
|
/* ── choice-cards ───────────────────────────────────────────────────── */
|
|
8812
11682
|
.twm-flow-choices {
|
|
8813
11683
|
display: flex;
|
|
@@ -9316,6 +12186,21 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
9316
12186
|
color: var(--twm-flow-blue-fg);
|
|
9317
12187
|
border-bottom: 1px solid var(--twm-flow-blue-line);
|
|
9318
12188
|
}
|
|
12189
|
+
/* A host policy's offer: its sentence, Accept and Not now, on one line. */
|
|
12190
|
+
.twm-flow-graph__offer {
|
|
12191
|
+
display: flex;
|
|
12192
|
+
flex-wrap: wrap;
|
|
12193
|
+
align-items: center;
|
|
12194
|
+
gap: 6px 8px;
|
|
12195
|
+
padding: 4px 10px;
|
|
12196
|
+
font-size: var(--font-size-xs);
|
|
12197
|
+
background: var(--twm-flow-blue-bg);
|
|
12198
|
+
color: var(--twm-flow-blue-fg);
|
|
12199
|
+
border-bottom: 1px solid var(--twm-flow-blue-line);
|
|
12200
|
+
}
|
|
12201
|
+
.twm-flow-graph__offer-text { margin: 0; flex: 1 1 200px; min-width: 0; line-height: 1.4; }
|
|
12202
|
+
.twm-flow-graph__offer-accept,
|
|
12203
|
+
.twm-flow-graph__offer-dismiss { flex: 0 0 auto; }
|
|
9319
12204
|
|
|
9320
12205
|
/* Three columns; the CANVAS is the one that flexes — `flex: 1 1 0px` AND
|
|
9321
12206
|
* `min-width: 0`, or an open settings panel squeezes the palette instead. */
|
|
@@ -9387,6 +12272,8 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
9387
12272
|
}
|
|
9388
12273
|
.twm-flow-graph__canvas { position: relative; flex: 1 1 0px; min-width: 0; min-height: 0; }
|
|
9389
12274
|
.twm-flow-graph__canvas--drop { outline: 2px dashed var(--twm-flow-focus); outline-offset: -2px; }
|
|
12275
|
+
/* Where a dragged line was let go: what the step picker is anchored to. */
|
|
12276
|
+
.twm-flow-graph__drop-anchor { position: absolute; width: 1px; height: 1px; pointer-events: none; }
|
|
9390
12277
|
.twm-flow-graph__aside {
|
|
9391
12278
|
flex: 0 0 300px;
|
|
9392
12279
|
min-width: 0;
|
|
@@ -9518,6 +12405,168 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
9518
12405
|
.twm-flow-graph__node-run[data-state="skipped"],
|
|
9519
12406
|
.twm-flow-graph__node-run[data-state="cancelled"],
|
|
9520
12407
|
.twm-flow-graph__node-run[data-state="not-reached"] { font-style: italic; }
|
|
12408
|
+
/* A TYPE'S OWN BODY, below its ports (a catalogue type's `render`). It adds
|
|
12409
|
+
* height under the rows and moves nothing above them, so the lines' arithmetic
|
|
12410
|
+
* stands. A type with `size.h` is exactly that tall: its body takes what is
|
|
12411
|
+
* left and clips (the node itself never does: its port dots stand out of it).
|
|
12412
|
+
* An `accent` is a stripe over the header, drawn on top of the box so it takes
|
|
12413
|
+
* no height. */
|
|
12414
|
+
.twm-flow-graph__node-body { box-sizing: border-box; padding: 4px 8px 6px; min-width: 0; }
|
|
12415
|
+
.twm-flow-graph__node--sized { display: flex; flex-direction: column; }
|
|
12416
|
+
.twm-flow-graph__node--sized > .twm-flow-graph__node-head,
|
|
12417
|
+
.twm-flow-graph__node--sized > .twm-flow-graph__node-row { flex: none; }
|
|
12418
|
+
.twm-flow-graph__node--sized > .twm-flow-graph__node-body { flex: 1 1 auto; min-height: 0; overflow: hidden; }
|
|
12419
|
+
/* EDITED ON THE NODE (`renameInPlace`, a type's `inline`). The title's box
|
|
12420
|
+
* takes the title's place in the header, as tall as the name was; the inline
|
|
12421
|
+
* settings sit under the ports, above a type's own body, and add height there
|
|
12422
|
+
* only, so the lines' arithmetic stands. */
|
|
12423
|
+
.twm-flow-graph__node-title-input {
|
|
12424
|
+
flex: 1 1 auto;
|
|
12425
|
+
min-width: 0;
|
|
12426
|
+
box-sizing: border-box;
|
|
12427
|
+
height: 22px;
|
|
12428
|
+
padding: 0 4px;
|
|
12429
|
+
background: var(--surface-1);
|
|
12430
|
+
border: 1px solid var(--twm-flow-focus);
|
|
12431
|
+
border-radius: 2px;
|
|
12432
|
+
color: var(--text-body);
|
|
12433
|
+
font: inherit;
|
|
12434
|
+
cursor: text;
|
|
12435
|
+
user-select: text;
|
|
12436
|
+
}
|
|
12437
|
+
.twm-flow-graph__node-title-input[aria-invalid="true"] { border-color: var(--twm-flow-error); }
|
|
12438
|
+
.twm-flow-graph__node-inline { box-sizing: border-box; display: grid; gap: 4px; padding: 4px 8px 6px; min-width: 0; cursor: default; }
|
|
12439
|
+
.twm-flow-graph__node--sized > .twm-flow-graph__node-inline { flex: none; }
|
|
12440
|
+
.twm-flow-graph__node[data-accent]::before {
|
|
12441
|
+
content: "";
|
|
12442
|
+
position: absolute;
|
|
12443
|
+
top: 0;
|
|
12444
|
+
left: 0;
|
|
12445
|
+
right: 0;
|
|
12446
|
+
height: 3px;
|
|
12447
|
+
border-radius: 3px 3px 0 0;
|
|
12448
|
+
pointer-events: none;
|
|
12449
|
+
}
|
|
12450
|
+
.twm-flow-graph__node[data-accent="violet"]::before { background: var(--twm-flow-violet-fg); }
|
|
12451
|
+
.twm-flow-graph__node[data-accent="teal"]::before { background: var(--twm-flow-teal-fg); }
|
|
12452
|
+
.twm-flow-graph__node[data-accent="amber"]::before { background: var(--twm-flow-amber-fg); }
|
|
12453
|
+
.twm-flow-graph__node[data-accent="grey"]::before { background: var(--twm-flow-grey-fg); }
|
|
12454
|
+
.twm-flow-graph__node[data-accent="blue"]::before { background: var(--twm-flow-blue-fg); }
|
|
12455
|
+
.twm-flow-graph__node[data-accent="indigo"]::before { background: var(--twm-flow-indigo-fg); }
|
|
12456
|
+
|
|
12457
|
+
/* ── a group and a note (`groups`, `notes`) ─────────────────────────── */
|
|
12458
|
+
/* A GROUP IS A FRAME BEHIND ITS NODES (first in the node layer). Its body
|
|
12459
|
+
* takes no pointer, so a press inside it between the nodes is the canvas's
|
|
12460
|
+
* (a marquee, a pan); its title bar is the handle that drags the members. */
|
|
12461
|
+
.twm-flow-graph__group {
|
|
12462
|
+
position: absolute;
|
|
12463
|
+
box-sizing: border-box;
|
|
12464
|
+
border: 1px dashed var(--border-strong);
|
|
12465
|
+
border-radius: 6px;
|
|
12466
|
+
background: rgba(255, 255, 255, 0.03);
|
|
12467
|
+
pointer-events: none;
|
|
12468
|
+
}
|
|
12469
|
+
.twm-flow-graph__group-head {
|
|
12470
|
+
box-sizing: border-box;
|
|
12471
|
+
height: 26px;
|
|
12472
|
+
display: flex;
|
|
12473
|
+
align-items: center;
|
|
12474
|
+
padding: 0 8px;
|
|
12475
|
+
border-radius: 6px 6px 0 0;
|
|
12476
|
+
background: var(--twm-flow-grey-bg);
|
|
12477
|
+
color: var(--twm-flow-grey-fg);
|
|
12478
|
+
font-size: var(--font-size-xs);
|
|
12479
|
+
font-weight: 600;
|
|
12480
|
+
cursor: move;
|
|
12481
|
+
pointer-events: auto;
|
|
12482
|
+
user-select: none;
|
|
12483
|
+
}
|
|
12484
|
+
.twm-flow-graph__group-label { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
12485
|
+
.twm-flow-graph__group-label--untitled { font-style: italic; font-weight: 400; }
|
|
12486
|
+
.twm-flow-graph__group-input { flex: 1 1 auto; min-width: 0; font: inherit; }
|
|
12487
|
+
.twm-flow-graph__group[data-tone="violet"] { border-color: var(--twm-flow-violet-fg); }
|
|
12488
|
+
.twm-flow-graph__group[data-tone="teal"] { border-color: var(--twm-flow-teal-fg); }
|
|
12489
|
+
.twm-flow-graph__group[data-tone="amber"] { border-color: var(--twm-flow-amber-fg); }
|
|
12490
|
+
.twm-flow-graph__group[data-tone="grey"] { border-color: var(--twm-flow-grey-fg); }
|
|
12491
|
+
.twm-flow-graph__group[data-tone="blue"] { border-color: var(--twm-flow-blue-fg); }
|
|
12492
|
+
.twm-flow-graph__group[data-tone="indigo"] { border-color: var(--twm-flow-indigo-fg); }
|
|
12493
|
+
.twm-flow-graph__group[data-tone="violet"] > .twm-flow-graph__group-head { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
|
|
12494
|
+
.twm-flow-graph__group[data-tone="teal"] > .twm-flow-graph__group-head { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
|
|
12495
|
+
.twm-flow-graph__group[data-tone="amber"] > .twm-flow-graph__group-head { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
|
|
12496
|
+
.twm-flow-graph__group[data-tone="blue"] > .twm-flow-graph__group-head { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
|
|
12497
|
+
.twm-flow-graph__group[data-tone="indigo"] > .twm-flow-graph__group-head { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
|
|
12498
|
+
/* A NOTE is free text on the canvas, its height its text's unless it has a size. */
|
|
12499
|
+
.twm-flow-graph__note {
|
|
12500
|
+
position: absolute;
|
|
12501
|
+
box-sizing: border-box;
|
|
12502
|
+
padding: 8px 10px;
|
|
12503
|
+
background: var(--twm-flow-amber-bg);
|
|
12504
|
+
border: 1px solid var(--border-strong);
|
|
12505
|
+
border-radius: 4px;
|
|
12506
|
+
color: var(--text-body);
|
|
12507
|
+
font-size: var(--font-size-xs);
|
|
12508
|
+
cursor: move;
|
|
12509
|
+
overflow: hidden;
|
|
12510
|
+
outline: none;
|
|
12511
|
+
}
|
|
12512
|
+
.twm-flow-graph__note:focus-visible { box-shadow: 0 0 0 2px var(--twm-flow-focus); }
|
|
12513
|
+
.twm-flow-graph__note--picked { border-color: var(--twm-flow-focus); box-shadow: 0 0 0 1px var(--twm-flow-focus); }
|
|
12514
|
+
.twm-flow-graph__note-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
12515
|
+
.twm-flow-graph__note-text--empty { color: var(--text-muted); font-style: italic; }
|
|
12516
|
+
.twm-flow-graph__note-input {
|
|
12517
|
+
box-sizing: border-box;
|
|
12518
|
+
width: 100%;
|
|
12519
|
+
min-height: 4em;
|
|
12520
|
+
resize: vertical;
|
|
12521
|
+
font: inherit;
|
|
12522
|
+
cursor: text;
|
|
12523
|
+
}
|
|
12524
|
+
/* LIVE VALUES (`setNodeValues`): a value on the header, before the step's id
|
|
12525
|
+
* tag, and one beside a port. Neither element exists until there is a value. */
|
|
12526
|
+
.twm-flow-graph__node-badge {
|
|
12527
|
+
flex: none;
|
|
12528
|
+
max-width: 40%;
|
|
12529
|
+
padding: 1px 5px;
|
|
12530
|
+
overflow: hidden;
|
|
12531
|
+
text-overflow: ellipsis;
|
|
12532
|
+
white-space: nowrap;
|
|
12533
|
+
font-size: var(--font-size-xs);
|
|
12534
|
+
font-weight: 600;
|
|
12535
|
+
font-variant-numeric: tabular-nums;
|
|
12536
|
+
color: var(--text-body);
|
|
12537
|
+
background: rgba(127, 127, 127, 0.18);
|
|
12538
|
+
border-radius: 2px;
|
|
12539
|
+
}
|
|
12540
|
+
.twm-flow-graph__node-badge[data-tone="violet"] { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
|
|
12541
|
+
.twm-flow-graph__node-badge[data-tone="teal"] { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
|
|
12542
|
+
.twm-flow-graph__node-badge[data-tone="amber"] { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
|
|
12543
|
+
.twm-flow-graph__node-badge[data-tone="grey"] { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
|
|
12544
|
+
.twm-flow-graph__node-badge[data-tone="blue"] { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
|
|
12545
|
+
.twm-flow-graph__node-badge[data-tone="indigo"] { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
|
|
12546
|
+
.twm-flow-graph__port-value { color: var(--twm-flow-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
12547
|
+
|
|
12548
|
+
/* FOLDED TO ITS HEADER (`collapsible`): everything under the header is hidden,
|
|
12549
|
+
* and the lines meet the header's middle. */
|
|
12550
|
+
.twm-flow-graph__node-fold {
|
|
12551
|
+
flex: none;
|
|
12552
|
+
display: inline-flex;
|
|
12553
|
+
align-items: center;
|
|
12554
|
+
justify-content: center;
|
|
12555
|
+
width: 20px;
|
|
12556
|
+
height: 20px;
|
|
12557
|
+
padding: 0;
|
|
12558
|
+
background: none;
|
|
12559
|
+
border: 0;
|
|
12560
|
+
border-radius: 3px;
|
|
12561
|
+
color: var(--twm-flow-muted);
|
|
12562
|
+
cursor: pointer;
|
|
12563
|
+
}
|
|
12564
|
+
.twm-flow-graph__node-fold .material-symbols-outlined { font-size: 16px; }
|
|
12565
|
+
.twm-flow-graph__node-fold:hover:not(:disabled) { color: var(--text-body); background: rgba(127, 127, 127, 0.18); }
|
|
12566
|
+
.twm-flow-graph__node-fold:focus-visible { outline: 1px solid var(--twm-flow-focus); }
|
|
12567
|
+
.twm-flow-graph__node-fold:disabled { cursor: default; opacity: 0.5; }
|
|
12568
|
+
.twm-flow-graph__node--collapsed > :not(.twm-flow-graph__node-head) { display: none; }
|
|
12569
|
+
.twm-flow-graph__node--collapsed > .twm-flow-graph__node-head { border-bottom: 0; border-radius: 3px; }
|
|
9521
12570
|
|
|
9522
12571
|
/* ── a port ─────────────────────────────────────────────────────────── */
|
|
9523
12572
|
.twm-flow-graph__port {
|
|
@@ -9559,16 +12608,53 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
9559
12608
|
.twm-flow-graph__port--taken .twm-flow-graph__port-dot { border-color: var(--twm-flow-ok); background: var(--twm-flow-ok); }
|
|
9560
12609
|
.twm-flow-graph__port--taken .twm-flow-graph__port-count { color: var(--twm-flow-ok); }
|
|
9561
12610
|
.twm-flow-graph__port--untaken { opacity: 0.5; }
|
|
12611
|
+
/* Under `connections` only the inputs the line may end on are lit. */
|
|
12612
|
+
.twm-flow-graph--linking.twm-flow-graph--connecting .twm-flow-graph__port--in:not(.twm-flow-graph__port--can-drop) .twm-flow-graph__port-dot {
|
|
12613
|
+
background: transparent;
|
|
12614
|
+
box-shadow: none;
|
|
12615
|
+
}
|
|
12616
|
+
.twm-flow-graph__port--can-drop .twm-flow-graph__port-dot {
|
|
12617
|
+
background: var(--twm-flow-focus);
|
|
12618
|
+
box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.35);
|
|
12619
|
+
}
|
|
9562
12620
|
|
|
9563
12621
|
/* ── a line ─────────────────────────────────────────────────────────── */
|
|
9564
|
-
|
|
9565
|
-
|
|
12622
|
+
/* A consumer's `edgeStyle` sets a line's tone and width as the two custom
|
|
12623
|
+
* properties below (unset, the line is drawn as it always was); a picked or
|
|
12624
|
+
* highlighted line still wins over them. */
|
|
12625
|
+
.twm-flow-graph__edge { fill: none; stroke: var(--twm-canvas-edge-stroke, #8fb4d8); stroke-width: var(--twm-canvas-edge-width, 1.6); }
|
|
12626
|
+
.twm-flow-graph__edge--picked { stroke: var(--twm-flow-focus); stroke-width: calc(var(--twm-canvas-edge-width, 1.6) + 0.8); }
|
|
9566
12627
|
/* A loop's body handing back to the loop: DASHED, and routed under both steps
|
|
9567
12628
|
* by the kernel's `returnEdge`, so it reads as "round again", not as one more
|
|
9568
12629
|
* step forward. */
|
|
9569
12630
|
.twm-flow-graph__edge--back { stroke-dasharray: 6 4; }
|
|
9570
12631
|
.twm-flow-graph__edge--taken { stroke: var(--twm-flow-ok); }
|
|
9571
12632
|
.twm-flow-graph__edge--untaken { opacity: 0.35; }
|
|
12633
|
+
/* The line a drag is drawing: dashed, and never what the release lands on. */
|
|
12634
|
+
.twm-flow-graph__edge--draft { stroke: var(--twm-flow-focus); stroke-dasharray: 4 3; pointer-events: none; }
|
|
12635
|
+
/* `edgeStyle`'s dash, and the lines of a hovered step or line (`hoverHighlight`). */
|
|
12636
|
+
.twm-flow-graph__edge--dashed { stroke-dasharray: 6 4; }
|
|
12637
|
+
.twm-flow-graph__edge--highlighted { stroke: var(--twm-flow-focus); stroke-width: calc(var(--twm-canvas-edge-width, 1.6) + 0.8); }
|
|
12638
|
+
/* `edgeStyle`'s marker at the input end: an arrowhead, or the kernel's crow's
|
|
12639
|
+
* foot in the line's own tone. */
|
|
12640
|
+
.twm-flow-graph__edge-arrow { fill: var(--twm-canvas-edge-stroke, #8fb4d8); stroke: none; }
|
|
12641
|
+
.twm-flow-graph__edge-foot line, .twm-flow-graph__edge-foot circle { stroke: var(--twm-canvas-edge-stroke, #8fb4d8); }
|
|
12642
|
+
/* `edgeStyle`'s label, centred on the line's midpoint. Its layer sits in the
|
|
12643
|
+
* node layer and is stacked ABOVE every node, so a step never hides it. */
|
|
12644
|
+
.twm-flow-graph__edge-labels { position: absolute; left: 0; top: 0; z-index: 1; }
|
|
12645
|
+
.twm-flow-graph__edge-label {
|
|
12646
|
+
position: absolute;
|
|
12647
|
+
transform: translate(-50%, -50%);
|
|
12648
|
+
padding: 1px 6px;
|
|
12649
|
+
border: 1px solid var(--twm-canvas-edge-stroke, #8fb4d8);
|
|
12650
|
+
border-radius: 8px;
|
|
12651
|
+
background: var(--surface-2);
|
|
12652
|
+
color: var(--text-body);
|
|
12653
|
+
font-size: var(--font-size-xs);
|
|
12654
|
+
line-height: 1.4;
|
|
12655
|
+
white-space: nowrap;
|
|
12656
|
+
cursor: pointer;
|
|
12657
|
+
}
|
|
9572
12658
|
/* The 14px target a 1.6px line cannot be. It opts back into the pointer the
|
|
9573
12659
|
* edge layer turns off. */
|
|
9574
12660
|
.twm-flow-graph__edge-hit { fill: none; stroke: transparent; stroke-width: 14; pointer-events: stroke; cursor: pointer; }
|
|
@@ -9595,6 +12681,26 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
9595
12681
|
}
|
|
9596
12682
|
.twm-flow-graph__ghost .material-symbols-outlined { font-size: 16px; }
|
|
9597
12683
|
.twm-flow-graph__ghost-label { white-space: nowrap; }
|
|
12684
|
+
/* ── the minimap (`minimap: true`) ──────────────────────────────────── */
|
|
12685
|
+
/* Over the canvas's lower right corner, a sibling of the kernel's surface, so a
|
|
12686
|
+
* press on it starts no pan and no marquee. The steps are drawn as boxes and
|
|
12687
|
+
* the view as a frame; a click centres the view there. */
|
|
12688
|
+
.twm-flow-graph__minimap {
|
|
12689
|
+
position: absolute;
|
|
12690
|
+
right: 12px;
|
|
12691
|
+
bottom: 12px;
|
|
12692
|
+
z-index: 1;
|
|
12693
|
+
line-height: 0;
|
|
12694
|
+
background: var(--surface-1);
|
|
12695
|
+
border: 1px solid var(--border-default);
|
|
12696
|
+
border-radius: 4px;
|
|
12697
|
+
box-shadow: var(--shadow-md);
|
|
12698
|
+
cursor: pointer;
|
|
12699
|
+
opacity: 0.92;
|
|
12700
|
+
}
|
|
12701
|
+
.twm-flow-graph__minimap-map { display: block; }
|
|
12702
|
+
.twm-flow-graph__minimap-node { fill: var(--border-strong); }
|
|
12703
|
+
.twm-flow-graph__minimap-view { fill: none; stroke: var(--twm-flow-focus); stroke-width: 1.5px; }
|
|
9598
12704
|
/* ══ end FLOW · CANVAS ══ */
|
|
9599
12705
|
|
|
9600
12706
|
|
|
@@ -11178,4 +14284,33 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
11178
14284
|
font-size: 16px;
|
|
11179
14285
|
line-height: 1;
|
|
11180
14286
|
}
|
|
14287
|
+
.twm-flow-lanes__menu-item.twm-flow-lanes__menu-item--refused {
|
|
14288
|
+
height: auto;
|
|
14289
|
+
min-height: 28px;
|
|
14290
|
+
padding-top: 4px;
|
|
14291
|
+
padding-bottom: 4px;
|
|
14292
|
+
}
|
|
14293
|
+
.twm-flow-lanes__menu-words {
|
|
14294
|
+
display: flex;
|
|
14295
|
+
flex-direction: column;
|
|
14296
|
+
min-width: 0;
|
|
14297
|
+
}
|
|
14298
|
+
.twm-flow-lanes__menu-label {
|
|
14299
|
+
white-space: nowrap;
|
|
14300
|
+
}
|
|
14301
|
+
.twm-flow-lanes__menu-reason {
|
|
14302
|
+
max-width: 280px;
|
|
14303
|
+
font-size: var(--font-size-xs);
|
|
14304
|
+
white-space: normal;
|
|
14305
|
+
}
|
|
14306
|
+
.twm-flow-lanes__menu-sep {
|
|
14307
|
+
height: 1px;
|
|
14308
|
+
margin: 4px 6px;
|
|
14309
|
+
background: var(--border-subtle);
|
|
14310
|
+
}
|
|
14311
|
+
.twm-flow-lanes__notice {
|
|
14312
|
+
margin-left: 8px;
|
|
14313
|
+
color: var(--twm-flow-warning);
|
|
14314
|
+
font-size: var(--font-size-xs);
|
|
14315
|
+
}
|
|
11181
14316
|
/* ══ end FLOW · LANES ══ */
|