@teamofsilicons/silicon-ui 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +21 -2
  2. package/check.mjs +245 -0
  3. package/components/activity-heatmap/activity-heatmap.module.css +4 -4
  4. package/components/alert/alert.module.css +1 -1
  5. package/components/announcement-bar/announcement-bar.module.css +6 -6
  6. package/components/avatar/avatar.d.ts +2 -2
  7. package/components/avatar/avatar.js +1 -1
  8. package/components/avatar/avatar.module.css +5 -2
  9. package/components/avatar-group/avatar-group.module.css +4 -4
  10. package/components/badge/badge.module.css +4 -4
  11. package/components/bar-chart/bar-chart.module.css +4 -4
  12. package/components/billing-toggle/billing-toggle.module.css +10 -10
  13. package/components/bottom-sheet/bottom-sheet.module.css +4 -5
  14. package/components/breadcrumb/breadcrumb.d.ts +8 -2
  15. package/components/breadcrumb/breadcrumb.js +21 -9
  16. package/components/breadcrumb/breadcrumb.module.css +7 -3
  17. package/components/brush-chart/brush-chart.module.css +9 -9
  18. package/components/button/button.d.ts +7 -2
  19. package/components/button/button.js +3 -1
  20. package/components/button/button.module.css +10 -1
  21. package/components/button-group/button-group.module.css +6 -6
  22. package/components/calendar/calendar.module.css +7 -7
  23. package/components/card/card.module.css +2 -2
  24. package/components/card-stack/card-stack.module.css +2 -3
  25. package/components/carousel/carousel.module.css +2 -2
  26. package/components/chat-thread/chat-thread.module.css +41 -41
  27. package/components/checkbox/checkbox.module.css +1 -1
  28. package/components/chip-group/chip-group.module.css +2 -2
  29. package/components/code-block/code-block.module.css +7 -14
  30. package/components/color-picker/color-picker.module.css +20 -21
  31. package/components/combobox/combobox.module.css +2 -2
  32. package/components/command-palette/command-palette.module.css +18 -18
  33. package/components/comment-thread/comment-thread.module.css +35 -35
  34. package/components/confirm-morph/confirm-morph.module.css +9 -9
  35. package/components/context-menu/context-menu.module.css +3 -3
  36. package/components/countdown/countdown.module.css +4 -4
  37. package/components/date-picker/date-picker.module.css +6 -6
  38. package/components/date-range-picker/date-range-picker.module.css +21 -21
  39. package/components/dialog/dialog.module.css +2 -2
  40. package/components/donut-chart/donut-chart.module.css +4 -4
  41. package/components/drawer/drawer.module.css +5 -5
  42. package/components/dropdown-menu/dropdown-menu.d.ts +71 -1
  43. package/components/dropdown-menu/dropdown-menu.js +100 -6
  44. package/components/dropdown-menu/dropdown-menu.module.css +15 -5
  45. package/components/elastic-slider/elastic-slider.module.css +4 -4
  46. package/components/expandable-card/expandable-card.module.css +1 -1
  47. package/components/expanding-button-group/expanding-button-group.module.css +1 -1
  48. package/components/expanding-search/expanding-search.module.css +9 -9
  49. package/components/file-dropzone/file-dropzone.module.css +21 -21
  50. package/components/file-upload/file-upload.module.css +7 -7
  51. package/components/filter-toolbar/filter-toolbar.module.css +9 -9
  52. package/components/floating-button-group/floating-button-group.module.css +6 -6
  53. package/components/gauge/gauge.module.css +2 -2
  54. package/components/hover-card/hover-card.module.css +2 -2
  55. package/components/image-compare/image-compare.module.css +4 -4
  56. package/components/inline-edit/inline-edit.module.css +12 -12
  57. package/components/json-viewer/json-viewer.module.css +12 -12
  58. package/components/line-chart/line-chart.module.css +8 -8
  59. package/components/mention-input/mention-input.module.css +8 -8
  60. package/components/metric-card/metric-card.module.css +1 -1
  61. package/components/money-input/money-input.module.css +9 -9
  62. package/components/morph-select/morph-select.module.css +13 -13
  63. package/components/multi-select/multi-select.module.css +6 -6
  64. package/components/nav-list/nav-list.d.ts +64 -0
  65. package/components/nav-list/nav-list.js +103 -0
  66. package/components/nav-list/nav-list.module.css +25 -0
  67. package/components/notification-center/notification-center.module.css +27 -27
  68. package/components/number-field/number-field.module.css +2 -2
  69. package/components/otp-input/otp-input.module.css +4 -4
  70. package/components/password-field/password-field.module.css +1 -1
  71. package/components/password-strength/password-strength.module.css +7 -7
  72. package/components/phone-input/phone-input.module.css +19 -19
  73. package/components/popover/popover.module.css +2 -2
  74. package/components/progress/progress.module.css +1 -1
  75. package/components/radio-cards/radio-cards.module.css +8 -8
  76. package/components/radio-group/radio-group.module.css +1 -1
  77. package/components/resizable-panels/resizable-panels.module.css +5 -5
  78. package/components/rich-text-editor/rich-text-editor.module.css +12 -12
  79. package/components/ridgeline/ridgeline.module.css +7 -7
  80. package/components/scroll-area/scroll-area.module.css +8 -8
  81. package/components/segmented-control/segmented-control.d.ts +3 -1
  82. package/components/segmented-control/segmented-control.js +2 -2
  83. package/components/segmented-control/segmented-control.module.css +7 -4
  84. package/components/select/select.module.css +5 -5
  85. package/components/shortcut-recorder/shortcut-recorder.module.css +15 -15
  86. package/components/signature-pad/signature-pad.module.css +11 -11
  87. package/components/slider/slider.module.css +4 -4
  88. package/components/slope-chart/slope-chart.module.css +7 -7
  89. package/components/sortable-data-table/sortable-data-table.module.css +4 -4
  90. package/components/split-button/split-button.module.css +5 -5
  91. package/components/stepper/stepper.module.css +3 -3
  92. package/components/streamgraph/streamgraph.module.css +7 -7
  93. package/components/swipe-actions/swipe-actions.module.css +5 -5
  94. package/components/switch/switch.module.css +1 -1
  95. package/components/tabs/tabs.d.ts +9 -2
  96. package/components/tabs/tabs.js +4 -2
  97. package/components/tabs/tabs.module.css +7 -2
  98. package/components/tag-input/tag-input.module.css +4 -4
  99. package/components/time-picker/time-picker.module.css +3 -3
  100. package/components/timeline/timeline.module.css +3 -3
  101. package/components/toast/toast.module.css +5 -5
  102. package/components/toast-stack/toast-stack.module.css +5 -5
  103. package/components/tooltip/tooltip.module.css +1 -1
  104. package/components/tree-view/tree-view.module.css +7 -7
  105. package/components/treemap/treemap.module.css +13 -13
  106. package/components/usage-meter/usage-meter.module.css +5 -5
  107. package/components/user-menu/user-menu.module.css +22 -22
  108. package/components/waffle-chart/waffle-chart.module.css +7 -7
  109. package/components.json +416 -1
  110. package/eslint.js +85 -0
  111. package/package.json +12 -2
  112. package/styles.css +44 -4
@@ -2,7 +2,7 @@
2
2
  --ink-black: var(--foreground);
3
3
  --ink-blue: oklch(46% .17 262);
4
4
  --ink-violet: oklch(49% .2 292);
5
- display: grid; gap: 10px; width: 100%; min-width: 0; font-family: var(--font-body); letter-spacing: var(--tracking-body);
5
+ display: grid; gap: var(--space-group); width: 100%; min-width: 0; font-family: var(--font-body); letter-spacing: var(--tracking-body);
6
6
  }
7
7
  :global(:root[data-theme="dark"]) .root { --ink-blue: oklch(76% .12 258); --ink-violet: oklch(77% .13 295); }
8
8
 
@@ -17,7 +17,7 @@
17
17
  .guide { position: absolute; inset: 0; pointer-events: none; }
18
18
  .baseline { position: absolute; left: 7%; right: 7%; top: 72%; border-top: 1.5px dashed var(--border-strong); }
19
19
  .mark { position: absolute; left: 7%; top: 72%; color: var(--text-muted); translate: 0 calc(-100% - 6px); }
20
- .signer { position: absolute; left: 7%; top: calc(72% + 8px); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); }
20
+ .signer { position: absolute; left: 7%; top: calc(72% + var(--space-related)); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); }
21
21
  .hint {
22
22
  position: absolute; left: 50%; top: 72%; translate: -50% calc(-100% - 8px); color: var(--text-muted);
23
23
  font-size: var(--text-lg); line-height: var(--leading-body); white-space: nowrap;
@@ -37,15 +37,15 @@
37
37
  background: var(--foreground); opacity: .5;
38
38
  }
