@scattered-light/loomiere-mojave 0.6.0 → 0.7.1

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 (40) hide show
  1. package/dist/exports/AGENTS.md +24 -8
  2. package/dist/exports/catalog.json +21 -0
  3. package/dist/exports/chakra.js +333 -0
  4. package/dist/exports/design-system/README.md +23 -7
  5. package/dist/exports/design-system/components/Badge/README.md +35 -0
  6. package/dist/exports/design-system/components/Badge/preview.html +19 -0
  7. package/dist/exports/design-system/components/Collection/README.md +14 -0
  8. package/dist/exports/design-system/components/CollectionPagination/README.md +15 -0
  9. package/dist/exports/design-system/components/CollectionToolbar/README.md +29 -0
  10. package/dist/exports/design-system/components/DataList/README.md +39 -0
  11. package/dist/exports/design-system/components/DataList/preview.html +475 -0
  12. package/dist/exports/design-system/components/DataTable/README.md +41 -0
  13. package/dist/exports/design-system/components/DataTable/preview.html +475 -0
  14. package/dist/exports/design-system/components/DatePicker/README.md +55 -0
  15. package/dist/exports/design-system/components/DatePicker/preview.html +475 -0
  16. package/dist/exports/design-system/components/EditableList/README.md +33 -0
  17. package/dist/exports/design-system/components/EditableList/preview.html +475 -0
  18. package/dist/exports/design-system/components/EmptyState/README.md +60 -0
  19. package/dist/exports/design-system/components/EmptyState/preview.html +475 -0
  20. package/dist/exports/design-system/components/ListDetail/README.md +43 -0
  21. package/dist/exports/design-system/components/ListDetail/preview.html +475 -0
  22. package/dist/exports/design-system/components/MoneyField/README.md +52 -0
  23. package/dist/exports/design-system/components/MoneyField/preview.html +475 -0
  24. package/dist/exports/design-system/components/Splitter/README.md +42 -0
  25. package/dist/exports/design-system/components/Splitter/preview.html +475 -0
  26. package/dist/exports/design-system/components/Table/README.md +2 -1
  27. package/dist/exports/design-system/components/Table/preview.html +1 -1
  28. package/dist/exports/design-system/components/bundle.css +2461 -190
  29. package/dist/exports/design-system/components/bundle.js +7 -5
  30. package/dist/exports/design-system/components/index.d.ts +3 -21
  31. package/dist/exports/design-system/tokens.json +15 -0
  32. package/dist/exports/figma.json +1 -1
  33. package/dist/exports/mui.js +727 -0
  34. package/dist/exports/tailwind.css +36 -0
  35. package/dist/exports/tokens.dtcg.json +320 -2
  36. package/dist/tokens.css +112 -4
  37. package/dist/tokens.d.ts +94 -0
  38. package/dist/tokens.js +95 -1
  39. package/dist/tokens.json +580 -2
  40. package/package.json +2 -2
@@ -742,6 +742,7 @@
742
742
  --sl-a11y-focus-outline-width: 2px; /** Focus ring thickness. 2px is the WCAG 2.2 minimum that stays visible on every surface. */
743
743
  --sl-a11y-link-focus-outline-offset: 0.25em; /** Links sit inside text, so the offset scales with the font (em) instead of a fixed px. */
744
744
  --sl-a11y-link-focus-ring-radius: 0.125em; /** A slight em-based rounding so inline focus rings hug the text. */
745
+ --sl-a11y-min-target: 24px; /** Smallest target for a fine pointer (WCAG 2.5.8). A mouse can hit 24px; a finger still needs min-touch-target. The splitter handle uses this so the grab area does not cover the scrollbar beside it. */
745
746
  --sl-a11y-min-touch-target: 44px; /** Smallest tap area for any control (WCAG 2.5.5 and Apple HIG both use 44px). */
746
747
  --sl-check-dot-scale: 0.4; /** A radio's dot as a share of the circle, so it scales with the size. */
747
748
  --sl-check-opacity-disabled: 0.5; /** A disabled box fades as a whole; its label turns to disabled text. */
@@ -781,11 +782,17 @@
781
782
  --sl-button-opacity-disabled: 0.5; /** A disabled button fades as a whole, keeping its shape so the layout doesn't jump. */
782
783
  --sl-drawer-popup-size: min(420px, 90vw); /** Width of a side drawer. A bottom or top drawer sizes to its content up to max-size. */
783
784
  --sl-drawer-popup-max-size: 85vh; /** Tallest a bottom or top drawer gets, leaving the page visible above it. */
785
+ --sl-list-detail-split-min-width: 720px; /** Side by side once this element, not the window, is this wide. Dryden used 1100px of the window. A container needs less: a list around 320px and a form around 400px still read at 720px. Narrower, the detail becomes a drawer or a page. */
786
+ --sl-list-detail-detail-default-size: 45%; /** The detail's share when it opens. The list fills the rest, about 55%, which is the split Dryden started from. */
787
+ --sl-list-detail-detail-min-size: 35%; /** The detail cannot be dragged narrower than this, so the form stays readable. */
788
+ --sl-list-detail-detail-max-size: 65%; /** The detail cannot cover more than this, so the list stays usable. Dryden kept the detail between 35% and 65%. */
784
789
  --sl-navigation-menu-popup-min-width: 400px; /** Narrowest a navigation panel gets on wider screens, and the widest a single column of links grows. */
785
790
  --sl-navigation-menu-column-width: 12rem; /** Width of each column in a two-column link list. */
786
791
  --sl-preview-card-popup-min-width: 300px; /** Narrowest a preview card gets, so a short title still has room for its image. */
787
792
  --sl-preview-card-popup-max-width: 450px; /** Widest a preview card gets, so its description keeps a comfortable line length. */
788
793
  --sl-slider-vertical-height: 200px; /** Default length of a vertical slider. */
794
+ --sl-splitter-key-step: 5%; /** One arrow press moves the handle by 5% of the splitter. Dryden used 5%: a nudge you can see, not a jump. */
795
+ --sl-splitter-key-step-large: 10%; /** The Shift step. Twice the arrow step, so a few presses cross the panel without holding the key. */
789
796
  --sl-switch-track-width: 48px; /** Wide enough for the thumb plus the ON/OFF text. */
790
797
  --sl-switch-track-width-sm: 44px;
791
798
  --sl-switch-track-width-lg: 68px;
@@ -1446,6 +1453,11 @@
1446
1453
  --sl-bar-group-gap: var(--sl-space-2); /** Space between groups in a toolbar, wider than inside a group. */
1447
1454
  --sl-bar-separator-length: var(--sl-space-6); /** Divider height, shorter than the controls so the groups still read as one strip. */
1448
1455
  --sl-bar-separator-spacing: var(--sl-space-1); /** Extra space either side of a divider. */
1456
+ --sl-calendar-day-size: var(--sl-space-10); /** A day cell on a pointer. space.10 keeps seven columns inside a phone; touch layouts raise the cell to the minimum touch target in CSS. */
1457
+ --sl-calendar-grid-gap: var(--sl-space-0-5); /** Space between week rows. Days in a week share an edge, so the range band reads as one shape. */
1458
+ --sl-calendar-month-gap: var(--sl-space-4); /** Space between months shown side by side, the same step as panel padding so the two columns line up. */
1459
+ --sl-calendar-header-gap: var(--sl-space-2); /** Space between the month title and the weekday row. */
1460
+ --sl-calendar-panel-padding: var(--sl-space-4); /** Padding inside the popup. The shared popup padding is one step and is too tight for a calendar. */
1449
1461
  --sl-overlay-base: var(--sl-color-black); /** Base color for scrims behind modals. Components apply their own opacity. */
1450
1462
  --sl-disclosure-animation-duration: var(--sl-duration-normal); /** How long a panel takes to open or close, and the chevron to turn. */
1451
1463
  --sl-disclosure-animation-easing: var(--sl-easing-in-out); /** Panels grow and shrink in place, so they ease both ways. */
@@ -1456,6 +1468,22 @@
1456
1468
  --sl-elevation-sm: var(--sl-shadow-sm);
1457
1469
  --sl-elevation-xl: var(--sl-shadow-xl);
1458
1470
  --sl-elevation-xs: var(--sl-shadow-xs);
1471
+ --sl-empty-padding-block-compact: var(--sl-space-6); /** 24px above and below a compact empty state. The same room a popup already gives a plain 'No results' line, so the two stay one height. */
1472
+ --sl-empty-padding-block-standard: var(--sl-space-10); /** 40px. A pane or a section needs more air than a table row, or the block looks stuck to the content around it. */
1473
+ --sl-empty-padding-block-spacious: var(--sl-space-16); /** 64px. A page with nothing else on it. The extra space above keeps the block off the top of the viewport. */
1474
+ --sl-empty-padding-inline-compact: var(--sl-space-4); /** 16px. Enough that a compact row doesn't touch the cell or popup edge. */
1475
+ --sl-empty-padding-inline-standard: var(--sl-space-6); /** 24px. A pane can be wide; the inline padding keeps the block off the sides before the description's own cap does. */
1476
+ --sl-empty-padding-inline-spacious: var(--sl-space-8); /** 32px. A full page, a step wider than a pane. */
1477
+ --sl-empty-gap-compact: var(--sl-space-3); /** 12px between the icon, the text and the actions in a table row or a popup. Tight, because the row is short. */
1478
+ --sl-empty-gap-standard: var(--sl-space-4); /** 16px. The stack in a pane: media, then words, then actions. */
1479
+ --sl-empty-gap-spacious: var(--sl-space-6); /** 24px. A page-sized stack needs the steps to separate, or the circle sits on the title. */
1480
+ --sl-empty-text-gap-compact: var(--sl-space-1); /** 4px between the title and the description in a compact row. They read as one message. */
1481
+ --sl-empty-text-gap-standard: var(--sl-space-1); /** 4px. Same as compact: the description belongs to the title, so it stays close. */
1482
+ --sl-empty-text-gap-spacious: var(--sl-space-2); /** 8px. The page title is larger, so the description steps down a little further. */
1483
+ --sl-empty-media-size-standard: var(--sl-space-12); /** 48px circle around a magnify icon (20px). The icon needs a field, or it reads as a bullet. */
1484
+ --sl-empty-media-size-spacious: var(--sl-space-16); /** 64px circle around a maximize icon (24px). A page can carry a larger mark. Compact has no circle: the icon is icon-size.condense on its own. */
1485
+ --sl-empty-description-max-width: var(--sl-measure-narrow); /** 45ch. A description is one sentence. Past a caption's measure it stretches across a wide pane and stops being a sentence. */
1486
+ --sl-empty-actions-gap: var(--sl-space-2); /** 8px between actions, the same gap a control uses between its icon and its label. The first action is the main one; the rest sit beside it. */
1459
1487
  --sl-field-gap: var(--sl-space-1-5); /** Between a field's label, control and messages. */
1460
1488
  --sl-field-label-spacing: var(--sl-space-1); /** Extra room under the label, so it reads as belonging to the control below it. */
1461
1489
  --sl-field-message-spacing: var(--sl-space-1); /** Extra room above a description or error, so it reads as a note on the control. */
@@ -1498,7 +1526,6 @@
1498
1526
  --sl-popup-separator-spacing: var(--sl-space-1); /** Space above and below a separator. */
1499
1527
  --sl-popup-group-label-padding-top: var(--sl-space-2); /** Space above a group label, so it sits closer to its own rows than to the group before. */
1500
1528
  --sl-popup-group-label-padding-bottom: var(--sl-space-1); /** Space between a group label and its first row. */
1501
- --sl-popup-empty-padding-block: var(--sl-space-6); /** Room around a 'No results' message, so an empty list doesn't collapse to a sliver. */
1502
1529
  --sl-control-height-lg: var(--sl-space-13);
1503
1530
  --sl-control-height-md: var(--sl-space-11);
1504
1531
  --sl-control-height-sm: var(--sl-space-9);
@@ -1809,11 +1836,36 @@
1809
1836
  --sl-avatar-initials-font-size-md: var(--sl-font-size-md); /** Sized to the avatar, not a text style: initials have to fit inside the circle at each size. The rest of the type is title-base. */
1810
1837
  --sl-avatar-initials-font-size-lg: var(--sl-font-size-lg); /** Sized to the avatar, not a text style: initials have to fit inside the circle at each size. The rest of the type is title-base. */
1811
1838
  --sl-avatar-initials-font-size-xl: var(--sl-font-size-2xl); /** Sized to the avatar, not a text style: initials have to fit inside the circle at each size. The rest of the type is title-base. */
1839
+ --sl-badge-height-minimize: var(--sl-space-5); /** 20px. The smallest pill that still holds trigger-minimize. */
1840
+ --sl-badge-height-condense: var(--sl-space-6); /** 24px, the default. Sits in a line of text and in dense rows. */
1841
+ --sl-badge-height-base: var(--sl-space-7); /** 28px, the small control height, for a badge beside base text. */
1842
+ --sl-badge-padding-inline-minimize: var(--sl-space-1); /** 4px. Tighter than a control so a short label stays a pill, not a button. */
1843
+ --sl-badge-padding-inline-condense: var(--sl-space-1-5); /** 6px, the default. */
1844
+ --sl-badge-padding-inline-base: var(--sl-space-2); /** 8px, still inside the small control's inline padding. */
1845
+ --sl-badge-gap-minimize: var(--sl-space-1); /** 4px between a dot or icon and the label at the smallest size. */
1846
+ --sl-badge-gap-condense: var(--sl-space-1); /** 4px, the default. The same gap as the smallest control. */
1847
+ --sl-badge-gap-base: var(--sl-space-1-5); /** 6px, a step wider once the label is base-sized. */
1848
+ --sl-badge-dot-minimize: var(--sl-space-1-5); /** 6px status dot. Smaller than icon-size-minimize so it reads as a mark, not an icon. */
1849
+ --sl-badge-dot-condense: var(--sl-space-2); /** 8px, the default. */
1850
+ --sl-badge-dot-base: var(--sl-space-2); /** 8px. The base badge is taller, but the dot stays a mark. */
1851
+ --sl-collection-tree-indent: var(--sl-space-4); /** How far each deeper level steps in, so a child sits under its parent's text. */
1852
+ --sl-collection-list-row-padding-block: var(--sl-space-3); /** Vertical padding of a list row. The row is not a fixed height, because a second line and an extra slot have to fit. */
1853
+ --sl-collection-list-row-gap: var(--sl-space-2); /** Between the checkbox, the text, the amount and the actions in a list row. */
1854
+ --sl-collection-toolbar-gap: var(--sl-space-2); /** Between the search, the filters and the actions. */
1855
+ --sl-collection-search-min-width: var(--sl-space-60); /** The narrowest the toolbar search gets beside the filters and actions. Under it, the search wraps to its own line, so a few words of a query still show. */
1856
+ --sl-collection-narrow-width: var(--sl-space-96); /** Below this, a table with narrow="list" becomes a list, and the toolbar's search takes the full width. A 360px pane is under it. */
1857
+ --sl-collection-editable-list-stack-width: var(--sl-space-80); /** Below this, editable rows stack and show their own labels. 320px matches. */
1858
+ --sl-collection-selection-column-width: var(--sl-space-10); /** The checkbox column. Wide enough for the control, no wider, so the data keeps the room. */
1812
1859
  --sl-drawer-handle-width: var(--sl-space-10); /** Grab bar length. */
1813
1860
  --sl-drawer-handle-height: var(--sl-space-1); /** Grab bar thickness. */
1861
+ --sl-list-detail-header-gap: var(--sl-space-3); /** Space between the title, the actions and Close. */
1862
+ --sl-list-detail-header-padding: var(--sl-space-4); /** Padding inside the detail header. One step under a dialog, because this is a pane, not a modal. */
1863
+ --sl-money-field-picker-min-inline-size: var(--sl-space-56); /** The currency list shows a code, a name and a symbol, so the popup is wider than the code trigger inside the field. */
1814
1864
  --sl-popover-text-max-width: var(--sl-measure-narrow); /** Keeps the title and description to a readable line length. The popup itself has no fixed cap, so wider content such as a calendar or a form fits; it stops at the space Base UI reports beside the trigger. */
1815
1865
  --sl-popover-popup-min-width: var(--sl-popup-min-width); /** Narrow enough for a short note, wide enough that a title doesn't wrap word by word. */
1816
1866
  --sl-slider-thumb-size: var(--sl-space-5); /** Knob diameter, big enough to grab with a finger on a 4px track. */
1867
+ --sl-splitter-handle-hit-size: var(--sl-a11y-min-touch-target); /** The part a finger grabs. The line stays one stroke. A fine pointer uses a11y.min-target (24px) instead, so the grab area does not cover the panel's scrollbar. Coarse pointers keep this 44px. */
1868
+ --sl-splitter-grip-size: var(--sl-space-1); /** 4px. The diameter of one grip dot. Small enough to sit on the hairline without becoming a second control. */
1817
1869
  --sl-switch-track-text-font-size: var(--sl-font-size-xs); /** Sized to the track, not a text style: the ON/OFF label has to fit inside the switch at each size. The rest of the label uses condense-subtitle-label. */
1818
1870
  --sl-switch-track-text-font-size-sm: var(--sl-font-size-xxs); /** Sized to the track, not a text style: the ON/OFF label has to fit inside the switch at each size. The rest of the label uses condense-subtitle-label. */
1819
1871
  --sl-switch-track-text-font-size-lg: var(--sl-font-size-sm); /** Sized to the track, not a text style: the ON/OFF label has to fit inside the switch at each size. The rest of the label uses condense-subtitle-label. */
@@ -1847,6 +1899,7 @@
1847
1899
  --sl-a11y-focus-ring-radius: var(--sl-radius-focus); /** Rounds the focus ring to match the small control radius. */
1848
1900
  --sl-bar-border-width: var(--sl-stroke-default); /** Strip edge thickness. */
1849
1901
  --sl-bar-radius: var(--sl-radius-surface); /** Strip corners. Controls inside a toggle group take radius.item, so the inner corners follow the outer ones. */
1902
+ --sl-calendar-day-radius: var(--sl-radius-pill); /** Selected days are circles. The pill radius is the same full radius badges and switches use. */
1850
1903
  --sl-check-border-width: var(--sl-stroke-default); /** Edge thickness. */
1851
1904
  --sl-check-radius: var(--sl-radius-box); /** Checkbox corners. Radios are always round. */
1852
1905
  --sl-check-transition: var(--sl-transition-input); /** Changes at the same speed as a field. */
@@ -1879,6 +1932,7 @@
1879
1932
  --sl-popup-radius: var(--sl-radius-surface); /** Corners of a free-floating popup. */
1880
1933
  --sl-popup-radius-field: var(--sl-radius-control); /** Corners of a list that drops from a field, matching the field so the two read as one control. */
1881
1934
  --sl-popup-shadow: var(--sl-elevation-lg); /** Lifts the popup above the page. */
1935
+ --sl-popup-empty-padding-block: var(--sl-empty-padding-block-compact); /** Room around a plain 'No results' line. The same padding as a compact empty state, so a sentence and an EmptyState in that slot take the same space. An EmptyState drops this padding and uses its own. */
1882
1936
  --sl-table-row-height: var(--sl-control-height-sm); /** Row height: the small control height, so a checkbox, input or button in a cell fits without growing the row. */
1883
1937
  --sl-table-header-height: var(--sl-control-height-md); /** Header row height: the regular control height, a little taller than rows so the header reads as its own band. */
