@scattered-light/loomiere-mojave 0.25.0 → 0.41.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.
Files changed (45) hide show
  1. package/dist/exports/AGENTS.md +1 -1
  2. package/dist/exports/base-ui.css +5574 -0
  3. package/dist/exports/base-ui.md +535 -0
  4. package/dist/exports/catalog.json +28 -0
  5. package/dist/exports/design-system/README.md +1 -1
  6. package/dist/exports/design-system/components/Badge/README.md +1 -1
  7. package/dist/exports/design-system/components/Badge/preview.html +43 -43
  8. package/dist/exports/design-system/components/ChecklistNotice/README.md +8 -4
  9. package/dist/exports/design-system/components/ChecklistNotice/preview.html +71 -71
  10. package/dist/exports/design-system/components/ChipPicker/README.md +43 -0
  11. package/dist/exports/design-system/components/ChipPicker/preview.html +475 -0
  12. package/dist/exports/design-system/components/DataTable/README.md +7 -1
  13. package/dist/exports/design-system/components/DataTable/preview.html +202 -202
  14. package/dist/exports/design-system/components/EmptyState/README.md +1 -1
  15. package/dist/exports/design-system/components/FileDropZone/README.md +38 -0
  16. package/dist/exports/design-system/components/FileDropZone/preview.html +19 -0
  17. package/dist/exports/design-system/components/LineItemGrid/README.md +7 -4
  18. package/dist/exports/design-system/components/LineItemGrid/preview.html +154 -154
  19. package/dist/exports/design-system/components/MultiSelect/README.md +8 -2
  20. package/dist/exports/design-system/components/MultiSelect/preview.html +2 -2
  21. package/dist/exports/design-system/components/Notice/README.md +6 -2
  22. package/dist/exports/design-system/components/Notice/preview.html +2 -2
  23. package/dist/exports/design-system/components/RadioCard/README.md +43 -0
  24. package/dist/exports/design-system/components/RadioCard/preview.html +19 -0
  25. package/dist/exports/design-system/components/Shortcuts/README.md +80 -0
  26. package/dist/exports/design-system/components/Shortcuts/preview.html +19 -0
  27. package/dist/exports/design-system/components/SourcePreview/README.md +45 -0
  28. package/dist/exports/design-system/components/SourcePreview/preview.html +19 -0
  29. package/dist/exports/design-system/components/SplitButton/README.md +2 -1
  30. package/dist/exports/design-system/components/SplitButton/preview.html +2 -2
  31. package/dist/exports/design-system/components/StatBand/README.md +34 -0
  32. package/dist/exports/design-system/components/StatBand/preview.html +475 -0
  33. package/dist/exports/design-system/components/Stepper/README.md +34 -0
  34. package/dist/exports/design-system/components/Stepper/preview.html +19 -0
  35. package/dist/exports/design-system/components/SummaryStrip/README.md +36 -0
  36. package/dist/exports/design-system/components/SummaryStrip/preview.html +19 -0
  37. package/dist/exports/design-system/components/Table/README.md +2 -1
  38. package/dist/exports/design-system/components/Tabs/README.md +2 -1
  39. package/dist/exports/design-system/components/Tabs/preview.html +1 -1
  40. package/dist/exports/design-system/components/Text/README.md +29 -0
  41. package/dist/exports/design-system/components/Text/preview.html +19 -0
  42. package/dist/exports/design-system/components/bundle.css +2229 -414
  43. package/dist/exports/design-system/components/bundle.js +7 -7
  44. package/dist/exports/design-system/components/index.d.ts +5 -3
  45. package/package.json +2 -2
@@ -6733,7 +6733,7 @@
6733
6733
  }
6734
6734
 
6735
6735
 
6736
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
6736
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
6737
6737
  /* Loomiere for Base UI: component styles. Brand-free: every value is a --sl- variable from a
6738
6738
  Loomiere theme. Load the theme first:
6739
6739
  @import '<your theme>/tokens.css';
@@ -6743,7 +6743,7 @@
6743
6743
  /* Document defaults, in the reset layer so any unlayered rule wins over them, and so layered
6744
6744
  frameworks (Chakra's recipes, Tailwind's utilities) are not undone by them. */