39
39
  .sweep::after {
40
- content: ""; position: absolute; top: 0; bottom: 0; left: -28px; width: 28px;
40
+ content: ""; position: absolute; top: 0; bottom: 0; left: calc(var(--space-block) * -1); width: 28px;
41
41
  background: linear-gradient(to right, transparent, color-mix(in oklab, var(--foreground) 5%, transparent));
42
42
  }
43
43
 
44
- .toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
45
- .group { display: flex; align-items: center; gap: 2px; }
46
- .divider { width: 1px; height: 20px; margin: 0 6px; background: var(--border); }
44
+ .toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-related); }
45
+ .group { display: flex; align-items: center; gap: var(--space-hair); }
46
+ .divider { width: 1px; height: 20px; margin: 0 var(--space-related); background: var(--border); }
47
47
 
48
- .choice { display: flex; align-items: center; gap: 2px; }
48
+ .choice { display: flex; align-items: center; gap: var(--space-hair); }
49
49
  .option {
50
50
  position: relative; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: var(--radius-full); corner-shape: round;
51
51
  background: transparent; color: var(--foreground); cursor: pointer; -webkit-tap-highlight-color: transparent;
@@ -66,16 +66,16 @@
66
66
  .iconButton[aria-pressed="true"] { background: var(--surface-muted); color: var(--foreground); }
67
67
  .swap { display: grid; place-items: center; }
68
68
 
69
- .exports { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
70
- .exportLabel { margin-right: 4px; color: var(--text-muted); font-size: var(--text-xs); }
69
+ .exports { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-related); }
70
+ .exportLabel { margin-right: var(--space-tight); color: var(--text-muted); font-size: var(--text-xs); }
71
71
  .export {
72
- display: grid; min-width: 76px; height: var(--control-height-sm); padding: 0 12px; border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape);
72
+ display: grid; min-width: 76px; height: var(--control-height-sm); padding: 0 var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape);
73
73
  background: var(--surface); color: var(--foreground); font: inherit; font-size: var(--text-sm); cursor: pointer; -webkit-tap-highlight-color: transparent;
74
74
  transition: background-color var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard);
75
75
  }
76
76
  .export:active:not(:disabled) { transform: scale(.97); }
77
77
  .export:disabled { color: var(--text-muted); cursor: default; }
78
- .exportContent { display: inline-flex; grid-area: 1 / 1; align-items: center; justify-content: center; gap: 6px; }
78
+ .exportContent { display: inline-flex; grid-area: 1 / 1; align-items: center; justify-content: center; gap: var(--space-related); }
79
79
 
80
80
  .srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
81
81
 
@@ -13,19 +13,19 @@
13
13
  .track { position: absolute; top: 50%; right: calc(var(--slider-thumb) / 2); left: calc(var(--slider-thumb) / 2); height: var(--slider-track); margin-top: calc(var(--slider-track) / -2); border-radius: var(--radius-full); corner-shape: round; background: var(--control-track); }
14
14
  /* The fill spans the track and is revealed by a clip that follows the thumbs on the same frame. Ticks inside it are the "on" set, cut exactly at the thumb. */
15
15
  .fill { position: absolute; inset: 0; border-radius: inherit; corner-shape: inherit; background: var(--control-fill); }
16
- .tick { position: absolute; top: 50%; width: 4px; height: 4px; margin: -2px 0 0 -2px; border-radius: var(--radius-full); corner-shape: round; background: color-mix(in oklab, var(--foreground) 30%, transparent); }
16
+ .tick { position: absolute; top: 50%; width: 4px; height: 4px; margin: calc(var(--space-hair) * -1) 0 0 calc(var(--space-hair) * -1); border-radius: var(--radius-full); corner-shape: round; background: color-mix(in oklab, var(--foreground) 30%, transparent); }
17
17
  .fill .tick { background: color-mix(in oklab, var(--control-glyph) 60%, transparent); }
18
18
  .thumbs { position: absolute; inset: 0 calc(var(--slider-thumb) / 2); container-type: inline-size; pointer-events: none; }
19
19
  /* Each layer is as wide as the track and slides by a percentage of itself; it only ever overflows to the left, which never scrolls. */
20
20
  .thumbLayer { position: absolute; inset: 0; }
21
21
  /* Centering uses the translate property, so Motion's scale on transform composes with it instead of replacing it. */
22
22
  .thumb { position: absolute; top: 50%; right: 0; box-sizing: border-box; width: var(--slider-thumb); height: var(--slider-thumb); translate: 50% -50%; border: 0; border-radius: var(--radius-full); corner-shape: round; background: var(--control-thumb); box-shadow: var(--control-thumb-shadow); pointer-events: auto; cursor: grab; transition: box-shadow var(--duration-fast) var(--ease-standard); }
23
- .thumb::after { content: ""; position: absolute; inset: -11px; border-radius: inherit; corner-shape: inherit; }
23
+ .thumb::after { content: ""; position: absolute; inset: calc(var(--space-group) * -1); border-radius: inherit; corner-shape: inherit; }
24
24
  .root[data-dragging], .root[data-dragging] .control, .root[data-dragging] .thumb { cursor: grabbing; }
25
25
  /* The bubble centers on the thumb until it would pass the component's edge, then holds there. --at is the thumb position in percent of
26
26
  the track, written each frame, and cqw measures the track, so the clamp needs no JavaScript measuring. It floats higher on touch so a fingertip never hides it. */
27
- .bubbleAnchor { --edge: calc(var(--slider-thumb) / 2); --x: calc(var(--at, 0) * 1cqw); position: absolute; right: 0; bottom: calc(50% + var(--slider-thumb) / 2 + 8px); display: flex; translate: clamp(calc(100% - var(--edge) - var(--x)), 50%, calc(100cqw + var(--edge) - var(--x))) 0; pointer-events: none; }
28
- @media (pointer: coarse) { .bubbleAnchor { bottom: calc(50% + var(--slider-thumb) / 2 + 18px); } }
27
+ .bubbleAnchor { --edge: calc(var(--slider-thumb) / 2); --x: calc(var(--at, 0) * 1cqw); position: absolute; right: 0; bottom: calc(50% + var(--slider-thumb) / 2 + var(--space-related)); display: flex; translate: clamp(calc(100% - var(--edge) - var(--x)), 50%, calc(100cqw + var(--edge) - var(--x))) 0; pointer-events: none; }
28
+ @media (pointer: coarse) { .bubbleAnchor { bottom: calc(50% + var(--slider-thumb) / 2 + var(--space-comfort)); } }
29
29
  .bubble { display: inline-flex; min-height: 1.75rem; align-items: center; padding: 0 var(--space-group); border: 1px solid color-mix(in oklab, var(--background) 14%, var(--foreground)); border-radius: var(--radius-full); corner-shape: round; background: var(--foreground); color: var(--background); box-shadow: var(--shadow-raised); font-size: var(--text-sm); font-weight: 500; white-space: nowrap; transform-origin: 50% 100%; }
30
30
  /* Mark labels sit on their ticks; one at a limit keeps its outer edge inside the component. */
31
31
  .marks { position: relative; grid-area: 2 / 2; height: 1.25rem; margin: calc(var(--space-tight) * -1) calc(var(--slider-thumb) / 2) 0; color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
@@ -21,27 +21,27 @@
21
21
 
22
22
  .labels { transition: opacity var(--duration-standard) var(--ease-standard); }
23
23
  .labels[data-dim] { opacity: .3; }
24
- .start, .end { position: absolute; top: 0; display: flex; height: 20px; align-items: center; gap: 8px; margin-top: -10px; font-size: var(--text-sm); line-height: 20px; white-space: nowrap; pointer-events: none; }
24
+ .start, .end { position: absolute; top: 0; display: flex; height: 20px; align-items: center; gap: var(--space-related); margin-top: calc(var(--space-group) * -1); font-size: var(--text-sm); line-height: 20px; white-space: nowrap; pointer-events: none; }
25
25
  .start { justify-content: flex-end; max-width: 100%; }
26
26
  /* On a phone the labels step down a size so the longest names fit beside the first column instead of running off the edge. */
27
- .stage[data-narrow] .start, .stage[data-narrow] .end { gap: 6px; font-size: var(--text-xs); }
27
+ .stage[data-narrow] .start, .stage[data-narrow] .end { gap: var(--space-related); font-size: var(--text-xs); }
28
28
  .name { min-width: 0; overflow: hidden; color: var(--text-secondary); text-overflow: ellipsis; }
29
29
  .value { color: var(--foreground); font-variant-numeric: tabular-nums; }
30
30
  .labels[data-on] .name, .labels[data-accent] .name { color: var(--foreground); }
31
31
  /* Only the story item is medium; the item in focus changes color, not weight, so its label never shifts sideways. */
32
32
  .labels[data-accent] .value { font-weight: 500; }
33
33
 
34
- .rank { display: inline-flex; min-width: 30px; align-items: center; gap: 2px; color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
34
+ .rank { display: inline-flex; min-width: 30px; align-items: center; gap: var(--space-hair); color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
35
35
  .rank[data-move="up"] { color: var(--text-secondary); }
36
36
  .rankSwap { position: relative; display: inline-flex; overflow: hidden; }
37
37
 
38
- .tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 168px; max-width: min(240px, 100%); gap: 3px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
38
+ .tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 168px; max-width: min(240px, 100%); gap: var(--space-tight); padding: var(--space-group) var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
39
39
  .stage[data-active] .tooltip { opacity: 1; scale: 1; }
40
- .tipTitle { margin: 0 0 2px; color: var(--foreground); font-size: var(--text-sm); font-weight: 500; line-height: var(--leading-body); white-space: nowrap; }
41
- .tipRow { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0; font-size: var(--text-sm); line-height: 1.3; }
40
+ .tipTitle { margin: 0 0 var(--space-hair); color: var(--foreground); font-size: var(--text-sm); font-weight: 500; line-height: var(--leading-body); white-space: nowrap; }
41
+ .tipRow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-group); margin: 0; font-size: var(--text-sm); line-height: 1.3; }
42
42
  .tipName { color: var(--text-secondary); }
43
43
  .tipValue { color: var(--foreground); font-weight: 500; font-variant-numeric: tabular-nums; }
44
- .tipMeta { margin: 2px 0 0; color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); font-variant-numeric: tabular-nums; }
44
+ .tipMeta { margin: var(--space-hair) 0 0; color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); font-variant-numeric: tabular-nums; }
45
45
 