1884
1938
  --sl-table-cell-padding-inline: var(--sl-control-padding-inline-sm); /** Space either side of cell text, matching small controls. */
@@ -2062,7 +2116,13 @@
2062
2116
  --sl-status-level-error-quiet-border: var(--sl-scope-error-border); /** quiet in error: outline in error */
2063
2117
  --sl-status-level-error-quiet-border-hover: var(--sl-scope-error-solid-hover); /** quiet in error: outline in error */
2064
2118
  --sl-button-radius: var(--sl-radius-pill); /** Buttons are pills, so they read as actions and never as fields or cards. */
2119
+ --sl-collection-row-height-sm: var(--sl-control-height-sm); /** The dense row, the same height the plain table already uses, so a checkbox fits. */
2120
+ --sl-collection-row-height-md: var(--sl-control-height-md); /** A roomier row when the collection is the page rather than a dense register. */
2121
+ --sl-collection-header-height-sm: var(--sl-control-height-md); /** The dense header, a step above the dense row, matching today's table header. */
2122
+ --sl-collection-header-height-md: var(--sl-control-height-lg); /** The header for the roomier row. */
2123
+ --sl-splitter-handle-size: var(--sl-stroke-default); /** The visible separator. One stroke, the same hairline as Separator, so a splitter reads as a divider you can grab. */
2065
2124
  --sl-focus-shadow-3px-error: 0 0 0 3px var(--sl-status-error); /** Focus halo for a field with an error. */
2125
+ --sl-calendar-day-color: var(--sl-text-primary); /** A day in the month being shown. */
2066
2126
  --sl-border-accent: var(--sl-scope-accent-border); /** Borders that signal selection or the active item. */
2067
2127
  --sl-border-default: var(--sl-scope-chrome-divider); /** Everyday dividers and control outlines. Darkens under prefers-contrast: more. */
2068
2128
  --sl-border-strong: var(--sl-scope-chrome-border-strong); /** Borders that identify a control, such as inputs and unchecked checkboxes. 3:1 against the canvas, as WCAG asks for control boundaries. */
@@ -2162,6 +2222,12 @@
2162
2222
  --sl-bar-background: var(--sl-surface-tray); /** Strip fill. */
2163
2223
  --sl-bar-border-color: var(--sl-border-default); /** Strip edge. */
2164
2224
  --sl-bar-separator-color: var(--sl-border-default); /** Divider between groups. */
2225
+ --sl-calendar-day-color-outside: var(--sl-text-tertiary); /** A day from the previous or next month, still selectable, drawn back so it does not compete with this month. */
2226
+ --sl-calendar-day-color-disabled: var(--sl-text-disabled); /** A day outside the allowed period, or one a length rule rejects. It stays in the tab order so the reason can be read. */
2227
+ --sl-calendar-range-background: var(--sl-interactive-tint-active); /** The band between the start and end of a period. Same tint as a selected list item, quieter than the start and end circles. */
2228
+ --sl-calendar-range-color: var(--sl-text-on-tint-strong); /** Day numbers that sit on the range band. The on-tint text color is the one that stays readable on interactive.tint-active. */
2229
+ --sl-calendar-today-ring: var(--sl-border-accent); /** An inset ring on today, including when today is also selected, so today is never only a color of the number. */
2230
+ --sl-calendar-weekday-color: var(--sl-text-tertiary); /** Weekday initials and week numbers are labels, not choices. */
2165
2231
  --sl-check-border-color: var(--sl-border-control); /** Empty box edge. Passes 3:1 so the box can be found before it's ticked. */
2166
2232
  --sl-check-border-color-hover: var(--sl-border-control-hover); /** Edge under the pointer. */
2167
2233
  --sl-check-background-checked: var(--sl-interactive-default); /** Ticked box fill, the brand's interactive color. */
@@ -2204,6 +2270,7 @@
2204
2270
  --sl-field-color-disabled: var(--sl-text-disabled); /** The value in a disabled field. */
2205
2271
  --sl-field-placeholder-color: var(--sl-text-tertiary); /** Hint text before anything is typed. */
2206
2272
  --sl-field-shadow-focus-error: var(--sl-focus-shadow-3px-error); /** Halo while typing in an invalid field. */
2273
+ --sl-field-affix-color: var(--sl-text-secondary); /** A prefix or suffix drawn inside the field (a currency symbol, a unit). Muted so it reads as part of the control, not as the value. */
2207
2274
  --sl-gauge-track-color: var(--sl-fill-track); /** The empty part of the bar. Every palette's fill reads 3:1 on it, so the amount is clear in both themes. */
2208
2275
  --sl-gauge-value-color: var(--sl-text-secondary); /** The number, quieter than its label. */
2209
2276
  --sl-icon-button-color: var(--sl-text-tertiary); /** Quiet at rest so it doesn't compete with the content. */
@@ -2226,12 +2293,15 @@
2226
2293
  --sl-table-header-background-hover: var(--sl-fill-subtle); /** A header cell under the pointer, showing it can be clicked to sort. */
2227
2294
  --sl-table-border-color: var(--sl-border-default); /** The grid's outer edge and the line under the header. */
2228
2295
  --sl-table-row-border-color: var(--sl-border-subtle); /** Hairlines between rows, quiet so the data leads. */
2296
+ --sl-table-row-current: var(--sl-surface-tray); /** The open row beside a detail pane. The tray, a step off the page, so secondary text on it still passes AA in dark. A selected row keeps its own tint, so a checked row and the row you are reading can both show. */
2297
+ --sl-table-group-header-background: var(--sl-surface-tray); /** A group header. The tray, like the column header, so a group reads as chrome rather than another data row. */
2229
2298
  --sl-table-column-hover: var(--sl-fill-subtle); /** Column under the pointer, when column hover is on. Neutral so it never reads as a selection. */
2230
2299
  --sl-table-range-background: var(--sl-interactive-tint); /** Cells inside a dragged range selection. */
2231
2300
  --sl-emphasis-bold-fg: var(--sl-scope-accent-on-solid); /** bold in default: solid in accent (primary) */
2232
2301
  --sl-status-level-default-bold-fg: var(--sl-scope-accent-on-solid); /** bold in default: solid in accent (primary) */
2233
2302
  --sl-drawer-handle-color: var(--sl-border-strong); /** The grab bar on bottom drawers. Strong border so it reads as something to drag. */
2234
2303
  --sl-shadow-outline: 0 0 0 3px color-mix(in oklab, var(--sl-focus-ring) 60%, transparent); /** Focus halo for controls that use box-shadow instead of outline: the focus ring color at 60% opacity, so it follows the accent and the theme. Becomes currentColor under prefers-contrast: more. */
2304
+ --sl-calendar-day-background-hover: var(--sl-item-background-hover); /** The same hover tint as a list item, so a day feels like a choice in a list. */
2235
2305
  --sl-check-mark-color: var(--sl-text-on-primary); /** Check mark, dash or dot on a ticked fill. */
2236
2306
  --sl-text-on-accent: var(--sl-text-on-primary); /** Alias for text placed on any accent fill. */
2237
2307
  --sl-content-kbd-text: var(--sl-text-on-inverse); /** Text on keycaps. */
@@ -5478,7 +5548,8 @@
5478
5548
  [data-emphasis='bold'],
5479
5549
  .Button[data-variant='solid']:not([data-emphasis]),
5480
5550
  .Button:not([data-variant]):not([data-emphasis]),
5481
- .AvatarRoot:not([data-emphasis]) {
5551
+ .AvatarRoot:not([data-emphasis]),
5552
+ .CalendarDay[data-selected]:not([data-emphasis]) {
5482
5553
  --sl-e-bg: var(--sl-scope-solid);
5483
5554
  --sl-e-bg-hover: var(--sl-scope-solid-hover);
5484
5555
  --sl-e-bg-active: var(--sl-scope-solid-active);
@@ -5498,7 +5569,9 @@
5498
5569
  --sl-e-border-hover: var(--sl-scope-solid-hover);
5499
5570
  }
5500
5571
 
5501
- [data-emphasis='subtle'] {
5572
+ [data-emphasis='subtle'],
5573
+ .Badge:not([data-emphasis]),
5574
+ .EmptyStateMedia:not([data-emphasis]) {
5502
5575
  --sl-e-bg: var(--sl-scope-soft);
5503
5576
  --sl-e-bg-hover: var(--sl-scope-soft-hover);
5504
5577
  --sl-e-bg-active: var(--sl-scope-soft-active);
@@ -5507,7 +5580,9 @@
5507
5580
  --sl-e-border-hover: var(--sl-scope-soft-hover);
5508
5581
  }
5509
5582
 
5510
- [data-emphasis='subtle']:not([data-color], [data-status], [data-status] *, .Toast[data-type], .Toast[data-type] *) {
5583
+ [data-emphasis='subtle']:not([data-color], [data-status], [data-status] *, .Toast[data-type], .Toast[data-type] *),
5584
+ .Badge:not([data-emphasis]):not([data-color], [data-status], [data-status] *, .Toast[data-type], .Toast[data-type] *),
5585
+ .EmptyStateMedia:not([data-emphasis]):not([data-color], [data-color] *, [data-status], [data-status] *, .Toast[data-type], .Toast[data-type] *) {
5511
5586
  --sl-scope-solid: var(--sl-scope-chrome-solid);
5512
5587
  --sl-scope-solid-hover: var(--sl-scope-chrome-solid-hover);
5513
5588
  --sl-scope-solid-active: var(--sl-scope-chrome-solid-active);
@@ -5646,6 +5721,13 @@
5646
5721
  --sl-bar-background: var(--sl-surface-tray);
5647
5722
  --sl-bar-border-color: var(--sl-border-default);
5648
5723
  --sl-bar-separator-color: var(--sl-border-default);
5724
+ --sl-calendar-day-color: var(--sl-text-primary);
5725
+ --sl-calendar-day-color-outside: var(--sl-text-tertiary);
5726
+ --sl-calendar-day-color-disabled: var(--sl-text-disabled);
5727
+ --sl-calendar-range-background: var(--sl-interactive-tint-active);
5728
+ --sl-calendar-range-color: var(--sl-text-on-tint-strong);
5729
+ --sl-calendar-today-ring: var(--sl-border-accent);
5730
+ --sl-calendar-weekday-color: var(--sl-text-tertiary);
5649
5731
  --sl-check-border-color: var(--sl-border-control);
5650
5732
  --sl-check-border-color-hover: var(--sl-border-control-hover);
5651
5733
  --sl-check-background-checked: var(--sl-interactive-default);
@@ -5674,6 +5756,7 @@
5674
5756
  --sl-field-color-disabled: var(--sl-text-disabled);
5675
5757
  --sl-field-placeholder-color: var(--sl-text-tertiary);
5676
5758
  --sl-field-shadow-focus: var(--sl-focus-shadow-3px-primary);
5759
+ --sl-field-affix-color: var(--sl-text-secondary);
5677
5760
  --sl-gauge-track-color: var(--sl-fill-track);
5678
5761
  --sl-gauge-label-color: var(--sl-text-primary);
5679
5762
  --sl-gauge-value-color: var(--sl-text-secondary);
@@ -5707,10 +5790,13 @@
5707
5790
  --sl-table-row-border-color: var(--sl-border-subtle);
5708
5791
  --sl-table-row-hover: var(--sl-item-background-hover);
5709
5792
  --sl-table-row-selected: var(--sl-item-background-selected);
5793
+ --sl-table-row-current: var(--sl-surface-tray);
5794
+ --sl-table-group-header-background: var(--sl-surface-tray);
5710
5795
  --sl-table-column-hover: var(--sl-fill-subtle);
5711
5796
  --sl-table-range-background: var(--sl-interactive-tint);
5712
5797
  --sl-table-range-border: var(--sl-focus-ring);
5713
5798
  --sl-drawer-handle-color: var(--sl-border-strong);
5799
+ --sl-calendar-day-background-hover: var(--sl-item-background-hover);
5714
5800
  --sl-check-background: var(--sl-field-background);
5715
5801
  }
5716
5802
 
@@ -5781,6 +5867,13 @@
5781
5867
  --sl-bar-background: var(--sl-surface-tray);
5782
5868
  --sl-bar-border-color: var(--sl-border-default);
5783
5869
  --sl-bar-separator-color: var(--sl-border-default);
5870
+ --sl-calendar-day-color: var(--sl-text-primary);
5871
+ --sl-calendar-day-color-outside: var(--sl-text-tertiary);
5872
+ --sl-calendar-day-color-disabled: var(--sl-text-disabled);
5873
+ --sl-calendar-range-background: var(--sl-interactive-tint-active);
5874
+ --sl-calendar-range-color: var(--sl-text-on-tint-strong);
5875
+ --sl-calendar-today-ring: var(--sl-border-accent);
5876
+ --sl-calendar-weekday-color: var(--sl-text-tertiary);
5784
5877
  --sl-check-border-color: var(--sl-border-control);
5785
5878
  --sl-check-border-color-hover: var(--sl-border-control-hover);
5786
5879
  --sl-check-background-checked: var(--sl-interactive-default);
@@ -5809,6 +5902,7 @@
5809
5902
  --sl-field-color-disabled: var(--sl-text-disabled);
5810
5903
  --sl-field-placeholder-color: var(--sl-text-tertiary);
5811
5904
  --sl-field-shadow-focus: var(--sl-focus-shadow-3px-primary);
5905
+ --sl-field-affix-color: var(--sl-text-secondary);
5812
5906
  --sl-gauge-track-color: var(--sl-fill-track);
5813
5907
  --sl-gauge-label-color: var(--sl-text-primary);
5814
5908
  --sl-gauge-value-color: var(--sl-text-secondary);
@@ -5842,10 +5936,13 @@
5842
5936
  --sl-table-row-border-color: var(--sl-border-subtle);
5843
5937
  --sl-table-row-hover: var(--sl-item-background-hover);
5844
5938
  --sl-table-row-selected: var(--sl-item-background-selected);
5939
+ --sl-table-row-current: var(--sl-surface-tray);
5940
+ --sl-table-group-header-background: var(--sl-surface-tray);
5845
5941
  --sl-table-column-hover: var(--sl-fill-subtle);
5846
5942
  --sl-table-range-background: var(--sl-interactive-tint);
5847
5943
  --sl-table-range-border: var(--sl-focus-ring);
5848
5944
  --sl-drawer-handle-color: var(--sl-border-strong);
5945
+ --sl-calendar-day-background-hover: var(--sl-item-background-hover);
5849
5946
  --sl-check-background: var(--sl-field-background);
5850
5947
  }
5851
5948
 
@@ -5916,6 +6013,13 @@
5916
6013
  --sl-bar-background: var(--sl-surface-tray);
5917
6014
  --sl-bar-border-color: var(--sl-border-default);
5918
6015
  --sl-bar-separator-color: var(--sl-border-default);
6016
+ --sl-calendar-day-color: var(--sl-text-primary);
6017
+ --sl-calendar-day-color-outside: var(--sl-text-tertiary);
6018
+ --sl-calendar-day-color-disabled: var(--sl-text-disabled);
6019
+ --sl-calendar-range-background: var(--sl-interactive-tint-active);
6020
+ --sl-calendar-range-color: var(--sl-text-on-tint-strong);
6021
+ --sl-calendar-today-ring: var(--sl-border-accent);
6022
+ --sl-calendar-weekday-color: var(--sl-text-tertiary);
5919
6023
  --sl-check-border-color: var(--sl-border-control);
5920
6024
  --sl-check-border-color-hover: var(--sl-border-control-hover);
5921
6025
  --sl-check-background-checked: var(--sl-interactive-default);
@@ -5944,6 +6048,7 @@
5944
6048
  --sl-field-color-disabled: var(--sl-text-disabled);
5945
6049
  --sl-field-placeholder-color: var(--sl-text-tertiary);
5946
6050
  --sl-field-shadow-focus: var(--sl-focus-shadow-3px-primary);
6051
+ --sl-field-affix-color: var(--sl-text-secondary);
5947
6052
  --sl-gauge-track-color: var(--sl-fill-track);
5948
6053
  --sl-gauge-label-color: var(--sl-text-primary);
5949
6054
  --sl-gauge-value-color: var(--sl-text-secondary);
@@ -5977,10 +6082,13 @@
5977
6082
  --sl-table-row-border-color: var(--sl-border-subtle);
5978
6083
  --sl-table-row-hover: var(--sl-item-background-hover);
5979
6084
  --sl-table-row-selected: var(--sl-item-background-selected);
6085
+ --sl-table-row-current: var(--sl-surface-tray);
6086
+ --sl-table-group-header-background: var(--sl-surface-tray);
5980
6087
  --sl-table-column-hover: var(--sl-fill-subtle);
5981
6088
  --sl-table-range-background: var(--sl-interactive-tint);
5982
6089
  --sl-table-range-border: var(--sl-focus-ring);
5983
6090
  --sl-drawer-handle-color: var(--sl-border-strong);
6091
+ --sl-calendar-day-background-hover: var(--sl-item-background-hover);
5984
6092
  --sl-check-background: var(--sl-field-background);
5985
6093
  }
5986
6094
  }
@@ -6306,7 +6414,7 @@
6306
6414
  }
6307
6415
 
6308
6416
 
6309
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
6417
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
6310
6418
  /* Loomiere for Base UI: component styles. Brand-free: every value is a --sl- variable from a
6311
6419
  Loomiere theme. Load the theme first:
6312
6420
  @import '<your theme>/tokens.css';
@@ -6316,7 +6424,7 @@
6316
6424
  /* Document defaults, in the reset layer so any unlayered rule wins over them, and so layered
6317
6425
  frameworks (Chakra's recipes, Tailwind's utilities) are not undone by them. */