6745
6745
  @layer reset {
6746
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
6746
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
6747
6747
  /* CSS Reset - Mojave Theme */
6748
6748
 
6749
6749
  /* ============================================
@@ -7187,7 +7187,7 @@ hr {
7187
7187
  }
7188
7188
  }
7189
7189
  @layer reset {
7190
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7190
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7191
7191
  /* Accessibility — base rules (no theme color dependencies). Theme-specific focus/invalid: accessibility-theme.css */
7192
7192
 
7193
7193
  /* Remove default focus; keyboard focus styled in accessibility-theme.css */
@@ -7300,7 +7300,7 @@ main:focus {
7300
7300
 
7301
7301
  }
7302
7302
  @layer reset {
7303
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7303
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7304
7304
  /* Focus, invalid, contrast — requires theme tokens (after theme-accessibility.css). */
7305
7305
 
7306
7306
  :focus-visible {
@@ -7368,7 +7368,7 @@ button,
7368
7368
 
7369
7369
  }
7370
7370
  /* Component styles */
7371
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7371
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7372
7372
  /* Accordion - Mojave Theme
7373
7373
  *
7374
7374
  * No component tokens. Hover, press, chevron, divider and motion are the disclosure
@@ -7489,7 +7489,7 @@ button,
7489
7489
  overflow: hidden;
7490
7490
  }
7491
7491
 
7492
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7492
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7493
7493
  /* Alert Dialog - Mojave Theme
7494
7494
  *
7495
7495
  * No component tokens and no rules of its own. An alert dialog looks exactly like a
@@ -7498,7 +7498,7 @@ button,
7498
7498
  * cancel quiet, and a destructive one bold with data-color="error".
7499
7499
  */
7500
7500
 
7501
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7501
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7502
7502
  /* Autocomplete - Mojave Theme
7503
7503
  *
7504
7504
  * No component tokens. The input is Input (Input.css), the clear button is an icon
@@ -7700,7 +7700,7 @@ button,
7700
7700
  (reset-accessibility.css).
7701
7701
  ============================================ */
7702
7702
 
7703
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7703
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7704
7704
  /* Avatar - Mojave Theme
7705
7705
  *
7706
7706
  * A round picture with a ring in the page color, so avatars in a group cut out of each other in
@@ -7808,7 +7808,7 @@ button,
7808
7808
  }
7809
7809
  }
7810
7810
 
7811
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7811
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7812
7812
  /* Button - Mojave Theme
7813
7813
  *
7814
7814
  * Colors are the brand's emphasis levels, sizes are control.*, text is the trigger
@@ -7979,7 +7979,7 @@ button,
7979
7979
  font-size: var(--sl-icon-size-maximize);
7980
7980
  }
7981
7981
 
7982
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
7982
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
7983
7983
  /* Checkbox - Mojave Theme
7984
7984
  * Sizes follow the label: the box is the icon size one tier above the label's text
7985
7985
  * tier (like a button's icon) and the check mark one tier below it.
@@ -8136,7 +8136,7 @@ button,
8136
8136
  border-radius: var(--sl-radius-pill);
8137
8137
  }
8138
8138
 
8139
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
8139
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
8140
8140
  /* Checkbox Group - Mojave Theme */
8141
8141
 
8142
8142
  /* Each checkbox row is already a full tap target tall, so the rows sit close. */
@@ -8152,7 +8152,7 @@ button,
8152
8152
  pointer-events: none;
8153
8153
  }
8154
8154
 
8155
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
8155
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
8156
8156
  /* Collapsible - Mojave Theme
8157
8157
  *
8158
8158
  * No component tokens. Hover, press, chevron and motion are the disclosure concept
@@ -8268,7 +8268,7 @@ button,
8268
8268
  background: var(--sl-surface-raised);
8269
8269
  }
8270
8270
 
8271
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
8271
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
8272
8272
  /* Combobox - Mojave Theme
8273
8273
  *
8274
8274
  * No component tokens. The input is Input (Input.css); the chips box is a field; the
@@ -8753,7 +8753,7 @@ button,
8753
8753
  color: var(--sl-text-tertiary);
8754
8754
  }
8755
8755
 
8756
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
8756
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
8757
8757
  /* Context Menu - Mojave Theme
8758
8758
  *
8759
8759
  * No component tokens. Opens on right-click; the trigger area only sets the cursor. The popup is the popup concept, rows are item rows at the
@@ -8922,7 +8922,7 @@ button,
8922
8922
  stroke-width: var(--sl-stroke-default);
8923
8923
  }
8924
8924
 
8925
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
8925
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
8926
8926
  /* Dialog and Alert dialog - Mojave Theme
8927
8927
  *
8928
8928
  * Both are centered modals built from the modal concept (tokens/semantic/modal.json):
@@ -9068,7 +9068,7 @@ button,
9068
9068
  margin-top: var(--sl-modal-actions-spacing);
9069
9069
  }
9070
9070
 
9071
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9071
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9072
9072
  /* Drawer - a panel that slides in from an edge and can be swiped away.
9073
9073
  The surface, scrim, heading and motion are the modal concept's (--sl-modal-*), so a
9074
9074
  drawer reads as a dialog's sibling; only its size and grab bar are its own
@@ -9201,7 +9201,7 @@ button,
9201
9201
  color: var(--sl-modal-description-color);
9202
9202
  }
9203
9203
 
9204
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9204
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9205
9205
  /* Field - Mojave Theme
9206
9206
  *
9207
9207
  * Label, control, description and error. No component tokens: spacing is the field
@@ -9262,7 +9262,7 @@ textarea.FieldControl {
9262
9262
  height: auto;
9263
9263
  }
9264
9264
 
9265
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9265
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9266
9266
  /* Fieldset - Mojave Theme
9267
9267
  *
9268
9268
  * No component tokens: a titled group of fields, spaced by the stack gaps, with
@@ -9304,7 +9304,7 @@ textarea.FieldControl {
9304
9304
  color: var(--sl-text-secondary);
9305
9305
  }
9306
9306
 
9307
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9307
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9308
9308
  /* Form - Mojave Theme
9309
9309
  *
9310
9310
  * No component tokens: fields stack with the large block space, and the action
@@ -9324,7 +9324,7 @@ textarea.FieldControl {
9324
9324
  margin-top: var(--sl-space-block-md);
9325
9325
  }
9326
9326
 
9327
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9327
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9328
9328
  /* Input - Mojave Theme
9329
9329
  *
9330
9330
  * No component tokens: the look is the field concept (tokens/semantic/field.json),
@@ -9471,7 +9471,7 @@ textarea.FieldControl {
9471
9471
  padding-inline: var(--sl-control-padding-inline-lg);
9472
9472
  }
9473
9473
 
9474
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9474
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9475
9475
  /* Menu - Mojave Theme
9476
9476
  *
9477
9477
  * No component tokens. The trigger is a Button. The popup is the popup concept, rows are item rows at the
@@ -9620,7 +9620,7 @@ textarea.FieldControl {
9620
9620
  color: var(--sl-text-tertiary);
9621
9621
  }
9622
9622
 
9623
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9623
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9624
9624
  /* Menubar - Mojave Theme
9625
9625
  *
9626
9626
  * No component tokens. A row of quiet triggers, each opening a menu. The popup is the popup concept, rows are item rows at the
@@ -9813,7 +9813,7 @@ textarea.FieldControl {
9813
9813
  color: var(--sl-text-tertiary);
9814
9814
  }
9815
9815
 
9816
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9816
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9817
9817
  /* Meter - Mojave Theme
9818
9818
  *
9819
9819
  * A gauge (tokens/semantic/gauge.json). The fill is the solid color of the scope around it:
@@ -9876,7 +9876,7 @@ textarea.FieldControl {
9876
9876
  height: var(--sl-gauge-height-lg);
9877
9877
  }
9878
9878
 
9879
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
9879
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
9880
9880
  /* Navigation Menu - Mojave Theme
9881
9881
  *
9882
9882
  * The strip is the bar concept, the panel is the popup concept and each link is an item
@@ -10296,7 +10296,7 @@ textarea.FieldControl {
10296
10296
  width: 100%;
10297
10297
  }
10298
10298
 
10299
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10299
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10300
10300
  /* Number Field - Mojave Theme
10301
10301
  *
10302
10302
  * No component tokens. The input is Input (Input.css) and the label, description and
@@ -10387,7 +10387,7 @@ textarea.FieldControl {
10387
10387
  user-select: none;
10388
10388
  }
10389
10389
 
10390
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10390
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10391
10391
  /* OTP Field - Mojave Theme
10392
10392
  *
10393
10393
  * One-time code entry: a row of single-character inputs. Each slot is the same control as Input
@@ -10450,7 +10450,7 @@ textarea.FieldControl {
10450
10450
  letter-spacing: var(--sl-font-body-magnify-letter-spacing);
10451
10451
  }
10452
10452
 
10453
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10453
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10454
10454
  /* Popover - Mojave Theme */
10455
10455
 
10456
10456
  /* ============================================
@@ -10615,7 +10615,7 @@ textarea.FieldControl {
10615
10615
  fill: var(--sl-popup-arrow-stroke);
10616
10616
  }
10617
10617
 
10618
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10618
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10619
10619
  /* Preview Card - Mojave Theme
10620
10620
  *
10621
10621
  * The popup concept (surface, arrow, motion) with a title-magnify title and condense
@@ -10732,7 +10732,7 @@ textarea.FieldControl {
10732
10732
  fill: var(--sl-popup-arrow-stroke);
10733
10733
  }
10734
10734
 
10735
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10735
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10736
10736
  /* Progress - Mojave Theme
10737
10737
  *
10738
10738
  * A gauge (tokens/semantic/gauge.json), the same bar as Meter. The fill is the solid color of
@@ -10809,7 +10809,7 @@ textarea.FieldControl {
10809
10809
  height: var(--sl-gauge-height-lg);
10810
10810
  }
10811
10811
 
10812
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10812
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10813
10813
  /* Radio - Mojave Theme
10814
10814
  * Same box as Checkbox, always round. Sizes follow the label the same way, and the
10815
10815
  * dot is a share of the circle (check.dot-scale).
@@ -10961,7 +10961,7 @@ textarea.FieldControl {
10961
10961
  gap: var(--sl-gap-stack-sm);
10962
10962
  }
10963
10963
 
10964
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
10964
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
10965
10965
  /* Scroll Area - Mojave Theme
10966
10966
  *
10967
10967
  * The scrollbar is the content scrollbar (content.scrollbar-*): a track that stays clear until
@@ -11043,7 +11043,7 @@ textarea.FieldControl {
11043
11043
  background: transparent;
11044
11044
  }
11045
11045
 
11046
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11046
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11047
11047
  /* Select - Mojave Theme
11048
11048
  *
11049
11049
  * The trigger is a field (the field pattern, control sizes, the base text style); the
@@ -11334,7 +11334,7 @@ textarea.FieldControl {
11334
11334
  stroke-width: var(--sl-stroke-default);
11335
11335
  }
11336
11336
 
11337
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11337
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11338
11338
  /* Separator - Mojave Theme
11339
11339
  *
11340
11340
  * A hairline in the everyday divider color (border.default), one stroke thick, with a step of
@@ -11362,7 +11362,7 @@ textarea.FieldControl {
11362
11362
  margin-inline: var(--sl-space-4);
11363
11363
  }
11364
11364
 
11365
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11365
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11366
11366
  /* Slider - Mojave Theme
11367
11367
  *
11368
11368
  * A slider is a gauge you can drag: the track, fill and label row are gauge.* (the same bar as
@@ -11528,7 +11528,7 @@ textarea.FieldControl {
11528
11528
  transform: translate(-50%, 50%);
11529
11529
  }
11530
11530
 
11531
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11531
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11532
11532
  /* Switch - Mojave Theme
11533
11533
  * Switch keeps its track sizes. The thumb, its travel and the ON/OFF text are
11534
11534
  * worked out from them: the thumb fills the track's height inside the padding,
@@ -11694,7 +11694,7 @@ textarea.FieldControl {
11694
11694
  color: var(--sl-text-disabled);
11695
11695
  }
11696
11696
 
11697
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11697
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11698
11698
  /* Tabs - Mojave Theme
11699
11699
  *
11700
11700
  * No component tokens. The divider, the selected line and color, hover and the disabled
@@ -11830,7 +11830,39 @@ textarea.FieldControl {
11830
11830
  padding: var(--sl-space-6);
11831
11831
  }
11832
11832
 
11833
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
11833
+ /* variant="sheet" (on the Tabs.List): the tabs of a working paper. The selected tab is a filled
11834
+ * tab in the Sheet tab colors, and the list keeps the sheet's heavy rule under all of them. */
11835
+ .TabsList[data-variant='sheet'] {
11836
+ gap: var(--sl-space-1);
11837
+ border-bottom: var(--sl-sheet-rule-width) solid var(--sl-sheet-rule-color);
11838
+ }
11839
+
11840
+ .TabsList[data-variant='sheet'] .TabsTab {
11841
+ height: var(--sl-sheet-tab-height);
11842
+ padding-block: 0;
11843
+ padding-inline: var(--sl-space-4);
11844
+ gap: var(--sl-space-2);
11845
+ border-bottom-width: 0;
11846
+ border-radius: var(--sl-sheet-tab-radius) var(--sl-sheet-tab-radius) 0 0;
11847
+ font-weight: 600;
11848
+ color: var(--sl-text-primary);
11849
+ }
11850
+
11851
+ .TabsList[data-variant='sheet'] .TabsTab[data-active],
11852
+ .TabsList[data-variant='sheet'] .TabsTab[data-active]:hover:not([data-disabled]) {
11853
+ background: var(--sl-sheet-tab-background);
11854
+ color: var(--sl-sheet-tab-color);
11855
+ }
11856
+
11857
+ /* A count after the label ("Register 7"), in the figures face. */
11858
+ .TabsList[data-variant='sheet'] .TabsTabCount {
11859
+ font-family: var(--sl-font-figures-condense-font-family, var(--sl-font-family-mono, ui-monospace, monospace));
11860
+ font-size: var(--sl-font-size-sm);
11861
+ font-weight: var(--sl-font-weight-normal);
11862
+ opacity: 0.8;
11863
+ }
11864
+
11865
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
11834
11866
  /* Toast - Mojave Theme
11835
11867
  *
11836
11868
  * A toast is a notice (tokens/semantic/notice.json) on the popup surface. A toast whose type
@@ -12066,7 +12098,7 @@ textarea.FieldControl {
12066
12098
  flex-shrink: 0;
12067
12099
  }
12068
12100
 
12069
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12101
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12070
12102
  /* Toggle - Mojave Theme
12071
12103
  * A toggle is a button that stays pressed: the same heights, padding, gap and
12072
12104
  * trigger text style as a button of the same size. Pressed, it takes its emphasis level's
@@ -12178,7 +12210,7 @@ textarea.FieldControl {
12178
12210
  height: var(--sl-icon-size-maximize);
12179
12211
  }
12180
12212
 
12181
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12213
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12182
12214
  /* Toggle Group - Mojave Theme
12183
12215
  *
12184
12216
  * No component tokens. The strip is the bar concept (tokens/semantic/bar.json); the
@@ -12240,7 +12272,7 @@ textarea.FieldControl {
12240
12272
  outline-offset: var(--sl-focus-outline-offset-inset);
12241
12273
  }
12242
12274
 
12243
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12275
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12244
12276
  /* Toolbar - Mojave Theme
12245
12277
  *
12246
12278
  * The strip is the bar concept (tokens/semantic/bar.json). Buttons, toggles, selects
@@ -12302,7 +12334,7 @@ textarea.FieldControl {
12302
12334
  max-width: var(--sl-toolbar-input-max-width);
12303
12335
  }
12304
12336
 
12305
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12337
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12306
12338
  /* Tooltip - Mojave Theme
12307
12339
  *
12308
12340
  * The inverse surface (surface.inverse, text.on-inverse-surface) with condense text, so a tooltip
@@ -12363,7 +12395,7 @@ textarea.FieldControl {
12363
12395
  }
12364
12396
 
12365
12397
  /* Custom components: not Base UI parts. Built from existing concepts and tokens. */
12366
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12398
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12367
12399
  /* Badge
12368
12400
  *
12369
12401
  * A status or count label. Not a Base UI part, and not interactive: no hover or focus.
@@ -12518,7 +12550,20 @@ textarea.FieldControl {
12518
12550
  margin-inline-start: calc(var(--sl-badge-gap-base) * -1);
12519
12551
  }
12520
12552
 
12521
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
12553
+ /* shape="square": a ruled status tag, not a pill. */
12554
+ .Badge[data-shape='square'] {
12555
+ border-radius: var(--sl-radius-base);
12556
+ text-transform: uppercase;
12557
+ letter-spacing: 0.04em;
12558
+ font-weight: 700;
12559
+ }
12560
+
12561
+ /* A provisional tag: the same badge with a dashed border (DRAFT on a line that is not final). */
12562
+ .Badge[data-border='dashed'] {
12563
+ border-style: dashed;
12564
+ }
12565
+
12566
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
12522
12567
  /*
12523
12568
  * DatePicker: a field that opens a calendar for one date or a period.
12524
12569
  * Not a Base UI part. The popup is Popover on a wide viewport and Drawer
@@ -13108,7 +13153,7 @@ textarea.FieldControl {
13108
13153
  flex-basis: 100%;
13109
13154
  }
13110
13155
 
13111
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
13156
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
13112
13157
  /* Money field
13113
13158
  *
13114
13159
  * An amount of money, built on Number field. The value is an integer in minor units
@@ -13453,7 +13498,7 @@ textarea.FieldControl {
13453
13498
  letter-spacing: var(--sl-font-body-base-letter-spacing);
13454
13499
  }
13455
13500
 
13456
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
13501
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
13457
13502
  /* ListDetail
13458
13503
  *
13459
13504
  * The detail of one item, next to its list. Not a Base UI part. It is a Splitter
@@ -13580,7 +13625,7 @@ textarea.FieldControl {
13580
13625
  background: transparent;
13581
13626
  }
13582
13627
 
13583
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
13628
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
13584
13629
  /* Splitter
13585
13630
  *
13586
13631
  * Two or more panels and a handle between them. Not a Base UI part. It follows the
@@ -13788,7 +13833,7 @@ textarea.FieldControl {
13788
13833
  background: var(--sl-border-default);
13789
13834
  }
13790
13835
 
13791
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
13836
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
13792
13837
  /* EmptyState
13793
13838
  *
13794
13839
  * The block a page, pane, table, list or popup shows when it has nothing to show.
@@ -13810,12 +13855,14 @@ textarea.FieldControl {
13810
13855
  * Text is a whole style per size, not a font-size on its own. Compact is a table
13811
13856
  * row or a popup, so the title is subtitle-condense (bold, the row's size) and the
13812
13857
  * description is body-condense. Standard is a pane: title-condense, the section
13813
- * heading, with body-base under it. Spacious is a page: title-magnify, the next
13814
- * title up, still body-base so the sentence doesn't grow with the heading.
13858
+ * heading, with body-base under it. Spacious is a page: title-amplify, the page
13859
+ * title size, still body-base so the sentence doesn't grow with the heading. A brand
13860
+ * that raises title-condense (Tulvo sets it to xl) would otherwise get a spacious
13861
+ * title smaller than the standard one.
13815
13862
  * Unselected is the quiet pane beside a list, so it drops the circle, the icon is
13816
13863
  * text-tertiary, and the title steps down one tier: subtitle-minimize where the
13817
13864
  * others use a condense style (there is no title at minimize), and title-condense
13818
- * where the others use title-magnify.
13865
+ * where the others use title-amplify.
13819
13866
  *
13820
13867
  * Compact is a row (icon, text, actions) centered across the cell. Standard and
13821
13868
  * spacious are a column. They take margin-block: auto so a flex or grid column
@@ -13984,11 +14031,11 @@ textarea.FieldControl {
13984
14031
  }
13985
14032
 
13986
14033
  .EmptyState[data-size='spacious'] .EmptyStateTitle {
13987
- font-family: var(--sl-font-title-magnify-font-family);
13988
- font-size: var(--sl-font-title-magnify-font-size);
13989
- font-weight: var(--sl-font-title-magnify-font-weight);
13990
- line-height: var(--sl-font-title-magnify-line-height);
13991
- letter-spacing: var(--sl-font-title-magnify-letter-spacing);
14034
+ font-family: var(--sl-font-title-amplify-font-family);
14035
+ font-size: var(--sl-font-title-amplify-font-size);
14036
+ font-weight: var(--sl-font-title-amplify-font-weight);
14037
+ line-height: var(--sl-font-title-amplify-line-height);
14038
+ letter-spacing: var(--sl-font-title-amplify-letter-spacing);
13992
14039
  }
13993
14040
 
13994
14041
  .EmptyState[data-size='spacious'] .EmptyStateMedia {
@@ -14302,7 +14349,7 @@ textarea.FieldControl {
14302
14349
  }
14303
14350
  }
14304
14351
 
14305
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
14352
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
14306
14353
  /* Table - Mojave Theme
14307
14354
  *
14308
14355
  * Base UI has no table, so this styles the native <table class="Table"> elements with the
@@ -14583,7 +14630,238 @@ textarea.FieldControl {
14583
14630
  color: inherit;
14584
14631
  }
14585
14632
 
14586
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
14633
+ /* A statement's footer totals (DataTable totalRows) read like its own total rows: the label in the
14634
+ * body face and sentence case, not in the caps of its header, and no tray band. */
14635
+ .Table[data-look='statement'] tfoot tr[data-total] > *,
14636
+ .Table[data-look='statement'][data-header-style] tfoot tr[data-total] > * {
14637
+ font-family: var(--sl-font-body-condense-font-family);
14638
+ font-size: 15px;
14639
+ font-weight: 600;
14640
+ letter-spacing: normal;
14641
+ text-transform: none;
14642
+ color: var(--sl-text-primary);
14643
+ background: transparent;
14644
+ }
14645
+ .Table[data-look='statement'] tfoot tr[data-total='grand'] > *,
14646
+ .Table[data-look='statement'][data-header-style] tfoot tr[data-total='grand'] > * {
14647
+ font-weight: 700;
14648
+ }
14649
+ .Table[data-look='statement'][data-density='compact'] tfoot tr[data-total] > * {
14650
+ font-size: 14px;
14651
+ }
14652
+ .Table[data-look='statement'] tfoot tr[data-total] > [data-align='end'],
14653
+ .Table[data-look='statement'][data-header-style] tfoot tr[data-total] > [data-align='end'] {
14654
+ font-family: var(--sl-font-figures-base-font-family);
14655
+ }
14656
+
14657
+ /* Statement rows: data-look="statement" (DataTable look="statement") draws a financial statement or
14658
+ * schedule as an open table on its sheet, and each row looks by its data-kind. One rule for every
14659
+ * report, so a report never styles its own rows:
14660
+ *
14661
+ * header No fill. Caps 12px/600 column names, one dark rule under it. A <small> in a header is
14662
+ * a second line (the Entity under "1040"). data-header="hidden" keeps it for screen
14663
+ * readers only, as on a statement with one Total column.
14664
+ * section Heads the lines under it: caps 13px/700, no fill, no rule, 40px, text on the bottom.
14665
+ * A link beside the label (.TableSectionLabel) takes the same caps in the accent color.
14666
+ * group A shaded band that carries its own figures (an account in Holdings): tray fill, 42px,
14667
+ * subtle rules above and below, caps 13px/700 label, figures 600. Its lines sit flush.
14668
+ * line Rows without a kind, or kind "line": 36px (taller with a second line), 15px body,
14669
+ * 15px figures, a faint rule under each. Indented past a section label (--statement-indent).
14670
+ * subtotal Also "total": 40px, 600, label indented 8px, a dark rule over the figure cells only.
14671
+ * grand 46px, 700, a dark rule across the row and a double rule under each figure.
14672
+ * note Explains the total above ("All holdings, before filters"): 14px secondary, no rule.
14673
+ * heading A block's head inside a long list (a ledger account): 600.
14674
+ * provisional A line that is not final yet (a Draft's provisional unclassified amount): a line with a
14675
+ * faint diagonal hatch. Put a dashed Badge ("DRAFT") beside its name to say why.
14676
+ *
14677
+ * data-density="compact" (DataTable density="compact") is the small version, for a table inside a
14678
+ * detail panel or a drawer: 30px lines, 14px text and figures, 11px headers, 12px padding.
14679
+ *
14680
+ * Padding: --statement-padding-start (18px) at the row start, --statement-padding-end (12px)
14681
+ * after the last figure, --statement-indent (14px) for lines under a section. Set them on the table.
14682
+ */
14683
+ .Table[data-look='statement'] {
14684
+ --statement-padding-start: 18px;
14685
+ --statement-padding-end: 12px;
14686
+ --statement-indent: 14px;
14687
+ --sl-table-cell-padding-inline: var(--statement-padding-start);
14688
+ border: 0;
14689
+ border-radius: 0;
14690
+ background: transparent;
14691
+ }
14692
+ .Table[data-look='statement'] tr > :last-child {
14693
+ padding-inline-end: var(--statement-padding-end);
14694
+ }
14695
+ .Table[data-look='statement'] > thead th {
14696
+ height: 40px;
14697
+ padding-block: 0 8px;
14698
+ background: transparent;
14699
+ border-top: 0;
14700
+ border-bottom: var(--sl-stroke-default) solid var(--sl-text-primary);
14701
+ vertical-align: bottom;
14702
+ font-size: 12px;
14703
+ font-weight: 600;
14704
+ letter-spacing: 0.08em;
14705
+ color: var(--sl-text-primary);
14706
+ }
14707
+ .Table[data-look='statement'] > thead th small {
14708
+ display: block;
14709
+ font-family: var(--sl-font-body-condense-font-family);
14710
+ font-size: 12px;
14711
+ font-weight: 400;
14712
+ letter-spacing: normal;
14713
+ text-transform: none;
14714
+ color: var(--sl-text-secondary);
14715
+ }
14716
+ .Table[data-look='statement'][data-header='hidden'] > thead > tr > th {
14717
+ height: 0;
14718
+ padding: 0;
14719
+ border: 0;
14720
+ font-size: 0;
14721
+ line-height: 0;
14722
+ overflow: hidden;
14723
+ }
14724
+ .Table[data-look='statement'] > tbody > tr > * {
14725
+ height: 36px;
14726
+ font-family: var(--sl-font-body-condense-font-family);
14727
+ font-size: 15px;
14728
+ font-weight: 400;
14729
+ letter-spacing: normal;
14730
+ text-transform: none;
14731
+ color: var(--sl-text-primary);
14732
+ background: transparent;
14733
+ border-top: 0;
14734
+ border-bottom: var(--sl-stroke-default) solid var(--sl-border-subtle);
14735
+ }
14736
+ .Table[data-look='statement'] > tbody > tr > [data-align='end'] {
14737
+ font-family: var(--sl-font-figures-base-font-family);
14738
+ white-space: nowrap;
14739
+ }
14740
+ @media (hover: hover) {
14741
+ .Table[data-look='statement'] > tbody > tr:is(:not([data-kind]), [data-kind='line']):hover > * {
14742
+ background: var(--sl-surface-tray);
14743
+ }
14744
+ }
14745
+ .Table[data-look='statement']:has(tr[data-kind='section']) > tbody > tr:is(:not([data-kind]), [data-kind='line']) > th > * {
14746
+ margin-inline-start: var(--statement-indent);
14747
+ }
14748
+ .Table[data-look='statement'] > tbody > tr[data-kind='section'] > * {
14749
+ height: 40px;
14750
+ padding-block: 6px 4px;
14751
+ vertical-align: bottom;
14752
+ border-bottom: 0;
14753
+ }
14754
+ .Table[data-look='statement'] > tbody > tr:is([data-kind='section'], [data-kind='group']) > th {
14755
+ font-size: 13px;
14756
+ font-weight: 700;
14757
+ letter-spacing: 0.1em;
14758
+ text-transform: uppercase;
14759
+ }
14760
+ .Table[data-look='statement'] > tbody > tr[data-kind='group'] > * {
14761
+ height: 42px;
14762
+ font-weight: 600;
14763
+ background: var(--sl-surface-tray);
14764
+ border-top: var(--sl-stroke-default) solid var(--sl-border-default);
14765
+ border-bottom: var(--sl-stroke-default) solid var(--sl-border-default);
14766
+ }
14767
+ .Table[data-look='statement'] > tbody > tr[data-kind='group'] + tr > * {
14768
+ border-top: 0;
14769
+ }
14770
+ .Table[data-look='statement'] > tbody > tr:is([data-kind='subtotal'], [data-kind='total']) > * {
14771
+ height: 40px;
14772
+ font-weight: 600;
14773
+ border-top: var(--sl-stroke-default) solid transparent;
14774
+ border-bottom: 0;
14775
+ }
14776
+ .Table[data-look='statement'] > tbody > tr:is([data-kind='subtotal'], [data-kind='total']) > td[data-align='end'] {
14777
+ border-top-color: var(--sl-text-primary);
14778
+ }
14779
+ .Table[data-look='statement'] > tbody > tr:is([data-kind='subtotal'], [data-kind='total']) > th > * {
14780
+ margin-inline-start: 8px;
14781
+ }
14782
+ .Table[data-look='statement'] > tbody > tr[data-kind='grand'] > * {
14783
+ height: 46px;
14784
+ font-weight: 700;
14785
+ border-top: var(--sl-stroke-default) solid var(--sl-text-primary);
14786
+ border-bottom: 0;
14787
+ }
14788
+ .Table[data-look='statement'] > tbody > tr[data-kind='grand'] > td[data-align='end']:not(:empty) {
14789
+ border-bottom: 3px double var(--sl-text-primary);
14790
+ }
14791
+ .Table[data-look='statement'] > tbody > tr[data-kind='grand'] + tr[data-kind='section'] > * {
14792
+ height: 48px;
14793
+ }
14794
+ .Table[data-look='statement'] > tbody > tr[data-kind='note'] > * {
14795
+ height: 40px;
14796
+ border-bottom: 0;
14797
+ font-size: 14px;
14798
+ color: var(--sl-text-secondary);
14799
+ }
14800
+ .Table[data-look='statement'] > tbody > tr[data-kind='note'] > [data-align='end'] {
14801
+ font-size: 15px;
14802
+ }
14803
+ .Table[data-look='statement'] > tbody > tr[data-kind='heading'] > * {
14804
+ font-weight: 600;
14805
+ }
14806
+ /* A section label with a link beside it: "INVESTMENT ACTIVITY OPEN THE SCHEDULE". */
14807
+ .TableSectionLabel {
14808
+ display: inline-flex;
14809
+ align-items: baseline;
14810
+ gap: 12px;
14811
+ }
14812
+ .TableSectionLabel :is(a, button) {
14813
+ min-height: 0;
14814
+ padding: 0;
14815
+ border: 0;
14816
+ background: none;
14817
+ font: inherit;
14818
+ letter-spacing: inherit;
14819
+ text-transform: inherit;
14820
+ color: var(--sl-text-accent);
14821
+ text-decoration: underline;
14822
+ text-underline-offset: 3px;
14823
+ cursor: pointer;
14824
+ }
14825
+
14826
+ /* Provisional: a line that is not final yet, hatched so it reads as provisional at a glance. */
14827
+ .Table[data-look='statement'] > tbody > tr[data-kind='provisional'] > * {
14828
+ background-image: repeating-linear-gradient(
14829
+ -45deg,
14830
+ transparent 0 6px,
14831
+ var(--sl-surface-tray) 6px 12px
14832
+ );
14833
+ }
14834
+
14835
+ /* Statement rows keep 6px above and below their content, so a row with a second line (a memo, a party
14836
+ * under a description) doesn't touch its rules. A one-line row stays at its kind's height. */
14837
+ .Table[data-look='statement'] > :is(tbody, tfoot) > tr > * {
14838
+ padding-block: 6px;
14839
+ }
14840
+
14841
+ /* Compact density: a small table inside a detail panel or a drawer. */
14842
+ .Table[data-density='compact'] {
14843
+ --sl-table-row-height: 30px;
14844
+ --sl-table-header-height: 30px;
14845
+ }
14846
+ .Table[data-look='statement'][data-density='compact'] {
14847
+ --statement-padding-start: 12px;
14848
+ --statement-padding-end: 12px;
14849
+ --statement-indent: 10px;
14850
+ }
14851
+ .Table[data-density='compact'] > thead th {
14852
+ height: 30px;
14853
+ padding-block: 0 6px;
14854
+ font-size: 11px;
14855
+ }
14856
+ .Table[data-density='compact'] > :is(tbody, tfoot) > tr > * {
14857
+ height: 30px;
14858
+ font-size: 14px;
14859
+ }
14860
+ .Table[data-look='statement'][data-density='compact'] > tbody > tr:is([data-kind='subtotal'], [data-kind='total'], [data-kind='grand'], [data-kind='note'], [data-kind='section']) > * {
14861
+ height: 32px;
14862
+ }
14863
+
14864
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
14587
14865
  /* Collection
14588
14866
  *
14589
14867
  * DataTable, DataList, the toolbar and the pagination, in one place so the two views
@@ -14594,7 +14872,7 @@ textarea.FieldControl {
14594
14872
  * the tabs and the search where they are, so selecting rows does not grow the toolbar.
14595
14873
  */
14596
14874
 
14597
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
14875
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
14598
14876
  /* Collection toolbar
14599
14877
  *
14600
14878
  * The wrap follows the toolbar's own width, not the window: a table in a narrow pane wraps
@@ -14806,7 +15084,7 @@ textarea.FieldControl {
14806
15084
  margin-inline-start: auto;
14807
15085
  }
14808
15086
 
14809
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15087
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
14810
15088
  /* DataTable additions on top of .Table.
14811
15089
  *
14812
15090
  * Sort buttons fill the header cell and inherit its hover, so old aria-sort markup keeps
@@ -15041,7 +15319,69 @@ textarea.FieldControl {
15041
15319
  background: var(--sl-border-default);
15042
15320
  }
15043
15321
 
15044
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15322
+ /* On a statement the row name is a button (the row header); it reads as the row's text. */
15323
+ .Table[data-look='statement'] .CollectionRowButton {
15324
+ font: inherit;
15325
+ letter-spacing: inherit;
15326
+ text-transform: inherit;
15327
+ color: inherit;
15328
+ }
15329
+
15330
+ /* Expandable rows (getRowDetail): an expand button in a narrow first column, the size of the small
15331
+ * disclosure, and a spacer of the same width on rows without detail. The open row's detail fills a
15332
+ * panel row under it, across every column, on the tray with a quiet rule. */
15333
+ .DataTable :is(th, td).DataTableDetailColumn {
15334
+ inline-size: calc(var(--sl-collection-disclosure-size-small) + var(--sl-table-cell-padding-inline));
15335
+ padding-inline-end: 0;
15336
+ }
15337
+
15338
+ .DataTable .DataTableDetailToggle,
15339
+ .DataTable .DataTableDetailSpacer {
15340
+ display: inline-flex;
15341
+ align-items: center;
15342
+ justify-content: center;
15343
+ inline-size: var(--sl-collection-disclosure-size-small);
15344
+ block-size: var(--sl-collection-disclosure-size-small);
15345
+ vertical-align: middle;
15346
+ color: var(--sl-collection-disclosure-color);
15347
+ }
15348
+
15349
+ .DataTable .DataTableDetailToggle > .material-symbols-outlined {
15350
+ font-size: var(--sl-icon-size-base);
15351
+ }
15352
+
15353
+ .DataTable tr[data-expanded] > * {
15354
+ background: var(--sl-surface-tray);
15355
+ border-bottom-color: transparent;
15356
+ }
15357
+
15358
+ .DataTable > tbody > tr.DataTableDetailRow > td.DataTableDetail {
15359
+ height: auto;
15360
+ padding: var(--sl-space-2) var(--sl-space-4) var(--sl-space-4) calc(var(--sl-collection-disclosure-size-small) + var(--sl-space-2) + var(--sl-table-cell-padding-inline));
15361
+ background: var(--sl-surface-tray);
15362
+ border-bottom: var(--sl-stroke-default) solid var(--sl-border-default);
15363
+ vertical-align: top;
15364
+ white-space: normal;
15365
+ }
15366
+
15367
+ @media (hover: hover) {
15368
+ .DataTable > tbody > tr.DataTableDetailRow:hover > * {
15369
+ background: var(--sl-surface-tray);
15370
+ }
15371
+ }
15372
+
15373
+ /* A total row's note ("Journal entries aren't in these totals"): quiet text beside the figures. */
15374
+ .DataTable .DataTableTotalNote {
15375
+ font-family: var(--sl-font-body-condense-font-family);
15376
+ font-size: 13px;
15377
+ font-weight: 400;
15378
+ letter-spacing: normal;
15379
+ text-transform: none;
15380
+ color: var(--sl-text-secondary);
15381
+ white-space: normal;
15382
+ }
15383
+
15384
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15045
15385
  /* DataList
15046
15386
  *
15047
15387
  * The same rows as the table, in one container with the table's borders, hover, selected
@@ -15183,7 +15523,7 @@ textarea.FieldControl {
15183
15523
  transition: opacity var(--sl-duration-fast) var(--sl-easing-default);
15184
15524
  }
15185
15525
 
15186
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15526
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15187
15527
  /* Collection cards
15188
15528
  *
15189
15529
  * The page of a collection as a grid. Columns fill the width, none narrower than
@@ -15208,7 +15548,7 @@ textarea.FieldControl {
15208
15548
  flex: 1 1 auto;
15209
15549
  }
15210
15550
 
15211
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15551
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15212
15552
  /* Pagination
15213
15553
  *
15214
15554
  * Not tied to a collection. Anything with a page, a page count and a total can use it.
@@ -15233,7 +15573,37 @@ textarea.FieldControl {
15233
15573
  margin: 0;
15234
15574
  }
15235
15575
 
15236
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15576
+ /* The summary on the left, the page buttons on the right. */
15577
+ .CollectionPagination [data-part='summary'] {
15578
+ margin-inline-end: auto;
15579
+ font-family: var(--sl-font-code-base-font-family, monospace);
15580
+ }
15581
+
15582
+ /* Page numbers: small square buttons in the figures face; the current page is filled. */
15583
+ .CollectionPagination [data-part='pages'] {
15584
+ display: inline-flex;
15585
+ align-items: center;
15586
+ gap: var(--sl-space-1);
15587
+ }
15588
+
15589
+ .CollectionPagination [data-part='page'] {
15590
+ min-width: var(--sl-control-height-sm);
15591
+ height: var(--sl-control-height-sm);
15592
+ padding-inline: var(--sl-space-2);
15593
+ font-family: var(--sl-font-code-base-font-family, monospace);
15594
+ }
15595
+
15596
+ .CollectionPagination [data-part='gap'] {
15597
+ padding-inline: var(--sl-space-1);
15598
+ }
15599
+
15600
+ .CollectionPagination [data-part='page'][data-current] {
15601
+ background: var(--sl-text-primary);
15602
+ border-color: var(--sl-text-primary);
15603
+ color: var(--sl-surface-raised);
15604
+ }
15605
+
15606
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15237
15607
  /* EditableList
15238
15608
  *
15239
15609
  * One table at every width, so a field is not submitted twice. Under the stack width each
@@ -15332,7 +15702,7 @@ textarea.FieldControl {
15332
15702
  }
15333
15703
  }
15334
15704
 
15335
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15705
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15336
15706
  /* Sheet
15337
15707
  *
15338
15708
  * A working-paper surface: the raised surface with a heavier rule across its top
@@ -15450,7 +15820,7 @@ textarea.FieldControl {
15450
15820
  border-top: 0;
15451
15821
  }
15452
15822
 
15453
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15823
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15454
15824
  /* StatFigure
15455
15825
  *
15456
15826
  * One large figure with a caps label above and a caption under it. The label is
@@ -15511,7 +15881,47 @@ textarea.FieldControl {
15511
15881
  color: var(--sl-stat-figure-caption-color);
15512
15882
  }
15513
15883
 
15514
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15884
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15885
+ /* StatBand
15886
+ *
15887
+ * The headline figures of a display page, in a band of their own: equal cells side by side, a 1px
15888
+ * border, the sheet's heavy rule on top (sheet.rule-width), and a StatFigure (size sm) in each cell.
15889
+ * The cells wrap to more rows when the band is narrow; each cell is at least 11rem wide.
15890
+ * A figure wrapped in a link takes the accent color and its own double underline.
15891
+ */
15892
+
15893
+ .StatBand {
15894
+ display: grid;
15895
+ grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
15896
+ margin: 0;
15897
+ border: var(--sl-stroke-default) solid var(--sl-border-default);
15898
+ border-top: var(--sl-sheet-rule-width) solid var(--sl-text-primary);
15899
+ background: var(--sl-surface-raised);
15900
+ }
15901
+
15902
+ .StatBand > .StatBandCell {
15903
+ display: flex;
15904
+ padding: var(--sl-space-3) var(--sl-space-4);
15905
+ border-inline-end: var(--sl-stroke-default) solid var(--sl-border-subtle);
15906
+ }
15907
+
15908
+ .StatBand > .StatBandCell:last-child {
15909
+ border-inline-end: 0;
15910
+ }
15911
+
15912
+ .StatBand .StatBandCell .StatFigureValue :is(a, button) {
15913
+ min-height: 0;
15914
+ padding: 0;
15915
+ border: 0;
15916
+ background: none;
15917
+ font: inherit;
15918
+ color: var(--sl-text-accent);
15919
+ text-decoration: none;
15920
+ border-bottom: 3px double currentColor;
15921
+ cursor: pointer;
15922
+ }
15923
+
15924
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15515
15925
  /* StatCard
15516
15926
  *
15517
15927
  * A card for one thing a page lists: a name (the heading), a caption, and a row of StatFigures
@@ -15673,7 +16083,7 @@ textarea.FieldControl {
15673
16083
  white-space: nowrap;
15674
16084
  }
15675
16085
 
15676
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16086
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15677
16087
  /* DescriptionList
15678
16088
  *
15679
16089
  * Label and value pairs in a native dl, one DescriptionItem (a div holding a dt and a dd)
@@ -15751,7 +16161,7 @@ textarea.FieldControl {
15751
16161
  text-align: end;
15752
16162
  }
15753
16163
 
15754
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16164
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15755
16165
  /* FormGrid
15756
16166
  *
15757
16167
  * Fields on a grid. Columns are as wide as the space allows up to --form-grid-columns
@@ -15788,7 +16198,7 @@ textarea.FieldControl {
15788
16198
  align-self: end;
15789
16199
  }
15790
16200
 
15791
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16201
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15792
16202
  /* Notice
15793
16203
  *
15794
16204
  * A message in the page: a thick leading edge and a tinted ground. data-status picks the
@@ -15844,7 +16254,40 @@ textarea.FieldControl {
15844
16254
  --notice-ground: var(--sl-surface-tray);
15845
16255
  }
15846
16256
 
15847
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16257
+ /* The row layout (heading, tag or action): the tag, then the heading over the text, then one action
16258
+ * at the end, centered on the row. The action wraps under the text when the notice is narrow. */
16259
+ .Notice[data-layout='row'] {
16260
+ display: flex;
16261
+ flex-wrap: wrap;
16262
+ align-items: center;
16263
+ gap: var(--sl-space-2) var(--sl-space-3);
16264
+ padding-block: var(--sl-space-3);
16265
+ }
16266
+
16267
+ .Notice .NoticeTag {
16268
+ flex: none;
16269
+ align-self: flex-start;
16270
+ }
16271
+
16272
+ .Notice .NoticeBody {
16273
+ flex: 1 1 20rem;
16274
+ min-width: 0;
16275
+ }
16276
+
16277
+ .Notice .NoticeBody > * {
16278
+ margin: 0;
16279
+ }
16280
+
16281
+ .Notice .NoticeHeading {
16282
+ font-weight: var(--sl-font-weight-semibold);
16283
+ }
16284
+
16285
+ .Notice .NoticeAction {
16286
+ flex: none;
16287
+ margin-inline-start: auto;
16288
+ }
16289
+
16290
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
15848
16291
  /* ChecklistNotice
15849
16292
  *
15850
16293
  * A Notice with a list of pass/fail rows. The title is subtitle-condense; each row is a mark
@@ -15852,6 +16295,13 @@ textarea.FieldControl {
15852
16295
  * secondary color. Rows are split by a hairline. A passed row's mark is the success color,
15853
16296
  * a failed one's the error color, so the two differ in lightness as well as hue in every
15854
16297
  * theme; the visually hidden "Done" / "Not done" carries the state for assistive tech.
16298
+ *
16299
+ * look="sheet" (data-look) is the working-paper version, for a check list in a drawer or panel:
16300
+ * the sheet surface (sheet.background, sheet.border, sheet.rule on top) with no status tint,
16301
+ * the tag and title as a header row over a hairline, 15px rows split by a faint rule, and each
16302
+ * mark a 22px filled circle: success-dark with a check, accent-dark with "!". An item's
16303
+ * content (the form that resolves it) sits under its row in a box with the accent edge on the
16304
+ * tray. The footer is the last row: a dashed info circle and the note in the secondary color.
15855
16305
  */
15856
16306
 
15857
16307
  .ChecklistNotice {
@@ -15869,6 +16319,13 @@ textarea.FieldControl {
15869
16319
  margin: 0;
15870
16320
  }
15871
16321
 
16322
+ .ChecklistNoticeTitle[data-tagged] {
16323
+ display: flex;
16324
+ flex-wrap: wrap;
16325
+ align-items: center;
16326
+ gap: var(--sl-space-2);
16327
+ }
16328
+
15872
16329
  .ChecklistNoticeList {
15873
16330
  display: flex;
15874
16331
  flex-direction: column;
@@ -15883,11 +16340,18 @@ textarea.FieldControl {
15883
16340
  font-weight: var(--sl-font-body-condense-font-weight);
15884
16341
  line-height: var(--sl-font-body-condense-line-height);
15885
16342
  letter-spacing: var(--sl-font-body-condense-letter-spacing);
16343
+ padding-block: var(--sl-space-1-5);
16344
+ border-top: var(--sl-stroke-default) solid var(--sl-border-subtle);
16345
+ }
16346
+
16347
+ .ChecklistNoticeRow {
15886
16348
  display: flex;
15887
16349
  align-items: flex-start;
15888
16350
  gap: var(--sl-space-2);
15889
- padding-block: var(--sl-space-1-5);
15890
- border-top: var(--sl-stroke-default) solid var(--sl-border-subtle);
16351
+ }
16352
+
16353
+ .ChecklistNoticeContent {
16354
+ margin-block-start: var(--sl-space-2);
15891
16355
  }
15892
16356
 
15893
16357
  .ChecklistNoticeMark {
@@ -15921,13 +16385,186 @@ textarea.FieldControl {
15921
16385
  gap: var(--sl-space-2);
15922
16386
  }
15923
16387
 
15924
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
15925
- /* ParameterBar
15926
- *
15927
- * Settings for a result, in one wrapping row on the tray: the app's fields at the start, the
15928
- * status line, the Run button and any extra actions at the end. Fields align on their controls
15929
- * (align-items: flex-end), so a field with a description does not push its neighbours' inputs
15930
- * down. When the bar is narrow the end group wraps onto its own line, at the start.
16388
+ /* The sheet look: a check list on a working paper, not a tinted notice. */
16389
+ .ChecklistNotice[data-look='sheet'] {
16390
+ gap: 0;
16391
+ padding: 0;
16392
+ background: var(--sl-sheet-background);
16393
+ border: var(--sl-sheet-border-width) solid var(--sl-sheet-border-color);
16394
+ border-top: var(--sl-sheet-rule-width) solid var(--sl-sheet-rule-color);
16395
+ border-radius: 0;
16396
+ }
16397
+
16398
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeTitle {
16399
+ font-family: var(--sl-font-body-base-font-family);
16400
+ font-size: var(--sl-font-body-base-font-size);
16401
+ font-weight: var(--sl-font-body-base-font-weight);
16402
+ line-height: var(--sl-font-body-base-line-height);
16403
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
16404
+ font-weight: var(--sl-font-weight-semibold);
16405
+ gap: 10px;
16406
+ padding: 10px 14px;
16407
+ border-bottom: var(--sl-stroke-default) solid var(--sl-sheet-border-color);
16408
+ }
16409
+
16410
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeItem {
16411
+ font-family: var(--sl-font-body-base-font-family);
16412
+ font-size: var(--sl-font-body-base-font-size);
16413
+ font-weight: var(--sl-font-body-base-font-weight);
16414
+ line-height: var(--sl-font-body-base-line-height);
16415
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
16416
+ padding: 9px 14px;
16417
+ border-top: 0;
16418
+ border-bottom: var(--sl-stroke-default) solid var(--sl-border-subtle);
16419
+ }
16420
+
16421
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeList:last-child > .ChecklistNoticeItem:last-child {
16422
+ border-bottom: 0;
16423
+ }
16424
+
16425
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeRow {
16426
+ gap: 10px;
16427
+ }
16428
+
16429
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeMark {
16430
+ display: inline-flex;
16431
+ align-items: center;
16432
+ justify-content: center;
16433
+ width: 22px;
16434
+ height: 22px;
16435
+ border-radius: 50%;
16436
+ font-size: 15px;
16437
+ font-weight: 700;
16438
+ background: var(--sl-text-accent);
16439
+ color: var(--sl-sheet-background);
16440
+ }
16441
+
16442
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeItem[data-passed] .ChecklistNoticeMark {
16443
+ background: var(--sl-status-success-dark);
16444
+ color: var(--sl-sheet-background);
16445
+ }
16446
+
16447
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeDetail {
16448
+ font-size: 13px;
16449
+ }
16450
+
16451
+ /* A failed check's fix: the accent edge on the tray, under its row and in line with the label. */
16452
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeContent {
16453
+ display: flex;
16454
+ flex-direction: column;
16455
+ gap: var(--sl-space-2);
16456
+ margin: 10px 0 3px 0;
16457
+ padding: 12px 14px;
16458
+ border: var(--sl-stroke-default) solid var(--sl-text-accent);
16459
+ background: var(--sl-surface-tray);
16460
+ }
16461
+
16462
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeFooter {
16463
+ font-family: var(--sl-font-body-condense-font-family);
16464
+ font-size: var(--sl-font-body-condense-font-size);
16465
+ font-weight: var(--sl-font-body-condense-font-weight);
16466
+ line-height: var(--sl-font-body-condense-line-height);
16467
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
16468
+ gap: 10px;
16469
+ padding: 9px 14px;
16470
+ color: var(--sl-text-secondary);
16471
+ }
16472
+
16473
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeFooterMark {
16474
+ display: inline-flex;
16475
+ align-items: center;
16476
+ justify-content: center;
16477
+ width: 22px;
16478
+ height: 22px;
16479
+ border: var(--sl-stroke-default) dashed var(--sl-border-strong);
16480
+ border-radius: 50%;
16481
+ font-size: 15px;
16482
+ }
16483
+
16484
+ .ChecklistNotice[data-look='sheet'] .ChecklistNoticeFooter > :not(.ChecklistNoticeFooterMark) {
16485
+ margin: 0;
16486
+ }
16487
+
16488
+ /* A control in the mark's place (a Checkbox the person ticks to pass the check). */
16489
+ .ChecklistNoticeControl {
16490
+ display: inline-flex;
16491
+ flex-shrink: 0;
16492
+ align-items: center;
16493
+ min-height: 1lh;
16494
+ }
16495
+
16496
+ .ChecklistNoticeControl + .ChecklistNoticeText label {
16497
+ cursor: pointer;
16498
+ }
16499
+
16500
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16501
+ /* ChipPicker
16502
+ *
16503
+ * Removable chips (subtle Badges with a close button) in a wrapping row, then a small round +
16504
+ * button that opens a menu of the groups not chosen yet. Read only, the chips have no close
16505
+ * button and an empty picker shows a dash.
16506
+ */
16507
+
16508
+ .ChipPicker {
16509
+ display: inline-flex;
16510
+ flex-wrap: wrap;
16511
+ align-items: center;
16512
+ gap: var(--sl-space-1);
16513
+ min-width: 0;
16514
+ }
16515
+
16516
+ /* A chip: a rounded tag in sentence case on the raised surface, its group named in bold in the
16517
+ * secondary color ("Project Lumen rebrand"). Stated with the ChipPicker so an app's square-tag
16518
+ * Badge rule doesn't turn the chips into status tags. */
16519
+ .ChipPicker .ChipPickerChip {
16520
+ font-family: var(--sl-font-body-condense-font-family);
16521
+ font-size: var(--sl-font-body-condense-font-size);
16522
+ font-weight: var(--sl-font-body-condense-font-weight);
16523
+ line-height: var(--sl-font-body-condense-line-height);
16524
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
16525
+ height: 24px;
16526
+ padding-inline: 8px;
16527
+ gap: 4px;
16528
+ border: var(--sl-stroke-default) solid var(--sl-border-default);
16529
+ border-radius: 12px;
16530
+ background: var(--sl-surface-raised);
16531
+ color: var(--sl-text-primary);
16532
+ font-size: 13px;
16533
+ font-weight: var(--sl-font-weight-normal);
16534
+ letter-spacing: normal;
16535
+ text-transform: none;
16536
+ }
16537
+
16538
+ .ChipPicker .ChipPickerChipGroup {
16539
+ font-weight: var(--sl-font-weight-semibold);
16540
+ color: var(--sl-text-secondary);
16541
+ }
16542
+
16543
+ .ChipPicker .ChipPickerAdd {
16544
+ min-height: 0;
16545
+ inline-size: 24px;
16546
+ block-size: 24px;
16547
+ padding: 0;
16548
+ border: var(--sl-stroke-default) dashed var(--sl-border-strong);
16549
+ border-radius: 999px;
16550
+ justify-content: center;
16551
+ }
16552
+
16553
+ .ChipPicker .ChipPickerAdd > .material-symbols-outlined {
16554
+ font-size: var(--sl-icon-size-condense);
16555
+ }
16556
+
16557
+ .ChipPickerEmpty {
16558
+ color: var(--sl-text-secondary);
16559
+ }
16560
+
16561
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16562
+ /* ParameterBar
16563
+ *
16564
+ * Settings for a result, in one wrapping row on the tray: the app's fields at the start, the
16565
+ * status line, the Run button and any extra actions at the end. Fields align on their controls
16566
+ * (align-items: flex-end), so a field with a description does not push its neighbours' inputs
16567
+ * down. When the bar is narrow the end group wraps onto its own line, at the start.
15931
16568
  *
15932
16569
  * data-changed (a setting changed since the last run) turns the status line to the warning
15933
16570
  * text color. The bar itself does not dim anything; the app dims its own stale result.
@@ -16020,7 +16657,7 @@ textarea.FieldControl {
16020
16657
  text-overflow: ellipsis;
16021
16658
  }
16022
16659
 
16023
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16660
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16024
16661
  /* LineItemGrid
16025
16662
  *
16026
16663
  * Editable lines (a journal entry, an invoice) on the Table styles. Cells hold controls, so
@@ -16032,6 +16669,12 @@ textarea.FieldControl {
16032
16669
  *
16033
16670
  * A footer row's data-tone colors its figures with the status text colors (the -dark steps,
16034
16671
  * which pass as text on the tray). The words in the cell carry the state; color only adds.
16672
+ *
16673
+ * look="statement" (data-look) puts the lines on a statement's terms: the Table's statement rows
16674
+ * with caps 11px headers, 6px cell padding, no frame and rows tall enough for their controls.
16675
+ * The footer rows move under the Add button into .LineItemGridSummary: a box on the base surface
16676
+ * with a 1px border and the sheet's heavy rule on top, label left and figure right, a toned row
16677
+ * in its status color, and the grand total over a dark rule with a double rule under its figure.
16035
16678
  */
16036
16679
 
16037
16680
  .LineItemGrid {
@@ -16096,6 +16739,33 @@ textarea.FieldControl {
16096
16739
  bottom: var(--sl-table-row-height);
16097
16740
  }
16098
16741
 
16742
+ /* Ruled totals (a footer row's total): no tray band. The rules come from the Table's total rows and
16743
+ * run under the figures only; the row keeps an opaque sheet so it can still stick over the lines.
16744
+ * 'line' is a plain row under a total, such as "Unallocated", with no rule at all. */
16745
+ .LineItemGridTable > tfoot > tr[data-total] > * {
16746
+ background: var(--sl-surface-base);
16747
+ font-weight: var(--sl-font-weight-semibold);
16748
+ }
16749
+
16750
+ .LineItemGridTable > tfoot > tr[data-total] > th {
16751
+ font-family: var(--sl-font-body-condense-font-family);
16752
+ }
16753
+
16754
+ .LineItemGridTable > tfoot > tr[data-total='line'] > :is(th, td, [data-rule]) {
16755
+ border-top-color: transparent;
16756
+ font-weight: var(--sl-font-weight-normal);
16757
+ }
16758
+
16759
+ /* Only the first total row keeps the footer's line across the row; the ones under it rule their figures only. */
16760
+ .LineItemGridTable > tfoot > tr[data-total] + tr[data-total] > [data-rule='none'] {
16761
+ border-top-color: transparent;
16762
+ }
16763
+
16764
+ .LineItemGridTable > tfoot > tr[data-total] > [data-align='end'] {
16765
+ font-family: var(--sl-font-figures-base-font-family);
16766
+ font-variant-numeric: tabular-nums;
16767
+ }
16768
+
16099
16769
  .LineItemGridTable > tfoot > tr[data-tone='success'] > [data-align='end'] {
16100
16770
  color: var(--sl-status-success-dark);
16101
16771
  }
@@ -16106,9 +16776,138 @@ textarea.FieldControl {
16106
16776
 
16107
16777
  .LineItemGridAdd {
16108
16778
  display: flex;
16779
+ flex-wrap: wrap;
16780
+ align-items: center;
16781
+ gap: var(--sl-space-2) var(--sl-space-3);
16782
+ }
16783
+
16784
+ .LineItemGridAddHint {
16785
+ font-family: var(--sl-font-body-minimize-font-family);
16786
+ font-size: var(--sl-font-body-minimize-font-size);
16787
+ font-weight: var(--sl-font-body-minimize-font-weight);
16788
+ line-height: var(--sl-font-body-minimize-line-height);
16789
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
16790
+ font-size: 13px;
16791
+ color: var(--sl-text-secondary);
16792
+ }
16793
+
16794
+ /* Statement look: open lines with caps headers, as on the boards' allocation tables. */
16795
+ .LineItemGridTable[data-look='statement'] {
16796
+ --statement-padding-start: 6px;
16797
+ --statement-padding-end: 6px;
16798
+ min-width: 36rem;
16799
+ }
16800
+
16801
+ .LineItemGridTable[data-look='statement'] > thead th {
16802
+ height: 34px;
16803
+ padding-block: 0 6px;
16804
+ font-size: 11px;
16805
+ color: var(--sl-text-secondary);
16806
+ }
16807
+
16808
+ .LineItemGridTable[data-look='statement'] > tbody > tr > td {
16809
+ height: 52px;
16810
+ padding-block: 6px;
16811
+ vertical-align: middle;
16812
+ }
16813
+
16814
+ .LineItemGrid[data-look='statement'] .LineItemGridAdd {
16815
+ padding-block-start: var(--sl-space-1);
16816
+ }
16817
+
16818
+ /* The totals under the Add button: Allocated, Unallocated, Transaction total. */
16819
+ .LineItemGrid > .Table.LineItemGridSummary {
16820
+ border: var(--sl-stroke-default) solid var(--sl-sheet-border-color);
16821
+ border-top: var(--sl-sheet-rule-width) solid var(--sl-sheet-rule-color);
16822
+ border-radius: 0;
16823
+ background: var(--sl-surface-base);
16824
+ }
16825
+
16826
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr > :is(th, td) {
16827
+ height: auto;
16828
+ padding: 2px 12px;
16829
+ border: 0;
16830
+ background: transparent;
16831
+ font-family: var(--sl-font-body-condense-font-family);
16832
+ font-size: 15px;
16833
+ font-weight: var(--sl-font-weight-normal);
16834
+ letter-spacing: normal;
16835
+ text-transform: none;
16836
+ color: var(--sl-text-primary);
16837
+ }
16838
+
16839
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr:first-child > * {
16840
+ padding-block-start: 10px;
16841
+ }
16842
+
16843
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr:last-child > * {
16844
+ padding-block-end: 10px;
16845
+ }
16846
+
16847
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr > [data-align='end'] {
16848
+ text-align: end;
16849
+ font-family: var(--sl-font-figures-base-font-family);
16850
+ font-size: 14px;
16851
+ }
16852
+
16853
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr[data-tone] > * {
16854
+ font-weight: var(--sl-font-weight-semibold);
16855
+ }
16856
+
16857
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr[data-tone='error'] > * {
16858
+ color: var(--sl-text-accent);
16859
+ }
16860
+
16861
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr[data-tone='success'] > * {
16862
+ color: var(--sl-status-success-dark);
16863
+ }
16864
+
16865
+ .LineItemGrid > .Table.LineItemGridSummary > tbody > tr[data-total='grand'] > * {
16866
+ padding-block-start: 4px;
16867
+ border-top: var(--sl-stroke-default) solid var(--sl-text-primary);
16868
+ font-weight: 700;
16869
+ }
16870
+
16871
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16872
+ /* FileDropZone
16873
+ *
16874
+ * A dashed, quiet box with one line of text and its buttons. It fills when a file is dragged over it.
16875
+ * Colors are the fill and border roles, so a brand restyles it without a component token.
16876
+ */
16877
+
16878
+ .FileDropZone {
16879
+ display: flex;
16880
+ flex-direction: column;
16881
+ align-items: center;
16882
+ gap: var(--sl-space-3);
16883
+ padding: var(--sl-space-6) var(--sl-space-4);
16884
+ /* The control border, not the hairline: the zone is something to find and drop on. */
16885
+ border: var(--sl-stroke-default) dashed var(--sl-border-strong);
16886
+ border-radius: var(--sl-radius-base);
16887
+ text-align: center;
16888
+ }
16889
+
16890
+ .FileDropZone[data-over] {
16891
+ background: var(--sl-fill-subtle);
16892
+ border-color: var(--sl-text-primary);
16893
+ }
16894
+
16895
+ .FileDropZone[data-disabled] {
16896
+ opacity: 0.6;
16897
+ }
16898
+
16899
+ .FileDropZoneText {
16900
+ margin: 0;
16901
+ }
16902
+
16903
+ .FileDropZoneActions {
16904
+ display: flex;
16905
+ flex-wrap: wrap;
16906
+ justify-content: center;
16907
+ gap: var(--sl-gap-control);
16109
16908
  }
16110
16909
 
16111
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16910
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16112
16911
  /* Spinner
16113
16912
  *
16114
16913
  * A ring that turns: the track in the subtle border, the moving arc in the accent border.
@@ -16144,66 +16943,842 @@ textarea.FieldControl {
16144
16943
  }
16145
16944
  }
16146
16945
 
16147
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16148
- /* AppBar
16946
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
16947
+ /* RadioCard
16149
16948
  *
16150
- * The bar across the top of an app window, one row on a line in the rule color. The line is
16151
- * app-bar.border-width while rule.width is 0, and the thicker of the two once a brand turns the
16152
- * rule on, so an ink-rule brand gets the working-paper rule under its app bar.
16153
- * AppBarSpacer pushes what follows it to the end. A vertical Separator inside is a short
16154
- * divider between groups of icon actions. Tokens: app-bar.* (tokens/component/app-bar.json).
16949
+ * A Radio Group drawn as a grid of cards. Each card is the radio (a span with role radio): a
16950
+ * preview, a bold label and a quiet description, on the raised surface with a 1px default border.
16951
+ * The chosen card's border is 2px in the text color (the padding gives back the extra pixel so
16952
+ * nothing moves) and a round check sits on its top right corner, half outside the card.
16155
16953
  */
16156
16954
 
16157
- .AppBar {
16955
+ .RadioCardGroup {
16956
+ --radio-card-columns: 3;
16957
+ --radio-card-min: 8rem;
16958
+ display: grid;
16959
+ grid-template-columns: repeat(auto-fill, minmax(max(var(--radio-card-min), calc((100% - (var(--radio-card-columns) - 1) * var(--sl-space-3)) / var(--radio-card-columns))), 1fr));
16960
+ gap: var(--sl-space-3);
16961
+ /* Room for the check marker, which sits half outside the top right corner. */
16962
+ padding: 10px 10px 0 0;
16963
+ }
16964
+
16965
+ .RadioCard {
16966
+ position: relative;
16158
16967
  box-sizing: border-box;
16159
16968
  display: flex;
16160
- align-items: center;
16161
- gap: var(--sl-app-bar-gap);
16162
- min-height: var(--sl-app-bar-height);
16163
- padding-inline: var(--sl-app-bar-padding-inline);
16164
- padding-block: var(--sl-space-2);
16165
- background: var(--sl-app-bar-background);
16166
- border-bottom: max(var(--sl-app-bar-border-width), var(--sl-rule-width)) solid var(--sl-app-bar-border-color);
16969
+ flex-direction: column;
16970
+ align-items: stretch;
16971
+ gap: var(--sl-space-2);
16167
16972
  min-width: 0;
16973
+ padding: 12px;
16974
+ border: 1px solid var(--sl-border-default);
16975
+ border-radius: var(--sl-radius-control);
16976
+ background: var(--sl-surface-raised);
16977
+ color: var(--sl-text-primary);
16978
+ cursor: pointer;
16979
+ text-align: left;
16980
+ outline: none;
16168
16981
  }
16169
16982
 
16170
- .AppBarSpacer {
16171
- flex: 1 1 var(--sl-space-4);
16172
- min-width: 0;
16983
+ .RadioCard:hover:not([data-disabled]):not([data-checked]) {
16984
+ border-color: var(--sl-text-secondary);
16173
16985
  }
16174
16986
 
16175
- .AppBar .Separator[data-orientation='vertical'] {
16176
- height: var(--sl-app-bar-divider-height);
16177
- margin-inline: var(--sl-space-1);
16178
- background: var(--sl-app-bar-divider-color);
16987
+ .RadioCard[data-checked] {
16988
+ border: 2px solid var(--sl-text-primary);
16989
+ padding: 11px;
16179
16990
  }
16180
16991
 
16181
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16182
- /* PickerButton
16183
- *
16184
- * A trigger with a caps label before the current choice: CLIENT Alpha Services. The field
16185
- * look and states of a Select trigger; the label is caps-condense in picker-button.label-color,
16186
- * the choice is cut with an ellipsis at picker-button.max-width and the chevron turns while
16187
- * its popup is open. Label and choice are centered on the control's height, so a caps label and its choice sit level at any font size;
16188
- * picker-button.text-offset nudges both down for a typeface that sits high. Tokens: picker-button.* (tokens/component/picker-button.json) and field.*.
16189
- */
16190
-
16191
- .PickerButton {
16192
- box-sizing: border-box;
16992
+ .RadioCard:focus-visible {
16993
+ outline: var(--sl-focus-outline);
16994
+ outline-offset: var(--sl-focus-outline-offset);
16995
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
16996
+ }
16997
+
16998
+ .RadioCard[data-disabled] {
16999
+ opacity: var(--sl-check-opacity-disabled);
17000
+ cursor: not-allowed;
17001
+ }
17002
+
17003
+ .RadioCardPreview {
17004
+ display: flex;
17005
+ min-width: 0;
17006
+ }
17007
+
17008
+ .RadioCardPreview > * {
17009
+ flex: 1;
17010
+ min-width: 0;
17011
+ }
17012
+
17013
+ .RadioCardLabel {
17014
+ font-family: var(--sl-font-subtitle-base-font-family);
17015
+ font-size: var(--sl-font-subtitle-base-font-size);
17016
+ font-weight: var(--sl-font-subtitle-base-font-weight);
17017
+ line-height: var(--sl-font-subtitle-base-line-height);
17018
+ letter-spacing: var(--sl-font-subtitle-base-letter-spacing);
17019
+ min-width: 0;
17020
+ }
17021
+
17022
+ .RadioCardDescription {
17023
+ font-family: var(--sl-font-body-condense-font-family);
17024
+ font-size: var(--sl-font-body-condense-font-size);
17025
+ font-weight: var(--sl-font-body-condense-font-weight);
17026
+ line-height: var(--sl-font-body-condense-line-height);
17027
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17028
+ margin-top: calc(var(--sl-space-2) * -1 + 2px);
17029
+ color: var(--sl-text-secondary);
17030
+ }
17031
+
17032
+ .RadioCardMark {
17033
+ position: absolute;
17034
+ top: -10px;
17035
+ right: -10px;
17036
+ display: inline-flex;
17037
+ align-items: center;
17038
+ justify-content: center;
17039
+ width: 20px;
17040
+ height: 20px;
17041
+ border: 2px solid var(--sl-surface-raised);
17042
+ border-radius: var(--sl-radius-pill);
17043
+ background: var(--sl-text-primary);
17044
+ color: var(--sl-surface-raised);
17045
+ }
17046
+
17047
+ .RadioCardMark[data-unchecked] {
17048
+ display: none;
17049
+ }
17050
+
17051
+ @media (forced-colors: active) {
17052
+ .RadioCard[data-checked] {
17053
+ border-color: Highlight;
17054
+ }
17055
+
17056
+ .RadioCardMark {
17057
+ background: Highlight;
17058
+ color: HighlightText;
17059
+ }
17060
+ }
17061
+
17062
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17063
+ /* Stepper
17064
+ *
17065
+ * Numbered steps in one row: a marker on a line, then the name and a short line under it. Done
17066
+ * markers are filled dark with a check and the line after them is solid; the current marker is
17067
+ * the accent fill; later markers are dashed rings on a quiet line.
17068
+ */
17069
+
17070
+ .Stepper {
17071
+ --stepper-marker: 1.75rem;
17072
+ display: grid;
17073
+ grid-auto-columns: minmax(0, 1fr);
17074
+ grid-auto-flow: column;
17075
+ margin: 0;
17076
+ padding: 0;
17077
+ list-style: none;
17078
+ }
17079
+
17080
+ .StepperStep {
17081
+ position: relative;
17082
+ min-width: 0;
17083
+ }
17084
+
17085
+ /* The line from this marker to the next one. */
17086
+ .StepperStep:not(:last-child)::after {
17087
+ content: '';
17088
+ position: absolute;
17089
+ top: calc(var(--stepper-marker) / 2);
17090
+ left: calc(var(--stepper-marker) + var(--sl-space-2));
17091
+ right: var(--sl-space-2);
17092
+ border-top: 2px solid var(--sl-border-default);
17093
+ }
17094
+
17095
+ .StepperStep[data-state='done']:not(:last-child)::after {
17096
+ border-top-color: var(--sl-text-primary);
17097
+ }
17098
+
17099
+ .StepperButton {
17100
+ display: flex;
17101
+ flex-direction: column;
17102
+ align-items: flex-start;
17103
+ gap: var(--sl-space-3);
17104
+ padding: 0;
17105
+ border: 0;
17106
+ background: none;
17107
+ color: inherit;
17108
+ font: inherit;
17109
+ text-align: left;
17110
+ }
17111
+
17112
+ button.StepperButton {
17113
+ cursor: pointer;
17114
+ }
17115
+
17116
+ button.StepperButton:focus-visible {
17117
+ outline: var(--sl-focus-outline);
17118
+ outline-offset: var(--sl-focus-outline-offset);
17119
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
17120
+ }
17121
+
17122
+ button.StepperButton:hover .StepperLabel {
17123
+ text-decoration: underline;
17124
+ }
17125
+
17126
+ .StepperMarker {
17127
+ font-family: var(--sl-font-figures-condense-font-family);
17128
+ font-size: var(--sl-font-figures-condense-font-size);
17129
+ font-weight: var(--sl-font-figures-condense-font-weight);
17130
+ line-height: var(--sl-font-figures-condense-line-height);
17131
+ letter-spacing: var(--sl-font-figures-condense-letter-spacing);
17132
+ font-variant-numeric: var(--sl-font-figures-condense-font-variant-numeric);
17133
+ display: inline-flex;
17134
+ align-items: center;
17135
+ justify-content: center;
17136
+ width: var(--stepper-marker);
17137
+ height: var(--stepper-marker);
17138
+ border-radius: 999px;
17139
+ border: 1.5px dashed var(--sl-border-strong);
17140
+ color: var(--sl-text-secondary);
17141
+ background: var(--sl-surface-base);
17142
+ }
17143
+
17144
+ .StepperStep[data-state='done'] .StepperMarker {
17145
+ border: 1.5px solid var(--sl-text-primary);
17146
+ background: var(--sl-text-primary);
17147
+ color: var(--sl-surface-base);
17148
+ }
17149
+
17150
+ .StepperStep[data-state='current'] .StepperMarker {
17151
+ border: 1.5px solid var(--sl-interactive-default);
17152
+ background: var(--sl-interactive-default);
17153
+ color: var(--sl-text-on-primary);
17154
+ }
17155
+
17156
+ .StepperText {
17157
+ display: flex;
17158
+ flex-direction: column;
17159
+ gap: 0.15rem;
17160
+ min-width: 0;
17161
+ }
17162
+
17163
+ .StepperLabel {
17164
+ font-family: var(--sl-font-subtitle-condense-font-family);
17165
+ font-size: var(--sl-font-subtitle-condense-font-size);
17166
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
17167
+ line-height: var(--sl-font-subtitle-condense-line-height);
17168
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
17169
+ color: var(--sl-text-primary);
17170
+ }
17171
+
17172
+ .StepperStep[data-state='upcoming'] .StepperLabel {
17173
+ color: var(--sl-text-secondary);
17174
+ }
17175
+
17176
+ .StepperDescription {
17177
+ font-family: var(--sl-font-body-condense-font-family);
17178
+ font-size: var(--sl-font-body-condense-font-size);
17179
+ font-weight: var(--sl-font-body-condense-font-weight);
17180
+ line-height: var(--sl-font-body-condense-line-height);
17181
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17182
+ color: var(--sl-text-secondary);
17183
+ }
17184
+
17185
+ .StepperStatus {
17186
+ position: absolute;
17187
+ width: 1px;
17188
+ height: 1px;
17189
+ overflow: hidden;
17190
+ clip-path: inset(50%);
17191
+ white-space: nowrap;
17192
+ }
17193
+
17194
+ @media (max-width: 40rem) {
17195
+ .Stepper {
17196
+ grid-auto-flow: row;
17197
+ gap: var(--sl-space-3);
17198
+ }
17199
+ .StepperStep:not(:last-child)::after {
17200
+ display: none;
17201
+ }
17202
+ .StepperButton {
17203
+ flex-direction: row;
17204
+ align-items: center;
17205
+ }
17206
+ }
17207
+
17208
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17209
+ /* SourcePreview
17210
+ *
17211
+ * A file's lines or a worksheet's rows in a ruled frame: the number in a quiet first column, rows
17212
+ * on hairlines, a header line with an accent edge and a tint, skipped lines struck through. Rows
17213
+ * share one grid (subgrid) so cells line up down the columns. Wide content scrolls inside.
17214
+ */
17215
+
17216
+ .SourcePreview {
17217
+ border: 1px solid var(--sl-border-default);
17218
+ background: var(--sl-surface-raised);
17219
+ min-width: 0;
17220
+ }
17221
+
17222
+ .SourcePreviewScroll {
17223
+ overflow-x: auto;
17224
+ }
17225
+
17226
+ .SourcePreviewGrid {
17227
+ display: grid;
17228
+ grid-template-columns: var(--source-preview-columns);
17229
+ min-width: 100%;
17230
+ width: max-content;
17231
+ }
17232
+
17233
+ .SourcePreviewRow {
17234
+ display: grid;
17235
+ grid-column: 1 / -1;
17236
+ grid-template-columns: subgrid;
17237
+ align-items: baseline;
17238
+ border-bottom: 1px solid var(--sl-border-subtle);
17239
+ font-family: var(--sl-font-body-condense-font-family);
17240
+ font-size: var(--sl-font-body-condense-font-size);
17241
+ font-weight: var(--sl-font-body-condense-font-weight);
17242
+ line-height: var(--sl-font-body-condense-line-height);
17243
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17244
+ color: var(--sl-text-primary);
17245
+ }
17246
+
17247
+ .SourcePreviewRow:last-child {
17248
+ border-bottom: 0;
17249
+ }
17250
+
17251
+ .SourcePreviewRow > * {
17252
+ padding: var(--sl-space-2) var(--sl-space-3);
17253
+ min-width: 0;
17254
+ }
17255
+
17256
+ .SourcePreview[data-mono] .SourcePreviewCell {
17257
+ font-family: var(--sl-font-code-condense-font-family);
17258
+ font-size: var(--sl-font-code-condense-font-size);
17259
+ font-weight: var(--sl-font-code-condense-font-weight);
17260
+ line-height: var(--sl-font-code-condense-line-height);
17261
+ letter-spacing: var(--sl-font-code-condense-letter-spacing);
17262
+ white-space: pre;
17263
+ overflow: hidden;
17264
+ text-overflow: ellipsis;
17265
+ max-width: 60ch;
17266
+ }
17267
+
17268
+ .SourcePreviewHead {
17269
+ border-bottom: 1px solid var(--sl-border-strong);
17270
+ font-family: var(--sl-font-label-base-font-family);
17271
+ font-size: var(--sl-font-label-base-font-size);
17272
+ font-weight: var(--sl-font-label-base-font-weight);
17273
+ line-height: var(--sl-font-label-base-line-height);
17274
+ letter-spacing: var(--sl-font-label-base-letter-spacing);
17275
+ }
17276
+
17277
+ .SourcePreviewHead > * {
17278
+ display: inline-flex;
17279
+ align-items: center;
17280
+ gap: var(--sl-space-2);
17281
+ }
17282
+
17283
+ .SourcePreviewNumber {
17284
+ font-family: var(--sl-font-code-condense-font-family);
17285
+ font-size: var(--sl-font-code-condense-font-size);
17286
+ font-weight: var(--sl-font-code-condense-font-weight);
17287
+ line-height: var(--sl-font-code-condense-line-height);
17288
+ letter-spacing: var(--sl-font-code-condense-letter-spacing);
17289
+ color: var(--sl-text-secondary);
17290
+ text-align: right;
17291
+ }
17292
+
17293
+ .SourcePreviewHead .SourcePreviewNumber {
17294
+ justify-content: flex-start;
17295
+ }
17296
+
17297
+ [data-align='end'] {
17298
+ text-align: right;
17299
+ justify-content: flex-end;
17300
+ }
17301
+
17302
+ .SourcePreviewDot {
17303
+ width: 0.45rem;
17304
+ height: 0.45rem;
17305
+ border-radius: 999px;
17306
+ background: var(--sl-text-primary);
17307
+ flex: none;
17308
+ }
17309
+
17310
+ .SourcePreviewIgnored {
17311
+ display: inline-flex;
17312
+ color: var(--sl-text-secondary);
17313
+ }
17314
+
17315
+ .SourcePreviewCell[data-marker='ignored'],
17316
+ .SourcePreviewColumn[data-marker='ignored'] {
17317
+ color: var(--sl-text-secondary);
17318
+ }
17319
+
17320
+ .SourcePreviewRow[data-state='skipped'] .SourcePreviewCell {
17321
+ color: var(--sl-text-secondary);
17322
+ text-decoration: line-through;
17323
+ }
17324
+
17325
+ .SourcePreviewRow[data-state='header'] {
17326
+ background: color-mix(in srgb, var(--sl-interactive-default) 7%, transparent);
17327
+ box-shadow: inset 3px 0 0 var(--sl-interactive-default);
17328
+ }
17329
+
17330
+ .SourcePreviewRow[data-state='header'] .SourcePreviewCell {
17331
+ font-weight: 600;
17332
+ }
17333
+
17334
+ .SourcePreviewTag {
17335
+ font-family: var(--sl-font-caps-condense-font-family);
17336
+ font-size: var(--sl-font-caps-condense-font-size);
17337
+ font-weight: var(--sl-font-caps-condense-font-weight);
17338
+ line-height: var(--sl-font-caps-condense-line-height);
17339
+ letter-spacing: var(--sl-font-caps-condense-letter-spacing);
17340
+ text-transform: var(--sl-font-caps-condense-text-transform);
17341
+ color: var(--sl-text-accent);
17342
+ text-align: right;
17343
+ }
17344
+
17345
+ .SourcePreviewRow[role='radio'] {
17346
+ cursor: pointer;
17347
+ }
17348
+
17349
+ .SourcePreviewRow[role='radio']:hover {
17350
+ background: var(--sl-surface-tray);
17351
+ }
17352
+
17353
+ .SourcePreviewRow[role='radio']:focus-visible {
17354
+ outline: 2px solid var(--sl-interactive-default);
17355
+ outline-offset: -2px;
17356
+ }
17357
+
17358
+ .SourcePreviewCell[data-formula] {
17359
+ background: color-mix(in srgb, var(--sl-interactive-default) 7%, transparent);
17360
+ white-space: nowrap;
17361
+ }
17362
+
17363
+ .SourcePreviewFx {
17364
+ font-family: var(--sl-font-code-condense-font-family);
17365
+ font-size: var(--sl-font-code-condense-font-size);
17366
+ font-weight: var(--sl-font-code-condense-font-weight);
17367
+ line-height: var(--sl-font-code-condense-line-height);
17368
+ letter-spacing: var(--sl-font-code-condense-letter-spacing);
17369
+ display: inline-block;
17370
+ margin-left: var(--sl-space-1);
17371
+ padding: 0 0.2rem;
17372
+ border: 1px dashed var(--sl-text-accent);
17373
+ color: var(--sl-text-accent);
17374
+ font-size: 0.75em;
17375
+ line-height: 1.3;
17376
+ }
17377
+
17378
+ .SourcePreviewHint {
17379
+ padding: var(--sl-space-2) var(--sl-space-3);
17380
+ border-top: 1px solid var(--sl-border-subtle);
17381
+ font-family: var(--sl-font-body-condense-font-family);
17382
+ font-size: var(--sl-font-body-condense-font-size);
17383
+ font-weight: var(--sl-font-body-condense-font-weight);
17384
+ line-height: var(--sl-font-body-condense-line-height);
17385
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17386
+ color: var(--sl-text-secondary);
17387
+ }
17388
+
17389
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17390
+ /* SummaryStrip
17391
+ *
17392
+ * A framed row of label / value / link items, divided by hairlines. Labels are caps; the link sits
17393
+ * under the value. Items wrap on narrow screens.
17394
+ */
17395
+
17396
+ .SummaryStrip {
17397
+ display: flex;
17398
+ flex-wrap: wrap;
17399
+ margin: 0;
17400
+ border: 1px solid var(--sl-border-default);
17401
+ background: var(--sl-surface-raised);
17402
+ }
17403
+
17404
+ .SummaryStripItem {
17405
+ display: flex;
17406
+ flex-direction: column;
17407
+ gap: 0.15rem;
17408
+ min-width: 0;
17409
+ padding: var(--sl-space-3) var(--sl-space-4);
17410
+ border-right: 1px solid var(--sl-border-subtle);
17411
+ }
17412
+
17413
+ .SummaryStripLabel {
17414
+ font-family: var(--sl-font-caps-condense-font-family);
17415
+ font-size: var(--sl-font-caps-condense-font-size);
17416
+ font-weight: var(--sl-font-caps-condense-font-weight);
17417
+ line-height: var(--sl-font-caps-condense-line-height);
17418
+ letter-spacing: var(--sl-font-caps-condense-letter-spacing);
17419
+ text-transform: var(--sl-font-caps-condense-text-transform);
17420
+ color: var(--sl-text-secondary);
17421
+ }
17422
+
17423
+ .SummaryStripValue {
17424
+ margin: 0;
17425
+ font-family: var(--sl-font-body-base-font-family);
17426
+ font-size: var(--sl-font-body-base-font-size);
17427
+ font-weight: var(--sl-font-body-base-font-weight);
17428
+ line-height: var(--sl-font-body-base-line-height);
17429
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
17430
+ color: var(--sl-text-primary);
17431
+ }
17432
+
17433
+ /* The action is a small link under the value: semibold accent, no underline, so the value leads. */
17434
+ .SummaryStripAction {
17435
+ margin: 0;
17436
+ font-family: var(--sl-font-body-condense-font-family);
17437
+ font-size: var(--sl-font-body-condense-font-size);
17438
+ font-weight: var(--sl-font-body-condense-font-weight);
17439
+ line-height: var(--sl-font-body-condense-line-height);
17440
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17441
+ }
17442
+
17443
+ .SummaryStripAction .Button {
17444
+ font-weight: 600;
17445
+ text-decoration: none;
17446
+ }
17447
+
17448
+ .SummaryStripAction .Button {
17449
+ height: auto;
17450
+ padding: 0;
17451
+ }
17452
+
17453
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17454
+ /* Text
17455
+ *
17456
+ * A line of body text. md is body-base, sm body-condense, lg body-magnify: whole styles, not a
17457
+ * font-size on its own. secondary is the quiet line under a heading or beside a control. No
17458
+ * margin: the parent's gap spaces it.
17459
+ */
17460
+
17461
+ .Text {
17462
+ font-family: var(--sl-font-body-base-font-family);
17463
+ font-size: var(--sl-font-body-base-font-size);
17464
+ font-weight: var(--sl-font-body-base-font-weight);
17465
+ line-height: var(--sl-font-body-base-line-height);
17466
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
17467
+ margin: 0;
17468
+ color: var(--sl-text-primary);
17469
+ }
17470
+
17471
+ .Text[data-size='sm'] {
17472
+ font-family: var(--sl-font-body-condense-font-family);
17473
+ font-size: var(--sl-font-body-condense-font-size);
17474
+ font-weight: var(--sl-font-body-condense-font-weight);
17475
+ line-height: var(--sl-font-body-condense-line-height);
17476
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
17477
+ }
17478
+
17479
+ .Text[data-size='lg'] {
17480
+ font-family: var(--sl-font-body-magnify-font-family);
17481
+ font-size: var(--sl-font-body-magnify-font-size);
17482
+ font-weight: var(--sl-font-body-magnify-font-weight);
17483
+ line-height: var(--sl-font-body-magnify-line-height);
17484
+ letter-spacing: var(--sl-font-body-magnify-letter-spacing);
17485
+ }
17486
+
17487
+ .Text[data-tone='secondary'] {
17488
+ color: var(--sl-text-secondary);
17489
+ }
17490
+
17491
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17492
+ /* AppBar
17493
+ *
17494
+ * The bar across the top of an app window, one row on a line in the rule color. The line is
17495
+ * app-bar.border-width while rule.width is 0, and the thicker of the two once a brand turns the
17496
+ * rule on, so an ink-rule brand gets the working-paper rule under its app bar.
17497
+ * AppBarSpacer pushes what follows it to the end. A vertical Separator inside is a short
17498
+ * divider between groups of icon actions. Tokens: app-bar.* (tokens/component/app-bar.json).
17499
+ */
17500
+
17501
+ .AppBar {
17502
+ box-sizing: border-box;
17503
+ display: flex;
17504
+ align-items: center;
17505
+ gap: var(--sl-app-bar-gap);
17506
+ min-height: var(--sl-app-bar-height);
17507
+ padding-inline: var(--sl-app-bar-padding-inline);
17508
+ padding-block: var(--sl-space-2);
17509
+ background: var(--sl-app-bar-background);
17510
+ border-bottom: max(var(--sl-app-bar-border-width), var(--sl-rule-width)) solid var(--sl-app-bar-border-color);
17511
+ min-width: 0;
17512
+ }
17513
+
17514
+ .AppBarSpacer {
17515
+ flex: 1 1 var(--sl-space-4);
17516
+ min-width: 0;
17517
+ }
17518
+
17519
+ .AppBar .Separator[data-orientation='vertical'] {
17520
+ height: var(--sl-app-bar-divider-height);
17521
+ margin-inline: var(--sl-space-1);
17522
+ background: var(--sl-app-bar-divider-color);
17523
+ }
17524
+
17525
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17526
+ /* PickerButton
17527
+ *
17528
+ * A trigger with a caps label before the current choice: CLIENT Alpha Services. The field
17529
+ * look and states of a Select trigger; the label is caps-condense in picker-button.label-color,
17530
+ * the choice is cut with an ellipsis at picker-button.max-width and the chevron turns while
17531
+ * its popup is open. Label and choice are centered on the control's height, so a caps label and its choice sit level at any font size;
17532
+ * picker-button.text-offset nudges both down for a typeface that sits high. Tokens: picker-button.* (tokens/component/picker-button.json) and field.*.
17533
+ */
17534
+
17535
+ .PickerButton {
17536
+ box-sizing: border-box;
17537
+ color: var(--sl-field-color);
17538
+ background: var(--sl-field-background);
17539
+ border: var(--sl-field-border-width) solid var(--sl-field-border-color);
17540
+ border-radius: var(--sl-field-radius);
17541
+ transition: var(--sl-field-transition);
17542
+ outline: none;
17543
+ font-family: var(--sl-font-body-base-font-family);
17544
+ font-size: var(--sl-font-body-base-font-size);
17545
+ font-weight: var(--sl-font-body-base-font-weight);
17546
+ line-height: var(--sl-font-body-base-line-height);
17547
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
17548
+ /* A grid, not a flex row: label and choice are centered on the same line, and align-content centers that
17549
+ pair in the button's height. The choice column shrinks so a long choice gets its ellipsis. */
17550
+ display: inline-grid;
17551
+ grid-auto-flow: column;
17552
+ grid-template-columns: max-content minmax(0, max-content);
17553
+ grid-auto-columns: max-content;
17554
+ align-items: center;
17555
+ align-content: center;
17556
+ justify-content: start;
17557
+ gap: var(--sl-gap-control);
17558
+ max-width: var(--sl-picker-button-max-width);
17559
+ min-width: 0;
17560
+ height: var(--sl-control-height-md);
17561
+ margin: 0;
17562
+ padding-block: var(--sl-control-padding-block);
17563
+ padding-inline: var(--sl-control-padding-inline);
17564
+ cursor: pointer;
17565
+ white-space: nowrap;
17566
+ }
17567
+
17568
+ .PickerButton:hover:not(:disabled) {
17569
+ border-color: var(--sl-field-border-color-hover);
17570
+ background: var(--sl-fill-subtle);
17571
+ }
17572
+
17573
+ .PickerButton:focus-visible {
17574
+ border-color: var(--sl-field-border-color-focus);
17575
+ box-shadow: var(--sl-field-shadow-focus);
17576
+ }
17577
+
17578
+ .PickerButton:disabled {
17579
+ background: var(--sl-field-background-disabled);
17580
+ color: var(--sl-field-color-disabled);
17581
+ cursor: not-allowed;
17582
+ }
17583
+
17584
+ .PickerButtonLabel {
17585
+ font-family: var(--sl-font-caps-condense-font-family);
17586
+ font-size: var(--sl-font-caps-condense-font-size);
17587
+ font-weight: var(--sl-font-caps-condense-font-weight);
17588
+ line-height: var(--sl-font-caps-condense-line-height);
17589
+ letter-spacing: var(--sl-font-caps-condense-letter-spacing);
17590
+ text-transform: var(--sl-font-caps-condense-text-transform);
17591
+ position: relative;
17592
+ top: var(--sl-picker-button-text-offset);
17593
+ flex: none;
17594
+ color: var(--sl-picker-button-label-color);
17595
+ }
17596
+
17597
+ .PickerButtonValue {
17598
+ position: relative;
17599
+ top: var(--sl-picker-button-text-offset);
17600
+ flex: 0 1 auto;
17601
+ min-width: 0;
17602
+ overflow: hidden;
17603
+ text-overflow: ellipsis;
17604
+ color: var(--sl-field-color);
17605
+ }
17606
+
17607
+ .PickerButtonValue[data-placeholder] {
17608
+ color: var(--sl-field-placeholder-color);
17609
+ }
17610
+
17611
+ .PickerButtonIcon {
17612
+ flex: none;
17613
+ align-self: center;
17614
+ width: var(--sl-icon-size-base);
17615
+ height: var(--sl-icon-size-base);
17616
+ color: var(--sl-text-tertiary);
17617
+ transition: transform var(--sl-duration-normal) var(--sl-easing-default);
17618
+ }
17619
+
17620
+ .PickerButton[aria-expanded='true'] .PickerButtonIcon,
17621
+ .PickerButton[data-popup-open] .PickerButtonIcon {
17622
+ transform: rotate(180deg);
17623
+ }
17624
+
17625
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17626
+ /* MultiSelect
17627
+ *
17628
+ * A PickerButton trigger that opens a popover of checkbox rows (label, count at the end) and a
17629
+ * footer with "Show all" and "Done". The rows reuse the Checkbox look; the counts are mono so
17630
+ * they line up. The popup is at least as wide as its widest row and never narrower than
17631
+ * popup.min-width.
17632
+ */
17633
+
17634
+ .MultiSelectPopup {
17635
+ min-width: var(--sl-popup-min-width);
17636
+ padding: 0;
17637
+ }
17638
+
17639
+ .MultiSelectList {
17640
+ display: flex;
17641
+ flex-direction: column;
17642
+ padding-block: var(--sl-space-block-xs);
17643
+ }
17644
+
17645
+ .MultiSelectOption {
17646
+ display: flex;
17647
+ flex-direction: row; /* an app's global label rule may stack children */
17648
+ align-items: center;
17649
+ gap: var(--sl-gap-control);
17650
+ padding-inline: var(--sl-control-padding-inline);
17651
+ cursor: pointer;
17652
+ }
17653
+
17654
+ .MultiSelectOption:hover {
17655
+ background: var(--sl-fill-subtle);
17656
+ }
17657
+
17658
+ .MultiSelectOptionLabel {
17659
+ flex: 1;
17660
+ min-width: 0;
17661
+ text-align: start;
17662
+ }
17663
+
17664
+ .MultiSelectOption[data-disabled] {
17665
+ cursor: not-allowed;
17666
+ color: var(--sl-text-tertiary);
17667
+ }
17668
+
17669
+ .MultiSelectOption[data-disabled]:hover {
17670
+ background: none;
17671
+ }
17672
+
17673
+ .MultiSelectOptionHint {
17674
+ flex: none;
17675
+ color: var(--sl-text-tertiary);
17676
+ font-size: var(--sl-font-size-sm);
17677
+ }
17678
+
17679
+ .MultiSelectOptionCount {
17680
+ flex: none;
17681
+ font-family: var(--sl-font-family-mono, ui-monospace, monospace);
17682
+ font-variant-numeric: tabular-nums;
17683
+ color: var(--sl-text-tertiary);
17684
+ }
17685
+
17686
+ .MultiSelectFooter {
17687
+ display: flex;
17688
+ justify-content: space-between;
17689
+ gap: var(--sl-gap-control);
17690
+ padding: var(--sl-space-block-xs) var(--sl-control-padding-inline);
17691
+ border-top: 1px solid var(--sl-popup-separator-color);
17692
+ }
17693
+
17694
+ /* labelPlacement="above": the label over a Select-style trigger, like the fields beside it. */
17695
+ .MultiSelectField {
17696
+ display: flex;
17697
+ flex-direction: column;
17698
+ min-width: 0;
17699
+ }
17700
+
17701
+ .MultiSelectField .MultiSelectTrigger {
17702
+ min-width: 12rem;
17703
+ max-width: 20rem;
17704
+ }
17705
+
17706
+ .MultiSelectField[data-disabled] .MultiSelectFieldLabel {
17707
+ color: var(--sl-text-disabled, var(--sl-text-tertiary));
17708
+ }
17709
+
17710
+ /* Find box and the "6 ENTITIES · 1 SELECTED" line (set `noun`). */
17711
+ .MultiSelectFind {
17712
+ box-sizing: border-box;
17713
+ inline-size: calc(100% - 2 * var(--sl-space-2));
17714
+ block-size: var(--sl-control-height-md);
17715
+ margin: var(--sl-space-2);
17716
+ padding-inline: var(--sl-control-padding-inline);
17717
+ border: 1px solid var(--sl-border-default);
17718
+ border-radius: var(--sl-radius-base);
17719
+ font: inherit;
17720
+ }
17721
+
17722
+ .MultiSelectGroupLabel {
17723
+ padding: var(--sl-space-2) var(--sl-control-padding-inline) 0;
17724
+ font-size: var(--sl-font-size-xs, 12px);
17725
+ letter-spacing: 0.08em;
17726
+ text-transform: uppercase;
17727
+ color: var(--sl-text-secondary);
17728
+ }
17729
+
17730
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17731
+ /* PickerSplit
17732
+ *
17733
+ * A PickerButton whose choice is itself a control: the main part (CLIENT Alpha Services) acts,
17734
+ * and a square trigger beside it, divided by a hairline, opens the list. The root carries the
17735
+ * field look so a popup anchors to the whole control; each part fills on hover and the border
17736
+ * darkens for the control as a whole. Label, choice and chevron reuse the PickerButton parts and
17737
+ * tokens (picker-button.*), so the two read as one family.
17738
+ */
17739
+
17740
+ .PickerSplit {
17741
+ box-sizing: border-box;
16193
17742
  color: var(--sl-field-color);
16194
17743
  background: var(--sl-field-background);
16195
17744
  border: var(--sl-field-border-width) solid var(--sl-field-border-color);
16196
17745
  border-radius: var(--sl-field-radius);
16197
17746
  transition: var(--sl-field-transition);
16198
17747
  outline: none;
17748
+ display: inline-grid;
17749
+ grid-template-columns: minmax(0, 1fr) var(--sl-control-height-md);
17750
+ grid-template-rows: minmax(0, 1fr);
17751
+ box-sizing: border-box;
17752
+ max-width: var(--sl-picker-button-max-width);
17753
+ min-width: 0;
17754
+ height: var(--sl-control-height-md);
17755
+ padding: 0;
17756
+ overflow: hidden;
17757
+ }
17758
+
17759
+ .PickerSplit:hover:not(:has(:disabled)) {
17760
+ border-color: var(--sl-field-border-color-hover);
17761
+ }
17762
+
17763
+ .PickerSplitMain,
17764
+ .PickerSplitTrigger {
16199
17765
  font-family: var(--sl-font-body-base-font-family);
16200
17766
  font-size: var(--sl-font-body-base-font-size);
16201
17767
  font-weight: var(--sl-font-body-base-font-weight);
16202
17768
  line-height: var(--sl-font-body-base-line-height);
16203
17769
  letter-spacing: var(--sl-font-body-base-letter-spacing);
16204
- /* A grid, not a flex row: label and choice are centered on the same line, and align-content centers that
16205
- pair in the button's height. The choice column shrinks so a long choice gets its ellipsis. */
16206
- display: inline-grid;
17770
+ box-sizing: border-box;
17771
+ height: 100%;
17772
+ margin: 0;
17773
+ border: 0;
17774
+ border-radius: 0;
17775
+ background: transparent;
17776
+ color: var(--sl-field-color);
17777
+ cursor: pointer;
17778
+ }
17779
+
17780
+ .PickerSplitMain {
17781
+ display: grid;
16207
17782
  grid-auto-flow: column;
16208
17783
  grid-template-columns: max-content minmax(0, max-content);
16209
17784
  grid-auto-columns: max-content;
@@ -16211,437 +17786,677 @@ textarea.FieldControl {
16211
17786
  align-content: center;
16212
17787
  justify-content: start;
16213
17788
  gap: var(--sl-gap-control);
16214
- max-width: var(--sl-picker-button-max-width);
16215
17789
  min-width: 0;
16216
- height: var(--sl-control-height-md);
16217
- margin: 0;
16218
- padding-block: var(--sl-control-padding-block);
17790
+ padding-block: 0;
16219
17791
  padding-inline: var(--sl-control-padding-inline);
17792
+ white-space: nowrap;
17793
+ }
17794
+
17795
+ .PickerSplitTrigger {
17796
+ display: inline-flex;
17797
+ align-items: center;
17798
+ justify-content: center;
17799
+ padding: 0;
17800
+ border-inline-start: var(--sl-stroke-default) solid var(--sl-field-border-color);
17801
+ }
17802
+
17803
+ @media (hover: hover) {
17804
+ .PickerSplitMain:hover:not(:disabled),
17805
+ .PickerSplitTrigger:hover:not(:disabled) {
17806
+ background: var(--sl-fill-subtle);
17807
+ }
17808
+ }
17809
+
17810
+ /* The focus ring sits inside each part, since the root clips its edges. */
17811
+ .PickerSplitMain:focus-visible,
17812
+ .PickerSplitTrigger:focus-visible {
17813
+ outline: var(--sl-stroke-strong) solid var(--sl-field-border-color-focus);
17814
+ outline-offset: calc(var(--sl-stroke-strong) * -1);
17815
+ }
17816
+
17817
+ .PickerSplitMain:disabled,
17818
+ .PickerSplitTrigger:disabled {
17819
+ color: var(--sl-field-color-disabled);
17820
+ cursor: not-allowed;
17821
+ }
17822
+
17823
+ .PickerSplitTrigger[aria-expanded='true'] .PickerButtonIcon,
17824
+ .PickerSplitTrigger[data-popup-open] .PickerButtonIcon {
17825
+ transform: rotate(180deg);
17826
+ }
17827
+
17828
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17829
+ /* SplitButton
17830
+ *
17831
+ * A Button and a square Menu trigger side by side, joined into one outline: the inner corners
17832
+ * are square and the trigger overlaps the main part's border by one stroke.
17833
+ */
17834
+
17835
+ .SplitButton {
17836
+ display: inline-flex;
17837
+ }
17838
+
17839
+ /* The open Menu adds hidden focus-guard spans beside the chevron, so :first-child and :last-child
17840
+ can match a span. Select the buttons by type instead. */
17841
+ .SplitButton > button:first-of-type {
17842
+ border-start-end-radius: 0;
17843
+ border-end-end-radius: 0;
17844
+ }
17845
+
17846
+ .SplitButton > button:last-of-type {
17847
+ border-start-start-radius: 0;
17848
+ border-end-start-radius: 0;
17849
+ margin-inline-start: -1px;
17850
+ }
17851
+
17852
+ /* Items with a description: the label in the body weight over a quiet line, a wider menu. The
17853
+ menu is portalled, so it is matched by its own marker, not as a child of .SplitButton. */
17854
+ .MenuPopup[data-described] {
17855
+ min-width: 20rem;
17856
+ }
17857
+
17858
+ .MenuPopup[data-described] [data-part='item'] {
17859
+ flex-direction: column;
17860
+ align-items: flex-start;
17861
+ gap: 2px;
17862
+ padding-block: 10px;
17863
+ }
17864
+
17865
+ .MenuPopup[data-described] [data-part='item-label'] {
17866
+ font-weight: 600;
17867
+ }
17868
+
17869
+ .MenuPopup[data-described] [data-part='item-description'] {
17870
+ color: var(--sl-text-secondary);
17871
+ font-size: 13px;
17872
+ }
17873
+
17874
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
17875
+ /* SideNav
17876
+ *
17877
+ * The column of links down the side of a workspace. Rows are ruled apart with a hairline; the
17878
+ * current row (aria-current="page") sits on the raised surface with a rule under it in the
17879
+ * working-paper ink; counts are figures; group headings are caps labels. SideNavToggle is a
17880
+ * small tab-shaped handle on the column's edge, whose chevron turns with the state. The parent
17881
+ * sets the width and must not clip the toggle (overflow: visible), since it hangs over the edge.
17882
+ * Tokens: side-nav.* (tokens/component/side-nav.json).
17883
+ */
17884
+
17885
+ .SideNav {
17886
+ position: relative;
17887
+ box-sizing: border-box;
17888
+ display: flex;
17889
+ flex-direction: column;
17890
+ height: 100%;
17891
+ min-width: 0;
17892
+ padding-block: var(--sl-space-4);
17893
+ background: var(--sl-side-nav-background);
17894
+ border-inline-end: var(--sl-stroke-default) solid var(--sl-side-nav-border-color);
17895
+ }
17896
+
17897
+ .SideNav[data-collapsed] {
17898
+ min-width: var(--sl-side-nav-collapsed-width);
17899
+ }
17900
+
17901
+ /* Collapsed: only the toggle stays. */
17902
+ .SideNav[data-collapsed] > :not(.SideNavToggle) {
17903
+ display: none;
17904
+ }
17905
+
17906
+ .SideNavItem {
17907
+ font-family: var(--sl-font-body-base-font-family);
17908
+ font-size: var(--sl-font-body-base-font-size);
17909
+ font-weight: var(--sl-font-body-base-font-weight);
17910
+ line-height: var(--sl-font-body-base-line-height);
17911
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
17912
+ box-sizing: border-box;
17913
+ display: flex;
17914
+ align-items: center;
17915
+ justify-content: space-between;
17916
+ gap: var(--sl-side-nav-item-gap);
17917
+ min-height: var(--sl-side-nav-item-height);
17918
+ padding-inline: var(--sl-side-nav-item-padding-inline);
17919
+ color: var(--sl-side-nav-item-color);
17920
+ text-decoration: none;
17921
+ border-bottom: var(--sl-stroke-default) solid var(--sl-side-nav-item-divider-color);
16220
17922
  cursor: pointer;
17923
+ transition: background var(--sl-duration-fast) var(--sl-easing-default);
17924
+ }
17925
+
17926
+ .SideNavItemText {
17927
+ display: flex;
17928
+ flex-direction: column;
17929
+ min-width: 0;
17930
+ }
17931
+
17932
+ .SideNavItemLabel {
17933
+ overflow: hidden;
17934
+ text-overflow: ellipsis;
16221
17935
  white-space: nowrap;
16222
17936
  }
16223
17937
 
16224
- .PickerButton:hover:not(:disabled) {
16225
- border-color: var(--sl-field-border-color-hover);
16226
- background: var(--sl-fill-subtle);
17938
+ .SideNavItemHint {
17939
+ font-family: var(--sl-font-body-minimize-font-family);
17940
+ font-size: var(--sl-font-body-minimize-font-size);
17941
+ font-weight: var(--sl-font-body-minimize-font-weight);
17942
+ line-height: var(--sl-font-body-minimize-line-height);
17943
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
17944
+ color: var(--sl-side-nav-item-color-disabled);
16227
17945
  }
16228
17946
 
16229
- .PickerButton:focus-visible {
16230
- border-color: var(--sl-field-border-color-focus);
16231
- box-shadow: var(--sl-field-shadow-focus);
17947
+ .SideNavItem:hover:not([data-current]):not([data-disabled]) {
17948
+ background: var(--sl-side-nav-item-background-hover);
17949
+ }
17950
+
17951
+ .SideNavItem:focus-visible {
17952
+ outline: var(--sl-focus-outline);
17953
+ outline-offset: var(--sl-focus-outline-offset-inset);
17954
+ }
17955
+
17956
+ .SideNavItem[data-current] {
17957
+ background: var(--sl-side-nav-item-background-current);
17958
+ font-weight: var(--sl-font-weight-semibold);
17959
+ box-shadow: inset 0 calc(-1 * var(--sl-side-nav-indicator-width)) 0 var(--sl-side-nav-indicator-color);
17960
+ }
17961
+
17962
+ /* A nested row is indented one step and set in regular weight, even when current. */
17963
+ .SideNavItem[data-nested] {
17964
+ padding-inline-start: calc(var(--sl-side-nav-item-padding-inline) + var(--sl-space-4));
17965
+ }
17966
+
17967
+ .SideNavItem[data-nested]:not([data-current]) {
17968
+ font-weight: var(--sl-font-weight-normal);
17969
+ }
17970
+
17971
+ .SideNavItem[data-disabled] {
17972
+ color: var(--sl-side-nav-item-color-disabled);
17973
+ cursor: default;
17974
+ }
17975
+
17976
+ .SideNavItemCount {
17977
+ flex: none;
17978
+ font-family: var(--sl-font-figures-condense-font-family);
17979
+ font-variant-numeric: var(--sl-font-figures-condense-font-variant-numeric);
17980
+ font-size: var(--sl-font-figures-condense-font-size);
17981
+ font-weight: var(--sl-font-weight-semibold);
17982
+ line-height: var(--sl-font-figures-condense-line-height);
17983
+ color: var(--sl-side-nav-count-color);
16232
17984
  }
16233
17985
 
16234
- .PickerButton:disabled {
16235
- background: var(--sl-field-background-disabled);
16236
- color: var(--sl-field-color-disabled);
16237
- cursor: not-allowed;
17986
+ .SideNavItemCount[data-tone='quiet'] {
17987
+ color: var(--sl-side-nav-count-color-quiet);
16238
17988
  }
16239
17989
 
16240
- .PickerButtonLabel {
17990
+ .SideNavGroupLabel {
16241
17991
  font-family: var(--sl-font-caps-condense-font-family);
16242
17992
  font-size: var(--sl-font-caps-condense-font-size);
16243
17993
  font-weight: var(--sl-font-caps-condense-font-weight);
16244
17994
  line-height: var(--sl-font-caps-condense-line-height);
16245
17995
  letter-spacing: var(--sl-font-caps-condense-letter-spacing);
16246
17996
  text-transform: var(--sl-font-caps-condense-text-transform);
16247
- position: relative;
16248
- top: var(--sl-picker-button-text-offset);
16249
- flex: none;
16250
- color: var(--sl-picker-button-label-color);
17997
+ padding-top: var(--sl-side-nav-group-padding-top);
17998
+ padding-bottom: var(--sl-space-1-5);
17999
+ padding-inline: var(--sl-side-nav-item-padding-inline);
18000
+ color: var(--sl-side-nav-group-label-color);
16251
18001
  }
16252
18002
 
16253
- .PickerButtonValue {
16254
- position: relative;
16255
- top: var(--sl-picker-button-text-offset);
16256
- flex: 0 1 auto;
16257
- min-width: 0;
16258
- overflow: hidden;
16259
- text-overflow: ellipsis;
16260
- color: var(--sl-field-color);
18003
+ /* ============================================
18004
+ COLLAPSE BUTTON
18005
+ ============================================ */
18006
+
18007
+ .SideNavToggle {
18008
+ all: unset;
18009
+ box-sizing: border-box;
18010
+ position: absolute;
18011
+ z-index: 1;
18012
+ top: var(--sl-side-nav-toggle-offset);
18013
+ inset-inline-end: calc(-0.5 * var(--sl-side-nav-toggle-width));
18014
+ display: inline-flex;
18015
+ align-items: center;
18016
+ justify-content: center;
18017
+ width: var(--sl-side-nav-toggle-width);
18018
+ height: var(--sl-side-nav-toggle-height);
18019
+ border-radius: var(--sl-side-nav-toggle-radius);
18020
+ background: var(--sl-side-nav-toggle-background);
18021
+ border: var(--sl-stroke-default) solid var(--sl-side-nav-toggle-border-color);
18022
+ color: var(--sl-side-nav-toggle-border-color);
18023
+ cursor: pointer;
18024
+ transition: color var(--sl-duration-fast) var(--sl-easing-default),
18025
+ background var(--sl-duration-fast) var(--sl-easing-default),
18026
+ border-color var(--sl-duration-fast) var(--sl-easing-default);
16261
18027
  }
16262
18028
 
16263
- .PickerButtonValue[data-placeholder] {
16264
- color: var(--sl-field-placeholder-color);
18029
+ .SideNavToggle:hover {
18030
+ color: var(--sl-side-nav-toggle-background);
18031
+ background: var(--sl-side-nav-toggle-border-color);
16265
18032
  }
16266
18033
 
16267
- .PickerButtonIcon {
16268
- flex: none;
16269
- align-self: center;
16270
- width: var(--sl-icon-size-base);
16271
- height: var(--sl-icon-size-base);
16272
- color: var(--sl-text-tertiary);
18034
+ .SideNavToggle:focus-visible {
18035
+ outline: var(--sl-focus-outline);
18036
+ outline-offset: var(--sl-focus-outline-offset);
18037
+ }
18038
+
18039
+ .SideNavToggleIcon {
18040
+ width: var(--sl-icon-size-minimize);
18041
+ height: var(--sl-icon-size-minimize);
16273
18042
  transition: transform var(--sl-duration-normal) var(--sl-easing-default);
16274
18043
  }
16275
18044
 
16276
- .PickerButton[aria-expanded='true'] .PickerButtonIcon,
16277
- .PickerButton[data-popup-open] .PickerButtonIcon {
18045
+ /* The chevron points the way the column will go: left to collapse, right to expand. */
18046
+ .SideNavToggle[aria-expanded='false'] .SideNavToggleIcon {
16278
18047
  transform: rotate(180deg);
16279
18048
  }
16280
18049
 
16281
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16282
- /* MultiSelect
18050
+ [dir='rtl'] .SideNavToggleIcon {
18051
+ transform: scaleX(-1);
18052
+ }
18053
+
18054
+ [dir='rtl'] .SideNavToggle[aria-expanded='false'] .SideNavToggleIcon {
18055
+ transform: scaleX(-1) rotate(180deg);
18056
+ }
18057
+
18058
+ @media (prefers-reduced-motion: reduce) {
18059
+ .SideNavToggleIcon,
18060
+ .SideNavItem,
18061
+ .SideNavToggle {
18062
+ transition: none;
18063
+ }
18064
+ }
18065
+
18066
+ /* @scattered-light/loomiere-base-ui 0.41.0 · styles for @base-ui/react 1.9.0 */
18067
+ /* Shortcuts
16283
18068
  *
16284
- * A PickerButton trigger that opens a popover of checkbox rows (label, count at the end) and a
16285
- * footer with "Show all" and "Done". The rows reuse the Checkbox look; the counts are mono so
16286
- * they line up. The popup is at least as wide as its widest row and never narrower than
16287
- * popup.min-width.
18069
+ * Kbd: key caps for a shortcut, in the figures face, each a small raised cap with a heavier bottom
18070
+ * edge. `data-tone="inverse"` draws them on a dark surface (a tooltip, the Go to hint) in the
18071
+ * surrounding text color.
18072
+ * ShortcutSequenceHint: the dark card that lists the next keys after the first key of a sequence.
18073
+ * ShortcutsDialog: the cheat sheet, a find box, one statement-look table per group, and the
18074
+ * single-key switch in its footer.
18075
+ * CommandPalette: a dialog near the top of the screen with a search field, grouped options and a
18076
+ * footer of key hints. The active option is tinted, not outlined, because focus stays in the field.
16288
18077
  */
16289
18078
 
16290
- .MultiSelectPopup {
16291
- min-width: var(--sl-popup-min-width);
16292
- padding: 0;
18079
+ .Kbd {
18080
+ display: inline-flex;
18081
+ align-items: center;
18082
+ vertical-align: middle;
18083
+ white-space: nowrap;
16293
18084
  }
16294
18085
 
16295
- .MultiSelectList {
16296
- display: flex;
16297
- flex-direction: column;
16298
- padding-block: var(--sl-space-block-xs);
18086
+ .KbdKeys {
18087
+ display: inline-flex;
18088
+ align-items: center;
18089
+ gap: var(--sl-space-0-5);
18090
+ /* Caps are a picture of keys: dragging across a list must not paint them with the selection. */
18091
+ user-select: none;
18092
+ -webkit-user-select: none;
16299
18093
  }
16300
18094
 
16301
- .MultiSelectOption {
16302
- display: flex;
16303
- flex-direction: row; /* an app's global label rule may stack children */
18095
+ .KbdKey {
18096
+ font-family: var(--sl-font-figures-condense-font-family);
18097
+ font-size: var(--sl-font-figures-condense-font-size);
18098
+ font-weight: var(--sl-font-figures-condense-font-weight);
18099
+ line-height: var(--sl-font-figures-condense-line-height);
18100
+ letter-spacing: var(--sl-font-figures-condense-letter-spacing);
18101
+ font-variant-numeric: var(--sl-font-figures-condense-font-variant-numeric);
18102
+ display: inline-flex;
16304
18103
  align-items: center;
16305
- gap: var(--sl-gap-control);
16306
- padding-inline: var(--sl-control-padding-inline);
16307
- cursor: pointer;
18104
+ justify-content: center;
18105
+ box-sizing: border-box;
18106
+ min-width: 1.375rem;
18107
+ height: 1.375rem;
18108
+ padding: 0 var(--sl-space-1);
18109
+ border: 1px solid var(--sl-border-strong);
18110
+ border-bottom-width: 2px;
18111
+ border-radius: var(--sl-radius-control);
18112
+ background: var(--sl-surface-raised);
18113
+ color: var(--sl-text-primary);
18114
+ font-size: 0.75rem;
18115
+ line-height: 1;
16308
18116
  }
16309
18117
 
16310
- .MultiSelectOption:hover {
16311
- background: var(--sl-fill-subtle);
18118
+ .KbdThen {
18119
+ font-family: var(--sl-font-body-minimize-font-family);
18120
+ font-size: var(--sl-font-body-minimize-font-size);
18121
+ font-weight: var(--sl-font-body-minimize-font-weight);
18122
+ line-height: var(--sl-font-body-minimize-line-height);
18123
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
18124
+ margin: 0 var(--sl-space-1);
18125
+ color: var(--sl-text-secondary);
16312
18126
  }
16313
18127
 
16314
- .MultiSelectOptionLabel {
16315
- flex: 1;
16316
- min-width: 0;
16317
- text-align: start;
18128
+ .Kbd[data-tone='inverse'] .KbdKey {
18129
+ border-color: color-mix(in srgb, currentColor 55%, transparent);
18130
+ background: color-mix(in srgb, currentColor 12%, transparent);
18131
+ color: inherit;
16318
18132
  }
16319
18133
 
16320
- .MultiSelectOptionCount {
16321
- flex: none;
16322
- font-family: var(--sl-font-family-mono, ui-monospace, monospace);
16323
- font-variant-numeric: tabular-nums;
16324
- color: var(--sl-text-tertiary);
18134
+ .Kbd[data-tone='inverse'] .KbdThen {
18135
+ color: inherit;
18136
+ opacity: 0.8;
16325
18137
  }
16326
18138
 
16327
- .MultiSelectFooter {
16328
- display: flex;
16329
- justify-content: space-between;
16330
- gap: var(--sl-gap-control);
16331
- padding: var(--sl-space-block-xs) var(--sl-control-padding-inline);
16332
- border-top: 1px solid var(--sl-popup-separator-color);
18139
+ /* In a button or a menu item the caps sit after the label, a step smaller. */
18140
+ .Button .Kbd,
18141
+ .MenuItem .Kbd {
18142
+ margin-inline-start: auto;
18143
+ padding-inline-start: var(--sl-space-2);
16333
18144
  }
16334
18145
 
16335
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16336
- /* PickerSplit
16337
- *
16338
- * A PickerButton whose choice is itself a control: the main part (CLIENT Alpha Services) acts,
16339
- * and a square trigger beside it, divided by a hairline, opens the list. The root carries the
16340
- * field look so a popup anchors to the whole control; each part fills on hover and the border
16341
- * darkens for the control as a whole. Label, choice and chevron reuse the PickerButton parts and
16342
- * tokens (picker-button.*), so the two read as one family.
16343
- */
16344
-
16345
- .PickerSplit {
16346
- box-sizing: border-box;
16347
- color: var(--sl-field-color);
16348
- background: var(--sl-field-background);
16349
- border: var(--sl-field-border-width) solid var(--sl-field-border-color);
16350
- border-radius: var(--sl-field-radius);
16351
- transition: var(--sl-field-transition);
16352
- outline: none;
16353
- display: inline-grid;
16354
- grid-template-columns: minmax(0, 1fr) var(--sl-control-height-md);
16355
- grid-template-rows: minmax(0, 1fr);
16356
- box-sizing: border-box;
16357
- max-width: var(--sl-picker-button-max-width);
16358
- min-width: 0;
16359
- height: var(--sl-control-height-md);
16360
- padding: 0;
16361
- overflow: hidden;
18146
+ .Button .KbdKey {
18147
+ min-width: 1.25rem;
18148
+ height: 1.25rem;
18149
+ font-size: 0.6875rem;
16362
18150
  }
16363
18151
 
16364
- .PickerSplit:hover:not(:has(:disabled)) {
16365
- border-color: var(--sl-field-border-color-hover);
18152
+ .TooltipPopup .Kbd {
18153
+ margin-inline-start: var(--sl-space-2);
16366
18154
  }
16367
18155
 
16368
- .PickerSplitMain,
16369
- .PickerSplitTrigger {
16370
- font-family: var(--sl-font-body-base-font-family);
16371
- font-size: var(--sl-font-body-base-font-size);
16372
- font-weight: var(--sl-font-body-base-font-weight);
16373
- line-height: var(--sl-font-body-base-line-height);
16374
- letter-spacing: var(--sl-font-body-base-letter-spacing);
16375
- box-sizing: border-box;
16376
- height: 100%;
16377
- margin: 0;
16378
- border: 0;
16379
- border-radius: 0;
16380
- background: transparent;
16381
- color: var(--sl-field-color);
16382
- cursor: pointer;
18156
+ .TooltipPopup .KbdKey {
18157
+ border-color: color-mix(in srgb, currentColor 55%, transparent);
18158
+ background: color-mix(in srgb, currentColor 12%, transparent);
18159
+ color: inherit;
16383
18160
  }
16384
18161
 
16385
- .PickerSplitMain {
16386
- display: grid;
16387
- grid-auto-flow: column;
16388
- grid-template-columns: max-content minmax(0, max-content);
16389
- grid-auto-columns: max-content;
16390
- align-items: center;
16391
- align-content: center;
16392
- justify-content: start;
16393
- gap: var(--sl-gap-control);
16394
- min-width: 0;
16395
- padding-block: 0;
16396
- padding-inline: var(--sl-control-padding-inline);
16397
- white-space: nowrap;
18162
+ /* Go to hint */
18163
+ .ShortcutSequenceHint {
18164
+ position: fixed;
18165
+ left: var(--sl-space-6);
18166
+ bottom: var(--sl-space-6);
18167
+ z-index: var(--sl-popup-z-index);
18168
+ display: flex;
18169
+ flex-direction: column;
18170
+ gap: var(--sl-space-2);
18171
+ min-width: 18rem;
18172
+ padding: var(--sl-space-3) var(--sl-space-4) var(--sl-space-4);
18173
+ border-radius: var(--sl-radius-control);
18174
+ background: var(--sl-text-primary);
18175
+ color: var(--sl-surface-raised);
18176
+ box-shadow: 0 12px 28px color-mix(in srgb, var(--sl-text-primary) 25%, transparent);
16398
18177
  }
16399
18178
 
16400
- .PickerSplitTrigger {
16401
- display: inline-flex;
18179
+ .ShortcutSequenceHintHead {
18180
+ display: flex;
16402
18181
  align-items: center;
16403
- justify-content: center;
16404
- padding: 0;
16405
- border-inline-start: var(--sl-stroke-default) solid var(--sl-field-border-color);
18182
+ gap: var(--sl-space-2);
16406
18183
  }
16407
18184
 
16408
- @media (hover: hover) {
16409
- .PickerSplitMain:hover:not(:disabled),
16410
- .PickerSplitTrigger:hover:not(:disabled) {
16411
- background: var(--sl-fill-subtle);
16412
- }
18185
+ .ShortcutSequenceHintTitle {
18186
+ font-family: var(--sl-font-label-base-font-family);
18187
+ font-size: var(--sl-font-label-base-font-size);
18188
+ font-weight: var(--sl-font-label-base-font-weight);
18189
+ line-height: var(--sl-font-label-base-line-height);
18190
+ letter-spacing: var(--sl-font-label-base-letter-spacing);
18191
+ font-weight: var(--sl-font-weight-semibold);
16413
18192
  }
16414
18193
 
16415
- /* The focus ring sits inside each part, since the root clips its edges. */
16416
- .PickerSplitMain:focus-visible,
16417
- .PickerSplitTrigger:focus-visible {
16418
- outline: var(--sl-stroke-strong) solid var(--sl-field-border-color-focus);
16419
- outline-offset: calc(var(--sl-stroke-strong) * -1);
18194
+ .ShortcutSequenceHintCancel {
18195
+ font-family: var(--sl-font-body-minimize-font-family);
18196
+ font-size: var(--sl-font-body-minimize-font-size);
18197
+ font-weight: var(--sl-font-body-minimize-font-weight);
18198
+ line-height: var(--sl-font-body-minimize-line-height);
18199
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
18200
+ margin-inline-start: auto;
18201
+ opacity: 0.8;
16420
18202
  }
16421
18203
 
16422
- .PickerSplitMain:disabled,
16423
- .PickerSplitTrigger:disabled {
16424
- color: var(--sl-field-color-disabled);
16425
- cursor: not-allowed;
18204
+ .ShortcutSequenceHintList {
18205
+ display: flex;
18206
+ flex-direction: column;
18207
+ gap: var(--sl-space-1-5);
18208
+ margin: 0;
18209
+ padding: 0;
18210
+ list-style: none;
16426
18211
  }
16427
18212
 
16428
- .PickerSplitTrigger[aria-expanded='true'] .PickerButtonIcon,
16429
- .PickerSplitTrigger[data-popup-open] .PickerButtonIcon {
16430
- transform: rotate(180deg);
18213
+ .ShortcutSequenceHintList li {
18214
+ font-family: var(--sl-font-body-condense-font-family);
18215
+ font-size: var(--sl-font-body-condense-font-size);
18216
+ font-weight: var(--sl-font-body-condense-font-weight);
18217
+ line-height: var(--sl-font-body-condense-line-height);
18218
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
18219
+ display: grid;
18220
+ grid-template-columns: 2rem 1fr;
18221
+ align-items: center;
18222
+ gap: var(--sl-space-2);
16431
18223
  }
16432
18224
 
16433
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16434
- /* SplitButton
16435
- *
16436
- * A Button and a square Menu trigger side by side, joined into one outline: the inner corners
16437
- * are square and the trigger overlaps the main part's border by one stroke.
16438
- */
16439
-
16440
- .SplitButton {
16441
- display: inline-flex;
18225
+ /* Cheat sheet */
18226
+ .ShortcutsDialog.DialogPopup {
18227
+ display: flex;
18228
+ flex-direction: column;
18229
+ width: min(56rem, calc(100vw - 2 * var(--sl-space-6)));
18230
+ max-width: none;
16442
18231
  }
16443
18232
 
16444
- /* The open Menu adds hidden focus-guard spans beside the chevron, so :first-child and :last-child
16445
- can match a span. Select the buttons by type instead. */
16446
- .SplitButton > button:first-of-type {
16447
- border-start-end-radius: 0;
16448
- border-end-end-radius: 0;
18233
+ .ShortcutsDialogFind {
18234
+ margin-block: var(--sl-space-3) var(--sl-space-2);
16449
18235
  }
16450
18236
 
16451
- .SplitButton > button:last-of-type {
16452
- border-start-start-radius: 0;
16453
- border-end-start-radius: 0;
16454
- margin-inline-start: -1px;
18237
+ .ShortcutsDialogFind .Input {
18238
+ width: 100%;
16455
18239
  }
16456
18240
 
16457
- /* @scattered-light/loomiere-base-ui 0.25.0 · styles for @base-ui/react 1.9.0 */
16458
- /* SideNav
16459
- *
16460
- * The column of links down the side of a workspace. Rows are ruled apart with a hairline; the
16461
- * current row (aria-current="page") sits on the raised surface with a rule under it in the
16462
- * working-paper ink; counts are figures; group headings are caps labels. SideNavToggle is a
16463
- * small tab-shaped handle on the column's edge, whose chevron turns with the state. The parent
16464
- * sets the width and must not clip the toggle (overflow: visible), since it hangs over the edge.
16465
- * Tokens: side-nav.* (tokens/component/side-nav.json).
16466
- */
16467
-
16468
- .SideNav {
16469
- position: relative;
16470
- box-sizing: border-box;
16471
- display: flex;
16472
- flex-direction: column;
16473
- height: 100%;
16474
- min-width: 0;
16475
- padding-block: var(--sl-space-4);
16476
- background: var(--sl-side-nav-background);
16477
- border-inline-end: var(--sl-stroke-default) solid var(--sl-side-nav-border-color);
18241
+ .ShortcutsDialogBody {
18242
+ flex: 1 1 auto;
18243
+ min-height: 0;
18244
+ overflow: auto;
16478
18245
  }
16479
18246
 
16480
- .SideNav[data-collapsed] {
16481
- min-width: var(--sl-side-nav-collapsed-width);
18247
+ .ShortcutsGroup + .ShortcutsGroup {
18248
+ margin-top: var(--sl-space-6);
16482
18249
  }
16483
18250
 
16484
- /* Collapsed: only the toggle stays. */
16485
- .SideNav[data-collapsed] > :not(.SideNavToggle) {
16486
- display: none;
18251
+ .ShortcutsGroupTitle {
18252
+ font-family: var(--sl-font-subtitle-base-font-family);
18253
+ font-size: var(--sl-font-subtitle-base-font-size);
18254
+ font-weight: var(--sl-font-subtitle-base-font-weight);
18255
+ line-height: var(--sl-font-subtitle-base-line-height);
18256
+ letter-spacing: var(--sl-font-subtitle-base-letter-spacing);
18257
+ margin: var(--sl-space-3) 0 var(--sl-space-2);
16487
18258
  }
16488
18259
 
16489
- .SideNavItem {
16490
- font-family: var(--sl-font-body-base-font-family);
16491
- font-size: var(--sl-font-body-base-font-size);
16492
- font-weight: var(--sl-font-body-base-font-weight);
16493
- line-height: var(--sl-font-body-base-line-height);
16494
- letter-spacing: var(--sl-font-body-base-letter-spacing);
16495
- box-sizing: border-box;
18260
+ .ShortcutsDialogFooter {
16496
18261
  display: flex;
18262
+ flex-wrap: wrap;
16497
18263
  align-items: center;
16498
- justify-content: space-between;
16499
- gap: var(--sl-side-nav-item-gap);
16500
- min-height: var(--sl-side-nav-item-height);
16501
- padding-inline: var(--sl-side-nav-item-padding-inline);
16502
- color: var(--sl-side-nav-item-color);
16503
- text-decoration: none;
16504
- border-bottom: var(--sl-stroke-default) solid var(--sl-side-nav-item-divider-color);
16505
- cursor: pointer;
16506
- transition: background var(--sl-duration-fast) var(--sl-easing-default);
18264
+ gap: var(--sl-space-3) var(--sl-space-4);
18265
+ margin-top: var(--sl-space-4);
18266
+ padding-top: var(--sl-space-3);
18267
+ border-top: 1px solid var(--sl-border-default);
16507
18268
  }
16508
18269
 
16509
- .SideNavItemText {
18270
+ .ShortcutsDialogSwitch {
18271
+ display: flex;
18272
+ align-items: flex-start;
18273
+ gap: var(--sl-space-3);
18274
+ flex: 1 1 22rem;
18275
+ }
18276
+
18277
+ .ShortcutsDialogSwitchText {
16510
18278
  display: flex;
16511
18279
  flex-direction: column;
16512
- min-width: 0;
16513
18280
  }
16514
18281
 
16515
- .SideNavItemLabel {
16516
- overflow: hidden;
16517
- text-overflow: ellipsis;
16518
- white-space: nowrap;
18282
+ .ShortcutsDialogSwitchLabel {
18283
+ font-family: var(--sl-font-label-base-font-family);
18284
+ font-size: var(--sl-font-label-base-font-size);
18285
+ font-weight: var(--sl-font-label-base-font-weight);
18286
+ line-height: var(--sl-font-label-base-line-height);
18287
+ letter-spacing: var(--sl-font-label-base-letter-spacing);
18288
+ font-weight: var(--sl-font-weight-semibold);
16519
18289
  }
16520
18290
 
16521
- .SideNavItemHint {
18291
+ .ShortcutsDialogSwitchNote,
18292
+ .ShortcutsDialogFooterNote {
16522
18293
  font-family: var(--sl-font-body-minimize-font-family);
16523
18294
  font-size: var(--sl-font-body-minimize-font-size);
16524
18295
  font-weight: var(--sl-font-body-minimize-font-weight);
16525
18296
  line-height: var(--sl-font-body-minimize-line-height);
16526
18297
  letter-spacing: var(--sl-font-body-minimize-letter-spacing);
16527
- color: var(--sl-side-nav-item-color-disabled);
18298
+ color: var(--sl-text-secondary);
16528
18299
  }
16529
18300
 
16530
- .SideNavItem:hover:not([data-current]):not([data-disabled]) {
16531
- background: var(--sl-side-nav-item-background-hover);
18301
+ /* Command palette: high on the screen, so the results grow down. */
18302
+ .CommandPalette.DialogPopup {
18303
+ display: flex;
18304
+ flex-direction: column;
18305
+ top: 12vh;
18306
+ transform: translateX(-50%);
18307
+ width: min(42rem, calc(100vw - 2 * var(--sl-space-4)));
18308
+ max-width: none;
18309
+ max-height: 76vh;
18310
+ padding: 0;
18311
+ overflow: hidden;
16532
18312
  }
16533
18313
 
16534
- .SideNavItem:focus-visible {
16535
- outline: var(--sl-focus-outline);
16536
- outline-offset: var(--sl-focus-outline-offset-inset);
18314
+ .CommandPalette.DialogPopup[data-starting-style],
18315
+ .CommandPalette.DialogPopup[data-ending-style] {
18316
+ transform: translateX(-50%) translateY(-0.5rem) scale(var(--sl-modal-scale-closed));
16537
18317
  }
16538
18318
 
16539
- .SideNavItem[data-current] {
16540
- background: var(--sl-side-nav-item-background-current);
16541
- font-weight: var(--sl-font-weight-semibold);
16542
- box-shadow: inset 0 calc(-1 * var(--sl-side-nav-indicator-width)) 0 var(--sl-side-nav-indicator-color);
18319
+ .CommandPaletteField {
18320
+ display: flex;
18321
+ align-items: center;
18322
+ gap: var(--sl-space-2-5);
18323
+ min-height: 3.5rem;
18324
+ padding: 0 var(--sl-space-3) 0 var(--sl-space-4);
18325
+ border-bottom: 1px solid var(--sl-border-strong);
18326
+ color: var(--sl-text-secondary);
16543
18327
  }
16544
18328
 
16545
- /* A nested row is indented one step and set in regular weight, even when current. */
16546
- .SideNavItem[data-nested] {
16547
- padding-inline-start: calc(var(--sl-side-nav-item-padding-inline) + var(--sl-space-4));
18329
+ /* Focus lives in the box for as long as the palette is open, so a full ring round the field reads
18330
+ as a second frame. Instead the field's bottom rule thickens to the focus color. */
18331
+ .CommandPaletteField:focus-within {
18332
+ border-bottom-color: var(--sl-focus-ring);
18333
+ box-shadow: inset 0 calc(-1 * var(--sl-focus-ring-width) + 1px) 0 var(--sl-focus-ring);
16548
18334
  }
16549
18335
 
16550
- .SideNavItem[data-nested]:not([data-current]) {
16551
- font-weight: var(--sl-font-weight-normal);
18336
+ .CommandPaletteInput {
18337
+ font-family: var(--sl-font-body-magnify-font-family);
18338
+ font-size: var(--sl-font-body-magnify-font-size);
18339
+ font-weight: var(--sl-font-body-magnify-font-weight);
18340
+ line-height: var(--sl-font-body-magnify-line-height);
18341
+ letter-spacing: var(--sl-font-body-magnify-letter-spacing);
18342
+ flex: 1;
18343
+ min-width: 0;
18344
+ height: 3.5rem;
18345
+ margin: 0;
18346
+ padding: 0;
18347
+ border: 0;
18348
+ border-radius: 0;
18349
+ background: transparent;
18350
+ color: var(--sl-text-primary);
18351
+ outline: none;
16552
18352
  }
16553
18353
 
16554
- .SideNavItem[data-disabled] {
16555
- color: var(--sl-side-nav-item-color-disabled);
16556
- cursor: default;
18354
+ .CommandPaletteInput:focus,
18355
+ .CommandPaletteInput:focus-visible {
18356
+ /* The field draws the focus ring around icon, box and Esc together. */
18357
+ outline: none;
18358
+ box-shadow: none;
16557
18359
  }
16558
18360
 
16559
- .SideNavItemCount {
16560
- flex: none;
16561
- font-family: var(--sl-font-figures-condense-font-family);
16562
- font-variant-numeric: var(--sl-font-figures-condense-font-variant-numeric);
16563
- font-size: var(--sl-font-figures-condense-font-size);
16564
- font-weight: var(--sl-font-weight-semibold);
16565
- line-height: var(--sl-font-figures-condense-line-height);
16566
- color: var(--sl-side-nav-count-color);
18361
+ .CommandPaletteInput::placeholder {
18362
+ color: var(--sl-field-placeholder-color);
16567
18363
  }
16568
18364
 
16569
- .SideNavItemCount[data-tone='quiet'] {
16570
- color: var(--sl-side-nav-count-color-quiet);
18365
+ .CommandPaletteList {
18366
+ flex: 1 1 auto;
18367
+ min-height: 0;
18368
+ overflow: auto;
18369
+ padding: var(--sl-space-1) 0 var(--sl-space-2);
16571
18370
  }
16572
18371
 
16573
- .SideNavGroupLabel {
18372
+ .CommandPaletteGroupLabel {
16574
18373
  font-family: var(--sl-font-caps-condense-font-family);
16575
18374
  font-size: var(--sl-font-caps-condense-font-size);
16576
18375
  font-weight: var(--sl-font-caps-condense-font-weight);
16577
18376
  line-height: var(--sl-font-caps-condense-line-height);
16578
18377
  letter-spacing: var(--sl-font-caps-condense-letter-spacing);
16579
18378
  text-transform: var(--sl-font-caps-condense-text-transform);
16580
- padding-top: var(--sl-side-nav-group-padding-top);
16581
- padding-bottom: var(--sl-space-1-5);
16582
- padding-inline: var(--sl-side-nav-item-padding-inline);
16583
- color: var(--sl-side-nav-group-label-color);
18379
+ padding: var(--sl-space-3) var(--sl-space-4) var(--sl-space-1);
18380
+ color: var(--sl-text-secondary);
16584
18381
  }
16585
18382
 
16586
- /* ============================================
16587
- COLLAPSE BUTTON
16588
- ============================================ */
18383
+ .CommandPaletteOption {
18384
+ display: grid;
18385
+ grid-template-columns: 1.5rem minmax(0, 1fr) auto;
18386
+ align-items: center;
18387
+ gap: var(--sl-space-3);
18388
+ min-height: 3rem;
18389
+ padding: var(--sl-space-1-5) var(--sl-space-4);
18390
+ color: var(--sl-text-primary);
18391
+ cursor: pointer;
18392
+ }
16589
18393
 
16590
- .SideNavToggle {
16591
- all: unset;
16592
- box-sizing: border-box;
16593
- position: absolute;
16594
- z-index: 1;
16595
- top: var(--sl-side-nav-toggle-offset);
16596
- inset-inline-end: calc(-0.5 * var(--sl-side-nav-toggle-width));
16597
- display: inline-flex;
18394
+ .CommandPaletteOption[data-active] {
18395
+ background: var(--sl-item-background-hover);
18396
+ }
18397
+
18398
+ .CommandPaletteIcon {
18399
+ display: flex;
16598
18400
  align-items: center;
16599
18401
  justify-content: center;
16600
- width: var(--sl-side-nav-toggle-width);
16601
- height: var(--sl-side-nav-toggle-height);
16602
- border-radius: var(--sl-side-nav-toggle-radius);
16603
- background: var(--sl-side-nav-toggle-background);
16604
- border: var(--sl-stroke-default) solid var(--sl-side-nav-toggle-border-color);
16605
- color: var(--sl-side-nav-toggle-border-color);
16606
- cursor: pointer;
16607
- transition: color var(--sl-duration-fast) var(--sl-easing-default),
16608
- background var(--sl-duration-fast) var(--sl-easing-default),
16609
- border-color var(--sl-duration-fast) var(--sl-easing-default);
18402
+ color: var(--sl-text-secondary);
16610
18403
  }
16611
18404
 
16612
- .SideNavToggle:hover {
16613
- color: var(--sl-side-nav-toggle-background);
16614
- background: var(--sl-side-nav-toggle-border-color);
18405
+ .CommandPaletteText {
18406
+ display: flex;
18407
+ flex-direction: column;
18408
+ min-width: 0;
16615
18409
  }
16616
18410
 
16617
- .SideNavToggle:focus-visible {
16618
- outline: var(--sl-focus-outline);
16619
- outline-offset: var(--sl-focus-outline-offset);
18411
+ .CommandPaletteLabel {
18412
+ font-family: var(--sl-font-body-base-font-family);
18413
+ font-size: var(--sl-font-body-base-font-size);
18414
+ font-weight: var(--sl-font-body-base-font-weight);
18415
+ line-height: var(--sl-font-body-base-line-height);
18416
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
18417
+ overflow: hidden;
18418
+ text-overflow: ellipsis;
18419
+ white-space: nowrap;
18420
+ font-weight: var(--sl-font-weight-semibold);
16620
18421
  }
16621
18422
 
16622
- .SideNavToggleIcon {
16623
- width: var(--sl-icon-size-minimize);
16624
- height: var(--sl-icon-size-minimize);
16625
- transition: transform var(--sl-duration-normal) var(--sl-easing-default);
18423
+ .CommandPaletteMeta {
18424
+ font-family: var(--sl-font-body-minimize-font-family);
18425
+ font-size: var(--sl-font-body-minimize-font-size);
18426
+ font-weight: var(--sl-font-body-minimize-font-weight);
18427
+ line-height: var(--sl-font-body-minimize-line-height);
18428
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
18429
+ overflow: hidden;
18430
+ text-overflow: ellipsis;
18431
+ white-space: nowrap;
18432
+ color: var(--sl-text-secondary);
16626
18433
  }
16627
18434
 
16628
- /* The chevron points the way the column will go: left to collapse, right to expand. */
16629
- .SideNavToggle[aria-expanded='false'] .SideNavToggleIcon {
16630
- transform: rotate(180deg);
18435
+ .CommandPaletteMatch {
18436
+ background: color-mix(in srgb, var(--sl-text-accent) 18%, transparent);
18437
+ color: inherit;
16631
18438
  }
16632
18439
 
16633
- [dir='rtl'] .SideNavToggleIcon {
16634
- transform: scaleX(-1);
18440
+ .CommandPaletteList .EmptyState {
18441
+ padding: var(--sl-space-6) var(--sl-space-4);
16635
18442
  }
16636
18443
 
16637
- [dir='rtl'] .SideNavToggle[aria-expanded='false'] .SideNavToggleIcon {
16638
- transform: scaleX(-1) rotate(180deg);
18444
+ .CommandPaletteFooter {
18445
+ font-family: var(--sl-font-body-minimize-font-family);
18446
+ font-size: var(--sl-font-body-minimize-font-size);
18447
+ font-weight: var(--sl-font-body-minimize-font-weight);
18448
+ line-height: var(--sl-font-body-minimize-line-height);
18449
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
18450
+ display: flex;
18451
+ flex-wrap: wrap;
18452
+ align-items: center;
18453
+ gap: var(--sl-space-1-5) var(--sl-space-4);
18454
+ padding: var(--sl-space-2-5) var(--sl-space-4);
18455
+ border-top: 1px solid var(--sl-border-default);
18456
+ background: var(--sl-surface-tray);
18457
+ color: var(--sl-text-secondary);
16639
18458
  }
16640
18459
 
16641
- @media (prefers-reduced-motion: reduce) {
16642
- .SideNavToggleIcon,
16643
- .SideNavItem,
16644
- .SideNavToggle {
16645
- transition: none;
16646
- }
18460
+ .CommandPaletteFooterNote {
18461
+ margin-inline-start: auto;
16647
18462
  }