46
46
  .message { display: grid; min-height: 160px; place-items: center; margin: 0; color: var(--text-muted); font-size: var(--text-sm); }
47
47
  .srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
@@ -21,7 +21,7 @@
21
21
 
22
22
  .sortButton { display: flex; width: 100%; height: 44px; align-items: center; justify-content: flex-start; border: 0; padding: 0 var(--space-inset); background: transparent; color: inherit; font: inherit; letter-spacing: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
23
23
  .table th[data-numeric] .sortButton { justify-content: flex-end; }
24
- .sortInner { display: inline-flex; align-items: center; gap: 6px; border-radius: var(--radius-control); transition: color var(--duration-fast) var(--ease-standard); }
24
+ .sortInner { display: inline-flex; align-items: center; gap: var(--space-related); border-radius: var(--radius-control); transition: color var(--duration-fast) var(--ease-standard); }
25
25
  /* Right-aligned columns lead with the arrow so the label lines up with the digits below it. */
26
26
  .table th[data-numeric] .sortInner { flex-direction: row-reverse; }
27
27
  .sortIcon { position: relative; display: grid; width: 16px; height: 16px; flex: none; place-items: center; }
@@ -79,15 +79,15 @@
79
79
  .table th.selectCell .selectHit { height: 32px; }
80
80
  /* Once the strip scrolls, a fade off the pinned cell hides the word sliding under it. */
81
81
  .table th.selectCell::after { position: absolute; top: 0; bottom: 0; left: 100%; width: 36px; background: linear-gradient(to right, var(--surface) 45%, transparent); content: ""; opacity: 0; pointer-events: none; animation: stripFade linear both; animation-timeline: scroll(nearest inline); animation-range: 0 24px; }
82
- .table th .sortButton, .table[data-selectable] th[data-primary] .sortButton { width: auto; height: 32px; border-radius: var(--radius-control); padding: 0 10px; transition: background-color var(--duration-standard) var(--ease-standard), color var(--duration-standard) var(--ease-standard); }
82
+ .table th .sortButton, .table[data-selectable] th[data-primary] .sortButton { width: auto; height: 32px; border-radius: var(--radius-control); padding: 0 var(--space-group); transition: background-color var(--duration-standard) var(--ease-standard), color var(--duration-standard) var(--ease-standard); }
83
83
  .table th[data-sorted] .sortButton { background: var(--surface-muted); }
84
84
  .table th[data-numeric] .sortInner { flex-direction: row; }
85
85
  .sortButton:focus-visible { --focus-outline-offset: 1px; }
86
86
  .table tbody { display: block; width: 100%; }
87
87
  /* Rows fold into two lines: the first column with its number, then the remaining details. */
88
- .table tbody tr { --row-fill: var(--surface); position: relative; display: flex; width: 100%; min-height: 64px; box-sizing: border-box; flex-wrap: wrap; align-items: baseline; align-content: center; gap: 2px var(--space-related); padding: 10px var(--space-inset); border-bottom: 1px solid var(--border-subtle); background-color: var(--row-fill); transition: background-color var(--duration-standard) var(--ease-standard); }
88
+ .table tbody tr { --row-fill: var(--surface); position: relative; display: flex; width: 100%; min-height: 64px; box-sizing: border-box; flex-wrap: wrap; align-items: baseline; align-content: center; gap: var(--space-hair) var(--space-related); padding: var(--space-group) var(--space-inset); border-bottom: 1px solid var(--border-subtle); background-color: var(--row-fill); transition: background-color var(--duration-standard) var(--ease-standard); }
89
89
  .table tbody tr::after { order: 1; flex-basis: 100%; content: ""; }
90
- .table[data-selectable] tbody tr { padding-left: 44px; }
90
+ .table[data-selectable] tbody tr { padding-left: var(--space-page); }
91
91
  .table[data-selectable] tbody tr[data-selected] { --row-fill: color-mix(in oklab, var(--accent) 8%, var(--surface)); }
92
92
  .table tbody tr:last-child { border-bottom: 0; }
93
93
  .table td { order: 2; display: block; min-width: 0; height: auto; border: 0; padding: 0; background: transparent; color: var(--text-secondary); font-size: var(--text-xs); text-align: left; }
@@ -2,13 +2,13 @@
2
2
  .group { display: inline-flex; align-items: stretch; border: 1px solid var(--foreground); border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: var(--foreground); transition: transform var(--duration-spring) var(--ease-spring); }
3
3
  .group:has(> .primary:active:not(:disabled)) { transform: scale(.97); transition-duration: var(--duration-instant); transition-timing-function: var(--ease-standard); }
4
4
  .primary, .trigger { border: 0; background: var(--foreground); color: var(--background); font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard); }
5
- .primary { position: relative; display: inline-grid; min-height: var(--control-height-md); place-items: center; padding: 0 var(--space-inset); border-radius: calc(var(--radius-control) - 1px) 0 0 calc(var(--radius-control) - 1px); corner-shape: var(--corner-shape); font-size: var(--text-sm); font-weight: 500; }
5
+ .primary { position: relative; display: inline-grid; min-height: var(--control-height-md); place-items: center; padding: 0 var(--space-inset); border-radius: calc(var(--radius-control) - var(--space-hair)) 0 0 calc(var(--radius-control) - var(--space-hair)); corner-shape: var(--corner-shape); font-size: var(--text-sm); font-weight: 500; }
6
6
  /* TextMorph springs the label's width, so the main half grows and shrinks with its text. */
7
7
  .primarySlot { display: inline-flex; min-width: 0; align-items: center; }
8
8
  .primaryContent { display: inline-flex; flex: none; align-items: center; gap: var(--space-related); white-space: nowrap; }
9
9
  .mainIcon { display: inline-grid; flex: none; place-items: center; }
10
10
  .iconPhase { grid-area: 1 / 1; display: inline-flex; align-items: center; justify-content: center; }
11
- .trigger { display: grid; width: 38px; min-height: var(--control-height-md); place-items: center; border-left: 1px solid color-mix(in oklab, var(--background) 18%, var(--foreground)); border-radius: 0 calc(var(--radius-control) - 1px) calc(var(--radius-control) - 1px) 0; corner-shape: var(--corner-shape); }
11
+ .trigger { display: grid; width: 38px; min-height: var(--control-height-md); place-items: center; border-left: 1px solid color-mix(in oklab, var(--background) 18%, var(--foreground)); border-radius: 0 calc(var(--radius-control) - var(--space-hair)) calc(var(--radius-control) - var(--space-hair)) 0; corner-shape: var(--corner-shape); }
12
12
  .chevron { transition: transform var(--duration-spring) var(--ease-spring); }
13
13
  .trigger[data-state="open"] .chevron { transform: rotate(180deg); }