6318
6426
  @layer reset {
6319
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
6427
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
6320
6428
  /* CSS Reset - Mojave Theme */
6321
6429
 
6322
6430
  /* ============================================
@@ -6760,7 +6868,7 @@ hr {
6760
6868
  }
6761
6869
  }
6762
6870
  @layer reset {
6763
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
6871
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
6764
6872
  /* Accessibility — base rules (no theme color dependencies). Theme-specific focus/invalid: accessibility-theme.css */
6765
6873
 
6766
6874
  /* Remove default focus; keyboard focus styled in accessibility-theme.css */
@@ -6873,7 +6981,7 @@ main:focus {
6873
6981
 
6874
6982
  }
6875
6983
  @layer reset {
6876
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
6984
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
6877
6985
  /* Focus, invalid, contrast — requires theme tokens (after theme-accessibility.css). */
6878
6986
 
6879
6987
  :focus-visible {
@@ -6941,7 +7049,7 @@ button,
6941
7049
 
6942
7050
  }
6943
7051
  /* Component styles */
6944
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7052
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
6945
7053
  /* Accordion - Mojave Theme
6946
7054
  *
6947
7055
  * No component tokens. Hover, press, chevron, divider and motion are the disclosure
@@ -7062,7 +7170,7 @@ button,
7062
7170
  overflow: hidden;
7063
7171
  }
7064
7172
 
7065
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7173
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7066
7174
  /* Alert Dialog - Mojave Theme
7067
7175
  *
7068
7176
  * No component tokens and no rules of its own. An alert dialog looks exactly like a
@@ -7071,7 +7179,7 @@ button,
7071
7179
  * cancel quiet, and a destructive one bold with data-color="error".
7072
7180
  */
7073
7181
 
7074
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7182
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7075
7183
  /* Autocomplete - Mojave Theme
7076
7184
  *
7077
7185
  * No component tokens. The input is Input (Input.css), the clear button is an icon
@@ -7273,7 +7381,7 @@ button,
7273
7381
  (reset-accessibility.css).
7274
7382
  ============================================ */
7275
7383
 
7276
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7384
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7277
7385
  /* Avatar - Mojave Theme
7278
7386
  *
7279
7387
  * A round picture with a ring in the page color, so avatars in a group cut out of each other in
@@ -7381,7 +7489,7 @@ button,
7381
7489
  }
7382
7490
  }
7383
7491
 
7384
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7492
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7385
7493
  /* Button - Mojave Theme
7386
7494
  *
7387
7495
  * Colors are the brand's emphasis levels, sizes are control.*, text is the trigger
@@ -7531,7 +7639,7 @@ button,
7531
7639
  font-size: var(--sl-icon-size-maximize);
7532
7640
  }
7533
7641
 
7534
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7642
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7535
7643
  /* Checkbox - Mojave Theme
7536
7644
  * Sizes follow the label: the box is the icon size one tier above the label's text
7537
7645
  * tier (like a button's icon) and the check mark one tier below it.
@@ -7688,7 +7796,7 @@ button,
7688
7796
  border-radius: var(--sl-radius-pill);
7689
7797
  }
7690
7798
 
7691
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7799
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7692
7800
  /* Checkbox Group - Mojave Theme */
7693
7801
 
7694
7802
  /* Each checkbox row is already a full tap target tall, so the rows sit close. */
@@ -7704,7 +7812,7 @@ button,
7704
7812
  pointer-events: none;
7705
7813
  }
7706
7814
 
7707
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7815
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7708
7816
  /* Collapsible - Mojave Theme
7709
7817
  *
7710
7818
  * No component tokens. Hover, press, chevron and motion are the disclosure concept
@@ -7820,7 +7928,7 @@ button,
7820
7928
  background: var(--sl-surface-raised);
7821
7929
  }
7822
7930
 
7823
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
7931
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
7824
7932
  /* Combobox - Mojave Theme
7825
7933
  *
7826
7934
  * No component tokens. The input is Input (Input.css); the chips box is a field; the
@@ -8305,7 +8413,7 @@ button,
8305
8413
  color: var(--sl-text-tertiary);
8306
8414
  }
8307
8415
 
8308
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8416
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8309
8417
  /* Context Menu - Mojave Theme
8310
8418
  *
8311
8419
  * 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
@@ -8474,7 +8582,7 @@ button,
8474
8582
  stroke-width: var(--sl-stroke-default);
8475
8583
  }
8476
8584
 
8477
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8585
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8478
8586
  /* Dialog and Alert dialog - Mojave Theme
8479
8587
  *
8480
8588
  * Both are centered modals built from the modal concept (tokens/semantic/modal.json):
@@ -8620,7 +8728,7 @@ button,
8620
8728
  margin-top: var(--sl-modal-actions-spacing);
8621
8729
  }
8622
8730
 
8623
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8731
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8624
8732
  /* Drawer - a panel that slides in from an edge and can be swiped away.
8625
8733
  The surface, scrim, heading and motion are the modal concept's (--sl-modal-*), so a
8626
8734
  drawer reads as a dialog's sibling; only its size and grab bar are its own
@@ -8747,7 +8855,7 @@ button,
8747
8855
  color: var(--sl-modal-description-color);
8748
8856
  }
8749
8857
 
8750
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8858
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8751
8859
  /* Field - Mojave Theme
8752
8860
  *
8753
8861
  * Label, control, description and error. No component tokens: spacing is the field
@@ -8808,7 +8916,7 @@ textarea.FieldControl {
8808
8916
  height: auto;
8809
8917
  }
8810
8918
 
8811
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8919
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8812
8920
  /* Fieldset - Mojave Theme
8813
8921
  *
8814
8922
  * No component tokens: a titled group of fields, spaced by the stack gaps, with
@@ -8850,7 +8958,7 @@ textarea.FieldControl {
8850
8958
  color: var(--sl-text-secondary);
8851
8959
  }
8852
8960
 
8853
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8961
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8854
8962
  /* Form - Mojave Theme
8855
8963
  *
8856
8964
  * No component tokens: fields stack with the large block space, and the action
@@ -8870,7 +8978,7 @@ textarea.FieldControl {
8870
8978
  margin-top: var(--sl-space-block-md);
8871
8979
  }
8872
8980
 
8873
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
8981
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
8874
8982
  /* Input - Mojave Theme
8875
8983
  *
8876
8984
  * No component tokens: the look is the field concept (tokens/semantic/field.json),
@@ -9007,7 +9115,7 @@ textarea.FieldControl {
9007
9115
  padding-inline: var(--sl-control-padding-inline-lg);
9008
9116
  }
9009
9117
 
9010
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
9118
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9011
9119
  /* Menu - Mojave Theme
9012
9120
  *
9013
9121
  * No component tokens. The trigger is a Button. The popup is the popup concept, rows are item rows at the
@@ -9156,7 +9264,7 @@ textarea.FieldControl {
9156
9264
  color: var(--sl-text-tertiary);
9157
9265
  }
9158
9266
 
9159
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
9267
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9160
9268
  /* Menubar - Mojave Theme
9161
9269
  *
9162
9270
  * No component tokens. A row of quiet triggers, each opening a menu. The popup is the popup concept, rows are item rows at the
@@ -9349,7 +9457,7 @@ textarea.FieldControl {
9349
9457
  color: var(--sl-text-tertiary);
9350
9458
  }
9351
9459
 
9352
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
9460
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9353
9461
  /* Meter - Mojave Theme
9354
9462
  *
9355
9463
  * A gauge (tokens/semantic/gauge.json). The fill is the solid color of the scope around it:
@@ -9412,7 +9520,7 @@ textarea.FieldControl {
9412
9520
  height: var(--sl-gauge-height-lg);
9413
9521
  }
9414
9522
 
9415
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
9523
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9416
9524
  /* Navigation Menu - Mojave Theme
9417
9525
  *
9418
9526
  * The strip is the bar concept, the panel is the popup concept and each link is an item
@@ -9832,7 +9940,7 @@ textarea.FieldControl {
9832
9940
  width: 100%;
9833
9941
  }
9834
9942
 
9835
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
9943
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9836
9944
  /* Number Field - Mojave Theme
9837
9945
  *
9838
9946
  * No component tokens. The input is Input (Input.css) and the label, description and
@@ -9923,7 +10031,7 @@ textarea.FieldControl {
9923
10031
  user-select: none;
9924
10032
  }
9925
10033
 
9926
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10034
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9927
10035
  /* OTP Field - Mojave Theme
9928
10036
  *
9929
10037
  * One-time code entry: a row of single-character inputs. Each slot is the same control as Input
@@ -9986,7 +10094,7 @@ textarea.FieldControl {
9986
10094
  letter-spacing: var(--sl-font-body-magnify-letter-spacing);
9987
10095
  }
9988
10096
 
9989
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10097
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
9990
10098
  /* Popover - Mojave Theme */
9991
10099
 
9992
10100
  /* ============================================
@@ -10151,7 +10259,7 @@ textarea.FieldControl {
10151
10259
  fill: var(--sl-popup-arrow-stroke);
10152
10260
  }
10153
10261
 
10154
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10262
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10155
10263
  /* Preview Card - Mojave Theme
10156
10264
  *
10157
10265
  * The popup concept (surface, arrow, motion) with a title-magnify title and condense
@@ -10268,7 +10376,7 @@ textarea.FieldControl {
10268
10376
  fill: var(--sl-popup-arrow-stroke);
10269
10377
  }
10270
10378
 
10271
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10379
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10272
10380
  /* Progress - Mojave Theme
10273
10381
  *
10274
10382
  * A gauge (tokens/semantic/gauge.json), the same bar as Meter. The fill is the solid color of
@@ -10345,7 +10453,7 @@ textarea.FieldControl {
10345
10453
  height: var(--sl-gauge-height-lg);
10346
10454
  }
10347
10455
 
10348
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10456
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10349
10457
  /* Radio - Mojave Theme
10350
10458
  * Same box as Checkbox, always round. Sizes follow the label the same way, and the
10351
10459
  * dot is a share of the circle (check.dot-scale).
@@ -10497,7 +10605,7 @@ textarea.FieldControl {
10497
10605
  gap: var(--sl-gap-stack-sm);
10498
10606
  }
10499
10607
 
10500
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10608
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10501
10609
  /* Scroll Area - Mojave Theme
10502
10610
  *
10503
10611
  * The scrollbar is the content scrollbar (content.scrollbar-*): a track that stays clear until
@@ -10579,7 +10687,7 @@ textarea.FieldControl {
10579
10687
  background: transparent;
10580
10688
  }
10581
10689
 
10582
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10690
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10583
10691
  /* Select - Mojave Theme
10584
10692
  *
10585
10693
  * The trigger is a field (the field pattern, control sizes, the base text style); the
@@ -10864,7 +10972,7 @@ textarea.FieldControl {
10864
10972
  stroke-width: var(--sl-stroke-default);
10865
10973
  }
10866
10974
 
10867
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
10975
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10868
10976
  /* Separator - Mojave Theme
10869
10977
  *
10870
10978
  * A hairline in the everyday divider color (border.default), one stroke thick, with a step of
@@ -10892,7 +11000,7 @@ textarea.FieldControl {
10892
11000
  margin-inline: var(--sl-space-4);
10893
11001
  }
10894
11002
 
10895
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11003
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
10896
11004
  /* Slider - Mojave Theme
10897
11005
  *
10898
11006
  * A slider is a gauge you can drag: the track, fill and label row are gauge.* (the same bar as
@@ -11058,7 +11166,7 @@ textarea.FieldControl {
11058
11166
  transform: translate(-50%, 50%);
11059
11167
  }
11060
11168
 
11061
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11169
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11062
11170
  /* Switch - Mojave Theme
11063
11171
  * Switch keeps its track sizes. The thumb, its travel and the ON/OFF text are
11064
11172
  * worked out from them: the thumb fills the track's height inside the padding,
@@ -11224,152 +11332,7 @@ textarea.FieldControl {
11224
11332
  color: var(--sl-text-disabled);
11225
11333
  }
11226
11334
 
11227
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11228
- /* Table - Mojave Theme
11229
- *
11230
- * Base UI has no table, so this styles the native <table class="Table"> elements with the
11231
- * table concept (tokens/semantic/table.json), the same tokens the AG Grid themes read: a small
11232
- * hand-built table and a full grid look alike. Rows answer to aria-selected="true" (or
11233
- * data-selected) for selection; cells take data-align="end" for numbers.
11234
- */
11235
-
11236
- .Table {
11237
- font-family: var(--sl-font-body-condense-font-family);
11238
- font-size: var(--sl-font-body-condense-font-size);
11239
- font-weight: var(--sl-font-body-condense-font-weight);
11240
- line-height: var(--sl-font-body-condense-line-height);
11241
- letter-spacing: var(--sl-font-body-condense-letter-spacing);
11242
- box-sizing: border-box;
11243
- width: 100%;
11244
- border-collapse: separate;
11245
- border-spacing: 0;
11246
- background: var(--sl-table-background);
11247
- color: var(--sl-table-color);
11248
- border: var(--sl-stroke-default) solid var(--sl-table-border-color);
11249
- border-radius: var(--sl-table-radius);
11250
- overflow: hidden;
11251
- font-variant-numeric: tabular-nums;
11252
- }
11253
-
11254
- .Table caption {
11255
- font-family: var(--sl-font-body-condense-font-family);
11256
- font-size: var(--sl-font-body-condense-font-size);
11257
- font-weight: var(--sl-font-body-condense-font-weight);
11258
- line-height: var(--sl-font-body-condense-line-height);
11259
- letter-spacing: var(--sl-font-body-condense-letter-spacing);
11260
- caption-side: bottom;
11261
- padding-block: var(--sl-space-2);
11262
- color: var(--sl-table-subtle-color);
11263
- text-align: start;
11264
- }
11265
-
11266
- /* Header: the tray band, a little taller than the rows */
11267
- .Table th {
11268
- font-family: var(--sl-font-subtitle-condense-font-family);
11269
- font-size: var(--sl-font-subtitle-condense-font-size);
11270
- font-weight: var(--sl-font-subtitle-condense-font-weight);
11271
- line-height: var(--sl-font-subtitle-condense-line-height);
11272
- letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
11273
- height: var(--sl-table-header-height);
11274
- padding-block: 0;
11275
- padding-inline: var(--sl-table-cell-padding-inline);
11276
- background: var(--sl-table-header-background);
11277
- color: var(--sl-table-header-color);
11278
- text-align: start;
11279
- vertical-align: middle;
11280
- border-bottom: var(--sl-stroke-default) solid var(--sl-table-border-color);
11281
- }
11282
-
11283
- /* A header that sorts: aria-sort on the th */
11284
- .Table th[aria-sort] {
11285
- cursor: pointer;
11286
- transition: background-color var(--sl-duration-fast) var(--sl-easing-default);
11287
- }
11288
-
11289
- .Table th[aria-sort]:hover {
11290
- background: var(--sl-table-header-background-hover);
11291
- }
11292
-
11293
- /* Body cells */
11294
- .Table td {
11295
- height: var(--sl-table-row-height);
11296
- padding-block: 0;
11297
- padding-inline: var(--sl-table-cell-padding-inline);
11298
- vertical-align: middle;
11299
- border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
11300
- }
11301
-
11302
- .Table tbody tr:last-child td,
11303
- .Table tbody:last-child tr:last-child td {
11304
- border-bottom: none;
11305
- }
11306
-
11307
- /* A row header (th in tbody) reads like a cell, in the header's weight */
11308
- .Table tbody th {
11309
- background: transparent;
11310
- border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
11311
- }
11312
-
11313
- /* Numbers and amounts: right-aligned so digits line up */
11314
- .Table [data-align='end'] {
11315
- text-align: end;
11316
- }
11317
-
11318
- .Table [data-align='center'] {
11319
- text-align: center;
11320
- }
11321
-
11322
- /* Secondary text in a cell */
11323
- .Table [data-subtle] {
11324
- color: var(--sl-table-subtle-color);
11325
- }
11326
-
11327
- /* Hover and selection: the same tints as list items */
11328
- @media (hover: hover) {
11329
- .Table tbody tr:hover > * {
11330
- background: var(--sl-table-row-hover);
11331
- color: var(--sl-item-color-hover);
11332
- }
11333
- }
11334
-
11335
- .Table tbody tr:is([aria-selected='true'], [data-selected]) > * {
11336
- background: var(--sl-table-row-selected);
11337
- color: var(--sl-item-color-selected);
11338
- }
11339
-
11340
- /* Footer: totals on the tray band */
11341
- .Table tfoot td {
11342
- font-family: var(--sl-font-subtitle-condense-font-family);
11343
- font-size: var(--sl-font-subtitle-condense-font-size);
11344
- font-weight: var(--sl-font-subtitle-condense-font-weight);
11345
- line-height: var(--sl-font-subtitle-condense-line-height);
11346
- letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
11347
- background: var(--sl-table-header-background);
11348
- border-top: var(--sl-stroke-default) solid var(--sl-table-border-color);
11349
- border-bottom: none;
11350
- }
11351
-
11352
- /* A header that stays put while the body scrolls (the table's wrapper scrolls) */
11353
- .Table[data-sticky-header] thead th {
11354
- position: sticky;
11355
- top: 0;
11356
- z-index: var(--sl-z-index-docked);
11357
- }
11358
-
11359
- /* Empty state: one cell spanning the columns */
11360
- .Table td[data-empty] {
11361
- height: auto;
11362
- padding-block: var(--sl-space-10);
11363
- color: var(--sl-text-tertiary);
11364
- text-align: center;
11365
- }
11366
-
11367
- .Table tbody tr:has(> td[data-empty]):hover > * {
11368
- background: transparent;
11369
- color: var(--sl-text-tertiary);
11370
- }
11371
-
11372
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11335
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11373
11336
  /* Tabs - Mojave Theme
11374
11337
  *
11375
11338
  * No component tokens. The divider, the selected line and color, hover and the disabled
@@ -11505,7 +11468,7 @@ textarea.FieldControl {
11505
11468
  padding: var(--sl-space-6);
11506
11469
  }
11507
11470
 
11508
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11471
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11509
11472
  /* Toast - Mojave Theme
11510
11473
  *
11511
11474
  * A toast is a notice (tokens/semantic/notice.json) on the popup surface. A toast whose type
@@ -11741,7 +11704,7 @@ textarea.FieldControl {
11741
11704
  flex-shrink: 0;
11742
11705
  }
11743
11706
 
11744
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11707
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11745
11708
  /* Toggle - Mojave Theme
11746
11709
  * A toggle is a button that stays pressed: the same heights, padding, gap and
11747
11710
  * trigger text style as a button of the same size. Pressed, it takes its emphasis level's
@@ -11853,7 +11816,7 @@ textarea.FieldControl {
11853
11816
  height: var(--sl-icon-size-maximize);
11854
11817
  }
11855
11818
 
11856
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11819
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11857
11820
  /* Toggle Group - Mojave Theme
11858
11821
  *
11859
11822
  * No component tokens. The strip is the bar concept (tokens/semantic/bar.json); the
@@ -11874,7 +11837,7 @@ textarea.FieldControl {
11874
11837
  border-radius: var(--sl-radius-item);
11875
11838
  }
11876
11839
 
11877
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11840
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11878
11841
  /* Toolbar - Mojave Theme
11879
11842
  *
11880
11843
  * The strip is the bar concept (tokens/semantic/bar.json). Buttons, toggles, selects
@@ -11936,7 +11899,7 @@ textarea.FieldControl {
11936
11899
  max-width: var(--sl-toolbar-input-max-width);
11937
11900
  }
11938
11901
 
11939
- /* @scattered-light/loomiere-base-ui 0.6.0 · styles for @base-ui/react 1.9.0 */
11902
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11940
11903
  /* Tooltip - Mojave Theme
11941
11904
  *
11942
11905
  * The inverse surface (surface.inverse, text.on-inverse-surface) with condense text, so a tooltip
@@ -11995,3 +11958,2311 @@ textarea.FieldControl {
11995
11958
  transform: none;
11996
11959
  }
11997
11960
  }
11961
+
11962
+ /* Custom components: not Base UI parts. Built from existing concepts and tokens. */
11963
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
11964
+ /* Badge
11965
+ *
11966
+ * A status or count label. Not a Base UI part, and not interactive: no hover or focus.
11967
+ * Colors are the emphasis levels (--sl-e-bg, --sl-e-fg, --sl-e-border), so data-emphasis,
11968
+ * data-status and data-color all recolor it. The default level is subtle, from
11969
+ * DEFAULT_LEVELS. The shape is radius.pill. Sizes are badge.* (tokens/component/badge.json).
11970
+ *
11971
+ * Text is the trigger style of the same tier (trigger-minimize, trigger-condense,
11972
+ * trigger-base): medium weight, and those three tiers already exist. subtitle is bold,
11973
+ * which would shout, and label only exists at base. Icons use icon-size of that same
11974
+ * tier (a badge icon is a mark beside the label, not a control that fills the line the
11975
+ * way a Button icon does).
11976
+ *
11977
+ * Min width equals the height on every badge, so a single digit is a circle and a
11978
+ * wider label is unchanged. Padding stays, so "12" does not touch the pill edges.
11979
+ */
11980
+
11981
+ .Badge {
11982
+ font-family: var(--sl-font-trigger-condense-font-family);
11983
+ font-size: var(--sl-font-trigger-condense-font-size);
11984
+ font-weight: var(--sl-font-trigger-condense-font-weight);
11985
+ line-height: var(--sl-font-trigger-condense-line-height);
11986
+ letter-spacing: var(--sl-font-trigger-condense-letter-spacing);
11987
+ display: inline-flex;
11988
+ align-items: center;
11989
+ justify-content: center;
11990
+ gap: var(--sl-badge-gap-condense);
11991
+ height: var(--sl-badge-height-condense);
11992
+ min-width: var(--sl-badge-height-condense);
11993
+ padding-inline: var(--sl-badge-padding-inline-condense);
11994
+ border: var(--sl-stroke-default) solid var(--sl-e-border);
11995
+ border-radius: var(--sl-radius-pill);
11996
+ background: var(--sl-e-bg);
11997
+ color: var(--sl-e-fg);
11998
+ white-space: nowrap;
11999
+ }
12000
+
12001
+ .Badge[data-size='minimize'] {
12002
+ font-family: var(--sl-font-trigger-minimize-font-family);
12003
+ font-size: var(--sl-font-trigger-minimize-font-size);
12004
+ font-weight: var(--sl-font-trigger-minimize-font-weight);
12005
+ line-height: var(--sl-font-trigger-minimize-line-height);
12006
+ letter-spacing: var(--sl-font-trigger-minimize-letter-spacing);
12007
+ gap: var(--sl-badge-gap-minimize);
12008
+ height: var(--sl-badge-height-minimize);
12009
+ min-width: var(--sl-badge-height-minimize);
12010
+ padding-inline: var(--sl-badge-padding-inline-minimize);
12011
+ }
12012
+
12013
+ .Badge[data-size='base'] {
12014
+ font-family: var(--sl-font-trigger-base-font-family);
12015
+ font-size: var(--sl-font-trigger-base-font-size);
12016
+ font-weight: var(--sl-font-trigger-base-font-weight);
12017
+ line-height: var(--sl-font-trigger-base-line-height);
12018
+ letter-spacing: var(--sl-font-trigger-base-letter-spacing);
12019
+ gap: var(--sl-badge-gap-base);
12020
+ height: var(--sl-badge-height-base);
12021
+ min-width: var(--sl-badge-height-base);
12022
+ padding-inline: var(--sl-badge-padding-inline-base);
12023
+ }
12024
+
12025
+ .Badge svg,
12026
+ .Badge .material-symbols-outlined {
12027
+ width: var(--sl-icon-size-condense);
12028
+ height: var(--sl-icon-size-condense);
12029
+ font-size: var(--sl-icon-size-condense);
12030
+ line-height: 1;
12031
+ flex-shrink: 0;
12032
+ }
12033
+
12034
+ .Badge[data-size='minimize'] svg,
12035
+ .Badge[data-size='minimize'] .material-symbols-outlined {
12036
+ width: var(--sl-icon-size-minimize);
12037
+ height: var(--sl-icon-size-minimize);
12038
+ font-size: var(--sl-icon-size-minimize);
12039
+ }
12040
+
12041
+ .Badge[data-size='base'] svg,
12042
+ .Badge[data-size='base'] .material-symbols-outlined {
12043
+ width: var(--sl-icon-size-base);
12044
+ height: var(--sl-icon-size-base);
12045
+ font-size: var(--sl-icon-size-base);
12046
+ }
12047
+
12048
+ /* A status dot, in the label color. */
12049
+ .Badge[data-dot]::before {
12050
+ content: '';
12051
+ width: var(--sl-badge-dot-condense);
12052
+ height: var(--sl-badge-dot-condense);
12053
+ border-radius: var(--sl-radius-pill);
12054
+ background: currentColor;
12055
+ flex-shrink: 0;
12056
+ }
12057
+
12058
+ .Badge[data-size='minimize'][data-dot]::before {
12059
+ width: var(--sl-badge-dot-minimize);
12060
+ height: var(--sl-badge-dot-minimize);
12061
+ }
12062
+
12063
+ .Badge[data-size='base'][data-dot]::before {
12064
+ width: var(--sl-badge-dot-base);
12065
+ height: var(--sl-badge-dot-base);
12066
+ }
12067
+
12068
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
12069
+ /*
12070
+ * DatePicker: a field that opens a calendar for one date or a period.
12071
+ * Not a Base UI part. The popup is Popover on a wide viewport and Drawer
12072
+ * below the md breakpoint. Calendar is the grid on its own; DatePresets is
12073
+ * the quick-selection list. Both are usable without the field.
12074
+ *
12075
+ * Concepts: calendar (day cell, range band, today ring), item (preset rows),
12076
+ * field (the trigger), emphasis bold (the selected day, via the default
12077
+ * emphasis level, so it follows data-color).
12078
+ *
12079
+ * Text styles, one whole style each: day numbers are trigger-condense and
12080
+ * selected days are selected-condense, weekday initials are eyebrow-minimize,
12081
+ * the month title is subtitle-base, a preset label is trigger-condense with
12082
+ * its hint in body-minimize, and the footer summary is body-condense.
12083
+ * The trigger text is text-body-base, the same style as Input.
12084
+ *
12085
+ * How many months are on screen is measured on the panel (40rem two months,
12086
+ * 32rem one, and one month in a drawer or for a coarse pointer under 48rem).
12087
+ * Those lengths are layout, not tokens. CSS only switches the preset row and
12088
+ * the sticky footer, from data-layout and data-compact.
12089
+ *
12090
+ * Keyboard (WAI-ARIA APG date picker dialog): Left/Right one day (they swap
12091
+ * in RTL), Up/Down one week, Home/End the week, PageUp/PageDown one month,
12092
+ * Shift+PageUp/PageDown one year, Enter/Space pick. With two months showing,
12093
+ * paging forward lands the focused day in the last column, so the view shifts
12094
+ * by one month. Delete or Backspace clears the draft. Escape drops a
12095
+ * half-picked range first, then closes. Escape in the month or year chooser
12096
+ * returns to the days. A range is a start click, then an end click; an end
12097
+ * before the start swaps. Hover or focus previews the band until the end is
12098
+ * chosen. Direction is read when the picker opens; a dir change while it is
12099
+ * open is not picked up.
12100
+ *
12101
+ * Day state: data-selected, data-range-start, data-range-end, data-in-range,
12102
+ * data-preview, data-today, data-outside-month, data-disabled, data-focused.
12103
+ * aria-selected is only the real value (the day, or the start and end).
12104
+ */
12105
+
12106
+ /* CALENDAR */
12107
+
12108
+ .Calendar {
12109
+ display: flex;
12110
+ flex-direction: column;
12111
+ gap: var(--sl-calendar-month-gap);
12112
+ min-width: 0;
12113
+ }
12114
+
12115
+ .DatePickerMonths {
12116
+ display: flex;
12117
+ flex-wrap: wrap;
12118
+ gap: var(--sl-calendar-month-gap);
12119
+ min-width: 0;
12120
+ }
12121
+
12122
+ .DatePickerNav {
12123
+ display: flex;
12124
+ align-items: center;
12125
+ gap: var(--sl-calendar-header-gap);
12126
+ flex: 1 0 100%;
12127
+ }
12128
+
12129
+ .DatePickerNav .DatePickerMonthTitle {
12130
+ flex: 1 1 auto;
12131
+ }
12132
+
12133
+ .DatePickerMonth {
12134
+ display: flex;
12135
+ flex-direction: column;
12136
+ gap: var(--sl-calendar-header-gap);
12137
+ min-width: 0;
12138
+ flex: 1 1 auto;
12139
+ }
12140
+
12141
+ .DatePickerMonthBar {
12142
+ display: flex;
12143
+ align-items: center;
12144
+ justify-content: space-between;
12145
+ gap: var(--sl-calendar-header-gap);
12146
+ min-height: var(--sl-control-height-sm);
12147
+ }
12148
+
12149
+ .DatePickerMonthSpacer {
12150
+ inline-size: var(--sl-control-height-sm);
12151
+ flex: 0 0 auto;
12152
+ }
12153
+
12154
+ .DatePickerMonthTitle {
12155
+ font-family: var(--sl-font-subtitle-base-font-family);
12156
+ font-size: var(--sl-font-subtitle-base-font-size);
12157
+ font-weight: var(--sl-font-subtitle-base-font-weight);
12158
+ line-height: var(--sl-font-subtitle-base-line-height);
12159
+ letter-spacing: var(--sl-font-subtitle-base-letter-spacing);
12160
+ outline: none;
12161
+ margin: 0;
12162
+ padding: var(--sl-space-1) var(--sl-space-2);
12163
+ border: 0;
12164
+ border-radius: var(--sl-radius-control);
12165
+ background: transparent;
12166
+ color: var(--sl-text-primary);
12167
+ cursor: pointer;
12168
+ }
12169
+
12170
+ .DatePickerMonthTitle:hover {
12171
+ background: var(--sl-item-background-hover);
12172
+ }
12173
+
12174
+ .DatePickerMonthTitle:focus-visible {
12175
+ outline: var(--sl-focus-outline);
12176
+ outline-offset: var(--sl-focus-outline-offset);
12177
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
12178
+ }
12179
+
12180
+ .CalendarGrid {
12181
+ display: flex;
12182
+ flex-direction: column;
12183
+ gap: var(--sl-calendar-grid-gap);
12184
+ }
12185
+
12186
+ .Calendar,
12187
+ .DatePickerPanel {
12188
+ --sl-calendar-cell: var(--sl-calendar-day-size);
12189
+ }
12190
+
12191
+ .DatePickerPanel[data-touch] {
12192
+ --sl-calendar-cell: max(var(--sl-calendar-day-size), var(--sl-a11y-min-touch-target));
12193
+ }
12194
+
12195
+ @media (pointer: coarse) {
12196
+ .Calendar {
12197
+ --sl-calendar-cell: max(var(--sl-calendar-day-size), var(--sl-a11y-min-touch-target));
12198
+ }
12199
+ }
12200
+
12201
+ .CalendarWeek {
12202
+ display: grid;
12203
+ grid-template-columns: repeat(7, var(--sl-calendar-cell));
12204
+ column-gap: 0;
12205
+ row-gap: var(--sl-calendar-grid-gap);
12206
+ }
12207
+
12208
+ .CalendarGrid:has(.CalendarWeekNumber) .CalendarWeek {
12209
+ grid-template-columns: auto repeat(7, var(--sl-calendar-cell));
12210
+ }
12211
+
12212
+ .CalendarWeekday,
12213
+ .CalendarWeekNumber {
12214
+ font-family: var(--sl-font-eyebrow-minimize-font-family);
12215
+ font-size: var(--sl-font-eyebrow-minimize-font-size);
12216
+ font-weight: var(--sl-font-eyebrow-minimize-font-weight);
12217
+ line-height: var(--sl-font-eyebrow-minimize-line-height);
12218
+ letter-spacing: var(--sl-font-eyebrow-minimize-letter-spacing);
12219
+ text-transform: var(--sl-font-eyebrow-minimize-text-transform);
12220
+ display: grid;
12221
+ place-items: center;
12222
+ min-block-size: var(--sl-space-6);
12223
+ color: var(--sl-calendar-weekday-color);
12224
+ text-decoration: none;
12225
+ }
12226
+
12227
+ .CalendarWeekNumber {
12228
+ padding-inline: var(--sl-space-1);
12229
+ }
12230
+
12231
+ .CalendarDay {
12232
+ font-family: var(--sl-font-trigger-condense-font-family);
12233
+ font-size: var(--sl-font-trigger-condense-font-size);
12234
+ font-weight: var(--sl-font-trigger-condense-font-weight);
12235
+ line-height: var(--sl-font-trigger-condense-line-height);
12236
+ letter-spacing: var(--sl-font-trigger-condense-letter-spacing);
12237
+ position: relative;
12238
+ display: grid;
12239
+ place-items: center;
12240
+ box-sizing: border-box;
12241
+ inline-size: 100%;
12242
+ aspect-ratio: 1;
12243
+ min-inline-size: 0;
12244
+ min-block-size: 0;
12245
+ padding: 0;
12246
+ border: 0;
12247
+ border-radius: var(--sl-calendar-day-radius);
12248
+ outline: none;
12249
+ background: transparent;
12250
+ color: var(--sl-calendar-day-color);
12251
+ cursor: pointer;
12252
+ }
12253
+
12254
+ .CalendarDay:focus-visible {
12255
+ outline: var(--sl-focus-outline);
12256
+ outline-offset: var(--sl-focus-outline-offset);
12257
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
12258
+ }
12259
+
12260
+ .CalendarDay--empty {
12261
+ cursor: default;
12262
+ pointer-events: none;
12263
+ }
12264
+
12265
+ .CalendarDayNumber {
12266
+ position: relative;
12267
+ z-index: 1;
12268
+ }
12269
+
12270
+ .CalendarDay:hover:not([data-disabled]):not([data-selected]) {
12271
+ background: var(--sl-calendar-day-background-hover);
12272
+ }
12273
+
12274
+ .CalendarDay[data-outside-month] {
12275
+ color: var(--sl-calendar-day-color-outside);
12276
+ }
12277
+
12278
+ .CalendarDay[data-disabled] {
12279
+ color: var(--sl-calendar-day-color-disabled);
12280
+ cursor: default;
12281
+ }
12282
+
12283
+ .CalendarDay[data-selected] {
12284
+ font-family: var(--sl-font-selected-condense-font-family);
12285
+ font-size: var(--sl-font-selected-condense-font-size);
12286
+ font-weight: var(--sl-font-selected-condense-font-weight);
12287
+ line-height: var(--sl-font-selected-condense-line-height);
12288
+ letter-spacing: var(--sl-font-selected-condense-letter-spacing);
12289
+ }
12290
+
12291
+ .CalendarDay[data-selected]:not([data-range-start]):not([data-range-end]) {
12292
+ background: var(--sl-e-bg);
12293
+ color: var(--sl-e-fg);
12294
+ }
12295
+
12296
+ .CalendarDay[data-range-start],
12297
+ .CalendarDay[data-range-end] {
12298
+ overflow: hidden;
12299
+ background: transparent;
12300
+ }
12301
+
12302
+ .CalendarDay[data-range-start] .CalendarDayNumber,
12303
+ .CalendarDay[data-range-end] .CalendarDayNumber {
12304
+ display: grid;
12305
+ place-items: center;
12306
+ inline-size: 100%;
12307
+ block-size: 100%;
12308
+ border-radius: var(--sl-calendar-day-radius);
12309
+ background: var(--sl-e-bg);
12310
+ color: var(--sl-e-fg);
12311
+ }
12312
+
12313
+ .CalendarDay[data-in-range],
12314
+ .CalendarDay[data-preview]:not([data-selected]) {
12315
+ border-radius: 0;
12316
+ background: var(--sl-calendar-range-background);
12317
+ color: var(--sl-calendar-range-color);
12318
+ }
12319
+
12320
+ .CalendarDay[data-range-start]::before,
12321
+ .CalendarDay[data-range-end]::before {
12322
+ content: '';
12323
+ position: absolute;
12324
+ inset: 0;
12325
+ z-index: 0;
12326
+ background: linear-gradient(to right, transparent 50%, var(--sl-calendar-range-background) 50%);
12327
+ }
12328
+
12329
+ .CalendarDay[data-range-end]::before {
12330
+ background: linear-gradient(to left, transparent 50%, var(--sl-calendar-range-background) 50%);
12331
+ }
12332
+
12333
+ [dir='rtl'] .CalendarDay[data-range-start]::before {
12334
+ background: linear-gradient(to left, transparent 50%, var(--sl-calendar-range-background) 50%);
12335
+ }
12336
+
12337
+ [dir='rtl'] .CalendarDay[data-range-end]::before {
12338
+ background: linear-gradient(to right, transparent 50%, var(--sl-calendar-range-background) 50%);
12339
+ }
12340
+
12341
+ .CalendarDay[data-range-start][data-range-end]::before {
12342
+ content: none;
12343
+ }
12344
+
12345
+ .CalendarDay[data-focused] {
12346
+ z-index: 1;
12347
+ }
12348
+
12349
+ .CalendarDay[data-today] .CalendarDayNumber {
12350
+ box-shadow: inset 0 0 0 var(--sl-stroke-default) var(--sl-calendar-today-ring);
12351
+ border-radius: var(--sl-calendar-day-radius);
12352
+ padding-inline: var(--sl-space-1);
12353
+ }
12354
+
12355
+ /* The selected fill is the bold accent, the same hue as the today ring, so the ring switches to the text color. */
12356
+ .CalendarDay[data-today][data-selected] .CalendarDayNumber {
12357
+ box-shadow: inset 0 0 0 var(--sl-stroke-default) var(--sl-e-fg);
12358
+ }
12359
+
12360
+ [data-theme$='high-contrast'] .CalendarDay[data-in-range],
12361
+ [data-theme$='high-contrast'] .CalendarDay[data-preview]:not([data-selected]) {
12362
+ box-shadow: inset 0 calc(var(--sl-stroke-default) * -1) 0 var(--sl-border-accent);
12363
+ }
12364
+
12365
+ .CalendarChooser {
12366
+ display: flex;
12367
+ flex-direction: column;
12368
+ gap: var(--sl-calendar-header-gap);
12369
+ }
12370
+
12371
+ .CalendarChooserGrid {
12372
+ display: grid;
12373
+ grid-template-columns: repeat(3, minmax(0, 1fr));
12374
+ gap: var(--sl-calendar-grid-gap);
12375
+ }
12376
+
12377
+ .CalendarChoice {
12378
+ font-family: var(--sl-font-trigger-condense-font-family);
12379
+ font-size: var(--sl-font-trigger-condense-font-size);
12380
+ font-weight: var(--sl-font-trigger-condense-font-weight);
12381
+ line-height: var(--sl-font-trigger-condense-line-height);
12382
+ letter-spacing: var(--sl-font-trigger-condense-letter-spacing);
12383
+ outline: none;
12384
+ min-block-size: var(--sl-control-height-sm);
12385
+ padding: var(--sl-space-1) var(--sl-space-2);
12386
+ border: 0;
12387
+ border-radius: var(--sl-radius-control);
12388
+ background: transparent;
12389
+ color: var(--sl-text-primary);
12390
+ cursor: pointer;
12391
+ }
12392
+
12393
+ .CalendarChoice:hover:not([aria-disabled='true']) {
12394
+ background: var(--sl-item-background-hover);
12395
+ }
12396
+
12397
+ .CalendarChoice:focus-visible {
12398
+ outline: var(--sl-focus-outline);
12399
+ outline-offset: var(--sl-focus-outline-offset);
12400
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
12401
+ }
12402
+
12403
+ .CalendarChoice[aria-disabled='true'] {
12404
+ color: var(--sl-calendar-day-color-disabled);
12405
+ cursor: default;
12406
+ }
12407
+
12408
+ /* PRESETS */
12409
+
12410
+ .DatePickerPresets {
12411
+ display: flex;
12412
+ flex-direction: column;
12413
+ gap: var(--sl-space-1);
12414
+ min-width: 0;
12415
+ }
12416
+
12417
+ .DatePickerPresets[data-layout='row'] {
12418
+ flex-direction: row;
12419
+ overflow-x: auto;
12420
+ }
12421
+
12422
+ .DatePickerPreset {
12423
+ font-family: var(--sl-font-trigger-condense-font-family);
12424
+ font-size: var(--sl-font-trigger-condense-font-size);
12425
+ font-weight: var(--sl-font-trigger-condense-font-weight);
12426
+ line-height: var(--sl-font-trigger-condense-line-height);
12427
+ letter-spacing: var(--sl-font-trigger-condense-letter-spacing);
12428
+ outline: none;
12429
+ display: flex;
12430
+ flex-direction: column;
12431
+ align-items: flex-start;
12432
+ gap: var(--sl-space-0-5);
12433
+ inline-size: 100%;
12434
+ padding: var(--sl-item-padding-block) var(--sl-item-padding-inline);
12435
+ border: 0;
12436
+ border-radius: var(--sl-item-radius);
12437
+ background: transparent;
12438
+ color: var(--sl-item-color);
12439
+ text-align: start;
12440
+ cursor: pointer;
12441
+ }
12442
+
12443
+ .DatePickerPresets[data-layout='row'] .DatePickerPreset {
12444
+ flex-direction: row;
12445
+ align-items: baseline;
12446
+ inline-size: auto;
12447
+ white-space: nowrap;
12448
+ }
12449
+
12450
+ .DatePickerPreset:hover:not([data-disabled]) {
12451
+ background: var(--sl-item-background-hover);
12452
+ }
12453
+
12454
+ .DatePickerPreset:focus-visible {
12455
+ outline: var(--sl-focus-outline);
12456
+ outline-offset: var(--sl-focus-outline-offset);
12457
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
12458
+ }
12459
+
12460
+ .DatePickerPreset[data-checked] {
12461
+ background: var(--sl-item-background-selected);
12462
+ color: var(--sl-item-color-selected);
12463
+ }
12464
+
12465
+ .DatePickerPreset[data-disabled] {
12466
+ color: var(--sl-text-disabled);
12467
+ cursor: default;
12468
+ }
12469
+
12470
+ .DatePickerPresetHint {
12471
+ font-family: var(--sl-font-body-minimize-font-family);
12472
+ font-size: var(--sl-font-body-minimize-font-size);
12473
+ font-weight: var(--sl-font-body-minimize-font-weight);
12474
+ line-height: var(--sl-font-body-minimize-line-height);
12475
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
12476
+ color: var(--sl-text-tertiary);
12477
+ }
12478
+
12479
+ .DatePickerPreset[data-checked] .DatePickerPresetHint {
12480
+ color: var(--sl-item-color-selected);
12481
+ }
12482
+
12483
+ /* PICKER */
12484
+
12485
+ .DatePickerField {
12486
+ position: relative;
12487
+ display: flex;
12488
+ align-items: center;
12489
+ min-width: 0;
12490
+ }
12491
+
12492
+ .DatePickerField .DatePickerTrigger {
12493
+ box-sizing: border-box;
12494
+ color: var(--sl-field-color);
12495
+ background: var(--sl-field-background);
12496
+ border: var(--sl-field-border-width) solid var(--sl-field-border-color);
12497
+ border-radius: var(--sl-field-radius);
12498
+ transition: var(--sl-field-transition);
12499
+ outline: none;
12500
+ font-family: var(--sl-font-body-base-font-family);
12501
+ font-size: var(--sl-font-body-base-font-size);
12502
+ font-weight: var(--sl-font-body-base-font-weight);
12503
+ line-height: var(--sl-font-body-base-line-height);
12504
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
12505
+ outline: none;
12506
+ display: inline-flex;
12507
+ align-items: center;
12508
+ gap: var(--sl-gap-control);
12509
+ inline-size: 100%;
12510
+ block-size: var(--sl-control-height-md);
12511
+ padding-inline: var(--sl-control-padding-inline);
12512
+ text-align: start;
12513
+ cursor: pointer;
12514
+ }
12515
+
12516
+ .DatePickerTrigger:disabled {
12517
+ color: var(--sl-text-disabled);
12518
+ cursor: default;
12519
+ }
12520
+
12521
+ .DatePickerField .DatePickerTrigger:focus-visible {
12522
+ outline: var(--sl-focus-outline);
12523
+ outline-offset: var(--sl-focus-outline-offset);
12524
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
12525
+ }
12526
+
12527
+ .DatePickerValue[data-placeholder] {
12528
+ color: var(--sl-text-tertiary);
12529
+ }
12530
+
12531
+ .DatePickerClear {
12532
+ position: absolute;
12533
+ inset-inline-end: var(--sl-space-1);
12534
+ z-index: 1;
12535
+ }
12536
+
12537
+ .DatePickerTrigger:has(~ .DatePickerClear) {
12538
+ padding-inline-end: var(--sl-control-height-sm);
12539
+ }
12540
+
12541
+ .DatePickerPopup {
12542
+ /* 52rem fits two months and the preset column; three months ask for 64rem. Layout, not a brand size. */
12543
+ inline-size: min(var(--available-width, 100vw), 52rem);
12544
+ max-inline-size: var(--available-width, 100vw);
12545
+ padding: 0;
12546
+ }
12547
+
12548
+ .DatePickerPopup[data-months='3'] {
12549
+ inline-size: min(var(--available-width, 100vw), 64rem);
12550
+ }
12551
+
12552
+ .DatePickerPanel {
12553
+ display: grid;
12554
+ /* 11rem is the preset column. Layout, not a brand size: wide enough for "Year to date" and a hint. */
12555
+ grid-template-columns: 11rem minmax(0, 1fr);
12556
+ align-items: start;
12557
+ gap: var(--sl-calendar-month-gap);
12558
+ padding: var(--sl-calendar-panel-padding);
12559
+ min-width: 0;
12560
+ }
12561
+
12562
+ .DatePickerPanel .DatePickerPresets {
12563
+ grid-column: 1;
12564
+ grid-row: 1 / span 2;
12565
+ inline-size: auto;
12566
+ }
12567
+
12568
+ .DatePickerPanel .Calendar {
12569
+ grid-column: 2;
12570
+ grid-row: 1;
12571
+ min-width: 0;
12572
+ }
12573
+
12574
+ .DatePickerPanel:not(:has(.DatePickerPresets)) {
12575
+ grid-template-columns: minmax(0, 1fr);
12576
+ }
12577
+
12578
+ .DatePickerPanel:not(:has(.DatePickerPresets)) .Calendar,
12579
+ .DatePickerPanel:not(:has(.DatePickerPresets)) .DatePickerFooter {
12580
+ grid-column: 1;
12581
+ }
12582
+
12583
+ .DatePickerFooter {
12584
+ display: flex;
12585
+ align-items: center;
12586
+ justify-content: space-between;
12587
+ gap: var(--sl-space-3);
12588
+ grid-column: 2;
12589
+ grid-row: 2;
12590
+ }
12591
+
12592
+ .DatePickerSummary {
12593
+ font-family: var(--sl-font-body-condense-font-family);
12594
+ font-size: var(--sl-font-body-condense-font-size);
12595
+ font-weight: var(--sl-font-body-condense-font-weight);
12596
+ line-height: var(--sl-font-body-condense-line-height);
12597
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
12598
+ margin: 0;
12599
+ color: var(--sl-text-secondary);
12600
+ }
12601
+
12602
+ .DatePickerActions {
12603
+ display: flex;
12604
+ gap: var(--sl-space-2);
12605
+ margin-inline-start: auto;
12606
+ }
12607
+
12608
+ /* Presets become a row once the measured panel is under 40rem, or the popup is a drawer. */
12609
+ .DatePickerPanel[data-layout='row'],
12610
+ .DatePickerPanel[data-layout='row']:not(:has(.DatePickerPresets)) {
12611
+ grid-template-columns: minmax(0, 1fr);
12612
+ }
12613
+
12614
+ .DatePickerPanel[data-layout='row'] .DatePickerPresets,
12615
+ .DatePickerPanel[data-layout='row'] .Calendar,
12616
+ .DatePickerPanel[data-layout='row'] .DatePickerFooter {
12617
+ grid-column: 1;
12618
+ grid-row: auto;
12619
+ }
12620
+
12621
+ .DatePickerPanel[data-compact] .DatePickerFooter {
12622
+ position: sticky;
12623
+ inset-block-end: 0;
12624
+ flex-wrap: wrap;
12625
+ background: var(--sl-popup-background);
12626
+ }
12627
+
12628
+ /* The action row shrinks to its buttons, so a percentage width on Apply never
12629
+ resolves. A 100% basis wraps Apply onto its own row of the footer. */
12630
+ .DatePickerPanel[data-compact] .DatePickerActions {
12631
+ flex-basis: 100%;
12632
+ flex-wrap: wrap;
12633
+ justify-content: flex-end;
12634
+ margin-inline-start: 0;
12635
+ }
12636
+
12637
+ .DatePickerPanel[data-compact] .DatePickerApply {
12638
+ flex-basis: 100%;
12639
+ }
12640
+
12641
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
12642
+ /* Money field
12643
+ *
12644
+ * An amount of money, built on Number field. The value is an integer in minor units
12645
+ * (cents, yen, fils) so 0.1 + 0.2 and 1.005 * 100 cannot drift, and so the number matches
12646
+ * what a payment API sends. Number field counts in major units; Money field converts at
12647
+ * the edge and rounds half away from zero. The default maximum is 10^15 - 1 minor
12648
+ * units, so the major amount stays inside 15 significant digits. Changing currency
12649
+ * keeps the number the person typed and re-rounds it to the new currency's digits
12650
+ * (12.50 USD becomes 13 JPY). There is no exchange rate. When the app
12651
+ * controls both the value and the currency, it decides whether to apply that rounding:
12652
+ * onValueChange still reports the re-rounded minor units.
12653
+ *
12654
+ * Keyboard is Number field's: ArrowUp and ArrowDown step one major unit, Shift steps 100
12655
+ * major units, Alt steps one minor unit, Home and End jump to the minimum and maximum.
12656
+ * The currency symbol is not in the text, so the caret does not fight it. A fixed symbol
12657
+ * is aria-hidden; the currency name is in the input's accessible description. A picker
12658
+ * is its own tab stop, before the input when the locale puts the symbol first and after
12659
+ * it when the locale puts the symbol last.
12660
+ *
12661
+ * State on the root: data-currency (USD), data-affix (start or end), data-affix-kind
12662
+ * (symbol or picker), data-negative (below zero; set data-color on the field to color
12663
+ * it, never on by default), data-align (start or end),
12664
+ * data-size (xs, sm, md, lg), data-readonly, plus data-invalid, data-disabled,
12665
+ * data-focused and data-scrubbing.
12666
+ *
12667
+ * The affix (symbol or picker) is drawn inside the field so it can later be lifted into
12668
+ * a general Input affix for units, https://, or @. Position comes from the locale, with
12669
+ * logical properties so RTL mirrors it. The group, not the input, carries the field
12670
+ * border, hover, focus halo, invalid edge and disabled fill, so the affix reads as part
12671
+ * of the field.
12672
+ */
12673
+
12674
+ /* ============================================
12675
+ FIELD
12676
+ ============================================ */
12677
+
12678
+ .MoneyField {
12679
+ display: inline-flex;
12680
+ flex-direction: column;
12681
+ gap: var(--sl-field-gap);
12682
+ width: 100%;
12683
+ }
12684
+
12685
+ .MoneyFieldGroup {
12686
+ box-sizing: border-box;
12687
+ color: var(--sl-field-color);
12688
+ background: var(--sl-field-background);
12689
+ border: var(--sl-field-border-width) solid var(--sl-field-border-color);
12690
+ border-radius: var(--sl-field-radius);
12691
+ transition: var(--sl-field-transition);
12692
+ outline: none;
12693
+ font-family: var(--sl-font-body-base-font-family);
12694
+ font-size: var(--sl-font-body-base-font-size);
12695
+ font-weight: var(--sl-font-body-base-font-weight);
12696
+ line-height: var(--sl-font-body-base-line-height);
12697
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
12698
+ display: flex;
12699
+ align-items: stretch;
12700
+ width: 100%;
12701
+ height: var(--sl-control-height-md);
12702
+ padding: 0;
12703
+ }
12704
+
12705
+ .MoneyField[data-size='xs'] .MoneyFieldGroup {
12706
+ font-family: var(--sl-font-body-minimize-font-family);
12707
+ font-size: var(--sl-font-body-minimize-font-size);
12708
+ font-weight: var(--sl-font-body-minimize-font-weight);
12709
+ line-height: var(--sl-font-body-minimize-line-height);
12710
+ letter-spacing: var(--sl-font-body-minimize-letter-spacing);
12711
+ height: var(--sl-control-height-xs);
12712
+ }
12713
+
12714
+ .MoneyField[data-size='sm'] .MoneyFieldGroup {
12715
+ font-family: var(--sl-font-body-condense-font-family);
12716
+ font-size: var(--sl-font-body-condense-font-size);
12717
+ font-weight: var(--sl-font-body-condense-font-weight);
12718
+ line-height: var(--sl-font-body-condense-line-height);
12719
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
12720
+ height: var(--sl-control-height-sm);
12721
+ }
12722
+
12723
+ .MoneyField[data-size='lg'] .MoneyFieldGroup {
12724
+ font-family: var(--sl-font-body-magnify-font-family);
12725
+ font-size: var(--sl-font-body-magnify-font-size);
12726
+ font-weight: var(--sl-font-body-magnify-font-weight);
12727
+ line-height: var(--sl-font-body-magnify-line-height);
12728
+ letter-spacing: var(--sl-font-body-magnify-letter-spacing);
12729
+ height: var(--sl-control-height-lg);
12730
+ }
12731
+
12732
+ .MoneyFieldGroup .MoneyFieldInput,
12733
+ .MoneyFieldAffix,
12734
+ .MoneyFieldGroup .MoneyFieldCurrencyTrigger {
12735
+ font: inherit;
12736
+ }
12737
+
12738
+ .MoneyFieldGroup .MoneyFieldInput {
12739
+ flex: 1;
12740
+ min-inline-size: 0;
12741
+ height: auto;
12742
+ border: 0;
12743
+ border-radius: 0;
12744
+ background: transparent;
12745
+ box-shadow: none;
12746
+ outline: none;
12747
+ font-variant-numeric: tabular-nums;
12748
+ }
12749
+
12750
+ .MoneyFieldGroup .MoneyFieldInput:hover,
12751
+ .MoneyFieldGroup .MoneyFieldInput:focus,
12752
+ .MoneyField[data-invalid] .MoneyFieldInput,
12753
+ .MoneyField[data-invalid] .MoneyFieldInput:focus,
12754
+ .MoneyField[data-disabled] .MoneyFieldInput {
12755
+ border-color: transparent;
12756
+ background: transparent;
12757
+ box-shadow: none;
12758
+ }
12759
+
12760
+ /* A symbol brings its own padding. A picker has a divider, so the amount keeps its inset. */
12761
+ .MoneyField[data-affix-kind='symbol'][data-affix='start'] .MoneyFieldInput {
12762
+ padding-inline-start: 0;
12763
+ }
12764
+
12765
+ .MoneyField[data-affix-kind='symbol'][data-affix='end']:not([data-steppers]) .MoneyFieldInput {
12766
+ padding-inline-end: 0;
12767
+ }
12768
+
12769
+ /* Number field always pads for its steppers. Those buttons are absent unless asked for. */
12770
+ .MoneyField:not([data-steppers]) .MoneyFieldInput {
12771
+ padding-inline-end: var(--sl-control-padding-inline);
12772
+ }
12773
+
12774
+ .MoneyField[data-size='xs']:not([data-steppers]) .MoneyFieldInput {
12775
+ padding-inline-end: var(--sl-control-padding-inline-xs);
12776
+ }
12777
+
12778
+ .MoneyField[data-size='sm']:not([data-steppers]) .MoneyFieldInput {
12779
+ padding-inline-end: var(--sl-control-padding-inline-sm);
12780
+ }
12781
+
12782
+ .MoneyField[data-size='lg']:not([data-steppers]) .MoneyFieldInput {
12783
+ padding-inline-end: var(--sl-control-padding-inline-lg);
12784
+ }
12785
+
12786
+ .MoneyField[data-align='end'] .MoneyFieldInput {
12787
+ text-align: end;
12788
+ }
12789
+
12790
+ .MoneyField[data-align='start'] .MoneyFieldInput {
12791
+ text-align: start;
12792
+ }
12793
+
12794
+ .MoneyFieldGroup:hover:not(:focus-within) {
12795
+ border-color: var(--sl-field-border-color-hover);
12796
+ }
12797
+
12798
+ .MoneyFieldGroup:focus-within,
12799
+ .MoneyField[data-focused] .MoneyFieldGroup {
12800
+ border-color: var(--sl-field-border-color-focus);
12801
+ box-shadow: var(--sl-field-shadow-focus);
12802
+ }
12803
+
12804
+ .MoneyField[data-invalid] .MoneyFieldGroup {
12805
+ border-color: var(--sl-field-border-color-error);
12806
+ }
12807
+
12808
+ .MoneyField[data-invalid] .MoneyFieldGroup:focus-within,
12809
+ .MoneyField[data-invalid][data-focused] .MoneyFieldGroup {
12810
+ border-color: var(--sl-field-border-color-error);
12811
+ box-shadow: var(--sl-field-shadow-focus-error);
12812
+ }
12813
+
12814
+ .MoneyField[data-disabled] .MoneyFieldGroup {
12815
+ background: var(--sl-field-background-disabled);
12816
+ cursor: not-allowed;
12817
+ }
12818
+
12819
+ .MoneyField[data-readonly] .MoneyFieldInput {
12820
+ cursor: default;
12821
+ }
12822
+
12823
+ /* The palette is the one on the field. An ancestor data-color does not recolor a balance. */
12824
+ .MoneyField[data-negative][data-color] .MoneyFieldInput {
12825
+ color: var(--sl-scope-fg);
12826
+ }
12827
+
12828
+ .MoneyField[data-scrubbing] .MoneyFieldInput {
12829
+ cursor: ns-resize;
12830
+ }
12831
+
12832
+ /* The sign toggle is for coarse pointers: an iOS decimal keypad has no minus key. */
12833
+ .MoneyFieldSign {
12834
+ display: none;
12835
+ align-self: center;
12836
+ flex: none;
12837
+ }
12838
+
12839
+ @media (pointer: coarse) {
12840
+ .MoneyFieldSign {
12841
+ display: inline-flex;
12842
+ }
12843
+ }
12844
+
12845
+ /* ============================================
12846
+ AFFIX
12847
+ ============================================ */
12848
+
12849
+ .MoneyFieldAffix {
12850
+ display: inline-flex;
12851
+ align-items: center;
12852
+ flex: none;
12853
+ padding-inline: var(--sl-control-padding-inline);
12854
+ color: var(--sl-field-affix-color);
12855
+ user-select: none;
12856
+ }
12857
+
12858
+ .MoneyField[data-size='xs'] .MoneyFieldAffix {
12859
+ padding-inline: var(--sl-control-padding-inline-xs);
12860
+ }
12861
+
12862
+ .MoneyField[data-size='sm'] .MoneyFieldAffix {
12863
+ padding-inline: var(--sl-control-padding-inline-sm);
12864
+ }
12865
+
12866
+ .MoneyField[data-size='lg'] .MoneyFieldAffix {
12867
+ padding-inline: var(--sl-control-padding-inline-lg);
12868
+ }
12869
+
12870
+ /* ============================================
12871
+ CURRENCY SELECT
12872
+ ============================================ */
12873
+
12874
+ .MoneyFieldCurrency {
12875
+ display: flex;
12876
+ align-self: stretch;
12877
+ flex: none;
12878
+ }
12879
+
12880
+ .MoneyFieldCurrencyTrigger {
12881
+ display: inline-flex;
12882
+ align-items: center;
12883
+ align-self: stretch;
12884
+ flex: none;
12885
+ gap: var(--sl-space-1);
12886
+ height: auto;
12887
+ min-height: 0;
12888
+ padding-inline: var(--sl-control-padding-inline);
12889
+ border: 0;
12890
+ border-radius: 0;
12891
+ background: transparent;
12892
+ box-shadow: none;
12893
+ color: var(--sl-field-affix-color);
12894
+ }
12895
+
12896
+ .MoneyField[data-size='xs'] .MoneyFieldCurrencyTrigger {
12897
+ padding-inline: var(--sl-control-padding-inline-xs);
12898
+ }
12899
+
12900
+ .MoneyField[data-size='sm'] .MoneyFieldCurrencyTrigger {
12901
+ padding-inline: var(--sl-control-padding-inline-sm);
12902
+ }
12903
+
12904
+ .MoneyField[data-size='lg'] .MoneyFieldCurrencyTrigger {
12905
+ padding-inline: var(--sl-control-padding-inline-lg);
12906
+ }
12907
+
12908
+ .MoneyField[data-affix='start'] .MoneyFieldCurrency {
12909
+ border-inline-end: var(--sl-field-border-width) solid var(--sl-field-border-color);
12910
+ }
12911
+
12912
+ .MoneyField[data-affix='end'] .MoneyFieldCurrency {
12913
+ border-inline-start: var(--sl-field-border-width) solid var(--sl-field-border-color);
12914
+ }
12915
+
12916
+ .MoneyFieldCurrencyTrigger:hover,
12917
+ .MoneyFieldCurrencyTrigger:focus,
12918
+ .MoneyFieldCurrencyTrigger[data-popup-open],
12919
+ .MoneyFieldCurrencyTrigger[aria-expanded='true'] {
12920
+ border-color: transparent;
12921
+ background: transparent;
12922
+ box-shadow: none;
12923
+ color: var(--sl-text-primary);
12924
+ }
12925
+
12926
+ /* The group halo says the field is focused. This says the picker, not the amount, has the caret. */
12927
+ .MoneyFieldCurrencyTrigger:focus-visible {
12928
+ outline: var(--sl-focus-outline);
12929
+ outline-offset: var(--sl-focus-outline-offset-inset);
12930
+ }
12931
+
12932
+ /* The picker is its own field, so it does not take the amount's label. */
12933
+ .MoneyFieldCurrencyField,
12934
+ .MoneyFieldGroup .ComboboxRoot {
12935
+ display: contents;
12936
+ }
12937
+
12938
+ .MoneyFieldCurrencyIcon {
12939
+ width: var(--sl-icon-size-base);
12940
+ height: var(--sl-icon-size-base);
12941
+ font-size: var(--sl-icon-size-base);
12942
+ }
12943
+
12944
+ .MoneyField[data-size='xs'] .MoneyFieldCurrencyIcon {
12945
+ width: var(--sl-icon-size-minimize);
12946
+ height: var(--sl-icon-size-minimize);
12947
+ font-size: var(--sl-icon-size-minimize);
12948
+ }
12949
+
12950
+ .MoneyField[data-size='sm'] .MoneyFieldCurrencyIcon {
12951
+ width: var(--sl-icon-size-condense);
12952
+ height: var(--sl-icon-size-condense);
12953
+ font-size: var(--sl-icon-size-condense);
12954
+ }
12955
+
12956
+ .MoneyField[data-size='lg'] .MoneyFieldCurrencyIcon {
12957
+ width: var(--sl-icon-size-magnify);
12958
+ height: var(--sl-icon-size-magnify);
12959
+ font-size: var(--sl-icon-size-magnify);
12960
+ }
12961
+
12962
+ .MoneyFieldCurrencyPopup {
12963
+ min-inline-size: var(--sl-money-field-picker-min-inline-size);
12964
+ }
12965
+
12966
+ .MoneyFieldCurrencyItem {
12967
+ display: flex;
12968
+ align-items: center;
12969
+ justify-content: space-between;
12970
+ gap: var(--sl-space-4);
12971
+ width: 100%;
12972
+ }
12973
+
12974
+ .MoneyFieldCurrencySymbol {
12975
+ color: var(--sl-text-secondary);
12976
+ }
12977
+
12978
+ .MoneyFieldCurrencyPopup .ComboboxInput {
12979
+ font-family: var(--sl-font-body-base-font-family);
12980
+ font-size: var(--sl-font-body-base-font-size);
12981
+ font-weight: var(--sl-font-body-base-font-weight);
12982
+ line-height: var(--sl-font-body-base-line-height);
12983
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
12984
+ }
12985
+
12986
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
12987
+ /* ListDetail
12988
+ *
12989
+ * The detail of one item, next to its list. Not a Base UI part. It is a Splitter
12990
+ * when this element is at least list-detail.split-min-width wide, measured on the
12991
+ * element itself so it still works inside another panel. Narrower, the detail is
12992
+ * the existing Drawer (the default) or it replaces the list, which stays mounted
12993
+ * and hidden so its scroll position survives Back.
12994
+ *
12995
+ * The list stays in the splitter's first panel whether the detail is open, closed,
12996
+ * or in a drawer, so its scroll survives. The detail is portaled into a node the
12997
+ * component created, and that node moves. The list sits on the page surface. The
12998
+ * detail sits on surface.raised: a pane
12999
+ * beside the list, one step off the page, with the splitter line as the only
13000
+ * divider. A modal surface would make the pane look like a dialog stuck in the
13001
+ * layout. Drawer mode does not restyle that; it uses the Drawer's own modal
13002
+ * surface, title and Close, so it matches every other drawer.
13003
+ *
13004
+ * The header title is text-title-condense. title-amplify is for a dialog or a
13005
+ * drawer, a layer over the page. A pane heading shares the view with the list,
13006
+ * so the condensed title fits the row. Close is a quiet icon-only Button: a
13007
+ * text Close would compete with the title and the actions in a short header.
13008
+ * Page mode puts Back, icon and word, where Close was.
13009
+ *
13010
+ * Focus moves to the heading when the detail opens, and back to the row when it
13011
+ * closes. Changing the title because another row was picked does not move focus.
13012
+ * Escape closes only when it bubbles out of the detail, so an open menu handles
13013
+ * it first. Nothing listens on window. Page changes are announced by that focus
13014
+ * move; there is no live region.
13015
+ *
13016
+ * data-layout is split, drawer or page. data-open is set while the detail is open.
13017
+ */
13018
+
13019
+ .ListDetail {
13020
+ display: flex;
13021
+ flex-direction: column;
13022
+ width: 100%;
13023
+ height: 100%;
13024
+ min-width: 0;
13025
+ min-height: 0;
13026
+ }
13027
+
13028
+ .ListDetailHost,
13029
+ .ListDetailSlot,
13030
+ .ListDetailSplit,
13031
+ .ListDetailList,
13032
+ .ListDetailDetail {
13033
+ display: flex;
13034
+ flex-direction: column;
13035
+ min-width: 0;
13036
+ min-height: 0;
13037
+ height: 100%;
13038
+ flex: 1;
13039
+ }
13040
+
13041
+ .ListDetailList {
13042
+ overflow: auto;
13043
+ background: transparent;
13044
+ }
13045
+
13046
+ .ListDetail[data-layout='split'],
13047
+ .ListDetail[data-layout='drawer'],
13048
+ .ListDetail[data-layout='page'] {
13049
+ min-width: 0;
13050
+ }
13051
+
13052
+ .ListDetail[data-open] .ListDetailList {
13053
+ min-height: 0;
13054
+ }
13055
+
13056
+ .ListDetailDetail[data-layout='split'],
13057
+ .ListDetailDetail[data-layout='page'] {
13058
+ background: var(--sl-surface-raised);
13059
+ }
13060
+
13061
+ .ListDetailDetail[data-layout='drawer'] {
13062
+ background: transparent;
13063
+ }
13064
+
13065
+ .DrawerPopup .ListDetailHeader,
13066
+ .ListDetailDetail[data-layout='drawer'] .ListDetailBody {
13067
+ padding: 0;
13068
+ }
13069
+
13070
+ .ListDetailHeader {
13071
+ display: flex;
13072
+ align-items: center;
13073
+ gap: var(--sl-list-detail-header-gap);
13074
+ padding: var(--sl-list-detail-header-padding);
13075
+ flex: none;
13076
+ }
13077
+
13078
+ .ListDetailTitle {
13079
+ font-family: var(--sl-font-title-condense-font-family);
13080
+ font-size: var(--sl-font-title-condense-font-size);
13081
+ font-weight: var(--sl-font-title-condense-font-weight);
13082
+ line-height: var(--sl-font-title-condense-line-height);
13083
+ letter-spacing: var(--sl-font-title-condense-letter-spacing);
13084
+ margin: 0;
13085
+ flex: 1;
13086
+ min-width: 0;
13087
+ }
13088
+
13089
+ .ListDetailHeader .DrawerTitle {
13090
+ flex: 1;
13091
+ min-width: 0;
13092
+ }
13093
+
13094
+ .ListDetailActions {
13095
+ display: flex;
13096
+ align-items: center;
13097
+ gap: var(--sl-list-detail-header-gap);
13098
+ flex: none;
13099
+ }
13100
+
13101
+ .ListDetailBody {
13102
+ flex: 1;
13103
+ min-height: 0;
13104
+ overflow: auto;
13105
+ padding-inline: var(--sl-list-detail-header-padding);
13106
+ padding-block-end: var(--sl-list-detail-header-padding);
13107
+ }
13108
+
13109
+ .ListDetail[data-layout='drawer'] .ListDetailDetail {
13110
+ background: transparent;
13111
+ }
13112
+
13113
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13114
+ /* Splitter
13115
+ *
13116
+ * Two or more panels and a handle between them. Not a Base UI part. It follows the
13117
+ * window splitter pattern: the handle is a separator you drag or move with the arrow
13118
+ * keys. Each panel's size is --sl-splitter-panel-size, so a drag can update the line
13119
+ * without rendering the tree again. The parent gives the root its height.
13120
+ *
13121
+ * One panel has no size and fills what the others leave (the last panel, when every
13122
+ * panel has a size). Px and percent mix, so a workstation can pin its sides in pixels
13123
+ * while a list keeps a percent.
13124
+ *
13125
+ * Arrow keys move one key step, 5% of the splitter; Shift uses the larger step.
13126
+ * Home and End jump to that panel's min and max. Enter collapses a collapsible panel
13127
+ * and restores the size it had. Double-click resets to the default size. In RTL,
13128
+ * Left and Right swap. A panel collapsed to nothing is hidden, so its contents leave
13129
+ * the tab order.
13130
+ *
13131
+ * data-orientation is on the root, the panel and the handle. data-dragging is on the
13132
+ * root and the handle while the pointer is down. data-collapsed is on a collapsed
13133
+ * panel and on the handle that resizes it. data-disabled is on the handle. data-grip
13134
+ * draws the grip. data-fill marks the panel that takes the leftover space.
13135
+ *
13136
+ * The line is one stroke. The part you grab sits on the next panel's inline-start,
13137
+ * not centered, so it does not cover the previous panel's scrollbar. A fine pointer
13138
+ * gets a11y.min-target (24px). A coarse pointer gets the 44px touch target. The
13139
+ * focus ring is drawn on that grab area: a ring around the 1px line reads as a
13140
+ * second hairline. Collapse animates with duration.normal. A drag does not animate.
13141
+ * Reduced motion is the shared reset, which finishes every transition at once.
13142
+ */
13143
+
13144
+ .Splitter {
13145
+ display: flex;
13146
+ width: 100%;
13147
+ height: 100%;
13148
+ min-width: 0;
13149
+ min-height: 0;
13150
+ }
13151
+
13152
+ .Splitter[data-orientation='horizontal'] {
13153
+ flex-direction: row;
13154
+ }
13155
+
13156
+ .Splitter[data-orientation='vertical'] {
13157
+ flex-direction: column;
13158
+ }
13159
+
13160
+ .Splitter[data-dragging] .SplitterPanel {
13161
+ transition: none;
13162
+ }
13163
+
13164
+ .SplitterPanel {
13165
+ --sl-splitter-panel-size: auto;
13166
+ position: relative;
13167
+ box-sizing: border-box;
13168
+ min-width: 0;
13169
+ min-height: 0;
13170
+ overflow: hidden;
13171
+ flex: 0 0 var(--sl-splitter-panel-size);
13172
+ transition:
13173
+ flex-basis var(--sl-duration-normal) var(--sl-easing-default),
13174
+ width var(--sl-duration-normal) var(--sl-easing-default),
13175
+ height var(--sl-duration-normal) var(--sl-easing-default);
13176
+ }
13177
+
13178
+ .SplitterPanel[data-orientation='horizontal'] {
13179
+ width: var(--sl-splitter-panel-size);
13180
+ height: auto;
13181
+ }
13182
+
13183
+ .SplitterPanel[data-orientation='vertical'] {
13184
+ height: var(--sl-splitter-panel-size);
13185
+ width: auto;
13186
+ }
13187
+
13188
+ .SplitterPanel[data-orientation='horizontal'][data-fill]:not([data-collapsed]) {
13189
+ flex: 1 1 auto;
13190
+ width: auto;
13191
+ }
13192
+
13193
+ .SplitterPanel[data-orientation='vertical'][data-fill]:not([data-collapsed]) {
13194
+ flex: 1 1 auto;
13195
+ height: auto;
13196
+ }
13197
+
13198
+ /* A ScrollArea thumb still stacks above the grab area, for a bar that lives in the
13199
+ next panel, under the part of the hit area that crosses the line. */
13200
+ .SplitterPanel .ScrollAreaScrollbar {
13201
+ z-index: 2;
13202
+ }
13203
+
13204
+ .SplitterHandle {
13205
+ position: relative;
13206
+ flex: none;
13207
+ box-sizing: border-box;
13208
+ border: 0;
13209
+ padding: 0;
13210
+ background: transparent;
13211
+ touch-action: none;
13212
+ color: var(--sl-border-default);
13213
+ }
13214
+
13215
+ .SplitterHandle[data-orientation='horizontal'] {
13216
+ width: var(--sl-splitter-handle-size);
13217
+ height: auto;
13218
+ align-self: stretch;
13219
+ cursor: col-resize;
13220
+ }
13221
+
13222
+ .SplitterHandle[data-orientation='vertical'] {
13223
+ height: var(--sl-splitter-handle-size);
13224
+ width: auto;
13225
+ align-self: stretch;
13226
+ cursor: row-resize;
13227
+ }
13228
+
13229
+ .SplitterHandle::before,
13230
+ .SplitterHandle::after {
13231
+ content: '';
13232
+ position: absolute;
13233
+ }
13234
+
13235
+ .SplitterHandle::before {
13236
+ left: 50%;
13237
+ top: 50%;
13238
+ transform: translate(-50%, -50%);
13239
+ }
13240
+
13241
+ .SplitterHandle[data-orientation='horizontal']::before {
13242
+ width: var(--sl-splitter-handle-size);
13243
+ height: 100%;
13244
+ background: var(--sl-border-default);
13245
+ }
13246
+
13247
+ .SplitterHandle[data-orientation='vertical']::before {
13248
+ height: var(--sl-splitter-handle-size);
13249
+ width: 100%;
13250
+ background: var(--sl-border-default);
13251
+ }
13252
+
13253
+ /* The grab area starts on the line and extends into the next panel. The previous
13254
+ panel keeps its scrollbar, which sits on its inline-end, against this line. */
13255
+ .SplitterHandle[data-orientation='horizontal']::after {
13256
+ inset-inline-start: 0;
13257
+ top: 0;
13258
+ bottom: 0;
13259
+ width: var(--sl-a11y-min-target);
13260
+ z-index: 1;
13261
+ }
13262
+
13263
+ .SplitterHandle[data-orientation='vertical']::after {
13264
+ inset-block-start: 0;
13265
+ left: 0;
13266
+ right: 0;
13267
+ height: var(--sl-a11y-min-target);
13268
+ z-index: 1;
13269
+ }
13270
+
13271
+ @media (pointer: coarse) {
13272
+ .SplitterHandle[data-orientation='horizontal']::after {
13273
+ width: var(--sl-splitter-handle-hit-size);
13274
+ }
13275
+
13276
+ .SplitterHandle[data-orientation='vertical']::after {
13277
+ height: var(--sl-splitter-handle-hit-size);
13278
+ }
13279
+ }
13280
+
13281
+ .SplitterHandle:hover::before,
13282
+ .SplitterHandle[data-dragging]::before,
13283
+ .SplitterHandle[data-collapsed]::before {
13284
+ background: var(--sl-border-strong);
13285
+ }
13286
+
13287
+ /* The dot edge (45% to 50%) is the shape of the grip, not a size token. */
13288
+ /* The dots sit on the line, at the start of the grab area, not in its middle. */
13289
+ .SplitterHandle[data-orientation='horizontal'][data-grip]::after {
13290
+ background:
13291
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start calc(50% - var(--sl-splitter-grip-size) * 2) / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
13292
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start center / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
13293
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) inline-start calc(50% + var(--sl-splitter-grip-size) * 2) / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat;
13294
+ }
13295
+
13296
+ .SplitterHandle[data-orientation='vertical'][data-grip]::after {
13297
+ background:
13298
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) calc(50% - var(--sl-splitter-grip-size) * 2) block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
13299
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) center block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat,
13300
+ radial-gradient(circle, var(--sl-border-strong) 45%, transparent 50%) calc(50% + var(--sl-splitter-grip-size) * 2) block-start / var(--sl-splitter-grip-size) var(--sl-splitter-grip-size) no-repeat;
13301
+ }
13302
+
13303
+ .SplitterHandle:focus {
13304
+ outline: none;
13305
+ }
13306
+
13307
+ .SplitterHandle:focus-visible::after {
13308
+ outline: var(--sl-focus-outline);
13309
+ outline-offset: var(--sl-focus-outline-offset);
13310
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
13311
+ }
13312
+
13313
+ .SplitterHandle[data-disabled] {
13314
+ cursor: not-allowed;
13315
+ }
13316
+
13317
+ .SplitterHandle[data-disabled]::before {
13318
+ background: var(--sl-border-default);
13319
+ }
13320
+
13321
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13322
+ /* EmptyState
13323
+ *
13324
+ * The block a page, pane, table, list or popup shows when it has nothing to show.
13325
+ * One look for every kind. data-kind only picks the media tone and, in the component,
13326
+ * the default icon and whether the block is announced. Sizes are empty.*
13327
+ * (tokens/semantic/empty.json). No border and no fill: the container provides those.
13328
+ *
13329
+ * The circle uses the subtle emphasis level (--sl-e-bg, --sl-e-fg), the same variables
13330
+ * Badge uses. data-status on the media recolors it. A parent data-color does too:
13331
+ * the subtle chrome pin skips this circle when a color scope is on an ancestor
13332
+ * (Badge keeps the pin). A brand pair re-points fill and text, not that chrome
13333
+ * scope. The circle stays chrome subtle inside a pair, the same as Badge, so a
13334
+ * pair does not get its own selector. High contrast and the vision themes come
13335
+ * with those variables. The title stays
13336
+ * text-primary and the description text-secondary: an error's title is not red,
13337
+ * because a sentence has to stay readable. Neutral kinds use the chrome palette,
13338
+ * which is what subtle resolves to when no status is set.
13339
+ *
13340
+ * Text is a whole style per size, not a font-size on its own. Compact is a table
13341
+ * row or a popup, so the title is subtitle-condense (bold, the row's size) and the
13342
+ * description is body-condense. Standard is a pane: title-condense, the section
13343
+ * heading, with body-base under it. Spacious is a page: title-magnify, the next
13344
+ * title up, still body-base so the sentence doesn't grow with the heading.
13345
+ * Unselected is the quiet pane beside a list, so it drops the circle, the icon is
13346
+ * text-tertiary, and the title steps down one tier: subtitle-minimize where the
13347
+ * others use a condense style (there is no title at minimize), and title-condense
13348
+ * where the others use title-magnify.
13349
+ *
13350
+ * Compact is a row (icon, text, actions) centered across the cell. Standard and
13351
+ * spacious are a column. They take margin-block: auto so a flex or grid column
13352
+ * centers them in the leftover space; in normal flow that margin is zero, so a
13353
+ * page that isn't a column doesn't grow a hole. There is no data-fill attribute.
13354
+ *
13355
+ * The icon for unselected is left_click: the pane is waiting for a choice in the
13356
+ * list beside it, which an empty inbox would not say.
13357
+ *
13358
+ * A popup's empty slot already pads a plain sentence (popup-empty). When the child
13359
+ * is an EmptyState, that padding drops so the two don't add. Menu.Empty has no
13360
+ * popup-empty padding of its own, so it needs nothing here.
13361
+ */
13362
+
13363
+ /* ============================================
13364
+ ROOT
13365
+ ============================================ */
13366
+
13367
+ .EmptyState {
13368
+ box-sizing: border-box;
13369
+ display: flex;
13370
+ flex-direction: column;
13371
+ align-items: center;
13372
+ justify-content: center;
13373
+ gap: var(--sl-empty-gap-standard);
13374
+ width: 100%;
13375
+ padding-block: var(--sl-empty-padding-block-standard);
13376
+ padding-inline: var(--sl-empty-padding-inline-standard);
13377
+ color: var(--sl-text-primary);
13378
+ text-align: center;
13379
+ }
13380
+
13381
+ /* ============================================
13382
+ MEDIA
13383
+ ============================================ */
13384
+
13385
+ .EmptyStateMedia {
13386
+ display: inline-flex;
13387
+ flex-shrink: 0;
13388
+ align-items: center;
13389
+ justify-content: center;
13390
+ width: var(--sl-empty-media-size-standard);
13391
+ height: var(--sl-empty-media-size-standard);
13392
+ border-radius: var(--sl-radius-pill);
13393
+ background: var(--sl-e-bg);
13394
+ color: var(--sl-e-fg);
13395
+ }
13396
+
13397
+ .EmptyStateMedia:not([data-custom]) .material-symbols-outlined,
13398
+ .EmptyStateMedia:not([data-custom]) svg {
13399
+ width: var(--sl-icon-size-magnify);
13400
+ height: var(--sl-icon-size-magnify);
13401
+ font-size: var(--sl-icon-size-magnify);
13402
+ line-height: 1;
13403
+ }
13404
+
13405
+ /* An illustration the app passed in. No circle and no tint. */
13406
+ .EmptyStateMedia[data-custom] {
13407
+ width: auto;
13408
+ height: auto;
13409
+ background: none;
13410
+ color: inherit;
13411
+ }
13412
+
13413
+ /* ============================================
13414
+ TEXT
13415
+ ============================================ */
13416
+
13417
+ .EmptyStateText {
13418
+ display: flex;
13419
+ flex-direction: column;
13420
+ align-items: center;
13421
+ gap: var(--sl-empty-text-gap-standard);
13422
+ min-width: 0;
13423
+ max-width: var(--sl-empty-description-max-width);
13424
+ }
13425
+
13426
+ .EmptyStateTitle {
13427
+ font-family: var(--sl-font-title-condense-font-family);
13428
+ font-size: var(--sl-font-title-condense-font-size);
13429
+ font-weight: var(--sl-font-title-condense-font-weight);
13430
+ line-height: var(--sl-font-title-condense-line-height);
13431
+ letter-spacing: var(--sl-font-title-condense-letter-spacing);
13432
+ margin: 0;
13433
+ max-width: 100%;
13434
+ color: var(--sl-text-primary);
13435
+ }
13436
+
13437
+ .EmptyStateDescription {
13438
+ font-family: var(--sl-font-body-base-font-family);
13439
+ font-size: var(--sl-font-body-base-font-size);
13440
+ font-weight: var(--sl-font-body-base-font-weight);
13441
+ line-height: var(--sl-font-body-base-line-height);
13442
+ letter-spacing: var(--sl-font-body-base-letter-spacing);
13443
+ margin: 0;
13444
+ max-width: 100%;
13445
+ color: var(--sl-text-secondary);
13446
+ }
13447
+
13448
+ /* ============================================
13449
+ ACTIONS
13450
+ ============================================ */
13451
+
13452
+ .EmptyStateActions {
13453
+ display: flex;
13454
+ flex-wrap: wrap;
13455
+ align-items: center;
13456
+ justify-content: center;
13457
+ gap: var(--sl-empty-actions-gap);
13458
+ }
13459
+
13460
+ /* ============================================
13461
+ SIZES
13462
+ ============================================ */
13463
+
13464
+ .EmptyState[data-size='compact'] {
13465
+ flex-direction: row;
13466
+ flex-wrap: wrap;
13467
+ gap: var(--sl-empty-gap-compact);
13468
+ padding-block: var(--sl-empty-padding-block-compact);
13469
+ padding-inline: var(--sl-empty-padding-inline-compact);
13470
+ }
13471
+
13472
+ .EmptyState[data-size='compact'] .EmptyStateText {
13473
+ gap: var(--sl-empty-text-gap-compact);
13474
+ }
13475
+
13476
+ .EmptyState[data-size='compact'] .EmptyStateTitle {
13477
+ font-family: var(--sl-font-subtitle-condense-font-family);
13478
+ font-size: var(--sl-font-subtitle-condense-font-size);
13479
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
13480
+ line-height: var(--sl-font-subtitle-condense-line-height);
13481
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
13482
+ }
13483
+
13484
+ .EmptyState[data-size='compact'] .EmptyStateDescription {
13485
+ font-family: var(--sl-font-body-condense-font-family);
13486
+ font-size: var(--sl-font-body-condense-font-size);
13487
+ font-weight: var(--sl-font-body-condense-font-weight);
13488
+ line-height: var(--sl-font-body-condense-line-height);
13489
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
13490
+ }
13491
+
13492
+ /* Icon only. The tone stays on the glyph, so an error is still an error. */
13493
+ .EmptyState[data-size='compact'] .EmptyStateMedia {
13494
+ width: auto;
13495
+ height: auto;
13496
+ background: none;
13497
+ }
13498
+
13499
+ .EmptyState[data-size='compact'] .EmptyStateMedia:not([data-custom]) .material-symbols-outlined,
13500
+ .EmptyState[data-size='compact'] .EmptyStateMedia:not([data-custom]) svg {
13501
+ width: var(--sl-icon-size-condense);
13502
+ height: var(--sl-icon-size-condense);
13503
+ font-size: var(--sl-icon-size-condense);
13504
+ }
13505
+
13506
+ .EmptyState[data-size='spacious'] {
13507
+ gap: var(--sl-empty-gap-spacious);
13508
+ padding-block: var(--sl-empty-padding-block-spacious);
13509
+ padding-inline: var(--sl-empty-padding-inline-spacious);
13510
+ }
13511
+
13512
+ .EmptyState[data-size='spacious'] .EmptyStateText {
13513
+ gap: var(--sl-empty-text-gap-spacious);
13514
+ }
13515
+
13516
+ .EmptyState[data-size='spacious'] .EmptyStateTitle {
13517
+ font-family: var(--sl-font-title-magnify-font-family);
13518
+ font-size: var(--sl-font-title-magnify-font-size);
13519
+ font-weight: var(--sl-font-title-magnify-font-weight);
13520
+ line-height: var(--sl-font-title-magnify-line-height);
13521
+ letter-spacing: var(--sl-font-title-magnify-letter-spacing);
13522
+ }
13523
+
13524
+ .EmptyState[data-size='spacious'] .EmptyStateMedia {
13525
+ width: var(--sl-empty-media-size-spacious);
13526
+ height: var(--sl-empty-media-size-spacious);
13527
+ }
13528
+
13529
+ .EmptyState[data-size='spacious'] .EmptyStateMedia:not([data-custom]) .material-symbols-outlined,
13530
+ .EmptyState[data-size='spacious'] .EmptyStateMedia:not([data-custom]) svg {
13531
+ width: var(--sl-icon-size-maximize);
13532
+ height: var(--sl-icon-size-maximize);
13533
+ font-size: var(--sl-icon-size-maximize);
13534
+ }
13535
+
13536
+ /* ============================================
13537
+ PLACES
13538
+ ============================================ */
13539
+
13540
+ /* A flex or grid column centers the block in the space left over. */
13541
+ .EmptyState:is([data-size='standard'], [data-size='spacious']) {
13542
+ margin-block: auto;
13543
+ }
13544
+
13545
+ /* The detail pane before a row is picked. Quieter than the list beside it. */
13546
+ .EmptyState[data-kind='unselected'] .EmptyStateMedia {
13547
+ width: auto;
13548
+ height: auto;
13549
+ background: none;
13550
+ color: var(--sl-text-tertiary);
13551
+ }
13552
+
13553
+ .EmptyState[data-kind='unselected'][data-size='compact'] .EmptyStateTitle,
13554
+ .EmptyState[data-kind='unselected'][data-size='standard'] .EmptyStateTitle {
13555
+ font-family: var(--sl-font-subtitle-minimize-font-family);
13556
+ font-size: var(--sl-font-subtitle-minimize-font-size);
13557
+ font-weight: var(--sl-font-subtitle-minimize-font-weight);
13558
+ line-height: var(--sl-font-subtitle-minimize-line-height);
13559
+ letter-spacing: var(--sl-font-subtitle-minimize-letter-spacing);
13560
+ }
13561
+
13562
+ .EmptyState[data-kind='unselected'][data-size='spacious'] .EmptyStateTitle {
13563
+ font-family: var(--sl-font-title-condense-font-family);
13564
+ font-size: var(--sl-font-title-condense-font-size);
13565
+ font-weight: var(--sl-font-title-condense-font-weight);
13566
+ line-height: var(--sl-font-title-condense-line-height);
13567
+ letter-spacing: var(--sl-font-title-condense-letter-spacing);
13568
+ }
13569
+
13570
+ /* The popup slot pads a plain sentence. An EmptyState brings its own padding. */
13571
+ .ComboboxEmpty:has(> .EmptyState),
13572
+ .AutocompleteEmpty:has(> .EmptyState) {
13573
+ padding: 0;
13574
+ color: inherit;
13575
+ }
13576
+
13577
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13578
+ /* Table - Mojave Theme
13579
+ *
13580
+ * Base UI has no table, so this styles the native <table class="Table"> elements with the
13581
+ * table concept (tokens/semantic/table.json), the same tokens the AG Grid themes read: a small
13582
+ * hand-built table and a full grid look alike. Rows answer to aria-selected="true",
13583
+ * aria-current="true" (the row whose detail is open) or data-selected; cells take
13584
+ * data-align="end" for numbers.
13585
+ *
13586
+ * An empty body keeps the header and the column widths: one cell spanning the columns,
13587
+ * `<tr><td data-empty colSpan={n}><EmptyState size="compact" … /></td></tr>`. A cell with
13588
+ * only text still uses this rule's padding. A cell whose child is an EmptyState lets the
13589
+ * empty state pad itself. The empty row does not take the row hover.
13590
+ */
13591
+
13592
+ .Table {
13593
+ font-family: var(--sl-font-body-condense-font-family);
13594
+ font-size: var(--sl-font-body-condense-font-size);
13595
+ font-weight: var(--sl-font-body-condense-font-weight);
13596
+ line-height: var(--sl-font-body-condense-line-height);
13597
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
13598
+ box-sizing: border-box;
13599
+ width: 100%;
13600
+ border-collapse: separate;
13601
+ border-spacing: 0;
13602
+ background: var(--sl-table-background);
13603
+ color: var(--sl-table-color);
13604
+ border: var(--sl-stroke-default) solid var(--sl-table-border-color);
13605
+ border-radius: var(--sl-table-radius);
13606
+ overflow: hidden;
13607
+ font-variant-numeric: tabular-nums;
13608
+ }
13609
+
13610
+ .Table caption {
13611
+ font-family: var(--sl-font-body-condense-font-family);
13612
+ font-size: var(--sl-font-body-condense-font-size);
13613
+ font-weight: var(--sl-font-body-condense-font-weight);
13614
+ line-height: var(--sl-font-body-condense-line-height);
13615
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
13616
+ caption-side: bottom;
13617
+ padding-block: var(--sl-space-2);
13618
+ color: var(--sl-table-subtle-color);
13619
+ text-align: start;
13620
+ }
13621
+
13622
+ /* Header: the tray band, a little taller than the rows */
13623
+ .Table th {
13624
+ font-family: var(--sl-font-subtitle-condense-font-family);
13625
+ font-size: var(--sl-font-subtitle-condense-font-size);
13626
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
13627
+ line-height: var(--sl-font-subtitle-condense-line-height);
13628
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
13629
+ height: var(--sl-table-header-height);
13630
+ padding-block: 0;
13631
+ padding-inline: var(--sl-table-cell-padding-inline);
13632
+ background: var(--sl-table-header-background);
13633
+ color: var(--sl-table-header-color);
13634
+ text-align: start;
13635
+ vertical-align: middle;
13636
+ border-bottom: var(--sl-stroke-default) solid var(--sl-table-border-color);
13637
+ }
13638
+
13639
+ /* A header that sorts: aria-sort on the th */
13640
+ .Table th[aria-sort] {
13641
+ cursor: pointer;
13642
+ transition: background-color var(--sl-duration-fast) var(--sl-easing-default);
13643
+ }
13644
+
13645
+ .Table th[aria-sort]:hover {
13646
+ background: var(--sl-table-header-background-hover);
13647
+ }
13648
+
13649
+ /* Body cells */
13650
+ .Table td {
13651
+ height: var(--sl-table-row-height);
13652
+ padding-block: 0;
13653
+ padding-inline: var(--sl-table-cell-padding-inline);
13654
+ vertical-align: middle;
13655
+ border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
13656
+ }
13657
+
13658
+ .Table tbody tr:last-child td,
13659
+ .Table tbody:last-child tr:last-child td {
13660
+ border-bottom: none;
13661
+ }
13662
+
13663
+ /* A row header (th in tbody) reads like a cell, in the header's weight */
13664
+ .Table tbody th {
13665
+ background: transparent;
13666
+ border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
13667
+ }
13668
+
13669
+ /* Numbers and amounts: right-aligned so digits line up */
13670
+ .Table [data-align='end'] {
13671
+ text-align: end;
13672
+ }
13673
+
13674
+ .Table [data-align='center'] {
13675
+ text-align: center;
13676
+ }
13677
+
13678
+ /* Secondary text in a cell */
13679
+ .Table [data-subtle] {
13680
+ color: var(--sl-table-subtle-color);
13681
+ }
13682
+
13683
+ /* Hover and selection: the same tints as list items */
13684
+ @media (hover: hover) {
13685
+ .Table tbody tr:hover > * {
13686
+ background: var(--sl-table-row-hover);
13687
+ color: var(--sl-item-color-hover);
13688
+ }
13689
+ }
13690
+
13691
+ .Table tbody tr:is([aria-selected='true'], [data-selected]) > * {
13692
+ background: var(--sl-table-row-selected);
13693
+ color: var(--sl-item-color-selected);
13694
+ }
13695
+
13696
+ /* The open row keeps a fill, and a bar on the inline start so it is not only a color. */
13697
+ .Table tbody tr[aria-current='true'] > * {
13698
+ background: var(--sl-table-row-current);
13699
+ color: var(--sl-table-color);
13700
+ box-shadow: inset var(--sl-stroke-strong) 0 0 0 var(--sl-border-accent);
13701
+ }
13702
+
13703
+ [dir='rtl'] .Table tbody tr[aria-current='true'] > * {
13704
+ box-shadow: inset calc(var(--sl-stroke-strong) * -1) 0 0 0 var(--sl-border-accent);
13705
+ }
13706
+
13707
+ /* Footer: totals on the tray band */
13708
+ .Table tfoot td {
13709
+ font-family: var(--sl-font-subtitle-condense-font-family);
13710
+ font-size: var(--sl-font-subtitle-condense-font-size);
13711
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
13712
+ line-height: var(--sl-font-subtitle-condense-line-height);
13713
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
13714
+ background: var(--sl-table-header-background);
13715
+ border-top: var(--sl-stroke-default) solid var(--sl-table-border-color);
13716
+ border-bottom: none;
13717
+ }
13718
+
13719
+ /* A header that stays put while the body scrolls (the table's wrapper scrolls) */
13720
+ .Table[data-sticky-header] thead th {
13721
+ position: sticky;
13722
+ top: 0;
13723
+ z-index: var(--sl-z-index-docked);
13724
+ }
13725
+
13726
+ /* Empty state: one cell spanning the columns. Plain text keeps the old padding.
13727
+ An EmptyState brings its own, and its title stays the normal text color on hover. */
13728
+ .Table td[data-empty] {
13729
+ height: auto;
13730
+ padding-block: var(--sl-space-10);
13731
+ color: var(--sl-text-tertiary);
13732
+ text-align: center;
13733
+ }
13734
+
13735
+ .Table td[data-empty]:has(> .EmptyState) {
13736
+ padding: 0;
13737
+ color: inherit;
13738
+ }
13739
+
13740
+ .Table tbody tr:has(> td[data-empty]):hover > * {
13741
+ background: transparent;
13742
+ color: var(--sl-text-tertiary);
13743
+ }
13744
+
13745
+ .Table tbody tr:has(> td[data-empty] > .EmptyState):hover > * {
13746
+ color: inherit;
13747
+ }
13748
+
13749
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13750
+ /* Collection
13751
+ *
13752
+ * DataTable, DataList, the toolbar and the pagination, in one place so the two views
13753
+ * share the table concept. Sections: toolbar, table additions, groups, list, pagination, sizes.
13754
+ * Each section is its own file so the design system can name the part. This file brings them in.
13755
+ *
13756
+ * The selection bar replaces the trailing controls (filters, sort, actions) and leaves
13757
+ * the tabs and the search where they are, so selecting rows does not grow the toolbar.
13758
+ */
13759
+
13760
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13761
+ /* Collection toolbar
13762
+ *
13763
+ * The wrap follows the toolbar's own width, not the window: a table in a narrow pane wraps
13764
+ * even when the page is wide. Search grows to fill the row beside the trailing controls, and
13765
+ * wraps to its own line before it shrinks under collection.search-min-width. Under the narrow
13766
+ * width it takes the full row and filters wrap under it.
13767
+ * A container query cannot read the width token, so the component also sets data-narrow.
13768
+ *
13769
+ * The search icon and the clear button sit inside the field. The browser's own search cancel
13770
+ * is hidden by the reset, so the clear button is the only one, in every browser.
13771
+ */
13772
+
13773
+ .CollectionToolbar {
13774
+ container-type: inline-size;
13775
+ display: flex;
13776
+ flex-direction: column;
13777
+ gap: var(--sl-collection-toolbar-gap);
13778
+ margin-block-end: var(--sl-collection-toolbar-gap);
13779
+ }
13780
+
13781
+ .CollectionToolbarMain,
13782
+ .CollectionSelectionBar,
13783
+ .CollectionSort {
13784
+ display: flex;
13785
+ flex-wrap: wrap;
13786
+ align-items: center;
13787
+ gap: var(--sl-collection-toolbar-gap);
13788
+ }
13789
+
13790
+ .CollectionSearch {
13791
+ display: flex;
13792
+ align-items: center;
13793
+ gap: var(--sl-collection-toolbar-gap);
13794
+ flex: 1 1 0;
13795
+ min-width: min(100%, var(--sl-collection-search-min-width));
13796
+ }
13797
+
13798
+ .CollectionSearchField {
13799
+ position: relative;
13800
+ flex: 1 1 auto;
13801
+ min-width: 0;
13802
+ }
13803
+
13804
+ /* Scoped to the field so it wins over Input.css, which loads later. */
13805
+ .CollectionSearchField .Input {
13806
+ min-width: 0;
13807
+ padding-inline-start: calc(var(--sl-control-padding-inline) + var(--sl-icon-size-magnify) + var(--sl-space-2));
13808
+ }
13809
+
13810
+ .CollectionSearchField[data-filled] .Input {
13811
+ padding-inline-end: calc(var(--sl-control-padding-inline) + var(--sl-icon-button-size));
13812
+ }
13813
+
13814
+ .CollectionSearchIcon {
13815
+ position: absolute;
13816
+ inset-inline-start: var(--sl-control-padding-inline);
13817
+ inset-block-start: 50%;
13818
+ transform: translateY(-50%);
13819
+ width: var(--sl-icon-size-magnify);
13820
+ height: var(--sl-icon-size-magnify);
13821
+ font-size: var(--sl-icon-size-magnify);
13822
+ line-height: 1;
13823
+ color: var(--sl-field-affix-color);
13824
+ pointer-events: none;
13825
+ }
13826
+
13827
+ .CollectionSearchClear {
13828
+ display: flex;
13829
+ align-items: center;
13830
+ justify-content: center;
13831
+ flex-shrink: 0;
13832
+ width: var(--sl-icon-button-size);
13833
+ height: var(--sl-icon-button-size);
13834
+ padding: 0;
13835
+ border: none;
13836
+ border-radius: var(--sl-icon-button-radius);
13837
+ background: transparent;
13838
+ color: var(--sl-icon-button-color);
13839
+ cursor: pointer;
13840
+ outline: none;
13841
+ transition: var(--sl-icon-button-transition);
13842
+ position: absolute;
13843
+ inset-inline-end: var(--sl-space-3);
13844
+ inset-block-start: 50%;
13845
+ transform: translateY(-50%);
13846
+ font-size: var(--sl-icon-size-magnify);
13847
+ line-height: 1;
13848
+ }
13849
+
13850
+ .CollectionSearchClear:hover {
13851
+ background: var(--sl-icon-button-background-hover);
13852
+ color: var(--sl-icon-button-color-hover);
13853
+ }
13854
+
13855
+ .CollectionSearchClear:focus-visible {
13856
+ outline: var(--sl-focus-outline);
13857
+ outline-offset: var(--sl-focus-outline-offset);
13858
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
13859
+ }
13860
+
13861
+ /* The trailing controls join the main row one by one, so each keeps its own width and
13862
+ wraps under the search on its own rather than squeezing. Search takes what is left. */
13863
+ .CollectionToolbarTrailing {
13864
+ display: contents;
13865
+ }
13866
+
13867
+ .CollectionSelectionBar {
13868
+ flex: 0 0 auto;
13869
+ max-width: 100%;
13870
+ }
13871
+
13872
+ /* Select.css and Combobox.css fill their container. In the row they size to their text. */
13873
+ .CollectionToolbarMain .SelectTrigger,
13874
+ .CollectionToolbarMain .ComboboxInputWrapper {
13875
+ flex: none;
13876
+ width: auto;
13877
+ max-width: 100%;
13878
+ }
13879
+
13880
+ .CollectionToolbarActions {
13881
+ display: flex;
13882
+ flex-wrap: wrap;
13883
+ gap: var(--sl-collection-toolbar-gap);
13884
+ margin-inline-start: auto;
13885
+ }
13886
+
13887
+ /* The width token is measured in JS (data-narrow). A container query cannot read a custom property. */
13888
+ .CollectionToolbar[data-narrow] .CollectionSearch,
13889
+ .CollectionView[data-narrow] .CollectionSearch {
13890
+ flex-basis: 100%;
13891
+ }
13892
+
13893
+ .CollectionCount {
13894
+ font-family: var(--sl-font-body-condense-font-family);
13895
+ font-size: var(--sl-font-body-condense-font-size);
13896
+ font-weight: var(--sl-font-body-condense-font-weight);
13897
+ line-height: var(--sl-font-body-condense-line-height);
13898
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
13899
+ }
13900
+
13901
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
13902
+ /* DataTable additions on top of .Table.
13903
+ *
13904
+ * Sort buttons fill the header cell and inherit its hover, so old aria-sort markup keeps
13905
+ * the hover it already had. The open row uses table.row-current, distinct from a selected row.
13906
+ * Loading dims the rows in place. Nothing here changes a plain .Table.
13907
+ */
13908
+
13909
+ .CollectionScroll {
13910
+ overflow: auto;
13911
+ max-width: 100%;
13912
+ }
13913
+
13914
+ .DataTable[data-size='sm'] {
13915
+ --sl-table-row-height: var(--sl-collection-row-height-sm);
13916
+ --sl-table-header-height: var(--sl-collection-header-height-sm);
13917
+ }
13918
+
13919
+ .DataTable[data-size='md'] {
13920
+ --sl-table-row-height: var(--sl-collection-row-height-md);
13921
+ --sl-table-header-height: var(--sl-collection-header-height-md);
13922
+ }
13923
+
13924
+ .Table th[aria-sort] > .TableSortButton {
13925
+ display: inline-flex;
13926
+ align-items: center;
13927
+ justify-content: inherit;
13928
+ gap: var(--sl-collection-toolbar-gap);
13929
+ width: 100%;
13930
+ height: 100%;
13931
+ margin: 0;
13932
+ padding: 0;
13933
+ border: 0;
13934
+ background: transparent;
13935
+ color: inherit;
13936
+ font: inherit;
13937
+ text-align: inherit;
13938
+ cursor: pointer;
13939
+ }
13940
+
13941
+ .TableSortIcon[data-state='none'] {
13942
+ visibility: hidden;
13943
+ }
13944
+
13945
+ .Table th[aria-sort]:hover .TableSortIcon[data-state='none'],
13946
+ .Table th[aria-sort]:focus-within .TableSortIcon[data-state='none'] {
13947
+ visibility: visible;
13948
+ }
13949
+
13950
+ .Table[data-sticky-row-header] tbody tr {
13951
+ --sl-row-fill: var(--sl-table-background);
13952
+ }
13953
+
13954
+ .Table[data-sticky-row-header] tbody tr:hover {
13955
+ --sl-row-fill: var(--sl-table-row-hover);
13956
+ }
13957
+
13958
+ .Table[data-sticky-row-header] tbody tr:is([aria-selected='true'], [data-selected]) {
13959
+ --sl-row-fill: var(--sl-table-row-selected);
13960
+ }
13961
+
13962
+ .Table[data-sticky-row-header] tbody tr[aria-current='true'] {
13963
+ --sl-row-fill: var(--sl-table-row-current);
13964
+ }
13965
+
13966
+ .Table[data-sticky-row-header] tbody th[scope='row'] {
13967
+ position: sticky;
13968
+ inset-inline-start: 0;
13969
+ z-index: var(--sl-z-index-docked);
13970
+ background: var(--sl-row-fill);
13971
+ }
13972
+
13973
+ .TableSortButton:focus-visible,
13974
+ .CollectionGroupButton:focus-visible,
13975
+ .CollectionRowButton:focus-visible {
13976
+ outline: var(--sl-focus-outline);
13977
+ outline-offset: var(--sl-focus-outline-offset);
13978
+ box-shadow: 0 0 0 var(--sl-focus-halo-spread) var(--sl-focus-halo-color);
13979
+ }
13980
+
13981
+ .Table tr[data-group] th {
13982
+ background: var(--sl-table-group-header-background);
13983
+ color: var(--sl-table-header-color);
13984
+ }
13985
+
13986
+ .CollectionGroupButton,
13987
+ .CollectionRowButton {
13988
+ margin: 0;
13989
+ padding: 0;
13990
+ border: 0;
13991
+ background: transparent;
13992
+ color: inherit;
13993
+ font: inherit;
13994
+ text-align: inherit;
13995
+ cursor: pointer;
13996
+ }
13997
+
13998
+ .DataTable[data-loading] tbody {
13999
+ opacity: var(--sl-item-opacity-disabled);
14000
+ transition: opacity var(--sl-duration-fast) var(--sl-easing-default);
14001
+ }
14002
+
14003
+ .CollectionSelectColumn {
14004
+ width: var(--sl-collection-selection-column-width);
14005
+ }
14006
+
14007
+ .Table th[data-width='min'],
14008
+ .Table td[data-width='min'] {
14009
+ width: min-content;
14010
+ white-space: nowrap;
14011
+ }
14012
+
14013
+ .CollectionStatus {
14014
+ font-family: var(--sl-font-body-condense-font-family);
14015
+ font-size: var(--sl-font-body-condense-font-size);
14016
+ font-weight: var(--sl-font-body-condense-font-weight);
14017
+ line-height: var(--sl-font-body-condense-line-height);
14018
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
14019
+ color: var(--sl-table-subtle-color);
14020
+ }
14021
+
14022
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
14023
+ /* DataList
14024
+ *
14025
+ * The same rows as the table, in one container with the table's borders, hover, selected
14026
+ * and current states. Not a stack of floating cards: the two views should read as one family.
14027
+ * variant=cards adds the surface radius and a gap when a queue should read as separate items.
14028
+ */
14029
+
14030
+ .DataList {
14031
+ font-family: var(--sl-font-body-condense-font-family);
14032
+ font-size: var(--sl-font-body-condense-font-size);
14033
+ font-weight: var(--sl-font-body-condense-font-weight);
14034
+ line-height: var(--sl-font-body-condense-line-height);
14035
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
14036
+ color: var(--sl-table-color);
14037
+ }
14038
+
14039
+ .DataList ul {
14040
+ margin: 0;
14041
+ padding: 0;
14042
+ list-style: none;
14043
+ background: var(--sl-table-background);
14044
+ border: var(--sl-stroke-default) solid var(--sl-table-border-color);
14045
+ border-radius: var(--sl-table-radius);
14046
+ }
14047
+
14048
+ .DataList li {
14049
+ display: flex;
14050
+ align-items: flex-start;
14051
+ gap: var(--sl-collection-list-row-gap);
14052
+ padding-block: var(--sl-collection-list-row-padding-block);
14053
+ padding-inline: var(--sl-table-cell-padding-inline);
14054
+ border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
14055
+ }
14056
+
14057
+ .DataList li:last-child {
14058
+ border-bottom: none;
14059
+ }
14060
+
14061
+ .DataList[data-size='md'] li {
14062
+ padding-block: var(--sl-collection-list-row-padding-block);
14063
+ min-height: var(--sl-collection-row-height-md);
14064
+ }
14065
+
14066
+ .DataList li[data-selected] {
14067
+ background: var(--sl-table-row-selected);
14068
+ color: var(--sl-table-color);
14069
+ }
14070
+
14071
+ .DataList li[aria-current='true'] {
14072
+ background: var(--sl-table-row-current);
14073
+ color: var(--sl-table-color);
14074
+ box-shadow: inset var(--sl-stroke-strong) 0 0 0 var(--sl-border-accent);
14075
+ }
14076
+
14077
+ @media (hover: hover) {
14078
+ .DataList li:hover:not([data-selected], [aria-current='true']) {
14079
+ background: var(--sl-table-row-hover);
14080
+ color: var(--sl-table-color);
14081
+ }
14082
+ }
14083
+
14084
+ .DataListPrimary {
14085
+ font-family: var(--sl-font-subtitle-condense-font-family);
14086
+ font-size: var(--sl-font-subtitle-condense-font-size);
14087
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
14088
+ line-height: var(--sl-font-subtitle-condense-line-height);
14089
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
14090
+ }
14091
+
14092
+ .DataListSecondary,
14093
+ .DataListMeta,
14094
+ .DataListSummary {
14095
+ font-family: var(--sl-font-body-condense-font-family);
14096
+ font-size: var(--sl-font-body-condense-font-size);
14097
+ font-weight: var(--sl-font-body-condense-font-weight);
14098
+ line-height: var(--sl-font-body-condense-line-height);
14099
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
14100
+ color: var(--sl-table-subtle-color);
14101
+ }
14102
+
14103
+ .DataListBody {
14104
+ display: flex;
14105
+ flex: 1;
14106
+ flex-direction: column;
14107
+ gap: var(--sl-space-1);
14108
+ min-width: 0;
14109
+ }
14110
+
14111
+ .DataListMeta {
14112
+ display: flex;
14113
+ flex-wrap: wrap;
14114
+ gap: var(--sl-collection-list-row-gap);
14115
+ }
14116
+
14117
+ .DataListAmount {
14118
+ margin-inline-start: auto;
14119
+ font-variant-numeric: tabular-nums;
14120
+ }
14121
+
14122
+ .DataListGroup {
14123
+ background: var(--sl-table-group-header-background);
14124
+ color: var(--sl-table-header-color);
14125
+ }
14126
+
14127
+ .DataList[data-variant='cards'] ul {
14128
+ display: flex;
14129
+ flex-direction: column;
14130
+ gap: var(--sl-collection-list-row-gap);
14131
+ background: transparent;
14132
+ border: 0;
14133
+ }
14134
+
14135
+ .DataList[data-variant='cards'] li {
14136
+ background: var(--sl-table-background);
14137
+ border: var(--sl-stroke-default) solid var(--sl-table-border-color);
14138
+ border-radius: var(--sl-table-radius);
14139
+ }
14140
+
14141
+ .DataList[data-loading] ul {
14142
+ opacity: var(--sl-item-opacity-disabled);
14143
+ transition: opacity var(--sl-duration-fast) var(--sl-easing-default);
14144
+ }
14145
+
14146
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
14147
+ /* Pagination
14148
+ *
14149
+ * Not tied to a collection. Anything with a page, a page count and a total can use it.
14150
+ * Previous and Next are quiet buttons. The count reads "1–25 of 312".
14151
+ */
14152
+
14153
+ .CollectionPagination {
14154
+ display: flex;
14155
+ flex-wrap: wrap;
14156
+ align-items: center;
14157
+ gap: var(--sl-collection-toolbar-gap);
14158
+ margin-block-start: var(--sl-collection-toolbar-gap);
14159
+ color: var(--sl-table-subtle-color);
14160
+ }
14161
+
14162
+ .CollectionPagination p {
14163
+ font-family: var(--sl-font-body-condense-font-family);
14164
+ font-size: var(--sl-font-body-condense-font-size);
14165
+ font-weight: var(--sl-font-body-condense-font-weight);
14166
+ line-height: var(--sl-font-body-condense-line-height);
14167
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
14168
+ margin: 0;
14169
+ }
14170
+
14171
+ /* @scattered-light/loomiere-base-ui 0.7.1 · styles for @base-ui/react 1.9.0 */
14172
+ /* EditableList
14173
+ *
14174
+ * One table at every width, so a field is not submitted twice. Under the stack width each
14175
+ * field shows its own label, so the lost header association does not matter: the input's
14176
+ * name comes from that label, not from the column header.
14177
+ *
14178
+ * Move up / Move down would be quiet buttons in the last cell, ahead of any future drag handle.
14179
+ */
14180
+
14181
+ .EditableList {
14182
+ container-type: inline-size;
14183
+ }
14184
+
14185
+ .EditableListAdd,
14186
+ .EditableListError,
14187
+ .EditableListBalance {
14188
+ margin-block-start: var(--sl-collection-toolbar-gap);
14189
+ }
14190
+
14191
+ .EditableListFieldLabel {
14192
+ display: none;
14193
+ }
14194
+
14195
+ .EditableListBalance {
14196
+ font-family: var(--sl-font-body-condense-font-family);
14197
+ font-size: var(--sl-font-body-condense-font-size);
14198
+ font-weight: var(--sl-font-body-condense-font-weight);
14199
+ line-height: var(--sl-font-body-condense-line-height);
14200
+ letter-spacing: var(--sl-font-body-condense-letter-spacing);
14201
+ padding: var(--sl-space-2) var(--sl-space-3);
14202
+ border-radius: var(--sl-radius-control);
14203
+ }
14204
+
14205
+ .EditableListBalance[data-color] {
14206
+ background: var(--sl-scope-soft);
14207
+ color: var(--sl-scope-on-soft);
14208
+ }
14209
+
14210
+ .EditableListStackedTitle {
14211
+ display: none;
14212
+ font-family: var(--sl-font-subtitle-condense-font-family);
14213
+ font-size: var(--sl-font-subtitle-condense-font-size);
14214
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
14215
+ line-height: var(--sl-font-subtitle-condense-line-height);
14216
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
14217
+ }
14218
+
14219
+ .EditableList[data-stacked] .EditableListStackedTitle {
14220
+ display: block;
14221
+ }
14222
+
14223
+ .EditableListRowLead {
14224
+ width: 0;
14225
+ padding: 0;
14226
+ border: 0;
14227
+ }
14228
+
14229
+ .EditableList td .Input,
14230
+ .EditableList td input,
14231
+ .EditableList td select {
14232
+ width: 100%;
14233
+ }
14234
+
14235
+ /* The width token is measured in JS. data-stacked is that measurement. */
14236
+ .EditableList[data-stacked] {
14237
+ .EditableListTable,
14238
+ .EditableListTable thead,
14239
+ .EditableListTable tbody,
14240
+ .EditableListTable tr,
14241
+ .EditableListTable td {
14242
+ display: block;
14243
+ width: 100%;
14244
+ height: auto;
14245
+ }
14246
+
14247
+ .EditableListTable thead {
14248
+ position: absolute;
14249
+ width: var(--sl-space-px);
14250
+ height: var(--sl-space-px);
14251
+ overflow: hidden;
14252
+ clip: rect(0, 0, 0, 0);
14253
+ }
14254
+
14255
+ .EditableListTable tr {
14256
+ padding-block: var(--sl-collection-list-row-padding-block);
14257
+ border-bottom: var(--sl-stroke-default) solid var(--sl-table-row-border-color);
14258
+ }
14259
+
14260
+ .EditableListFieldLabel {
14261
+ display: block;
14262
+ font-family: var(--sl-font-subtitle-condense-font-family);
14263
+ font-size: var(--sl-font-subtitle-condense-font-size);
14264
+ font-weight: var(--sl-font-subtitle-condense-font-weight);
14265
+ line-height: var(--sl-font-subtitle-condense-line-height);
14266
+ letter-spacing: var(--sl-font-subtitle-condense-letter-spacing);
14267
+ }
14268
+ }