14
14
  @media (hover: hover) and (pointer: fine) {
@@ -26,7 +26,7 @@
26
26
  .srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
27
27
  /* The menu grows from the trigger edge: offset toward the trigger, scale from the Radix origin, fade quickly; it leaves faster than it arrives.
28
28
  Transitions instead of keyframes, so a close that interrupts the open reverses from where the menu is instead of snapping to rest first. */
29
- .menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index: 60; min-width: min(12rem, var(--radix-dropdown-menu-content-available-width)); max-width: var(--radix-dropdown-menu-content-available-width); padding: 5px; border: 1px solid var(--border); border-radius: var(--radius-container); corner-shape: var(--corner-shape); background: var(--surface-raised); color: var(--foreground); box-shadow: var(--shadow-floating); transform-origin: var(--radix-dropdown-menu-content-transform-origin); transition: opacity var(--duration-fast) var(--ease-enter), transform var(--duration-spring) var(--ease-spring); }
29
+ .menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index: var(--layer-dropdown); min-width: min(12rem, var(--radix-dropdown-menu-content-available-width)); max-width: var(--radix-dropdown-menu-content-available-width); padding: var(--space-tight); border: 1px solid var(--border); border-radius: var(--radius-container); corner-shape: var(--corner-shape); background: var(--surface-raised); color: var(--foreground); box-shadow: var(--shadow-floating); transform-origin: var(--radix-dropdown-menu-content-transform-origin); transition: opacity var(--duration-fast) var(--ease-enter), transform var(--duration-spring) var(--ease-spring); }
30
30
  .menu[data-side="top"] { --menu-y: 5px; }
31
31
  .menu[data-side="left"] { --menu-x: 5px; --menu-y: 0px; }
32
32
  .menu[data-side="right"] { --menu-x: -5px; --menu-y: 0px; }
@@ -36,10 +36,10 @@
36
36
  }
37
37
  /* Radix unmounts when the exit animation ends, so a no-op keyframe times the exit while the transition does the visual work. */
38
38
  .menu[data-state="closed"] { opacity: 0; transform: translate(calc(var(--menu-x) * .5), calc(var(--menu-y) * .5)) scale(.985); transition: opacity 130ms var(--ease-standard), transform 130ms var(--ease-standard); animation: menu-exit 130ms linear both; pointer-events: none; }
39
- .highlight { position: absolute; top: 0; right: 5px; left: 5px; border-radius: calc(var(--radius-container) - 6px); background: var(--surface-muted); opacity: 0; pointer-events: none; transition: background-color var(--duration-fast) var(--ease-standard); }
39
+ .highlight { position: absolute; top: 0; right: var(--space-tight); left: var(--space-tight); border-radius: calc(var(--radius-container) - var(--space-related)); background: var(--surface-muted); opacity: 0; pointer-events: none; transition: background-color var(--duration-fast) var(--ease-standard); }
40
40
  .highlight[data-tone="danger"] { background: color-mix(in oklab, var(--danger) 8%, var(--surface)); }
41
41
  /* One highlight glides between items for the pointer and jumps instantly for the keyboard (lib/menu-highlight). */
42
- .item { position: relative; display: flex; min-height: var(--control-height-sm); align-items: center; gap: 10px; padding: 0 11px; border-radius: calc(var(--radius-container) - 6px); corner-shape: var(--corner-shape); font-size: var(--text-sm); cursor: pointer; outline: none; transition: opacity var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms), transform var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms); }
42
+ .item { position: relative; display: flex; min-height: var(--control-height-sm); align-items: center; gap: var(--space-group); padding: 0 var(--space-group); border-radius: calc(var(--radius-container) - var(--space-related)); corner-shape: var(--corner-shape); font-size: var(--text-sm); cursor: pointer; outline: none; transition: opacity var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms), transform var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms); }
43
43
  .item[data-disabled] { cursor: default; opacity: .45; }
44
44
  .destructive { color: var(--danger); }
45
45
  @keyframes menu-exit { to { --menu-exit: 1; } }
@@ -31,7 +31,7 @@
31
31
  .connector { position: absolute; overflow: hidden; border-radius: var(--radius-full); corner-shape: round; background: var(--border); pointer-events: none; }
32
32
  .horizontal .connector { top: calc(var(--marker) / 2 - 1px); inset-inline: calc(var(--marker) + var(--halo) + var(--space-tight)) calc(var(--halo) + var(--space-tight)); height: 2px; }
33
33
  /* Both ends keep a clear gap from the markers, and from the current step's ring. */
34
- .vertical .connector { top: calc(var(--marker) + var(--halo) + 2px); bottom: calc(var(--halo) + 2px); inset-inline-start: calc(var(--marker) / 2 - 1px); width: 2px; }
34
+ .vertical .connector { top: calc(var(--marker) + var(--halo) + var(--space-hair)); bottom: calc(var(--halo) + var(--space-hair)); inset-inline-start: calc(var(--marker) / 2 - 1px); width: 2px; }
35
35
  .fill { position: absolute; inset: 0; border-radius: inherit; corner-shape: inherit; background: var(--accent); }
36
36
  .horizontal .fill { transform-origin: left center; }
37
37
  .horizontal .fill:dir(rtl) { transform-origin: right center; }
@@ -39,14 +39,14 @@
39
39
 
40
40
  .text { display: grid; min-width: 0; }
41
41
  /* Centers the first line of the label on the marker. */
42
- .vertical .text { padding-top: .25rem; }
42
+ .vertical .text { padding-top: var(--space-tight); }
43
43
  .label { display: block; color: var(--text-muted); font-size: var(--text-sm); font-weight: 500; line-height: 1.25rem; overflow-wrap: break-word; transition: color var(--duration-standard) var(--ease-standard); }
44
44
  .item[data-status="complete"] .label { color: var(--text-secondary); }
45
45
  .item[data-status="current"] .label, .item[data-status="error"] .label { color: var(--foreground); }
46
46
  /* Changing text pops out of flow against this box while it leaves, so it must be the positioned parent. */
47
47
  .slot { display: block; }
48
48
  .slotInner { position: relative; display: block; }
49
- .description, .error { display: block; padding-top: 2px; font-size: var(--text-xs); font-weight: 400; line-height: var(--leading-body); overflow-wrap: break-word; }
49
+ .description, .error { display: block; padding-top: var(--space-hair); font-size: var(--text-xs); font-weight: 400; line-height: var(--leading-body); overflow-wrap: break-word; }
50
50
  .description { color: var(--text-muted); }
51
51
  .error { color: var(--danger); }
52
52
 
@@ -3,8 +3,8 @@
3
3
  /* Series colors (--series-1 to --series-4) come from registry/foundation.css. */
4
4
 
5
5
  /* Layer toggles: a rect swatch mirrors the area it names. Hover or focus previews that layer in the plot. */
6
- .legend { display: flex; flex-wrap: wrap; gap: 2px 4px; min-width: 0; margin-inline: -8px; }
7
- .toggle { display: inline-flex; min-height: 32px; align-items: center; gap: 8px; padding: 0 10px 0 8px; border: 0; border-radius: var(--radius-full); corner-shape: round; background: transparent; color: var(--text-secondary); cursor: pointer; font: inherit; font-size: var(--text-sm); line-height: var(--leading-body); -webkit-tap-highlight-color: transparent; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard); }
6
+ .legend { display: flex; flex-wrap: wrap; gap: var(--space-hair) var(--space-tight); min-width: 0; margin-inline: calc(var(--space-related) * -1); }
7
+ .toggle { display: inline-flex; min-height: 32px; align-items: center; gap: var(--space-related); padding: 0 var(--space-group) 0 var(--space-related); border: 0; border-radius: var(--radius-full); corner-shape: round; background: transparent; color: var(--text-secondary); cursor: pointer; font: inherit; font-size: var(--text-sm); line-height: var(--leading-body); -webkit-tap-highlight-color: transparent; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard); }
8
8
  .toggle:active { transform: scale(.97); }
9
9
  .toggle[data-active] { color: var(--foreground); background: color-mix(in oklab, var(--foreground) 5%, transparent); }
10
10
  .toggle[data-dim] { opacity: .56; }
@@ -31,20 +31,20 @@
31
31
  .label[data-hidden] { opacity: 0 !important; }
32
32
  .chart[data-layer] .label[data-dim] { opacity: 0 !important; }
33
33
 
34
- .tooltip { position: absolute; top: 0; left: 0; z-index: 1; display: grid; min-width: 156px; max-width: min(256px, 100%); gap: 4px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
34
+ .tooltip { position: absolute; top: 0; left: 0; z-index: 1; display: grid; min-width: 156px; max-width: min(256px, 100%); gap: var(--space-tight); padding: var(--space-group) var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
35
35
  .chart[data-active] .tooltip { opacity: 1; scale: 1; }
36
- .tipTitle { margin: 0 0 2px; color: var(--text-secondary); font-size: var(--text-xs); line-height: var(--leading-body); white-space: nowrap; font-variant-numeric: tabular-nums; }
37
- .tipRow { display: flex; min-width: 0; align-items: center; gap: 8px; margin: 0; font-size: var(--text-sm); line-height: var(--leading-body); transition: opacity var(--duration-fast) var(--ease-standard); }
36
+ .tipTitle { margin: 0 0 var(--space-hair); color: var(--text-secondary); font-size: var(--text-xs); line-height: var(--leading-body); white-space: nowrap; font-variant-numeric: tabular-nums; }
37
+ .tipRow { display: flex; min-width: 0; align-items: center; gap: var(--space-related); margin: 0; font-size: var(--text-sm); line-height: var(--leading-body); transition: opacity var(--duration-fast) var(--ease-standard); }
38
38
  .tipRow[data-dim] { opacity: .5; }
39
39
  .tipSwatch { width: 10px; height: 2.5px; flex: none; border-radius: var(--radius-full); corner-shape: round; background: var(--series); }
40
40
  .tipName { min-width: 0; flex: 1; overflow: hidden; color: var(--text-secondary); text-overflow: ellipsis; white-space: nowrap; }
41
41
  .tipRow[data-active] .tipName { color: var(--foreground); }
42
- .tipValue { flex: none; margin-left: 8px; color: var(--foreground); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
42
+ .tipValue { flex: none; margin-left: var(--space-related); color: var(--foreground); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
43
43
 
44
44
  .message { position: absolute; inset: 0; display: grid; place-items: center; margin: 0; color: var(--text-muted); font-size: var(--text-sm); pointer-events: none; }
45
45
 
46
46
  .axis { position: relative; min-width: 0; }
47
- .axisLabel { position: absolute; top: 8px; color: var(--text-muted); font-size: var(--text-xs); line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; transition: opacity var(--duration-standard) var(--ease-standard); }
47
+ .axisLabel { position: absolute; top: var(--space-related); color: var(--text-muted); font-size: var(--text-xs); line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; transition: opacity var(--duration-standard) var(--ease-standard); }
48
48
  /* New labels fade in while the stream morphs to a new range instead of popping in a single frame. */
49
49
  @starting-style { .axisLabel { opacity: 0; } }
50
50
 
@@ -8,11 +8,11 @@
8
8
  .list:focus-visible { outline: none; }
9
9
  .row { position: relative; isolation: isolate; overflow: hidden; }
10
10
  /* The content follows the finger by transform only; vertical pans stay with the page. */
11
- .content { position: relative; z-index: 10; display: flex; min-height: 64px; align-items: center; gap: var(--space-related); padding: var(--space-group) var(--space-related) var(--space-group) var(--space-inset); background: var(--surface); touch-action: pan-y; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
11
+ .content { position: relative; z-index: var(--layer-raised); display: flex; min-height: 64px; align-items: center; gap: var(--space-related); padding: var(--space-group) var(--space-related) var(--space-group) var(--space-inset); background: var(--surface); touch-action: pan-y; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
12
12
  .content::after { position: absolute; right: 0; bottom: 0; left: var(--swipe-actions-inset, var(--space-inset)); height: 1px; background: var(--border); content: ""; pointer-events: none; }
13
13
  .content img { -webkit-user-drag: none; }
14
14
  .body { min-width: 0; flex: 1 1 auto; }
15
- .more { display: grid; width: 32px; height: 32px; flex: none; place-items: center; border: 0; border-radius: calc(var(--radius-control) - 6px); background: transparent; color: var(--text-muted); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
15
+ .more { display: grid; width: 32px; height: 32px; flex: none; place-items: center; border: 0; border-radius: calc(var(--radius-control) - var(--space-related)); background: transparent; color: var(--text-muted); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
16
16
  /* The button anchors a menu, so a press answers with colour, never scale. */
17
17
  .more:active, .more[data-state="open"] { background: var(--surface-muted); color: var(--foreground); }
18
18
  .more:focus-visible { outline: none; }
@@ -33,18 +33,18 @@
33
33
  .anchor { position: absolute; top: 0; bottom: 0; width: 0; }
34
34
  .layer[data-side="trailing"] .anchor { left: 0; }
35
35
  .layer[data-side="leading"] .anchor { right: 0; }
36
- .glyph { position: absolute; top: 0; bottom: 0; left: calc(var(--swipe-action-width) / -2); display: flex; width: var(--swipe-action-width); flex-direction: column; align-items: center; justify-content: center; gap: 3px; }
36
+ .glyph { position: absolute; top: 0; bottom: 0; left: calc(var(--swipe-action-width) / -2); display: flex; width: var(--swipe-action-width); flex-direction: column; align-items: center; justify-content: center; gap: var(--space-tight); }
37
37
  .icon { display: grid; place-items: center; }
38
38
  .icon svg { width: 20px; height: 20px; }
39
39
  .label { font-size: var(--text-xs); font-weight: 500; letter-spacing: var(--tracking-body); line-height: var(--leading-body); white-space: nowrap; }
40
40
 
41
41
  /* The menu grows from its trigger, matching the library dropdown. */
42
- .menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index: 60; min-width: 11rem; padding: 5px; border: 1px solid var(--border); border-radius: var(--radius-container); background: var(--surface-raised); box-shadow: var(--shadow-floating); transform-origin: var(--radix-dropdown-menu-content-transform-origin); }
42
+ .menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index: var(--layer-dropdown); min-width: 11rem; padding: var(--space-tight); border: 1px solid var(--border); border-radius: var(--radius-container); background: var(--surface-raised); box-shadow: var(--shadow-floating); transform-origin: var(--radix-dropdown-menu-content-transform-origin); }
43
43
  .menu[data-side="top"] { --menu-y: 5px; }
44
44
  .menu[data-state="open"] { animation: menu-fade-in var(--duration-fast) var(--ease-enter) both, menu-rise-in var(--duration-spring) var(--ease-spring) both; }
45
45
  .menu[data-state="closed"] { animation: menu-out var(--duration-instant) var(--ease-standard) both; }
46
46
  .menu[data-state="open"] .item { animation: menu-item-in var(--duration-standard) var(--ease-enter) both; animation-delay: calc(min(var(--i, 0), 4) * 35ms); }
47
- .item { position: relative; display: flex; min-height: 36px; align-items: center; gap: 10px; padding: 0 11px; border-radius: calc(var(--radius-container) - 6px); color: var(--foreground); font-size: var(--text-sm); cursor: pointer; outline: none; transition: background-color var(--duration-instant) var(--ease-standard); }
47
+ .item { position: relative; display: flex; min-height: 36px; align-items: center; gap: var(--space-group); padding: 0 var(--space-group); border-radius: calc(var(--radius-container) - var(--space-related)); color: var(--foreground); font-size: var(--text-sm); cursor: pointer; outline: none; transition: background-color var(--duration-instant) var(--ease-standard); }
48
48
  .item[data-highlighted] { background: var(--surface-muted); }
49
49
  .item[data-tone="danger"] { color: var(--danger); }
50
50
  .item[data-tone="danger"][data-highlighted] { background: color-mix(in oklab, var(--danger) 8%, var(--surface-raised)); }
@@ -1,7 +1,7 @@
1
1
  .switch { display: inline-flex; min-height: var(--control-height-md); align-items: center; gap: var(--space-group); padding: 0; border: 0; color: var(--foreground); background: transparent; font: inherit; font-size: var(--text-sm); cursor: pointer; -webkit-tap-highlight-color: transparent; }
2
2
  .switch:disabled { cursor: not-allowed; opacity: .5; }
3
3
  /* Fixed box: the thumb moves inside it with transforms, so nothing around the switch shifts. The track crossfades between the two fills. */
4
- .track { position: relative; box-sizing: border-box; display: flex; flex: 0 0 auto; width: 42px; height: 24px; align-items: center; padding: 3px; border-radius: var(--radius-full); corner-shape: round; background: var(--control-track); isolation: isolate; transition: background-color var(--duration-fast) var(--ease-standard); }
4
+ .track { position: relative; box-sizing: border-box; display: flex; flex: 0 0 auto; width: 42px; height: 24px; align-items: center; padding: var(--space-tight); border-radius: var(--radius-full); corner-shape: round; background: var(--control-track); isolation: isolate; transition: background-color var(--duration-fast) var(--ease-standard); }
5
5
  .track::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; corner-shape: inherit; background: var(--control-on); opacity: 0; transition: opacity var(--duration-standard) var(--ease-standard); }
6
6
  .switch[data-state="checked"] .track::before { opacity: 1; }
7
7
  .thumb { flex: 0 0 auto; width: 18px; height: 18px; border-radius: var(--radius-full); corner-shape: round; background: var(--control-thumb); box-shadow: var(--control-thumb-shadow); will-change: transform; transition: background-color var(--duration-standard) var(--ease-standard); }
@@ -1,8 +1,15 @@
1
1
  import * as TabsPrimitive from "@radix-ui/react-tabs";
2
- import type { ComponentPropsWithoutRef } from "react";
2
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
3
3
  type RootProps = ComponentPropsWithoutRef<typeof TabsPrimitive.Root>;
4
4
  export declare function Tabs({ value, defaultValue, onValueChange, className, ...props }: RootProps): import("react").JSX.Element;
5
5
  export declare function TabsList({ className, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.List>): import("react").JSX.Element;
6
- export declare function TabsTrigger({ className, children, value, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>): import("react").JSX.Element;
6
+ export interface TabsTriggerProps extends ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger> {
7
+ /**
8
+ * An icon before the label, such as a 16px Lucide icon. It is sized, coloured with the label (muted, then the active
9
+ * colour when selected) and hidden from screen readers. For an icon-only tab, leave out the label and pass `aria-label`.
10
+ */
11
+ icon?: ReactNode;
12
+ }
13
+ export declare function TabsTrigger({ className, children, value, icon, ...props }: TabsTriggerProps): import("react").JSX.Element;
7
14
  export declare function TabsContent({ className, value, forceMount, children, ...props }: ComponentPropsWithoutRef<typeof TabsPrimitive.Content>): import("react").JSX.Element;
8
15
  export {};
@@ -78,11 +78,13 @@ export function TabsList({ className, ...props }) {
78
78
  return _jsxs("div", { ref: shell, className: styles.listShell, "data-overflow": edges.overflow, "data-left": edges.left, "data-right": edges.right, children: [edges.overflow && _jsx("button", { type: "button", className: `${styles.scrollButton} ${styles.scrollLeft}`, "aria-label": "Scroll tabs left", disabled: !edges.left, onClick: () => scrollTabs(-1), children: _jsx(NavArrowLeft, { width: 17, height: 17, "aria-hidden": "true" }) }), _jsx(motion.div, { ref: viewport, layoutScroll: true, className: styles.viewport, onFocusCapture: event => { if (event.target instanceof HTMLElement && event.target.getAttribute("role") === "tab")
79
79
  reveal(event.target); }, children: _jsx(TabsPrimitive.List, { ...props, ref: list, className: [styles.list, className].filter(Boolean).join(" ") }) }), edges.overflow && _jsx("button", { type: "button", className: `${styles.scrollButton} ${styles.scrollRight}`, "aria-label": "Scroll tabs right", disabled: !edges.right, onClick: () => scrollTabs(1), children: _jsx(NavArrowRight, { width: 17, height: 17, "aria-hidden": "true" }) })] });
80
80
  }
81
- export function TabsTrigger({ className, children, value, ...props }) {
81
+ export function TabsTrigger({ className, children, value, icon, ...props }) {
82
82
  const { active } = useContext(TabsContext);
83
83
  const reduced = useReducedMotion();
84
84
  // The LayoutGroup in Tabs scopes the highlight to this instance, so it glides between triggers but never flies in from another tab set.
85
- return _jsxs(TabsPrimitive.Trigger, { ...props, value: value, "data-value": value, className: [styles.trigger, className].filter(Boolean).join(" "), children: [active === value && _jsx(motion.span, { className: styles.selection, layoutId: "selection", layoutDependency: active, transition: reduced ? { duration: 0 } : motionTokens.spring.morph, "aria-hidden": "true" }), _jsx("span", { className: styles.triggerLabel, children: children })] });
85
+ // An icon with no label is a square tab instead of a text tab's minimum width.
86
+ const iconOnly = !!icon && (children === undefined || children === null || children === false);
87
+ return _jsxs(TabsPrimitive.Trigger, { ...props, value: value, "data-value": value, "data-icon-only": iconOnly || undefined, className: [styles.trigger, className].filter(Boolean).join(" "), children: [active === value && _jsx(motion.span, { className: styles.selection, layoutId: "selection", layoutDependency: active, transition: reduced ? { duration: 0 } : motionTokens.spring.morph, "aria-hidden": "true" }), _jsxs("span", { className: styles.triggerLabel, children: [icon ? _jsx("span", { className: styles.icon, "aria-hidden": "true", children: icon }) : null, children] })] });
86
88
  }
87
89
  const panelMotion = {
88
90
  enter: (direction) => ({ opacity: 0, x: direction * 8 }),
@@ -13,11 +13,16 @@
13
13
  .scrollRight { right: 0; border-radius: 0 var(--radius-control) var(--radius-control) 0; }
14
14
  .scrollButton:disabled { opacity: 0; pointer-events: none; }
15
15
  .scrollButton:focus-visible { --focus-outline-offset: -3px; }
16
- .trigger { position: relative; -webkit-tap-highlight-color: transparent; display: inline-grid; min-width: 5.5rem; place-items: center; flex: 0 0 auto; min-height: var(--control-height-sm); border: 0; border-radius: calc(var(--radius-control) - 3px); padding: 0 var(--space-group); background: transparent; color: var(--text-muted); font: inherit; font-size: var(--text-sm); font-weight: 500; white-space: nowrap; cursor: pointer; transition: color var(--duration-fast) var(--ease-standard); }
16
+ .trigger { position: relative; -webkit-tap-highlight-color: transparent; display: inline-grid; min-width: 5.5rem; place-items: center; flex: 0 0 auto; min-height: var(--control-height-sm); border: 0; border-radius: calc(var(--radius-control) - var(--space-tight)); padding: 0 var(--space-group); background: transparent; color: var(--text-muted); font: inherit; font-size: var(--text-sm); font-weight: 500; white-space: nowrap; cursor: pointer; transition: color var(--duration-fast) var(--ease-standard); }
17
17
  @media (hover: hover) and (pointer: fine) { .trigger:hover { color: var(--foreground); } }
18
18
  .trigger:active { color: var(--foreground); }.trigger[data-state="active"] { color: var(--accent-strong); }
19
19
  .selection { position: absolute; z-index: -1; inset: 0; border: 1px solid var(--border); border-radius: inherit; corner-shape: inherit; background: var(--surface); box-shadow: var(--shadow-resting); will-change: transform; }
20
- .triggerLabel { position: relative; z-index: 1; }
20
+ .triggerLabel { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: var(--space-related); }
21
+ /* An icon before the label: one size for every tab set, coloured with the label so it follows hover and selection. */
22
+ .icon { display: inline-grid; flex: none; place-items: center; color: currentColor; }
23
+ .icon svg { width: 16px; height: 16px; }
24
+ /* Icon-only tabs are square, the height of the strip's controls. */
25
+ .trigger[data-icon-only] { min-width: var(--control-height-sm); padding: 0; }
21
26
  .trigger:disabled { cursor: not-allowed; opacity: .5; }
22
27
  .content { margin-top: var(--space-inset); color: var(--text-secondary); font-size: var(--text-sm); line-height: var(--leading-body); }
23
28
  /* The outgoing panel is lifted out of flow by the presence animation; drop its margin so it stays in place and ignore stray clicks. */
@@ -7,18 +7,18 @@
7
7
  @media (hover: hover) and (pointer: fine) { .control:hover:not(:focus-within) { border-color: var(--border-strong); } }
8
8
  .control:focus-within { border-color: var(--foreground); box-shadow: 0 0 0 3px var(--focus-ring); outline: 2px solid transparent; outline-offset: 2px; }
9
9
  /* Equal 7px padding makes one row fill the minimum height exactly, so existing tags hold their line when a second row opens. */
10
- .content { position: relative; display: flex; flex-wrap: wrap; align-items: center; align-content: flex-start; gap: 6px; min-height: calc(var(--control-height-md) - 2px); box-sizing: border-box; padding: 7px; cursor: text; }
11
- .tag { position: relative; display: inline-flex; align-items: center; gap: 3px; min-height: 28px; box-sizing: border-box; border: 1px solid var(--border); border-radius: var(--radius-full); corner-shape: round; padding: 0 4px 0 9px; background: var(--surface-muted); color: var(--foreground); font-size: var(--text-sm); white-space: nowrap; cursor: default; }
10
+ .content { position: relative; display: flex; flex-wrap: wrap; align-items: center; align-content: flex-start; gap: var(--space-related); min-height: calc(var(--control-height-md) - 2px); box-sizing: border-box; padding: var(--space-related); cursor: text; }
11
+ .tag { position: relative; display: inline-flex; align-items: center; gap: var(--space-tight); min-height: 28px; box-sizing: border-box; border: 1px solid var(--border); border-radius: var(--radius-full); corner-shape: round; padding: 0 var(--space-tight) 0 var(--space-related); background: var(--surface-muted); color: var(--foreground); font-size: var(--text-sm); white-space: nowrap; cursor: default; }
12
12
  .tag button { display: grid; width: 22px; height: 22px; place-items: center; border: 0; border-radius: 50%; corner-shape: round; background: transparent; color: var(--text-secondary); cursor: pointer; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), transform var(--duration-spring) var(--ease-spring); }
13
13
  @media (hover: hover) and (pointer: fine) { .tag button:hover { background: var(--surface); color: var(--foreground); } }
14
14
  .tag button:focus-visible { background: var(--surface); color: var(--foreground); outline: none; box-shadow: inset 0 0 0 1.5px var(--focus-ring); }
15
15
  /* Quick press, spring release. */
16
16
  .tag button:active { transform: scale(.96); transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard); }
17
- .content input { flex: 1 1 100px; min-width: 80px; min-height: 28px; box-sizing: border-box; border: 0; padding: 0 5px; background: transparent; color: var(--foreground); font: inherit; font-size: var(--text-sm); }
17
+ .content input { flex: 1 1 100px; min-width: 80px; min-height: 28px; box-sizing: border-box; border: 0; padding: 0 var(--space-tight); background: transparent; color: var(--foreground); font: inherit; font-size: var(--text-sm); }
18
18
  .content input:focus, .content input:focus-visible { outline: none; }
19
19
  .content input::placeholder { color: transparent; }
20
20
  /* The visible placeholder is drawn here so it can rise in when the last tag leaves. The native one stays for assistive tech. Inset matches the content and input padding. */
21
- .placeholder { position: absolute; inset: 0; display: flex; align-items: center; overflow: hidden; padding: 0 12px; color: var(--text-muted); font-size: var(--text-sm); white-space: nowrap; pointer-events: none; }
21
+ .placeholder { position: absolute; inset: 0; display: flex; align-items: center; overflow: hidden; padding: 0 var(--space-group); color: var(--text-muted); font-size: var(--text-sm); white-space: nowrap; pointer-events: none; }
22
22
  /* The pick ring rides above the pills and sizes itself to the picked tag, so it can glide between tags without scaling its border. */
23
23
  .ring { position: absolute; top: 0; left: 0; z-index: 1; box-sizing: border-box; border: 1px solid var(--accent); border-radius: var(--radius-full); corner-shape: round; background: var(--accent-subtle); opacity: 0; pointer-events: none; }
24
24
  /* A resting tag is not a stacking context (its filter ends at none), so its label and button sit above the ring while its fill stays below. */
@@ -2,7 +2,7 @@
2
2
  .label { font-size: var(--text-sm); font-weight: 500; line-height: var(--leading-body); }
3
3
  .anchor { position: relative; min-width: 0; }
4
4
  /* The trigger anchors the menu, so press feedback stays in color; it never scales. */
5
- .trigger { position: relative; display: flex; width: 100%; min-height: var(--control-height-md); align-items: center; gap: 9px; border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape); padding: 0 12px; background: var(--surface); color: var(--foreground); font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer; transition: border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
5
+ .trigger { position: relative; display: flex; width: 100%; min-height: var(--control-height-md); align-items: center; gap: var(--space-related); border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape); padding: 0 var(--space-group); background: var(--surface); color: var(--foreground); font: inherit; font-size: var(--text-sm); text-align: left; cursor: pointer; transition: border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
6
6
  @media (hover: hover) and (pointer: fine) { .trigger:hover:not(:disabled) { border-color: var(--border-strong); background: var(--surface-muted); } }
7
7
  .trigger:active:not(:disabled), .trigger[aria-expanded="true"] { border-color: var(--border-strong); background: var(--surface-muted); }
8
8
  .trigger:disabled { opacity: .5; cursor: not-allowed; }
@@ -15,9 +15,9 @@
15
15
  .chevron { flex: 0 0 auto; color: var(--text-muted); transition: transform var(--duration-spring) var(--ease-spring); }
16
16
  .trigger[aria-expanded="true"] .chevron { transform: rotate(180deg); }
17
17
  .description { font-size: var(--text-xs); }
18
- .menu { position: absolute; z-index: 80; top: calc(100% + 6px); right: 0; left: 0; max-height: 250px; overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--border); border-radius: var(--radius-container); corner-shape: var(--corner-shape); padding: 5px; background: var(--surface-raised); box-shadow: var(--shadow-floating); transform-origin: top center; will-change: transform, opacity; }
18
+ .menu { position: absolute; z-index: var(--layer-dropdown); top: calc(100% + var(--space-related)); right: 0; left: 0; max-height: 250px; overflow-y: auto; overscroll-behavior: contain; border: 1px solid var(--border); border-radius: var(--radius-container); corner-shape: var(--corner-shape); padding: var(--space-tight); background: var(--surface-raised); box-shadow: var(--shadow-floating); transform-origin: top center; will-change: transform, opacity; }
19
19
  /* Arrow keys move the highlight often, so it changes almost instantly. The dot marks the chosen time, so only one row is ever highlighted. */
20
- .option { display: flex; width: 100%; min-height: 36px; align-items: center; justify-content: space-between; border: 0; border-radius: calc(var(--radius-container) - 5px); corner-shape: var(--corner-shape); padding: 0 12px; background: transparent; color: var(--foreground); font: inherit; font-size: var(--text-sm); font-variant-numeric: tabular-nums; text-align: left; cursor: pointer; transition: background-color 80ms var(--ease-standard); }
20
+ .option { display: flex; width: 100%; min-height: 36px; align-items: center; justify-content: space-between; border: 0; border-radius: calc(var(--radius-container) - var(--space-tight)); corner-shape: var(--corner-shape); padding: 0 var(--space-group); background: transparent; color: var(--foreground); font: inherit; font-size: var(--text-sm); font-variant-numeric: tabular-nums; text-align: left; cursor: pointer; transition: background-color 80ms var(--ease-standard); }
21
21
  .option[data-active="true"] { background: var(--surface-muted); }
22
22
  .dot { width: 6px; height: 6px; border-radius: var(--radius-full); corner-shape: round; background: var(--foreground); }
23
23
  @media (prefers-reduced-motion: reduce) { .trigger, .chevron, .option { transition: none; } }
@@ -28,14 +28,14 @@
28
28
  .marker[data-tone="danger"] { background: color-mix(in oklab, var(--danger) 12%, var(--surface)); color: var(--danger); }
29
29
  .marker svg { width: 14px; height: 14px; stroke-width: 2; }
30
30
  /* The line runs from just under this marker to just above the next one and draws downward from its top. */
31
- .segment { position: absolute; top: calc(var(--marker-top) + var(--marker) + var(--line-gap)); bottom: calc(var(--line-gap) - var(--marker-top)); left: calc(var(--marker) / 2 - .5px); width: 1px; background: var(--border-strong); transform-origin: 50% 0; }
31
+ .segment { position: absolute; top: calc(var(--marker-top) + var(--marker) + var(--line-gap)); bottom: calc(var(--line-gap) - var(--marker-top)); left: calc(var(--marker) / 2 - var(--space-hair)); width: 1px; background: var(--border-strong); transform-origin: 50% 0; }
32
32
 
33
33
  .content { min-width: 0; }
34
- .trigger { display: grid; width: 100%; grid-template-columns: minmax(0, 1fr) auto; align-items: start; column-gap: var(--space-group); margin: 0; padding: 12px var(--space-group); border: 0; border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: transparent; color: inherit; font: inherit; text-align: left; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard); }
34
+ .trigger { display: grid; width: 100%; grid-template-columns: minmax(0, 1fr) auto; align-items: start; column-gap: var(--space-group); margin: 0; padding: var(--space-group) var(--space-group); border: 0; border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: transparent; color: inherit; font: inherit; text-align: left; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard); }
35
35
  button.trigger { grid-template-columns: minmax(0, 1fr) auto 16px; cursor: pointer; }
36
36
  @media (hover: hover) and (pointer: fine) { button.trigger:hover { background: var(--surface-muted); } }
37
37
  button.trigger:active { background: var(--surface-muted); }
38
- .text { display: grid; min-width: 0; gap: 2px; }
38
+ .text { display: grid; min-width: 0; gap: var(--space-hair); }
39
39
  .title { color: var(--text-secondary); font-size: var(--text-sm); line-height: 20px; }
40
40
  .actor { color: var(--foreground); font-weight: 500; }
41
41
  .meta { color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); }
@@ -3,8 +3,8 @@
3
3
  width: min(100%, 26rem);
4
4
  min-width: 0;
5
5
  align-items: flex-start;
6
- gap: 0.75rem;
7
- padding: 0.875rem 0.875rem 0.875rem 1rem;
6
+ gap: var(--space-group);
7
+ padding: var(--space-inset) var(--space-inset) var(--space-inset) var(--space-inset);
8
8
  border: 1px solid var(--border);
9
9
  border-radius: var(--radius-container); corner-shape: var(--corner-shape);
10
10
  background: color-mix(in oklab, var(--surface) 94%, var(--background));
@@ -35,9 +35,9 @@
35
35
  position: relative;
36
36
  display: grid;
37
37
  min-width: 0;
38
- gap: 0.125rem;
38
+ gap: var(--space-hair);
39
39
  /* Centers the title's first line on the 30px status icon. */
40
- padding-top: 0.3125rem;
40
+ padding-top: var(--space-tight);
41
41
  }
42
42
 
43
43
  .title {
@@ -69,7 +69,7 @@
69
69
  height: 2rem;
70
70
  flex: 0 0 auto;
71
71
  place-items: center;
72
- margin: -0.0625rem -0.125rem 0 0;
72
+ margin: calc(var(--space-hair) * -1) calc(var(--space-hair) * -1) 0 0;
73
73
  border: 0;
74
74
  border-radius: var(--radius-full); corner-shape: round;
75
75
  background: transparent;
@@ -1,5 +1,5 @@
1
1
  /* The region only holds the list; it never blocks clicks outside the toasts themselves. */
2
- .viewport { position: fixed; z-index: 60; bottom: var(--space-section); width: min(22.5rem, calc(100% - var(--space-block))); pointer-events: none; }
2
+ .viewport { position: fixed; z-index: var(--layer-toast); bottom: var(--space-section); width: min(22.5rem, calc(100% - var(--space-block))); pointer-events: none; }
3
3
  .bottom-right { right: var(--space-section); }
4
4
  .bottom-left { left: var(--space-section); }
5
5
  .bottom-center { right: 0; left: 0; margin-inline: auto; }
@@ -32,14 +32,14 @@
32
32
  .copy { position: relative; min-width: 0; flex: 1; font-size: var(--text-sm); letter-spacing: var(--tracking-body); line-height: 20px; }
33
33
  .title { position: relative; display: block; font-weight: 500; }
34
34
  .line { display: block; }
35
- .description { display: block; margin-top: 2px; color: var(--text-secondary); }
35
+ .description { display: block; margin-top: var(--space-hair); color: var(--text-secondary); }
36
36
 
37
37
  /* Clips only while its width folds, so the focus ring stays whole at rest. */
38
- .actionSlot { display: flex; flex: none; justify-content: flex-end; margin-top: -4px; }
38
+ .actionSlot { display: flex; flex: none; justify-content: flex-end; margin-top: calc(var(--space-tight) * -1); }
39
39
  .actionSlot[data-moving="true"] { overflow: hidden; }
40
40
  .action, .close { flex: none; border: 1px solid transparent; font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: scale var(--duration-spring) var(--ease-spring), background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
41
41
  .action { height: 28px; padding: 0 var(--space-group); border-color: var(--border); border-radius: var(--radius-full); corner-shape: round; background: var(--surface); color: var(--foreground); font-size: var(--text-sm); font-weight: 500; white-space: nowrap; }
42
- .close { display: grid; width: 28px; height: 28px; margin: -4px -2px 0 0; place-items: center; border-radius: var(--radius-full); corner-shape: round; background: transparent; color: var(--text-muted); }
42
+ .close { display: grid; width: 28px; height: 28px; margin: calc(var(--space-tight) * -1) calc(var(--space-hair) * -1) 0 0; place-items: center; border-radius: var(--radius-full); corner-shape: round; background: transparent; color: var(--text-muted); }
43
43
  @media (hover: hover) and (pointer: fine) {
44
44
  .action:hover { border-color: var(--border-strong); background: var(--surface-muted); }
45
45
  .close:hover { background: var(--surface-muted); color: var(--foreground); }
@@ -49,7 +49,7 @@
49
49
  /* A narrow toast keeps its copy wide: the action drops under the copy instead of squeezing it. */
50
50
  @container (max-width: 21rem) {
51
51
  .content { flex-wrap: wrap; row-gap: var(--space-related); }
52
- .actionSlot { order: 1; flex-basis: 100%; justify-content: flex-start; margin-top: 0; padding-left: calc(18px + var(--space-group)); }
52
+ .actionSlot { order: 1; flex-basis: 100%; justify-content: flex-start; margin-top: 0; padding-left: calc(var(--space-comfort) + var(--space-group)); }
53
53
  }
54
54
  .srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
55
55
 
@@ -1,4 +1,4 @@
1
- .tooltip { --tooltip-y: 3px; z-index: 90; max-width: 15rem; padding: var(--space-group) var(--space-inset); border: 1px solid color-mix(in oklab, var(--background) 14%, var(--foreground)); border-radius: var(--radius-control); background: var(--foreground); color: var(--background); box-shadow: var(--shadow-raised); font-size: var(--text-sm); font-weight: 400; line-height: var(--leading-body); transform-origin: var(--radix-tooltip-content-transform-origin); transition: opacity var(--duration-fast) var(--ease-enter), transform var(--duration-fast) var(--ease-enter); }
1
+ .tooltip { --tooltip-y: 3px; z-index: var(--layer-tooltip); max-width: 15rem; padding: var(--space-group) var(--space-inset); border: 1px solid color-mix(in oklab, var(--background) 14%, var(--foreground)); border-radius: var(--radius-control); background: var(--foreground); color: var(--background); box-shadow: var(--shadow-raised); font-size: var(--text-sm); font-weight: 400; line-height: var(--leading-body); transform-origin: var(--radix-tooltip-content-transform-origin); transition: opacity var(--duration-fast) var(--ease-enter), transform var(--duration-fast) var(--ease-enter); }
2
2
  .tooltip[data-side="bottom"] { --tooltip-y: -3px; }
3
3
  /* The first tooltip waits, then rises a few pixels from its trigger. Within the skip window the next one only fades.
4
4
  Transitions instead of keyframes, so returning to the trigger while it fades out reverses the fade instead of restarting it. */
@@ -1,21 +1,21 @@
1
- .tree { display: block; width: 100%; min-width: 0; box-sizing: border-box; padding: 6px 8px 8px; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface); color: var(--foreground); overflow: hidden; }
1
+ .tree { display: block; width: 100%; min-width: 0; box-sizing: border-box; padding: var(--space-related) var(--space-related) var(--space-related); border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface); color: var(--foreground); overflow: hidden; }
2
2
  /* Rows clip only while their height animates (Motion sets overflow), so the selection can glide between them unclipped. */
3
3
  .row { position: relative; display: flow-root; min-width: 0; height: 38px; }
4
- .item { position: relative; display: flex; width: 100%; min-width: 0; height: 36px; margin-top: 2px; align-items: center; gap: 8px; padding: 0 10px; padding-left: calc(10px + (var(--tree-depth) - 1) * 18px); border: 0; border-radius: var(--radius-detail); background: transparent; color: var(--text-secondary); font: inherit; font-size: var(--text-sm); line-height: 1; text-align: left; cursor: pointer; outline: none; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
4
+ .item { position: relative; display: flex; width: 100%; min-width: 0; height: 36px; margin-top: var(--space-hair); align-items: center; gap: var(--space-related); padding: 0 var(--space-group); padding-left: calc(var(--space-group) + (var(--tree-depth) - 1) * var(--space-comfort)); border: 0; border-radius: var(--radius-detail); background: transparent; color: var(--text-secondary); font: inherit; font-size: var(--text-sm); line-height: 1; text-align: left; cursor: pointer; outline: none; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
5
5
  /* Selection changes color only; a heavier weight would reflow the label. */
6
6
  .item[aria-selected="true"] { color: var(--foreground); }
7
7
  .selection { position: absolute; inset: 0; z-index: 0; border-radius: var(--radius-detail); background: var(--surface-muted); }
8
- .branch { position: absolute; top: 4px; bottom: 4px; left: calc(16.5px + (var(--tree-depth) - 2) * 18px); z-index: 1; width: 1px; background: var(--border); transform-origin: top; pointer-events: none; }
8
+ .branch { position: absolute; top: var(--space-tight); bottom: var(--space-tight); left: calc(var(--space-inset) + (var(--tree-depth) - 2) * var(--space-comfort)); z-index: 1; width: 1px; background: var(--border); transform-origin: top; pointer-events: none; }
9
9
  .disclosure, .icon, .label { position: relative; z-index: 1; }
10
10
  .disclosure { display: grid; width: 14px; height: 16px; flex: 0 0 14px; place-items: center; color: var(--text-muted); }
11
11
  .icon { display: grid; width: 16px; height: 16px; flex: 0 0 16px; place-items: center; color: var(--text-muted); transition: color var(--duration-fast) var(--ease-standard); }
12
12
  .folder { color: var(--text-secondary); }
13
13
  .item[aria-expanded="true"] .folder, .item[aria-selected="true"] .folder { color: var(--foreground); }
14
14
  .folderGlyph { position: absolute; inset: 0; display: grid; place-items: center; }
15
- .typescript { color: color-mix(in oklab, #3178c6 78%, var(--foreground)); }
16
- .stylesheet { color: color-mix(in oklab, #8b6ace 73%, var(--foreground)); }
17
- .markdown { color: color-mix(in oklab, #38896b 74%, var(--foreground)); }
18
- .json { color: color-mix(in oklab, #c48637 78%, var(--foreground)); }
15
+ .typescript { color: color-mix(in oklab, var(--file-typescript) 78%, var(--foreground)); }
16
+ .stylesheet { color: color-mix(in oklab, var(--file-stylesheet) 73%, var(--foreground)); }
17
+ .markdown { color: color-mix(in oklab, var(--file-markdown) 74%, var(--foreground)); }
18
+ .json { color: color-mix(in oklab, var(--file-json) 78%, var(--foreground)); }
19
19
  /* Its own line height: the row sets 1, and the clipped box (needed for the ellipsis) would cut descenders like g. */
20
20
  .label { min-width: 0; overflow: hidden; line-height: 1.45; text-overflow: ellipsis; white-space: nowrap; }
21
21
  @media (hover: hover) and (pointer: fine) { .item:hover { background: var(--surface-muted); color: var(--foreground); } }