@trading-game/design-intelligence-layer 0.17.4 → 1.0.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 (77) hide show
  1. package/AGENTS.md +104 -231
  2. package/README.md +46 -746
  3. package/dist/index.cjs +2753 -2986
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +247 -261
  6. package/dist/index.d.ts +247 -261
  7. package/dist/index.js +2648 -2856
  8. package/dist/index.js.map +1 -1
  9. package/docs/components/accordion.md +85 -0
  10. package/docs/components/alert-dialog.md +98 -0
  11. package/docs/components/aspect-ratio.md +55 -0
  12. package/docs/components/avatar.md +88 -0
  13. package/docs/components/badge.md +75 -0
  14. package/docs/components/banner.md +84 -0
  15. package/docs/components/bottom-navigation.md +90 -0
  16. package/docs/components/breadcrumb.md +85 -0
  17. package/docs/components/button.md +94 -0
  18. package/docs/components/calendar.md +74 -0
  19. package/docs/components/card.md +79 -0
  20. package/docs/components/carousel.md +82 -0
  21. package/docs/components/checkbox.md +66 -0
  22. package/docs/components/chip.md +72 -0
  23. package/docs/components/command.md +86 -0
  24. package/docs/components/context-menu.md +90 -0
  25. package/docs/components/dialog.md +95 -0
  26. package/docs/components/drawer.md +97 -0
  27. package/docs/components/dropdown-menu.md +92 -0
  28. package/docs/components/empty.md +87 -0
  29. package/docs/components/field.md +117 -0
  30. package/docs/components/hover-card.md +77 -0
  31. package/docs/components/input-group.md +105 -0
  32. package/docs/components/input-otp.md +87 -0
  33. package/docs/components/input.md +71 -0
  34. package/docs/components/item.md +105 -0
  35. package/docs/components/label.md +56 -0
  36. package/docs/components/link.md +66 -0
  37. package/docs/components/menubar.md +102 -0
  38. package/docs/components/native-select.md +71 -0
  39. package/docs/components/navigation-button.md +68 -0
  40. package/docs/components/navigation-menu.md +99 -0
  41. package/docs/components/numpad.md +78 -0
  42. package/docs/components/pagination.md +84 -0
  43. package/docs/components/popover.md +89 -0
  44. package/docs/components/profile-photo.md +81 -0
  45. package/docs/components/progress.md +60 -0
  46. package/docs/components/radio-group.md +82 -0
  47. package/docs/components/resizable.md +79 -0
  48. package/docs/components/scroll-area.md +66 -0
  49. package/docs/components/section-message.md +99 -0
  50. package/docs/components/select.md +105 -0
  51. package/docs/components/separator.md +55 -0
  52. package/docs/components/sheet.md +91 -0
  53. package/docs/components/sidebar.md +125 -0
  54. package/docs/components/skeleton.md +51 -0
  55. package/docs/components/slider.md +61 -0
  56. package/docs/components/spinner.md +52 -0
  57. package/docs/components/stepper.md +68 -0
  58. package/docs/components/switch.md +57 -0
  59. package/docs/components/table.md +86 -0
  60. package/docs/components/tabs.md +95 -0
  61. package/docs/components/textarea.md +58 -0
  62. package/docs/components/toast.md +66 -0
  63. package/docs/components/toggle-group.md +77 -0
  64. package/docs/components/toggle.md +60 -0
  65. package/docs/components/tooltip.md +83 -0
  66. package/docs/foundations/colors.md +109 -0
  67. package/docs/foundations/motion.md +63 -0
  68. package/docs/foundations/shape-layout.md +56 -0
  69. package/docs/foundations/typography.md +83 -0
  70. package/docs/patterns/forms.md +70 -0
  71. package/docs/patterns/menus.md +50 -0
  72. package/docs/patterns/on-brand.md +43 -0
  73. package/guides/audits/design-system-audit-2026-07.md +135 -0
  74. package/guides/rules/design-system-consuming-project.mdc +56 -0
  75. package/package.json +5 -6
  76. package/src/styles.css +1616 -251
  77. package/guides/design-system-guide/trading-game-ds-guide.md +0 -933
package/src/styles.css CHANGED
@@ -10,11 +10,79 @@
10
10
  */
11
11
 
12
12
  /* Fonts — Plus Jakarta Sans (all) */
13
- @import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap");
13
+ @import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap");
14
+
15
+ /* Overlay enter/exit animation utilities (animate-in/out, fade, zoom, slide)
16
+ — part of the styles contract; without it consumer dialogs/menus teleport. */
17
+ @import "tw-animate-css";
14
18
 
15
19
 
16
20
  /* ── Tailwind theme bridge — maps CSS vars to utility classes ── */
17
21
  @theme inline {
22
+ /* ── New semantic layer (Quill grammar) ── */
23
+ --color-background-primary-canvas: var(--background-primary-canvas);
24
+ --color-background-primary-surface: var(--background-primary-surface);
25
+ --color-background-secondary-surface: var(--background-secondary-surface);
26
+ --color-background-hover-default: var(--background-hover-default);
27
+ --color-background-pressed-default: var(--background-pressed-default);
28
+ --color-background-brand-default: var(--background-brand-default);
29
+ --color-background-brand-hover: var(--background-brand-hover);
30
+ --color-background-brand-pressed: var(--background-brand-pressed);
31
+ /* background-brand-container is a layered value (gradient + base) — consume
32
+ it with `background: var(--background-brand-container)`, not a bg-* utility. */
33
+ --color-background-inverse-surface: var(--background-inverse-surface);
34
+ --color-background-overlay-default: var(--background-overlay-default);
35
+ --color-background-static-white: var(--background-static-white);
36
+ --color-text-static-black: var(--text-static-black);
37
+ --color-background-demo-solid: var(--background-demo-solid);
38
+ --color-background-demo-default: var(--background-demo-default);
39
+ --color-text-demo-default: var(--text-demo-default);
40
+ --color-background-success-solid: var(--background-success-solid);
41
+ --color-background-error-solid: var(--background-error-solid);
42
+ --color-background-warning-solid: var(--background-warning-solid);
43
+ --color-text-on-status-static: var(--text-on-status-static);
44
+ --color-text-brand-default: var(--text-brand-default);
45
+ --color-text-brand-hover: var(--text-brand-hover);
46
+ --color-background-brand-selected: var(--background-brand-selected);
47
+ --color-text-brand-selected: var(--text-brand-selected);
48
+ --color-border-brand-selected: var(--border-brand-selected);
49
+ --color-background-success-default: var(--background-success-default);
50
+ --color-background-error-default: var(--background-error-default);
51
+ --color-background-warning-default: var(--background-warning-default);
52
+ --color-background-information-default: var(--background-information-default);
53
+ --color-border-default-default: var(--border-default-default);
54
+ --color-border-prominent-default: var(--border-prominent-default);
55
+ --color-border-neutral-default: var(--border-neutral-default);
56
+ --color-border-success-default: var(--border-success-default);
57
+ --color-border-error-default: var(--border-error-default);
58
+ --color-border-warning-default: var(--border-warning-default);
59
+ --color-border-information-default: var(--border-information-default);
60
+ --color-text-prominent-default: var(--text-prominent-default);
61
+ --color-text-subtle-default: var(--text-subtle-default);
62
+ --color-text-disabled-default: var(--text-disabled-default);
63
+ --color-text-prominent-inverse: var(--text-prominent-inverse);
64
+ --color-text-subtle-inverse: var(--text-subtle-inverse);
65
+ --color-text-on-brand-static: var(--text-on-brand-static);
66
+ --color-text-brand-container-static: var(--text-brand-container-static);
67
+ --color-text-success-default: var(--text-success-default);
68
+ --color-text-error-default: var(--text-error-default);
69
+ --color-text-warning-default: var(--text-warning-default);
70
+ --color-text-information-default: var(--text-information-default);
71
+ --color-icon-prominent-default: var(--icon-prominent-default);
72
+ --color-icon-subtle-default: var(--icon-subtle-default);
73
+ --color-icon-disabled-default: var(--icon-disabled-default);
74
+ --color-icon-success-default: var(--icon-success-default);
75
+ --color-icon-error-default: var(--icon-error-default);
76
+ --color-icon-warning-default: var(--icon-warning-default);
77
+ --color-icon-information-default: var(--icon-information-default);
78
+ --color-ring-focus-default: var(--ring-focus-default);
79
+ --color-ring-focus-strong: var(--ring-focus-strong);
80
+ --color-ring-focus-soft: var(--ring-focus-soft);
81
+ --color-ring-error-default: var(--ring-error-default);
82
+ --color-ring-error-soft: var(--ring-error-soft);
83
+ --color-ring-brand-soft: var(--ring-brand-soft);
84
+ --color-background-secondary-wash: var(--background-secondary-wash);
85
+ --color-background-static-white-wash: var(--background-static-white-wash);
18
86
  --color-prominent: var(--prominent);
19
87
  --color-on-prominent: var(--on-prominent);
20
88
  --color-on-prominent-static-inverse: var(--on-prominent-static-inverse);
@@ -87,11 +155,12 @@
87
155
  --radius-2xl: calc(var(--radius) + 8px);
88
156
  --radius-3xl: calc(var(--radius) + 12px);
89
157
  --radius-4xl: calc(var(--radius) + 16px);
90
- /* ── Transitions — duration ── */
158
+ /* ── Transitions — duration (fast/base/slow resolve through the
159
+ semantic motion roles; instant/open/blink stay primitive) ── */
91
160
  --duration-instant: var(--primitive-duration-instant);
92
- --duration-fast: var(--primitive-duration-fast);
93
- --duration-base: var(--primitive-duration-base);
94
- --duration-slow: var(--primitive-duration-slow);
161
+ --duration-fast: var(--motion-hover);
162
+ --duration-base: var(--motion-surface);
163
+ --duration-slow: var(--motion-progress);
95
164
  --duration-open: var(--primitive-duration-open);
96
165
  --duration-blink: var(--primitive-duration-blink);
97
166
  /* ── Transitions — easing ── */
@@ -99,6 +168,11 @@
99
168
  --ease-enter: var(--primitive-ease-enter);
100
169
  --ease-exit: var(--primitive-ease-exit);
101
170
  --ease-linear: var(--primitive-ease-linear);
171
+ --ease-spring: var(--primitive-ease-spring);
172
+ --ease-overshoot: var(--primitive-ease-overshoot);
173
+ /* ── Named animations ── */
174
+ --animate-button-shimmer: button-shimmer 4s linear infinite;
175
+ --animate-skeleton-sweep: skeleton-sweep 1.6s var(--primitive-ease-standard) infinite;
102
176
  }
103
177
 
104
178
  /* ══════════════════════════════════════════════════════════════
@@ -109,117 +183,175 @@
109
183
  --font-plus-jakarta-sans: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif;
110
184
  --radius: 0.625rem;
111
185
 
112
- /* ── Blue scale ── */
113
- --primitive-blue-50: oklch(0.93 0.05 267);
114
- /* #E6E6FF */
115
- --primitive-blue-100: oklch(0.77 0.14 267);
116
- /* #B8B8FF */
117
- --primitive-blue-200: oklch(0.66 0.21 267);
118
- /* #8A8AFF */
119
- --primitive-blue-300: oklch(0.57 0.26 267);
120
- /* #5C5CFF */
121
- --primitive-blue-400: oklch(0.51 0.285 267);
122
- /* #3939FF */
123
- --primitive-blue-500: oklch(0.476 0.297 267.4);
124
- /* #2323FF — brand blue */
125
- --primitive-blue-600: oklch(0.40 0.27 265);
126
- /* #0B0BD2 */
127
- --primitive-blue-700: oklch(0.31 0.21 264);
128
- /* #0000A5 */
129
- --primitive-blue-800: oklch(0.23 0.16 264);
130
- /* #000078 */
131
- --primitive-blue-900: oklch(0.15 0.10 264);
132
- /* #00004C */
133
- --primitive-blue-1000: oklch(0.07 0.05 264);
134
- /* #00001F */
135
-
136
- /* ── Monochrome scale ── */
137
- --primitive-mono-50: oklch(1 0 0);
138
- /* #FFFFFF */
139
- --primitive-mono-100: oklch(0.95 0 0);
140
- /* #EEEEEE */
141
- --primitive-mono-200: oklch(0.90 0 0);
142
- /* #EEEEEE */
143
- --primitive-mono-300: oklch(0.84 0 0);
144
- /* #CCCCCC */
145
- --primitive-mono-400: oklch(0.79 0 0);
146
- /* #BBBBBB */
147
- --primitive-mono-500: oklch(0.74 0 0);
148
- /* #AAAAAA */
149
- --primitive-mono-600: oklch(0.63 0 0);
150
- /* #888888 */
151
- --primitive-mono-700: oklch(0.51 0 0);
152
- /* #666666 */
153
- --primitive-mono-800: oklch(0.39 0 0);
154
- /* #444444 */
155
- --primitive-mono-900: oklch(0.25 0 0);
156
- /* #222222 */
157
- --primitive-mono-1000: oklch(0 0 0);
158
- /* #000000 */
159
-
160
- /* ── Green ── */
161
- --primitive-green-400: oklch(0.492 0.162 144);
162
- /* #008832 */
163
-
164
- /* ── Sky ── */
165
- --primitive-sky-600: oklch(0.6 0.18 245);
166
- /* #3DAAFF */
167
-
168
- /* ── Red ── */
169
- --primitive-red-600: #F92E26;
170
- /* #F92E26 */
171
- --primitive-red-500: oklch(0.653 0.234 18.5);
172
- /* #FF3355 */
173
-
174
- /* ── Orange ── */
175
- --primitive-orange-600: oklch(0.52 0.168 38);
176
- /* #D45200 */
177
- --primitive-orange-500: oklch(0.62 0.185 38);
178
- /* #FF6600 */
179
- --primitive-orange-400: oklch(0.751 0.179 58.3);
180
- /* #FF8C00 */
181
-
182
- /* ── Amber ── */
183
- --primitive-amber-300: #FDCA8A;
184
- /* #FDCA8A — credit/boost badge surface (peach, contrast on grey card) */
185
- --primitive-amber-600: #F9840F;
186
- /* #F9840F — warm orange-amber; boost badge background base */
187
- --primitive-amber-900: oklch(0.30 0.10 52);
188
- /* #521900 — deep amber/brown; credit/boost badge label text */
189
-
190
- /* ── Yellow ── */
191
- --primitive-yellow-500: oklch(0.65 0.16 82);
192
- /* #E0AE00 — golden warning yellow; clearly distinct from orange/red */
193
-
194
- /* ── Violet ── */
195
- --primitive-violet-500: oklch(0.601 0.263 301.6);
196
- /* #A040FF */
197
-
198
- /* ── Mono alpha scale ── */
199
- --primitive-mono-alpha-4: oklch(0 0 0 / 4%);
200
- --primitive-mono-alpha-8: oklch(0 0 0 / 8%);
201
- --primitive-mono-alpha-16: oklch(0 0 0 / 16%);
202
- --primitive-mono-alpha-24: oklch(0 0 0 / 24%);
203
- --primitive-mono-alpha-32: oklch(0 0 0 / 32%);
204
- --primitive-mono-alpha-40: oklch(0 0 0 / 40%);
205
- --primitive-mono-alpha-50: oklch(0 0 0 / 50%);
206
- --primitive-mono-alpha-64: oklch(0 0 0 / 64%);
207
- --primitive-mono-alpha-80: oklch(0 0 0 / 80%);
208
-
209
- /* ── Blue alpha scale ── */
210
- --primitive-blue-alpha-4: oklch(0.476 0.297 267.4 / 4%);
211
- --primitive-blue-alpha-8: oklch(0.476 0.297 267.4 / 8%);
212
- --primitive-blue-alpha-16: oklch(0.476 0.297 267.4 / 16%);
213
- --primitive-blue-alpha-24: oklch(0.476 0.297 267.4 / 24%);
214
- --primitive-blue-alpha-32: oklch(0.476 0.297 267.4 / 32%);
215
- --primitive-blue-alpha-40: oklch(0.476 0.297 267.4 / 40%);
216
- --primitive-blue-alpha-50: oklch(0.476 0.297 267.4 / 50%);
217
- --primitive-blue-alpha-64: oklch(0.476 0.297 267.4 / 64%);
218
- --primitive-blue-alpha-80: oklch(0.476 0.297 267.4 / 80%);
219
-
220
- /* ── Overlay ── */
221
- --primitive-black-50: var(--primitive-mono-alpha-50);
222
- /* @deprecated — use --primitive-mono-alpha-50 */
186
+ /* ── Blue scale ── */ /* brand #2323FF at 600 · 25 = light canvas · 1000 = dark canvas */
187
+ --primitive-blue-25: #F7F8FC;
188
+ --primitive-blue-50: #E6F3FF;
189
+ --primitive-blue-100: #BFD8FF;
190
+ --primitive-blue-200: #99B7FF;
191
+ --primitive-blue-300: #7392FF;
192
+ --primitive-blue-400: #4D6BFF;
193
+ --primitive-blue-500: #3445FF;
194
+ --primitive-blue-600: #2323FF;
195
+ --primitive-blue-700: #0606C7;
196
+ --primitive-blue-800: #00008F;
197
+ --primitive-blue-900: #000057;
198
+ --primitive-blue-1000: #00001F;
199
+
200
+ /* ── Mono scale ── */
201
+ --primitive-mono-50: #FFFFFF;
202
+ --primitive-mono-100: #F1F1F1;
203
+ --primitive-mono-200: #E3E3E3;
204
+ --primitive-mono-300: #D5D5D5;
205
+ --primitive-mono-400: #C6C6C6;
206
+ --primitive-mono-500: #B8B8B8;
207
+ --primitive-mono-600: #AAAAAA;
208
+ --primitive-mono-700: #8E8E8E;
209
+ --primitive-mono-800: #717171;
210
+ --primitive-mono-900: #555555;
211
+ --primitive-mono-1000: #393939;
212
+ --primitive-mono-1100: #1C1C1C;
213
+ --primitive-mono-1200: #000000;
214
+
215
+ /* ── Green scale ── */ /* status base at 600 */
216
+ --primitive-green-50: #E6FFEA;
217
+ --primitive-green-100: #BFFFCC;
218
+ --primitive-green-200: #99FEAF;
219
+ --primitive-green-300: #73F593;
220
+ --primitive-green-400: #4DE778;
221
+ --primitive-green-500: #26D45E;
222
+ --primitive-green-600: #00BD46;
223
+ --primitive-green-700: #00A632;
224
+ --primitive-green-800: #008420;
225
+ --primitive-green-900: #005712;
226
+ --primitive-green-1000: #001F06;
227
+
228
+ /* ── Red scale ── */ /* status base at 600 */
229
+ --primitive-red-50: #FFE6E6;
230
+ --primitive-red-100: #FFBFBF;
231
+ --primitive-red-200: #FF9999;
232
+ --primitive-red-300: #FF7373;
233
+ --primitive-red-400: #FF514D;
234
+ --primitive-red-500: #FF3A36;
235
+ --primitive-red-600: #FE2925;
236
+ --primitive-red-700: #C70C08;
237
+ --primitive-red-800: #8F0000;
238
+ --primitive-red-900: #570000;
239
+ --primitive-red-1000: #1F0000;
240
+
241
+ /* ── Amber scale ── */ /* status base at 600 */
242
+ --primitive-amber-50: #FFF8E0;
243
+ --primitive-amber-100: #FFEDBB;
244
+ --primitive-amber-200: #FFE196;
245
+ --primitive-amber-300: #FFD370;
246
+ --primitive-amber-400: #FFC34B;
247
+ --primitive-amber-500: #FFB125;
248
+ --primitive-amber-600: #F49E00;
249
+ --primitive-amber-700: #C78200;
250
+ --primitive-amber-800: #8F6300;
251
+ --primitive-amber-900: #573F00;
252
+ --primitive-amber-1000: #1F1700;
253
+
254
+ /* ── Azure scale ── */ /* game accent + information base at 600 · sky ≈ 500 */
255
+ --primitive-azure-50: #D9F0FF;
256
+ --primitive-azure-100: #B5E1FF;
257
+ --primitive-azure-200: #91D2FF;
258
+ --primitive-azure-300: #6CC2FF;
259
+ --primitive-azure-400: #51B2FF;
260
+ --primitive-azure-500: #3BA1F1;
261
+ --primitive-azure-600: #2A90E0;
262
+ --primitive-azure-700: #0F73C1;
263
+ --primitive-azure-800: #00548F;
264
+ --primitive-azure-900: #003457;
265
+ --primitive-azure-1000: #00131F;
266
+
267
+ /* ── Ember scale ── */ /* game accent · base at 500 */
268
+ --primitive-ember-50: #FDEFE8;
269
+ --primitive-ember-100: #F9D1BF;
270
+ --primitive-ember-200: #F4B496;
271
+ --primitive-ember-300: #F0976D;
272
+ --primitive-ember-400: #EC7943;
273
+ --primitive-ember-500: #E85C1A;
274
+ --primitive-ember-600: #C14B13;
275
+ --primitive-ember-700: #983B0F;
276
+ --primitive-ember-800: #6F2B0B;
277
+ --primitive-ember-900: #461B07;
278
+ --primitive-ember-1000: #1C0B03;
279
+
280
+ /* ── Violet scale ── */ /* game accent · base at 500 · lilac ≈ 200 */
281
+ --primitive-violet-50: #F3E8FD;
282
+ --primitive-violet-100: #E1C5FB;
283
+ --primitive-violet-200: #CFA3F8;
284
+ --primitive-violet-300: #BE81F5;
285
+ --primitive-violet-400: #AC5EF3;
286
+ --primitive-violet-500: #9A3CF0;
287
+ --primitive-violet-600: #8012E5;
288
+ --primitive-violet-700: #640EB3;
289
+ --primitive-violet-800: #480A81;
290
+ --primitive-violet-900: #2C064F;
291
+ --primitive-violet-1000: #10021D;
292
+
293
+ /* ── Jade scale ── */ /* game accent · base at 500 */
294
+ --primitive-jade-50: #E7FEF4;
295
+ --primitive-jade-100: #ACFAD9;
296
+ --primitive-jade-200: #71F6BD;
297
+ --primitive-jade-300: #36F2A2;
298
+ --primitive-jade-400: #0EDB84;
299
+ --primitive-jade-500: #0AA060;
300
+ --primitive-jade-600: #088650;
301
+ --primitive-jade-700: #076C41;
302
+ --primitive-jade-800: #055231;
303
+ --primitive-jade-900: #033721;
304
+ --primitive-jade-1000: #021D12;
305
+
306
+ /* ── White alpha — lifts and glazes on dark surfaces ── */
307
+ --primitive-white-alpha-4: rgb(255 255 255 / 4%);
308
+ --primitive-white-alpha-6: rgb(255 255 255 / 6%);
309
+ --primitive-white-alpha-8: rgb(255 255 255 / 8%);
310
+ --primitive-white-alpha-12: rgb(255 255 255 / 12%);
311
+ --primitive-white-alpha-16: rgb(255 255 255 / 16%);
312
+ --primitive-white-alpha-20: rgb(255 255 255 / 20%);
313
+ --primitive-white-alpha-24: rgb(255 255 255 / 24%);
314
+ --primitive-white-alpha-32: rgb(255 255 255 / 32%);
315
+ --primitive-white-alpha-40: rgb(255 255 255 / 40%);
316
+ --primitive-white-alpha-50: rgb(255 255 255 / 50%);
317
+ --primitive-white-alpha-64: rgb(255 255 255 / 64%);
318
+ --primitive-white-alpha-80: rgb(255 255 255 / 80%);
319
+
320
+ /* ── Black alpha — fills, glazes, and scrims on light surfaces ── */
321
+ --primitive-black-alpha-4: rgb(0 0 0 / 4%);
322
+ --primitive-black-alpha-6: rgb(0 0 0 / 6%);
323
+ --primitive-black-alpha-8: rgb(0 0 0 / 8%);
324
+ --primitive-black-alpha-12: rgb(0 0 0 / 12%);
325
+ --primitive-black-alpha-16: rgb(0 0 0 / 16%);
326
+ --primitive-black-alpha-20: rgb(0 0 0 / 20%);
327
+ --primitive-black-alpha-24: rgb(0 0 0 / 24%);
328
+ --primitive-black-alpha-32: rgb(0 0 0 / 32%);
329
+ --primitive-black-alpha-40: rgb(0 0 0 / 40%);
330
+ --primitive-black-alpha-50: rgb(0 0 0 / 50%);
331
+ --primitive-black-alpha-64: rgb(0 0 0 / 64%);
332
+ --primitive-black-alpha-80: rgb(0 0 0 / 80%);
333
+
334
+ /* ── Blue alpha — frosted brand washes ── */
335
+ --primitive-blue-alpha-4: rgb(35 35 255 / 4%);
336
+ --primitive-blue-alpha-8: rgb(35 35 255 / 8%);
337
+ --primitive-blue-alpha-16: rgb(35 35 255 / 16%);
338
+ --primitive-blue-alpha-24: rgb(35 35 255 / 24%);
339
+ --primitive-blue-alpha-32: rgb(35 35 255 / 32%);
340
+ --primitive-blue-alpha-40: rgb(35 35 255 / 40%);
341
+ --primitive-blue-alpha-50: rgb(35 35 255 / 50%);
342
+ --primitive-blue-alpha-64: rgb(35 35 255 / 64%);
343
+ --primitive-blue-alpha-80: rgb(35 35 255 / 80%);
344
+
345
+ /* @deprecated — old mono-alpha names; use black-alpha. Deleted when the component walk completes. */
346
+ --primitive-mono-alpha-4: var(--primitive-black-alpha-4);
347
+ --primitive-mono-alpha-8: var(--primitive-black-alpha-8);
348
+ --primitive-mono-alpha-16: var(--primitive-black-alpha-16);
349
+ --primitive-mono-alpha-24: var(--primitive-black-alpha-24);
350
+ --primitive-mono-alpha-32: var(--primitive-black-alpha-32);
351
+ --primitive-mono-alpha-40: var(--primitive-black-alpha-40);
352
+ --primitive-mono-alpha-50: var(--primitive-black-alpha-50);
353
+ --primitive-mono-alpha-64: var(--primitive-black-alpha-64);
354
+ --primitive-mono-alpha-80: var(--primitive-black-alpha-80);
223
355
 
224
356
  /* ── Transitions — Duration scale ── */
225
357
  --primitive-duration-instant: 50ms;
@@ -244,6 +376,10 @@
244
376
  /* accelerates — elements leaving the screen */
245
377
  --primitive-ease-linear: linear;
246
378
  /* constant speed — sidebar width, progress bar */
379
+ --primitive-ease-spring: cubic-bezier(0.3, 1.25, 0.4, 1);
380
+ /* liquid travel — slight overshoot, settles (selection indicators) */
381
+ --primitive-ease-overshoot: cubic-bezier(0.2, 1.8, 0.4, 1);
382
+ /* pops & ticks — icon arrival, chip tick, success check */
247
383
 
248
384
  /* ── Layout — Standard responsive grid (gutter / margin) ── */
249
385
  --primitive-layout-gutter-none: 0px;
@@ -255,6 +391,58 @@
255
391
  --primitive-layout-diagram-max-default: 319px;
256
392
  --primitive-layout-diagram-max-small: 599px;
257
393
  --primitive-layout-diagram-max-medium: 1135px;
394
+
395
+ /* ── Typography — Font size scale (px) ── */
396
+ --primitive-font-size-10: 10px;
397
+ --primitive-font-size-12: 12px;
398
+ --primitive-font-size-14: 14px;
399
+ --primitive-font-size-16: 16px;
400
+ --primitive-font-size-18: 18px;
401
+ --primitive-font-size-20: 20px;
402
+ --primitive-font-size-22: 22px;
403
+ --primitive-font-size-24: 24px;
404
+ --primitive-font-size-26: 26px;
405
+ --primitive-font-size-30: 30px;
406
+ --primitive-font-size-32: 32px;
407
+ --primitive-font-size-36: 36px;
408
+ --primitive-font-size-40: 40px;
409
+ --primitive-font-size-56: 56px;
410
+
411
+ /* ── Typography — Line-height scale (px) ── */
412
+ --primitive-line-height-16: 16px;
413
+ --primitive-line-height-20: 20px;
414
+ --primitive-line-height-24: 24px;
415
+ --primitive-line-height-28: 28px;
416
+ --primitive-line-height-32: 32px;
417
+ --primitive-line-height-36: 36px;
418
+ --primitive-line-height-40: 40px;
419
+ --primitive-line-height-48: 48px;
420
+ --primitive-line-height-64: 64px;
421
+
422
+ /* ── Typography — Font weight scale ── */
423
+ --primitive-font-weight-regular: 400;
424
+ --primitive-font-weight-medium: 500;
425
+ --primitive-font-weight-semibold: 600;
426
+ --primitive-font-weight-bold: 700;
427
+ --primitive-font-weight-extrabold: 800;
428
+
429
+ /* ── Typography — Letter-spacing (tracking) scale ── */
430
+ --primitive-tracking-tightest: -0.03em;
431
+ /* display */
432
+ --primitive-tracking-tighter: -0.025em;
433
+ /* h1 */
434
+ --primitive-tracking-tight: -0.02em;
435
+ /* h2 */
436
+ --primitive-tracking-snug: -0.015em;
437
+ /* h3 */
438
+ --primitive-tracking-close: -0.01em;
439
+ /* h4 */
440
+ --primitive-tracking-normal: 0em;
441
+ /* h5, body */
442
+ --primitive-tracking-loose: 0.005em;
443
+ /* caption */
444
+ --primitive-tracking-widest: 0.12em;
445
+ /* overline */
258
446
  }
259
447
 
260
448
  /* ══════════════════════════════════════════════════════════════
@@ -262,95 +450,355 @@
262
450
  UI role and meaning. References primitives only.
263
451
  ══════════════════════════════════════════════════════════════ */
264
452
  :root {
265
- --prominent: var(--primitive-mono-50);
266
- /* #FFFFFF — light surface (page chrome, cards) */
267
- --on-prominent: var(--primitive-mono-1000);
268
- /* #000000 — text/icon color for use on prominent surfaces */
269
- --prominent-inverse: var(--primitive-mono-1000);
270
- /* #000000 — dark surface for use on light pages (e.g. toasts) */
271
- --on-prominent-inverse: var(--primitive-mono-50);
272
- /* #FFFFFF — text/icon color for use on prominent-inverse surfaces */
273
- --primary: var(--primitive-blue-500);
274
- /* #2323FF — brand primary surface */
275
- --on-primary: var(--primitive-mono-50);
276
- /* #FFFFFF — text/icon color for use on primary surfaces */
453
+ /* ── Typography — Semantic type styles ──
454
+ One block per text style. The four fluid headings (display, h1/h2/h3)
455
+ carry both a -desktop and -mobile value per property — the equivalent of a
456
+ Figma variable with a Desktop mode and a Mobile mode. The component layer
457
+ (the .display, .h1, etc. classes) clamps between the two. Fixed-size
458
+ styles (h4–h6, body-*, caption, overline) carry one value each. */
459
+ --type-display-weight: var(--primitive-font-weight-extrabold);
460
+ --type-display-tracking: var(--primitive-tracking-tightest);
461
+ --type-display-size-desktop: var(--primitive-font-size-56);
462
+ --type-display-size-mobile: var(--primitive-font-size-36);
463
+ --type-display-line-desktop: var(--primitive-line-height-64);
464
+ --type-display-line-mobile: var(--primitive-line-height-40);
465
+
466
+ --type-h1-weight: var(--primitive-font-weight-bold);
467
+ --type-h1-tracking: var(--primitive-tracking-tighter);
468
+ --type-h1-size-desktop: var(--primitive-font-size-40);
469
+ --type-h1-size-mobile: var(--primitive-font-size-30);
470
+ --type-h1-line-desktop: var(--primitive-line-height-48);
471
+ --type-h1-line-mobile: var(--primitive-line-height-36);
472
+
473
+ --type-h2-weight: var(--primitive-font-weight-bold);
474
+ --type-h2-tracking: var(--primitive-tracking-tight);
475
+ --type-h2-size-desktop: var(--primitive-font-size-32);
476
+ --type-h2-size-mobile: var(--primitive-font-size-26);
477
+ --type-h2-line-desktop: var(--primitive-line-height-40);
478
+ --type-h2-line-mobile: var(--primitive-line-height-32);
479
+
480
+ --type-h3-weight: var(--primitive-font-weight-semibold);
481
+ --type-h3-tracking: var(--primitive-tracking-snug);
482
+ --type-h3-size-desktop: var(--primitive-font-size-24);
483
+ --type-h3-size-mobile: var(--primitive-font-size-22);
484
+ --type-h3-line-desktop: var(--primitive-line-height-32);
485
+ --type-h3-line-mobile: var(--primitive-line-height-28);
486
+
487
+ --type-h4-weight: var(--primitive-font-weight-semibold);
488
+ --type-h4-tracking: var(--primitive-tracking-close);
489
+ --type-h4-size: var(--primitive-font-size-20);
490
+ --type-h4-line: var(--primitive-line-height-28);
491
+
492
+ --type-h5-weight: var(--primitive-font-weight-semibold);
493
+ --type-h5-tracking: var(--primitive-tracking-normal);
494
+ --type-h5-size: var(--primitive-font-size-18);
495
+ --type-h5-line: var(--primitive-line-height-24);
496
+
497
+ --type-h6-weight: var(--primitive-font-weight-semibold);
498
+ --type-h6-tracking: var(--primitive-tracking-normal);
499
+ --type-h6-size: var(--primitive-font-size-16);
500
+ --type-h6-line: var(--primitive-line-height-24);
501
+
502
+ --type-label-weight: var(--primitive-font-weight-medium);
503
+ --type-label-tracking: var(--primitive-tracking-normal);
504
+ --type-label-size: var(--primitive-font-size-14);
505
+ --type-label-line: var(--primitive-line-height-20);
506
+
507
+ --type-body-lg-weight: var(--primitive-font-weight-regular);
508
+ --type-body-lg-size: var(--primitive-font-size-18);
509
+ --type-body-lg-line: var(--primitive-line-height-28);
510
+
511
+ --type-body-md-weight: var(--primitive-font-weight-regular);
512
+ --type-body-md-size: var(--primitive-font-size-16);
513
+ --type-body-md-line: var(--primitive-line-height-24);
514
+
515
+ --type-body-sm-weight: var(--primitive-font-weight-regular);
516
+ --type-body-sm-size: var(--primitive-font-size-14);
517
+ --type-body-sm-line: var(--primitive-line-height-20);
518
+
519
+ --type-caption-weight: var(--primitive-font-weight-medium);
520
+ --type-caption-tracking: var(--primitive-tracking-loose);
521
+ --type-caption-size: var(--primitive-font-size-12);
522
+ --type-caption-line: var(--primitive-line-height-16);
523
+
524
+ --type-overline-weight: var(--primitive-font-weight-semibold);
525
+ --type-overline-tracking: var(--primitive-tracking-widest);
526
+ --type-overline-size: var(--primitive-font-size-12);
527
+ --type-overline-line: var(--primitive-line-height-16);
528
+
529
+ /* ── Colour — semantic tokens (Quill grammar: {element}-{role}-{variant}) ──
530
+ Light values here; the dark theme overrides live in the `.dark` block
531
+ below. Every value points at a primitive scale step, an alpha primitive,
532
+ or a color-mix() recipe over those. */
533
+
534
+ /* Background */
535
+ --background-primary-canvas: var(--primitive-blue-25);
536
+ --background-primary-surface: var(--primitive-mono-50);
537
+ --background-secondary-surface: var(--primitive-mono-100);
538
+ --background-hover-default: var(--primitive-black-alpha-4);
539
+ --background-pressed-default: var(--primitive-black-alpha-8);
540
+ --background-brand-default: var(--primitive-blue-600);
541
+ --background-brand-hover: color-mix(in srgb, black 16%, var(--background-brand-default));
542
+ --background-brand-pressed: color-mix(in srgb, black 32%, var(--background-brand-default));
543
+ --background-secondary-wash: color-mix(in srgb, var(--background-secondary-surface) 80%, transparent);
544
+ /* pressed wash on outline chips */
545
+ --background-static-white-wash: var(--primitive-white-alpha-80);
546
+ /* hover on the white on-brand button fills */
547
+ --background-brand-container:
548
+ linear-gradient(rgb(255 255 255 / 92%), rgb(255 255 255 / 92%)),
549
+ var(--primitive-blue-600);
550
+ /* Two layers, not a flattened colour: brand base + white 92% glaze on top,
551
+ exactly like a Figma fill stack. Static — same in both themes. Layered
552
+ values paint via `background`, not `background-color`. */
553
+ --background-inverse-surface: var(--primitive-mono-1100);
554
+
555
+ /* Status backgrounds — pale tint surfaces for Alert / Section Message */
556
+ /* Solid status fills + their shared static ink (badges, chips) */
557
+ /* Demo badge role — rides the ember scale, static in both themes */
558
+ /* Static pair — never flips; for elements on fixed-colour art panels */
559
+ --background-static-white: var(--primitive-mono-50);
560
+ --text-static-black: var(--primitive-mono-1100);
561
+ --background-demo-solid: var(--primitive-ember-500);
562
+ --background-demo-default: var(--primitive-ember-50);
563
+ --text-demo-default: var(--primitive-ember-500);
564
+ --background-success-solid: var(--primitive-green-600);
565
+ --background-error-solid: var(--primitive-red-600);
566
+ --background-warning-solid: var(--primitive-amber-600);
567
+ --text-on-status-static: var(--primitive-mono-50);
568
+ /* white on the bright 600 fills — deliberate style call, below AA on green/amber */
569
+ /* Brand-coloured text on the canvas (links, ghost badges) */
570
+ --text-brand-default: var(--primitive-blue-600);
571
+ --text-brand-hover: var(--primitive-blue-700);
572
+ /* Selection — brand-selected states (active nav, chosen chip, current page).
573
+ Light: a 10% brand tint, solid-mixed over the surface. Dark deliberately
574
+ diverges (not a mirror): stronger solid fill, lighter ink and border,
575
+ because a 10% wash vanishes on near-black and blue-400 ink loses AA. */
576
+ --background-brand-selected: color-mix(in srgb, var(--primitive-blue-600) 10%, var(--primitive-mono-50));
577
+ --text-brand-selected: var(--primitive-blue-600);
578
+ --border-brand-selected: var(--primitive-blue-600);
579
+ /* Chrome — floating mobile chrome (Bottom Navigation), straight from the
580
+ Refined Mobile file: heavy near-solid frost + a soft ambient lift. The
581
+ ambient shadow is the ONE sanctioned exception to the no-shadow rule:
582
+ floating chrome over scrolling content needs separation; inline
583
+ components still never carry shadows. The bubble is a top-lit gloss
584
+ over the brand-selected fill; layered values paint via `background:`.
585
+ Chrome ink resolves through text-subtle-default (2026-09-03, AA fix —
586
+ was the Refined file's #8A8AA0/#9A9AC4 literals, 3.4:1 on the light
587
+ frost); the frost/border/shadow literals remain until an ink scale
588
+ joins the palette. */
589
+ --background-chrome-default: rgb(255 255 255 / 78%);
590
+ --border-chrome-default: rgb(10 10 60 / 8%);
591
+ --shadow-chrome-default: 0 12px 30px rgb(10 10 60 / 14%);
592
+ --text-chrome-subtle: var(--text-subtle-default);
593
+ --background-chrome-selected:
594
+ linear-gradient(rgb(255 255 255 / 55%), rgb(255 255 255 / 15%)),
595
+ var(--background-brand-selected);
596
+ --chrome-highlight-default: var(--primitive-white-alpha-80);
597
+ --text-chrome-selected: var(--primitive-blue-600);
598
+ --background-success-default: var(--primitive-green-50);
599
+ --background-error-default: var(--primitive-red-50);
600
+ --background-warning-default: var(--primitive-amber-50);
601
+ --background-information-default: var(--primitive-azure-50);
602
+ --background-overlay-default: var(--primitive-black-alpha-50);
603
+
604
+ /* Border */
605
+ --border-default-default: var(--primitive-mono-200);
606
+ --border-prominent-default: var(--primitive-mono-1100);
607
+
608
+ /* Status borders — solid status-600 outline, same in both themes */
609
+ --border-neutral-default: var(--primitive-mono-500);
610
+ /* soft hairline for neutral tint chips */
611
+ --border-success-default: var(--primitive-green-600);
612
+ --border-error-default: var(--primitive-red-600);
613
+ --border-warning-default: var(--primitive-amber-600);
614
+ --border-information-default: var(--primitive-azure-600);
615
+
616
+ /* Text */
617
+ --text-prominent-default: var(--primitive-mono-1100);
618
+ --text-subtle-default: var(--primitive-mono-900);
619
+ --text-disabled-default: var(--primitive-mono-500);
620
+ --text-prominent-inverse: var(--primitive-mono-50);
621
+ --text-subtle-inverse: color-mix(in srgb, var(--text-prominent-inverse) 78%, var(--background-inverse-surface));
622
+ /* supporting copy on the inverse surface (Toast description) — a real
623
+ mixed ink, not an opacity hack; the ingredients flip per theme. */
624
+ --text-on-brand-static: var(--primitive-mono-50);
625
+ --text-brand-container-static: var(--primitive-blue-600);
626
+ --text-success-default: var(--primitive-green-600);
627
+ --text-error-default: var(--primitive-red-600);
628
+ --text-warning-default: var(--primitive-amber-600);
629
+ --text-information-default: var(--primitive-azure-600);
630
+
631
+ /* Icon — aliases of text today; a separate namespace so icons can diverge
632
+ later (icons only need 3:1, so they may one day get brighter steps). */
633
+ --icon-prominent-default: var(--text-prominent-default);
634
+ --icon-subtle-default: var(--text-subtle-default);
635
+ --icon-disabled-default: var(--text-disabled-default);
636
+ --icon-success-default: var(--text-success-default);
637
+ --icon-error-default: var(--text-error-default);
638
+ --icon-warning-default: var(--text-warning-default);
639
+ --icon-information-default: var(--text-information-default);
640
+
641
+ /* Ring */
642
+ --ring-focus-default: var(--primitive-blue-600);
643
+ --ring-focus-strong: color-mix(in srgb, var(--ring-focus-default) 50%, transparent);
644
+ /* the 3px control focus ring */
645
+ --ring-focus-soft: color-mix(in srgb, var(--ring-focus-default) 8%, transparent);
646
+ /* the soft text-field focus ring */
647
+ --ring-error-default: var(--text-error-default);
648
+ --ring-error-soft: color-mix(in srgb, var(--ring-error-default) 20%, transparent);
649
+ /* invalid-field ring */
650
+ --ring-brand-soft: color-mix(in srgb, var(--background-brand-default) 40%, transparent);
651
+ /* brand hairline ring — sidebar icon-rail hover/active */
652
+
653
+ /* ── @deprecated aliases — the old semantic layer, repointed at the new
654
+ tokens. Each is deleted when the last component using it migrates. ── */
655
+ --prominent: var(--background-primary-canvas);
656
+ --on-prominent: var(--text-prominent-default);
657
+ --prominent-inverse: var(--background-inverse-surface);
658
+ --on-prominent-inverse: var(--text-prominent-inverse);
659
+ --primary: var(--background-brand-default);
660
+ --on-primary: var(--text-on-brand-static);
277
661
  --primary-inverse: var(--primitive-mono-50);
278
- /* #FFFFFF — inverted primary surface for use on dark/coloured areas */
279
- --on-primary-inverse: var(--primitive-blue-500);
280
- /* #2323FF — text/icon color for use on primary-inverse surfaces */
281
- --primary-hover: oklch(0.403 0.251 267.5);
282
- /* @deprecated — use the on-X / X-inverse / on-X-inverse pairs above. Kept for backwards compat with external consumers referencing these via var(). */
283
- --on-prominent-static-inverse: var(--on-prominent-inverse);
284
- --surface-inverse-static: var(--primary-inverse);
285
- --subtle: oklch(0.96 0 0);
286
- --on-subtle: oklch(0.52 0 0);
287
- --on-disabled: var(--primitive-mono-400);
288
-
289
- --border-subtle: oklch(0.92 0 0);
290
- --border: var(--border-subtle);
291
- /* @deprecated alias — use --border-subtle or --border-prominent */
292
- --border-prominent: var(--primitive-mono-1000);
293
- /* #000000 */
294
- --secondary-hover: var(--primitive-mono-100);
295
- /* #EEEEEE */
296
- --ring: var(--primitive-blue-500);
297
- --overlay: var(--primitive-black-50);
298
- --semantic-win: var(--primitive-green-400);
662
+ --on-primary-inverse: var(--text-brand-container-static);
663
+ --primary-hover: var(--background-brand-hover);
664
+ --on-prominent-static-inverse: var(--text-prominent-inverse);
665
+ --surface-inverse-static: var(--primitive-mono-50);
666
+ --subtle: var(--primitive-mono-100);
667
+ --on-subtle: var(--text-subtle-default);
668
+ --on-disabled: var(--text-disabled-default);
669
+
670
+ --border-subtle: var(--border-default-default);
671
+ --border: var(--border-default-default);
672
+ --border-prominent: var(--border-prominent-default);
673
+ --secondary-hover: var(--background-hover-default);
674
+ --ring: var(--ring-focus-default);
675
+ --overlay: var(--background-overlay-default);
676
+ --semantic-win: var(--text-success-default);
299
677
  --on-semantic-win: var(--primitive-mono-50);
300
- /* #FFFFFF — text/icon color for use on semantic-win surfaces */
301
- --semantic-loss: var(--primitive-red-500);
678
+ --semantic-loss: var(--text-error-default);
302
679
  --on-semantic-loss: var(--primitive-mono-50);
303
- /* #FFFFFF — text/icon color for use on semantic-loss surfaces */
304
- --semantic-info: var(--primitive-sky-600);
305
- --semantic-error: var(--primitive-red-600);
306
- --semantic-warning: var(--primitive-yellow-500);
680
+ --semantic-info: var(--text-information-default);
681
+ --semantic-error: var(--text-error-default);
682
+ --semantic-warning: var(--text-warning-default);
307
683
  --on-semantic-warning: var(--primitive-mono-50);
308
- /* #FFFFFF — text/icon color for use on semantic-warning surfaces */
309
- --semantic-demo: var(--primitive-orange-500);
310
- /* #FF6600 — red-orange for "demo account" / "test mode" badges; independent
311
- of severity (warning/danger), reserved for marking non-real-money flows */
312
- --semantic-demo-surface: color-mix(in oklch, var(--semantic-demo) 10%, var(--prominent));
313
- /* Opaque light-peach version of the demo tint — solid color so the badge
314
- looks the same on any background (mirrors --semantic-boost-surface for credit) */
315
- --semantic-boost: var(--primitive-amber-600);
316
- /* #F9840F — boost badge surface */
317
- --semantic-boost-surface: oklch(1 0 0 / 0.22);
318
- /* Frosted glass surface for credit/boost badges — translucent white that
319
- composes over whatever surface sits behind it (typically a coloured
320
- hero card). Pair with backdrop-blur and `text-on-primary` for the
321
- classic glass-chip look. */
322
- --on-semantic-boost: var(--primitive-amber-900);
323
- /* #521900 — text/icon color for use on semantic-boost surfaces */
324
- --tabs: var(--primitive-mono-alpha-4);
684
+ --semantic-demo: #FF6600;
685
+ /* TODO revisit with Badge — demo-account marker, outside the status set */
686
+ --semantic-demo-surface: color-mix(in srgb, var(--semantic-demo) 10%, var(--primitive-mono-50));
687
+ --semantic-boost: #F9840F;
688
+ /* TODO revisit with Badge — credit/boost marker, outside the status set */
689
+ --semantic-boost-surface: rgb(255 255 255 / 22%);
690
+ --on-semantic-boost: #521900;
691
+ /* TODO revisit with Badge */
692
+ --tabs: var(--primitive-black-alpha-4);
325
693
  --tabs-active: var(--primitive-mono-50);
326
694
 
327
695
  --semantic-layout-diagram-max-default: var(--primitive-layout-diagram-max-default);
328
696
  --semantic-layout-diagram-max-small: var(--primitive-layout-diagram-max-small);
329
697
  --semantic-layout-diagram-max-medium: var(--primitive-layout-diagram-max-medium);
330
698
 
331
- /* ── Transitions — Semantic duration ── */
332
- --transition-duration-interactive: var(--primitive-duration-fast);
333
- /* buttons, inputs, badges, checkboxes, toggles, tabs hover */
334
- --transition-duration-surface: var(--primitive-duration-base);
335
- /* dropdowns, popovers, tooltips, accordions, navigation menus */
336
- --transition-duration-overlay-close: var(--primitive-duration-slow);
337
- /* dialogs, sheets, drawers, alert-dialogs closing */
338
- --transition-duration-overlay-open: var(--primitive-duration-open);
339
- /* sheets, drawers entering */
340
- --transition-duration-structural: var(--primitive-duration-base);
341
- /* sidebar collapse, progress fill, layout changes */
342
-
343
- /* ── Transitions — Semantic easing ── */
344
- --transition-ease-interactive: var(--primitive-ease-standard);
345
- /* buttons, inputs — bidirectional state changes */
346
- --transition-ease-enter: var(--primitive-ease-enter);
347
- /* overlays / surfaces entering */
348
- --transition-ease-exit: var(--primitive-ease-exit);
349
- /* overlays / surfaces leaving */
350
- --transition-ease-structural: var(--primitive-ease-linear);
351
- /* sidebar, progress — constant-speed structural changes */
699
+ /* ── Motion — Semantic roles ─────────────────────────────────
700
+ The duration and ease utilities resolve through these, so a
701
+ role retunes every consumer in one line. Roles never flip in
702
+ dark. Press is a pattern, not a utility: apply with
703
+ `active:duration-0` so the glaze lands the frame it happens
704
+ and fades on release. */
705
+ --motion-hover: var(--primitive-duration-fast);
706
+ /* hover tints & fills arriving (backs the duration-fast utility) */
707
+ --motion-hover-ease: var(--primitive-ease-standard);
708
+ --motion-press: 0ms;
709
+ /* pressed state lands instantly */
710
+ --motion-press-release: var(--primitive-duration-fast);
711
+ /* …and fades out on release */
712
+ --motion-surface: var(--primitive-duration-base);
713
+ /* menus, popovers, tooltips (backs the duration-base utility) */
714
+ --motion-surface-enter: var(--primitive-ease-enter);
715
+ --motion-surface-exit: var(--primitive-ease-exit);
716
+ --motion-overlay-open: 320ms;
717
+ /* dialogs, sheets, drawers entering (ease-enter) */
718
+ --motion-overlay-close: 250ms;
719
+ /* …and leaving (ease-exit) — exits are quicker */
720
+ --motion-structural: var(--primitive-duration-base);
721
+ /* sidebar collapse, accordion, chevrons */
722
+ --motion-structural-ease: var(--primitive-ease-linear);
723
+ --motion-progress: var(--primitive-duration-slow);
724
+ /* bars & timers (backs the duration-slow utility) */
725
+ --motion-progress-ease: var(--primitive-ease-linear);
726
+
727
+ /* ── Motion — Signature moves ────────────────────────────────
728
+ The liquid selection language, named. Travel pairs with
729
+ ease-spring; pop pairs with ease-overshoot. */
730
+ --motion-travel-lead: 200ms;
731
+ /* liquid indicator leading edge */
732
+ --motion-travel-trail: 380ms;
733
+ /* liquid indicator trailing edge, dragged behind */
734
+ --motion-pop: 450ms;
735
+ /* arrival pop — icon lift, chip tick, success check */
736
+ }
737
+
738
+ /* ══════════════════════════════════════════════════════════════
739
+ DARK THEME — semantic overrides only.
740
+ Primitives never change; each semantic token repoints to a
741
+ different step. Activate with class="dark" or data-theme="dark".
742
+ ══════════════════════════════════════════════════════════════ */
743
+ .dark,
744
+ [data-theme="dark"] {
745
+ /* Background */
746
+ --background-primary-canvas: var(--primitive-blue-1000);
747
+ --background-primary-surface: color-mix(in srgb, white 6%, var(--primitive-blue-1000));
748
+ --background-secondary-surface: color-mix(in srgb, white 12%, var(--primitive-blue-1000));
749
+ /* solid #1F1F3A — one glaze step above the card (6%) */
750
+ /* solid #0F0F2C — base + white glaze, flattened */
751
+ --background-hover-default: var(--primitive-white-alpha-12);
752
+ --background-pressed-default: var(--primitive-white-alpha-20);
753
+ --background-brand-default: var(--primitive-blue-400);
754
+ /* brand-hover / brand-pressed need no override — the black state layer
755
+ recipe re-derives from the dark brand automatically */
756
+ --background-inverse-surface: var(--primitive-mono-50);
757
+
758
+ /* Status backgrounds — solid base + 24% status glaze */
759
+ --background-success-default: color-mix(in srgb, var(--primitive-green-600) 24%, var(--primitive-blue-1000));
760
+ --background-error-default: color-mix(in srgb, var(--primitive-red-600) 24%, var(--primitive-blue-1000));
761
+ --background-warning-default: color-mix(in srgb, var(--primitive-amber-600) 24%, var(--primitive-blue-1000));
762
+ --background-information-default: color-mix(in srgb, var(--primitive-azure-600) 24%, var(--primitive-blue-1000));
763
+ --background-overlay-default: var(--primitive-black-alpha-64);
764
+
765
+ /* Border */
766
+ --border-default-default: var(--primitive-white-alpha-12);
767
+ --border-prominent-default: var(--primitive-mono-50);
768
+ --border-neutral-default: var(--primitive-white-alpha-12);
769
+
770
+ /* Text */
771
+ --text-prominent-default: var(--primitive-mono-50);
772
+ --text-subtle-default: var(--primitive-mono-600);
773
+ --text-disabled-default: var(--primitive-mono-800);
774
+ --text-prominent-inverse: var(--primitive-mono-1100);
775
+ /* status + on-brand + brand-container are static — no overrides */
776
+
777
+ /* Ring */
778
+ --ring-focus-default: var(--primitive-blue-400);
779
+ --text-brand-default: var(--primitive-blue-400);
780
+ --text-brand-hover: var(--primitive-blue-300);
781
+ --background-brand-selected: color-mix(in srgb, var(--primitive-blue-400) 24%, var(--primitive-blue-1000));
782
+ --text-brand-selected: var(--primitive-blue-200);
783
+ --border-brand-selected: var(--primitive-blue-300);
784
+ --background-chrome-default: rgb(20 20 44 / 72%);
785
+ --border-chrome-default: rgb(255 255 255 / 14%);
786
+ --shadow-chrome-default: 0 12px 30px rgb(0 0 20 / 50%);
787
+ --text-chrome-subtle: var(--text-subtle-default);
788
+ --background-chrome-selected:
789
+ linear-gradient(rgb(255 255 255 / 10%), rgb(255 255 255 / 0%)),
790
+ var(--background-brand-selected);
791
+ --chrome-highlight-default: var(--primitive-white-alpha-24);
792
+ --text-chrome-selected: var(--primitive-mono-50);
793
+
794
+ /* @deprecated aliases that don't resolve through a flipping token */
795
+ --primary-inverse: var(--primitive-mono-50);
796
+ --subtle: color-mix(in srgb, white 8%, var(--primitive-blue-1000));
797
+ --tabs: var(--primitive-white-alpha-8);
798
+ --tabs-active: color-mix(in srgb, white 12%, var(--primitive-blue-1000));
352
799
  }
353
800
 
801
+
354
802
  /* ══════════════════════════════════════════════════════════════
355
803
  RESPONSIVE LAYOUT — Standard grid (columns / gutter / margin)
356
804
  ══════════════════════════════════════════════════════════════ */
@@ -389,28 +837,312 @@
389
837
  Component-specific tokens. References semantics or primitives.
390
838
  ══════════════════════════════════════════════════════════════ */
391
839
  :root {
392
- --card: var(--primitive-mono-50);
393
- --card-foreground: oklch(0.07 0.012 165);
394
- --popover: var(--primitive-mono-50);
395
- --popover-foreground: oklch(0.07 0.012 165);
840
+ --card: var(--background-primary-surface);
841
+ --card-foreground: var(--text-prominent-default);
842
+ --popover: var(--background-primary-surface);
843
+ --popover-foreground: var(--text-prominent-default);
396
844
  --input: var(--border-subtle);
397
845
  /* Sunken dark fill for Input/InputGroup variant="inverse" — sits on
398
846
  coloured surfaces (brand-blue, etc.) where a frosted-white fill would
399
847
  blend into the surrounding chrome. 35 % black overlay deepens the
400
848
  surface enough for white text to read cleanly. */
401
- --input-inverse-surface: oklch(0 0 0 / 0.35);
849
+ --input-inverse-surface: rgb(0 0 0 / 35%);
850
+ /* ── Accordion — component type tokens (private) ──
851
+ Typography follows the same three-layer model as color: these reference
852
+ primitives only and are consumed by Accordion alone — retuning them
853
+ never affects any other component. */
854
+ --accordion-trigger-font-size: var(--primitive-font-size-14);
855
+ --accordion-trigger-font-weight: var(--primitive-font-weight-medium);
856
+ --accordion-trigger-line-height: var(--primitive-line-height-20);
857
+ --accordion-content-font-size: var(--primitive-font-size-14);
858
+ --accordion-content-font-weight: var(--primitive-font-weight-regular);
859
+ --accordion-content-line-height: var(--primitive-line-height-20);
860
+ /* ── Banner — component type tokens (private) ──
861
+ The editorial gradient panel: extrabold title, medium supporting line,
862
+ extrabold pill CTA — matching the design file's 800/500/800 weights. */
863
+ --banner-title-font-size: var(--primitive-font-size-18);
864
+ --banner-title-font-weight: var(--primitive-font-weight-semibold);
865
+ --banner-title-line-height: var(--primitive-line-height-24);
866
+ --banner-description-font-size: var(--primitive-font-size-12);
867
+ --banner-description-font-weight: var(--primitive-font-weight-medium);
868
+ --banner-description-line-height: var(--primitive-line-height-16);
869
+ --banner-action-font-size: var(--primitive-font-size-12);
870
+ --banner-action-font-weight: var(--primitive-font-weight-semibold);
871
+ --banner-action-line-height: var(--primitive-line-height-16);
872
+ /* ── Menu family — shared type tokens (private) ──
873
+ One deliberate shared anatomy for Command, Context Menu, Dropdown
874
+ Menu, Menubar, and Select rows: retune here, every menu follows. */
875
+ --menu-item-font-size: var(--primitive-font-size-14);
876
+ --menu-item-line-height: var(--primitive-line-height-20);
877
+ --menu-item-font-weight: var(--primitive-font-weight-regular);
878
+ --menu-heading-font-size: var(--primitive-font-size-12);
879
+ --menu-heading-line-height: var(--primitive-line-height-16);
880
+ --menu-trigger-font-size: var(--primitive-font-size-14);
881
+ --menu-trigger-font-weight: var(--primitive-font-weight-medium);
882
+ --menu-trigger-line-height: var(--primitive-line-height-20);
883
+ --menu-shortcut-font-size: var(--primitive-font-size-12);
884
+ --menu-shortcut-font-weight: var(--primitive-font-weight-regular);
885
+ --menu-shortcut-line-height: var(--primitive-line-height-16);
886
+ --menu-heading-font-weight: var(--primitive-font-weight-medium);
887
+ /* ── Chip — component type tokens (private) ── */
888
+ --chip-font-size-md: var(--primitive-font-size-14);
889
+ --chip-line-height-md: var(--primitive-line-height-20);
890
+ --chip-font-size-sm: var(--primitive-font-size-12);
891
+ --chip-line-height-sm: var(--primitive-line-height-16);
892
+ --chip-font-weight: var(--primitive-font-weight-semibold);
893
+ /* ── Calendar — component type tokens (private) ── */
894
+ --calendar-caption-font-size: var(--primitive-font-size-14);
895
+ --calendar-caption-font-weight: var(--primitive-font-weight-semibold);
896
+ --calendar-caption-line-height: var(--primitive-line-height-20);
897
+ --calendar-weekday-font-size: var(--primitive-font-size-12);
898
+ --calendar-weekday-font-weight: var(--primitive-font-weight-medium);
899
+ --calendar-weekday-line-height: var(--primitive-line-height-16);
900
+ --calendar-day-font-size: var(--primitive-font-size-14);
901
+ --calendar-day-font-weight: var(--primitive-font-weight-regular);
902
+ --calendar-day-line-height: var(--primitive-line-height-20);
903
+ /* ── Button — component type tokens (private) ──
904
+ One primitive step per size (18/16/14), icons tracking the height. */
905
+ --button-font-size-lg: var(--primitive-font-size-18);
906
+ --button-line-height-lg: var(--primitive-line-height-24);
907
+ --button-font-size-md: var(--primitive-font-size-16);
908
+ --button-line-height-md: var(--primitive-line-height-24);
909
+ --button-font-size-sm: var(--primitive-font-size-14);
910
+ --button-line-height-sm: var(--primitive-line-height-20);
911
+ --button-font-weight: var(--primitive-font-weight-semibold);
912
+ /* ── Breadcrumb — component type tokens (private) ── */
913
+ --breadcrumb-font-size: var(--primitive-font-size-14);
914
+ --breadcrumb-font-weight: var(--primitive-font-weight-regular);
915
+ --breadcrumb-line-height: var(--primitive-line-height-20);
916
+ --breadcrumb-page-font-weight: var(--primitive-font-weight-medium);
917
+ /* ── Section Message — component type tokens (private) ──
918
+ Line-heights follow the foundation's pairing for each size (14→20, 12→16),
919
+ replacing the old 1.375 ratio that rendered fractional 19.25/16.5px. */
920
+ --section-message-title-font-size: var(--primitive-font-size-14);
921
+ --section-message-title-font-weight: var(--primitive-font-weight-semibold);
922
+ --section-message-title-line-height: var(--primitive-line-height-20);
923
+ --section-message-description-font-size: var(--primitive-font-size-14);
924
+ --section-message-description-font-weight: var(--primitive-font-weight-regular);
925
+ --section-message-description-line-height: var(--primitive-line-height-20);
926
+ /* sm density — one scale step below md */
927
+ --section-message-title-font-size-sm: var(--primitive-font-size-12);
928
+ --section-message-title-line-height-sm: var(--primitive-line-height-16);
929
+ --section-message-description-font-size-sm: var(--primitive-font-size-12);
930
+ --section-message-description-line-height-sm: var(--primitive-line-height-16);
931
+ /* ── Alert Dialog — component type tokens (private) ── */
932
+ --alert-dialog-title-font-size: var(--primitive-font-size-18);
933
+ --alert-dialog-title-font-weight: var(--primitive-font-weight-semibold);
934
+ --alert-dialog-title-line-height: var(--primitive-line-height-24);
935
+ --alert-dialog-description-font-size: var(--primitive-font-size-14);
936
+ --alert-dialog-description-font-weight: var(--primitive-font-weight-regular);
937
+ --alert-dialog-description-line-height: var(--primitive-line-height-20);
938
+ /* ── Dialog — component type tokens (private) ──
939
+ Same ladder as Alert Dialog: 18/semibold/24 title, 14/regular/20 body. */
940
+ --dialog-title-font-size: var(--primitive-font-size-18);
941
+ --dialog-title-font-weight: var(--primitive-font-weight-semibold);
942
+ --dialog-title-line-height: var(--primitive-line-height-24);
943
+ --dialog-description-font-size: var(--primitive-font-size-14);
944
+ --dialog-description-font-weight: var(--primitive-font-weight-regular);
945
+ --dialog-description-line-height: var(--primitive-line-height-20);
946
+ /* ── Drawer — component type tokens (private) ──
947
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
948
+ --drawer-title-font-size: var(--primitive-font-size-18);
949
+ --drawer-title-font-weight: var(--primitive-font-weight-semibold);
950
+ --drawer-title-line-height: var(--primitive-line-height-24);
951
+ --drawer-description-font-size: var(--primitive-font-size-14);
952
+ --drawer-description-font-weight: var(--primitive-font-weight-regular);
953
+ --drawer-description-line-height: var(--primitive-line-height-20);
954
+ /* ── Empty — component type tokens (private) ──
955
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
956
+ --empty-title-font-size: var(--primitive-font-size-18);
957
+ --empty-title-font-weight: var(--primitive-font-weight-semibold);
958
+ --empty-title-line-height: var(--primitive-line-height-24);
959
+ --empty-description-font-size: var(--primitive-font-size-14);
960
+ --empty-description-font-weight: var(--primitive-font-weight-regular);
961
+ --empty-description-line-height: var(--primitive-line-height-20);
962
+ /* ── Field — component type tokens (private) ──
963
+ Legend 16/medium/24 (label variant one step down), body 14/regular/20;
964
+ FieldError rides the description ladder in error ink. */
965
+ --field-legend-font-size: var(--primitive-font-size-16);
966
+ --field-legend-font-weight: var(--primitive-font-weight-medium);
967
+ --field-legend-line-height: var(--primitive-line-height-24);
968
+ --field-legend-label-font-size: var(--primitive-font-size-14);
969
+ --field-legend-label-font-weight: var(--primitive-font-weight-medium);
970
+ --field-legend-label-line-height: var(--primitive-line-height-20);
971
+ /* Label rides the control's text step per size; helper text stays 12
972
+ at every size (help text shouldn't shout). */
973
+ --field-label-font-size-sm: var(--primitive-font-size-12);
974
+ --field-label-line-height-sm: var(--primitive-line-height-16);
975
+ --field-label-font-size-md: var(--primitive-font-size-14);
976
+ --field-label-line-height-md: var(--primitive-line-height-20);
977
+ --field-label-font-size-lg: var(--primitive-font-size-16);
978
+ --field-label-line-height-lg: var(--primitive-line-height-24);
979
+ --field-label-font-weight: var(--primitive-font-weight-medium);
980
+ --field-description-font-size: var(--primitive-font-size-12);
981
+ --field-description-font-weight: var(--primitive-font-weight-regular);
982
+ --field-description-line-height: var(--primitive-line-height-16);
983
+ /* ── Input — component type tokens (private) ──
984
+ One primitive step per size (12/14/16), matching the Field label ladder. */
985
+ --input-font-size-sm: var(--primitive-font-size-12);
986
+ --input-line-height-sm: var(--primitive-line-height-16);
987
+ --input-font-size-md: var(--primitive-font-size-14);
988
+ --input-line-height-md: var(--primitive-line-height-20);
989
+ --input-font-size-lg: var(--primitive-font-size-16);
990
+ --input-line-height-lg: var(--primitive-line-height-24);
991
+ --input-font-weight: var(--primitive-font-weight-regular);
992
+ /* ── Input OTP — component type tokens (private) ──
993
+ Digits ride the input md step (14/regular/20). */
994
+ --input-otp-font-size: var(--primitive-font-size-14);
995
+ --input-otp-font-weight: var(--primitive-font-weight-regular);
996
+ --input-otp-line-height: var(--primitive-line-height-20);
997
+ /* ── Native Select — component type tokens (private) ──
998
+ Same ladder as Input (12/14/16, regular). */
999
+ --native-select-font-size-sm: var(--primitive-font-size-12);
1000
+ --native-select-line-height-sm: var(--primitive-line-height-16);
1001
+ --native-select-font-size-md: var(--primitive-font-size-14);
1002
+ --native-select-line-height-md: var(--primitive-line-height-20);
1003
+ --native-select-font-size-lg: var(--primitive-font-size-16);
1004
+ --native-select-line-height-lg: var(--primitive-line-height-24);
1005
+ --native-select-font-weight: var(--primitive-font-weight-regular);
1006
+ /* ── Select — component type tokens (private) ──
1007
+ Trigger rides the input ladder (12/14/16, regular); rows use the menu family. */
1008
+ --select-font-size-sm: var(--primitive-font-size-12);
1009
+ --select-line-height-sm: var(--primitive-line-height-16);
1010
+ --select-font-size-md: var(--primitive-font-size-14);
1011
+ --select-line-height-md: var(--primitive-line-height-20);
1012
+ --select-font-size-lg: var(--primitive-font-size-16);
1013
+ --select-line-height-lg: var(--primitive-line-height-24);
1014
+ --select-font-weight: var(--primitive-font-weight-regular);
1015
+ /* ── Textarea — component type tokens (private) ──
1016
+ Rides the input md step (14/regular/20). */
1017
+ --textarea-font-size: var(--primitive-font-size-14);
1018
+ --textarea-font-weight: var(--primitive-font-weight-regular);
1019
+ --textarea-line-height: var(--primitive-line-height-20);
1020
+ /* ── Sheet — component type tokens (private) ──
1021
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
1022
+ --sheet-title-font-size: var(--primitive-font-size-18);
1023
+ --sheet-title-font-weight: var(--primitive-font-weight-semibold);
1024
+ --sheet-title-line-height: var(--primitive-line-height-24);
1025
+ --sheet-description-font-size: var(--primitive-font-size-14);
1026
+ --sheet-description-font-weight: var(--primitive-font-weight-regular);
1027
+ --sheet-description-line-height: var(--primitive-line-height-20);
1028
+ /* ── Table — component type tokens (private) ──
1029
+ Cells 14/regular/20; header + footer 14/medium/20. */
1030
+ --table-font-size: var(--primitive-font-size-14);
1031
+ --table-font-weight: var(--primitive-font-weight-regular);
1032
+ --table-line-height: var(--primitive-line-height-20);
1033
+ --table-head-font-weight: var(--primitive-font-weight-medium);
1034
+ /* ── Bottom Navigation — component type tokens (private) ──
1035
+ 12/medium/16 labels; the active destination goes semibold. */
1036
+ --bottom-navigation-label-font-size: var(--primitive-font-size-12);
1037
+ --bottom-navigation-label-font-weight: var(--primitive-font-weight-medium);
1038
+ --bottom-navigation-label-line-height: var(--primitive-line-height-16);
1039
+ --bottom-navigation-label-active-font-weight: var(--primitive-font-weight-semibold);
1040
+ /* ── Sidebar — component type tokens (private) ──
1041
+ Menu rows 14/regular/20 (sm 12/16); labels + badges 12/medium/16.
1042
+ Active rows go semibold via the data-active rule below. */
1043
+ --sidebar-menu-font-size: var(--primitive-font-size-14);
1044
+ --sidebar-menu-line-height: var(--primitive-line-height-20);
1045
+ --sidebar-menu-font-size-sm: var(--primitive-font-size-12);
1046
+ --sidebar-menu-line-height-sm: var(--primitive-line-height-16);
1047
+ --sidebar-menu-font-weight: var(--primitive-font-weight-regular);
1048
+ --sidebar-menu-active-font-weight: var(--primitive-font-weight-semibold);
1049
+ --sidebar-label-font-size: var(--primitive-font-size-12);
1050
+ --sidebar-label-line-height: var(--primitive-line-height-16);
1051
+ --sidebar-label-font-weight: var(--primitive-font-weight-medium);
1052
+ /* ── Tabs — component type tokens (private) ──
1053
+ Trigger rides one primitive step per list size (12/14/16); active goes
1054
+ semibold via the data-state rule below. */
1055
+ --tabs-trigger-font-size-sm: var(--primitive-font-size-12);
1056
+ --tabs-trigger-line-height-sm: var(--primitive-line-height-16);
1057
+ --tabs-trigger-font-size-md: var(--primitive-font-size-14);
1058
+ --tabs-trigger-line-height-md: var(--primitive-line-height-20);
1059
+ --tabs-trigger-font-size-lg: var(--primitive-font-size-16);
1060
+ --tabs-trigger-line-height-lg: var(--primitive-line-height-24);
1061
+ --tabs-trigger-font-weight: var(--primitive-font-weight-regular);
1062
+ --tabs-trigger-active-font-weight: var(--primitive-font-weight-semibold);
1063
+ /* ── Toggle — component type tokens (private) ── */
1064
+ --toggle-font-size: var(--primitive-font-size-14);
1065
+ --toggle-font-weight: var(--primitive-font-weight-medium);
1066
+ --toggle-line-height: var(--primitive-line-height-20);
1067
+ /* ── Tooltip — component type tokens (private) ── */
1068
+ --tooltip-font-size: var(--primitive-font-size-14);
1069
+ --tooltip-font-weight: var(--primitive-font-weight-medium);
1070
+ --tooltip-line-height: var(--primitive-line-height-20);
1071
+ /* ── Item — component type tokens (private) ──
1072
+ List rows: 14/medium/20 title, 14/regular/20 body. */
1073
+ --item-title-font-size: var(--primitive-font-size-14);
1074
+ --item-title-font-weight: var(--primitive-font-weight-medium);
1075
+ --item-title-line-height: var(--primitive-line-height-20);
1076
+ --item-description-font-size: var(--primitive-font-size-14);
1077
+ --item-description-font-weight: var(--primitive-font-weight-regular);
1078
+ --item-description-line-height: var(--primitive-line-height-20);
1079
+ /* ── Numpad — component type tokens (private) ──
1080
+ Bare digit keys: 20/medium/28. */
1081
+ --numpad-font-size: var(--primitive-font-size-20);
1082
+ --numpad-font-weight: var(--primitive-font-weight-medium);
1083
+ --numpad-line-height: var(--primitive-line-height-28);
1084
+ /* ── Pagination — component type tokens (private) ── */
1085
+ --pagination-font-size: var(--primitive-font-size-14);
1086
+ --pagination-font-weight: var(--primitive-font-weight-semibold);
1087
+ --pagination-line-height: var(--primitive-line-height-20);
1088
+ /* ── Popover — component type tokens (private) ── */
1089
+ --popover-title-font-size: var(--primitive-font-size-14);
1090
+ --popover-title-font-weight: var(--primitive-font-weight-medium);
1091
+ --popover-title-line-height: var(--primitive-line-height-20);
1092
+ --popover-description-font-size: var(--primitive-font-size-14);
1093
+ --popover-description-font-weight: var(--primitive-font-weight-regular);
1094
+ --popover-description-line-height: var(--primitive-line-height-20);
1095
+ /* ── Label — component type tokens (private) ── */
1096
+ --label-font-size: var(--primitive-font-size-14);
1097
+ --label-font-weight: var(--primitive-font-weight-medium);
1098
+ --label-line-height: var(--primitive-line-height-20);
1099
+ /* ── Link — component type tokens (private) ──
1100
+ One primitive step per size (16/14/12), semibold like Button. */
1101
+ --link-font-size-lg: var(--primitive-font-size-16);
1102
+ --link-line-height-lg: var(--primitive-line-height-24);
1103
+ --link-font-size-md: var(--primitive-font-size-14);
1104
+ --link-line-height-md: var(--primitive-line-height-20);
1105
+ --link-font-size-sm: var(--primitive-font-size-12);
1106
+ --link-line-height-sm: var(--primitive-line-height-16);
1107
+ --link-font-weight: var(--primitive-font-weight-semibold);
1108
+ /* ── Avatar — component type tokens (private) ──
1109
+ The initials scale with the avatar's own size prop (not the viewport):
1110
+ 12px in a 24px circle, 16px in a 48px one. Weight stays 400, matching
1111
+ what the component rendered before it had tokens. */
1112
+ --avatar-fallback-font-size-sm: var(--primitive-font-size-12);
1113
+ --avatar-fallback-line-height-sm: var(--primitive-line-height-16);
1114
+ --avatar-fallback-font-size: var(--primitive-font-size-14);
1115
+ --avatar-fallback-line-height: var(--primitive-line-height-20);
1116
+ --avatar-fallback-font-size-xl: var(--primitive-font-size-16);
1117
+ --avatar-fallback-line-height-xl: var(--primitive-line-height-24);
1118
+ --avatar-fallback-font-weight: var(--primitive-font-weight-regular);
1119
+ --avatar-group-count-font-size: var(--primitive-font-size-14);
1120
+ --avatar-group-count-line-height: var(--primitive-line-height-20);
1121
+ --avatar-group-count-font-weight: var(--primitive-font-weight-regular);
1122
+ /* ── Badge — component type tokens (private) ──
1123
+ Four sizes; xs is the 10px stamp scale used for status and catalogue
1124
+ corner pills, below the shared type scale's 12px floor. */
1125
+ --badge-font-size-xs: var(--primitive-font-size-10);
1126
+ --badge-line-height-xs: var(--primitive-line-height-16);
1127
+ --badge-font-size-sm: var(--primitive-font-size-12);
1128
+ --badge-line-height-sm: var(--primitive-line-height-16);
1129
+ --badge-font-size-md: var(--primitive-font-size-14);
1130
+ --badge-line-height-md: var(--primitive-line-height-20);
1131
+ --badge-font-size-lg: var(--primitive-font-size-16);
1132
+ --badge-line-height-lg: var(--primitive-line-height-24);
1133
+ --badge-font-weight: var(--primitive-font-weight-semibold);
402
1134
  --alert-info-text: var(--semantic-info);
403
1135
  --alert-info-border: var(--semantic-info);
404
1136
  --alert-error-text: var(--semantic-error);
405
1137
  --alert-error-border: var(--semantic-error);
406
- --slider-range: oklch(0.476 0.297 267.4 / 40%);
407
- --sidebar: var(--primitive-mono-50);
408
- --sidebar-foreground: oklch(0.07 0.012 165);
1138
+ --slider-range: var(--primitive-blue-alpha-40);
1139
+ --sidebar: var(--background-primary-surface);
1140
+ --sidebar-foreground: var(--text-prominent-default);
409
1141
  --sidebar-primary: var(--primary);
410
- --sidebar-primary-foreground: var(--primitive-mono-50);
411
- --sidebar-accent: oklch(0.96 0 0);
412
- --sidebar-accent-foreground: oklch(0.12 0.015 160);
413
- --sidebar-border: oklch(0.92 0 0);
1142
+ --sidebar-primary-foreground: var(--text-on-brand-static);
1143
+ --sidebar-accent: var(--primitive-mono-100);
1144
+ --sidebar-accent-foreground: var(--text-prominent-default);
1145
+ --sidebar-border: var(--border-default-default);
414
1146
  --sidebar-ring: var(--ring);
415
1147
  }
416
1148
 
@@ -446,6 +1178,12 @@
446
1178
  100% { transform: translateX(100%); opacity: 1; }
447
1179
  }
448
1180
 
1181
+ /* Skeleton — directional loading sweep (replaces the generic pulse) */
1182
+ @keyframes skeleton-sweep {
1183
+ from { transform: translateX(-100%); }
1184
+ to { transform: translateX(100%); }
1185
+ }
1186
+
449
1187
  /* Spinner — pill-style activity indicator */
450
1188
  @keyframes spinner-fade {
451
1189
  0% {
@@ -453,83 +1191,710 @@
453
1191
  }
454
1192
 
455
1193
  100% {
456
- opacity: 0.2;
1194
+ opacity: 0.15;
1195
+ }
1196
+ }
1197
+
1198
+ /* ── GameLoadingBlock ────────────────────────────────────────────────
1199
+ Brand-blue dotted splash backdrop. The dot colour is derived from the
1200
+ --on-primary token (not a raw white) so it tracks the palette; the dot
1201
+ grid is a background-image, which Tailwind utilities can't express
1202
+ cleanly, so it lives here as a class. */
1203
+ .game-loader-backdrop {
1204
+ background-color: var(--primary);
1205
+ background-image: radial-gradient(
1206
+ color-mix(in oklch, var(--on-primary) 16%, transparent) 1px,
1207
+ transparent 1px
1208
+ );
1209
+ background-size: 14px 14px;
1210
+ }
1211
+
1212
+ /* Exit reveal — the monogram hangs, snaps outward, and the app is revealed
1213
+ behind it (X/Twitter-style). Suppressed under prefers-reduced-motion by
1214
+ the component, which falls back to a plain fade. */
1215
+ @keyframes game-loader-zoom {
1216
+ 0% {
1217
+ transform: scale(1);
1218
+ animation-timing-function: cubic-bezier(0.3, 0, 0.5, 1);
1219
+ }
1220
+
1221
+ 22% {
1222
+ transform: scale(0.85);
1223
+ animation-timing-function: cubic-bezier(0.7, 0, 0.85, 0.35);
1224
+ }
1225
+
1226
+ 100% {
1227
+ transform: scale(22);
457
1228
  }
458
1229
  }
459
1230
 
460
- /* Typography — Heading scale (Plus Jakarta Sans · Semibold 600 · LS 1.5px) */
461
- .heading-h1 {
1231
+ .game-loader-mark {
1232
+ transform-origin: center;
1233
+ will-change: transform;
1234
+ }
1235
+
1236
+ .game-loader-mark-exit {
1237
+ animation: game-loader-zoom 0.34s forwards;
1238
+ }
1239
+
1240
+ /* Progress-bar shimmer — sweeps across the filled portion while a stage is
1241
+ still loading, so a held bar still reads as "working". */
1242
+ @keyframes game-loader-sweep {
1243
+ 0% {
1244
+ left: -60%;
1245
+ }
1246
+
1247
+ 100% {
1248
+ left: 110%;
1249
+ }
1250
+ }
1251
+
1252
+ .game-loader-shimmer {
1253
+ background: linear-gradient(
1254
+ 90deg,
1255
+ transparent,
1256
+ color-mix(in oklch, var(--primary) 35%, transparent),
1257
+ transparent
1258
+ );
1259
+ animation: game-loader-sweep 1.4s ease-in-out infinite;
1260
+ }
1261
+
1262
+ /* ─────────────────────────────────────────────────────────────────
1263
+ Typography — Plus Jakarta Sans
1264
+ Sentence-case headings in mixed weights (600–800) with tight tracking,
1265
+ and a Regular-weight body. 8-point aligned; the top four heading sizes
1266
+ scale fluidly on small screens via clamp().
1267
+
1268
+ Weight roles:
1269
+ 400 Regular — body
1270
+ 500 Medium — captions, dense UI
1271
+ 600 SemiBold — subheads, emphasis
1272
+ 700 Bold — headings
1273
+ 800 ExtraBold — display
1274
+ ───────────────────────────────────────────────────────────────── */
1275
+
1276
+ /* Display & headings (600–800) — the top four scale fluidly. Both font-size
1277
+ AND line-height clamp between each style's -mobile and -desktop tokens, so
1278
+ they land on the 8-point grid at each end: e.g. display 56/64 (desktop) →
1279
+ 36/40 (mobile). Every number below is a semantic --type-* token (§ above),
1280
+ never a raw literal — the vw-based midpoint is the interpolation formula
1281
+ itself, not a "value," so it stays inline.
1282
+
1283
+ ONE CLASS PER TIER — sizes, line-heights and weights come from the
1284
+ --type-* tokens, which carry both mobile and desktop values, so a tier
1285
+ never changes name between breakpoints. h1–h6 are style names, not HTML
1286
+ tags. Changing a tier's look is a one-line token edit here and updates
1287
+ every product. */
1288
+ .display {
462
1289
  font-family: var(--font-plus-jakarta-sans);
463
- font-weight: 600;
464
- font-size: 72px;
465
- line-height: 72px;
466
- letter-spacing: 1.5px;
467
- text-transform: uppercase;
1290
+ font-weight: var(--type-display-weight);
1291
+ font-size: clamp(var(--type-display-size-mobile), 1.4rem + 4vw, var(--type-display-size-desktop));
1292
+ line-height: clamp(var(--type-display-line-mobile), 1.48rem + 4.8vw, var(--type-display-line-desktop));
1293
+ letter-spacing: var(--type-display-tracking);
468
1294
  }
469
1295
 
470
- .heading-h2 {
1296
+ .h1 {
471
1297
  font-family: var(--font-plus-jakarta-sans);
472
- font-weight: 600;
473
- font-size: 64px;
474
- line-height: 64px;
475
- letter-spacing: 1.5px;
476
- text-transform: uppercase;
1298
+ font-weight: var(--type-h1-weight);
1299
+ font-size: clamp(var(--type-h1-size-mobile), 1.6rem + 2vw, var(--type-h1-size-desktop));
1300
+ line-height: clamp(var(--type-h1-line-mobile), 1.92rem + 2.4vw, var(--type-h1-line-desktop));
1301
+ letter-spacing: var(--type-h1-tracking);
477
1302
  }
478
1303
 
479
- .heading-h3 {
1304
+ .h2 {
480
1305
  font-family: var(--font-plus-jakarta-sans);
481
- font-weight: 600;
482
- font-size: 48px;
483
- line-height: 48px;
484
- letter-spacing: 1.5px;
485
- text-transform: uppercase;
1306
+ font-weight: var(--type-h2-weight);
1307
+ font-size: clamp(var(--type-h2-size-mobile), 1.4rem + 1.2vw, var(--type-h2-size-desktop));
1308
+ line-height: clamp(var(--type-h2-line-mobile), 1.7rem + 1.6vw, var(--type-h2-line-desktop));
1309
+ letter-spacing: var(--type-h2-tracking);
486
1310
  }
487
1311
 
488
- .heading-h4 {
1312
+ .h3 {
489
1313
  font-family: var(--font-plus-jakarta-sans);
490
- font-weight: 600;
491
- font-size: 40px;
492
- line-height: 40px;
493
- letter-spacing: 1.5px;
494
- text-transform: uppercase;
1314
+ font-weight: var(--type-h3-weight);
1315
+ font-size: clamp(var(--type-h3-size-mobile), 1.3rem + 0.4vw, var(--type-h3-size-desktop));
1316
+ line-height: clamp(var(--type-h3-line-mobile), 1.6rem + 0.8vw, var(--type-h3-line-desktop));
1317
+ letter-spacing: var(--type-h3-tracking);
495
1318
  }
496
1319
 
497
- .heading-xs {
1320
+ .h4 {
498
1321
  font-family: var(--font-plus-jakarta-sans);
499
- font-weight: 600;
500
- font-size: 24px;
501
- line-height: 24px;
502
- letter-spacing: 1.5px;
503
- text-transform: uppercase;
1322
+ font-weight: var(--type-h4-weight);
1323
+ font-size: var(--type-h4-size);
1324
+ line-height: var(--type-h4-line);
1325
+ letter-spacing: var(--type-h4-tracking);
1326
+ }
1327
+
1328
+ .h5 {
1329
+ font-family: var(--font-plus-jakarta-sans);
1330
+ font-weight: var(--type-h5-weight);
1331
+ font-size: var(--type-h5-size);
1332
+ line-height: var(--type-h5-line);
1333
+ letter-spacing: var(--type-h5-tracking);
504
1334
  }
505
1335
 
506
- /* Typography — Body scale (Plus Jakarta Sans · Semibold 600) */
1336
+ .h6 {
1337
+ font-family: var(--font-plus-jakarta-sans);
1338
+ font-weight: var(--type-h6-weight);
1339
+ font-size: var(--type-h6-size);
1340
+ line-height: var(--type-h6-line);
1341
+ letter-spacing: var(--type-h6-tracking);
1342
+ }
1343
+
1344
+ /* Body (400–600) */
507
1345
  .body-lg {
508
1346
  font-family: var(--font-plus-jakarta-sans);
509
- font-weight: 600;
510
- font-size: 18px;
511
- line-height: 28px;
1347
+ font-weight: var(--type-body-lg-weight);
1348
+ font-size: var(--type-body-lg-size);
1349
+ line-height: var(--type-body-lg-line);
512
1350
  }
513
1351
 
514
1352
  .body-md {
515
1353
  font-family: var(--font-plus-jakarta-sans);
516
- font-weight: 600;
517
- font-size: 16px;
518
- line-height: 24px;
1354
+ font-weight: var(--type-body-md-weight);
1355
+ font-size: var(--type-body-md-size);
1356
+ line-height: var(--type-body-md-line);
519
1357
  }
520
1358
 
521
1359
  .body-sm {
522
1360
  font-family: var(--font-plus-jakarta-sans);
523
- font-weight: 600;
524
- font-size: 12px;
525
- line-height: 16px;
1361
+ font-weight: var(--type-body-sm-weight);
1362
+ font-size: var(--type-body-sm-size);
1363
+ line-height: var(--type-body-sm-line);
1364
+ }
1365
+
1366
+ /* Label — identifying text on interactive/dense UI (form labels, item
1367
+ titles, table headers, tooltips). Medium weight for scannability. */
1368
+ .label-text {
1369
+ font-family: var(--font-plus-jakarta-sans);
1370
+ font-weight: var(--type-label-weight);
1371
+ font-size: var(--type-label-size);
1372
+ line-height: var(--type-label-line);
1373
+ letter-spacing: var(--type-label-tracking);
1374
+ }
1375
+
1376
+ .caption {
1377
+ font-family: var(--font-plus-jakarta-sans);
1378
+ font-weight: var(--type-caption-weight);
1379
+ font-size: var(--type-caption-size);
1380
+ line-height: var(--type-caption-line);
1381
+ letter-spacing: var(--type-caption-tracking);
1382
+ }
1383
+
1384
+ /* ── Component type classes ───────────────────────────────────
1385
+ Plain CSS, not Tailwind utilities: a generated `text-*` utility is
1386
+ indistinguishable from a text-colour utility to tailwind-merge, which
1387
+ strips one of them inside cn(). Named `type-*` so it is left alone.
1388
+ Each class reads only that component's own private tokens. */
1389
+ .type-accordion-trigger {
1390
+ font-size: var(--accordion-trigger-font-size);
1391
+ line-height: var(--accordion-trigger-line-height);
1392
+ font-weight: var(--accordion-trigger-font-weight);
1393
+ }
1394
+
1395
+ .type-accordion-content {
1396
+ font-size: var(--accordion-content-font-size);
1397
+ line-height: var(--accordion-content-line-height);
1398
+ font-weight: var(--accordion-content-font-weight);
1399
+ }
1400
+
1401
+ .type-badge-xs {
1402
+ font-size: var(--badge-font-size-xs);
1403
+ line-height: var(--badge-line-height-xs);
1404
+ font-weight: var(--badge-font-weight);
1405
+ }
1406
+
1407
+ .type-badge-sm {
1408
+ font-size: var(--badge-font-size-sm);
1409
+ line-height: var(--badge-line-height-sm);
1410
+ font-weight: var(--badge-font-weight);
1411
+ }
1412
+
1413
+ .type-badge-md {
1414
+ font-size: var(--badge-font-size-md);
1415
+ line-height: var(--badge-line-height-md);
1416
+ font-weight: var(--badge-font-weight);
1417
+ }
1418
+
1419
+ .type-badge-lg {
1420
+ font-size: var(--badge-font-size-lg);
1421
+ line-height: var(--badge-line-height-lg);
1422
+ font-weight: var(--badge-font-weight);
1423
+ }
1424
+
1425
+ .type-avatar-fallback {
1426
+ font-size: var(--avatar-fallback-font-size);
1427
+ line-height: var(--avatar-fallback-line-height);
1428
+ font-weight: var(--avatar-fallback-font-weight);
1429
+ }
1430
+
1431
+ /* Sizes come off the Avatar root's data-size, so the fallback follows the
1432
+ circle it sits in. sm and xl differ; default and lg share the base. */
1433
+ [data-slot="avatar"][data-size="sm"] .type-avatar-fallback {
1434
+ font-size: var(--avatar-fallback-font-size-sm);
1435
+ line-height: var(--avatar-fallback-line-height-sm);
1436
+ }
1437
+
1438
+ [data-slot="avatar"][data-size="xl"] .type-avatar-fallback {
1439
+ font-size: var(--avatar-fallback-font-size-xl);
1440
+ line-height: var(--avatar-fallback-line-height-xl);
1441
+ }
1442
+
1443
+ .type-avatar-group-count {
1444
+ font-size: var(--avatar-group-count-font-size);
1445
+ line-height: var(--avatar-group-count-line-height);
1446
+ font-weight: var(--avatar-group-count-font-weight);
1447
+ }
1448
+
1449
+ .type-alert-dialog-title {
1450
+ font-size: var(--alert-dialog-title-font-size);
1451
+ line-height: var(--alert-dialog-title-line-height);
1452
+ font-weight: var(--alert-dialog-title-font-weight);
1453
+ }
1454
+
1455
+ .type-alert-dialog-description {
1456
+ font-size: var(--alert-dialog-description-font-size);
1457
+ line-height: var(--alert-dialog-description-line-height);
1458
+ font-weight: var(--alert-dialog-description-font-weight);
1459
+ }
1460
+
1461
+ .type-dialog-title {
1462
+ font-size: var(--dialog-title-font-size);
1463
+ line-height: var(--dialog-title-line-height);
1464
+ font-weight: var(--dialog-title-font-weight);
1465
+ }
1466
+
1467
+ .type-dialog-description {
1468
+ font-size: var(--dialog-description-font-size);
1469
+ line-height: var(--dialog-description-line-height);
1470
+ font-weight: var(--dialog-description-font-weight);
1471
+ }
1472
+
1473
+ .type-drawer-title {
1474
+ font-size: var(--drawer-title-font-size);
1475
+ line-height: var(--drawer-title-line-height);
1476
+ font-weight: var(--drawer-title-font-weight);
526
1477
  }
527
1478
 
528
- .body-xs {
1479
+ .type-drawer-description {
1480
+ font-size: var(--drawer-description-font-size);
1481
+ line-height: var(--drawer-description-line-height);
1482
+ font-weight: var(--drawer-description-font-weight);
1483
+ }
1484
+
1485
+ .type-empty-title {
1486
+ font-size: var(--empty-title-font-size);
1487
+ line-height: var(--empty-title-line-height);
1488
+ font-weight: var(--empty-title-font-weight);
1489
+ }
1490
+
1491
+ .type-empty-description {
1492
+ font-size: var(--empty-description-font-size);
1493
+ line-height: var(--empty-description-line-height);
1494
+ font-weight: var(--empty-description-font-weight);
1495
+ }
1496
+
1497
+ .type-field-legend {
1498
+ font-size: var(--field-legend-font-size);
1499
+ line-height: var(--field-legend-line-height);
1500
+ font-weight: var(--field-legend-font-weight);
1501
+ }
1502
+
1503
+ .type-field-legend-label {
1504
+ font-size: var(--field-legend-label-font-size);
1505
+ line-height: var(--field-legend-label-line-height);
1506
+ font-weight: var(--field-legend-label-font-weight);
1507
+ }
1508
+
1509
+ .type-label {
1510
+ font-size: var(--label-font-size);
1511
+ line-height: var(--label-line-height);
1512
+ font-weight: var(--label-font-weight);
1513
+ }
1514
+
1515
+ .type-link-lg {
1516
+ font-size: var(--link-font-size-lg);
1517
+ line-height: var(--link-line-height-lg);
1518
+ font-weight: var(--link-font-weight);
1519
+ }
1520
+
1521
+ .type-link-md {
1522
+ font-size: var(--link-font-size-md);
1523
+ line-height: var(--link-line-height-md);
1524
+ font-weight: var(--link-font-weight);
1525
+ }
1526
+
1527
+ .type-link-sm {
1528
+ font-size: var(--link-font-size-sm);
1529
+ line-height: var(--link-line-height-sm);
1530
+ font-weight: var(--link-font-weight);
1531
+ }
1532
+
1533
+ .type-numpad {
1534
+ font-size: var(--numpad-font-size);
1535
+ line-height: var(--numpad-line-height);
1536
+ font-weight: var(--numpad-font-weight);
1537
+ }
1538
+
1539
+ .type-pagination {
1540
+ font-size: var(--pagination-font-size);
1541
+ line-height: var(--pagination-line-height);
1542
+ font-weight: var(--pagination-font-weight);
1543
+ }
1544
+
1545
+ .type-popover-title {
1546
+ font-size: var(--popover-title-font-size);
1547
+ line-height: var(--popover-title-line-height);
1548
+ font-weight: var(--popover-title-font-weight);
1549
+ }
1550
+
1551
+ .type-popover-description {
1552
+ font-size: var(--popover-description-font-size);
1553
+ line-height: var(--popover-description-line-height);
1554
+ font-weight: var(--popover-description-font-weight);
1555
+ }
1556
+
1557
+ .type-field-label-sm {
1558
+ font-size: var(--field-label-font-size-sm);
1559
+ line-height: var(--field-label-line-height-sm);
1560
+ font-weight: var(--field-label-font-weight);
1561
+ }
1562
+
1563
+ .type-field-label-md {
1564
+ font-size: var(--field-label-font-size-md);
1565
+ line-height: var(--field-label-line-height-md);
1566
+ font-weight: var(--field-label-font-weight);
1567
+ }
1568
+
1569
+ .type-field-label-lg {
1570
+ font-size: var(--field-label-font-size-lg);
1571
+ line-height: var(--field-label-line-height-lg);
1572
+ font-weight: var(--field-label-font-weight);
1573
+ }
1574
+
1575
+ .type-field-description {
1576
+ font-size: var(--field-description-font-size);
1577
+ line-height: var(--field-description-line-height);
1578
+ font-weight: var(--field-description-font-weight);
1579
+ }
1580
+
1581
+ .type-input-sm {
1582
+ font-size: var(--input-font-size-sm);
1583
+ line-height: var(--input-line-height-sm);
1584
+ font-weight: var(--input-font-weight);
1585
+ }
1586
+
1587
+ .type-input-md {
1588
+ font-size: var(--input-font-size-md);
1589
+ line-height: var(--input-line-height-md);
1590
+ font-weight: var(--input-font-weight);
1591
+ }
1592
+
1593
+ .type-input-lg {
1594
+ font-size: var(--input-font-size-lg);
1595
+ line-height: var(--input-line-height-lg);
1596
+ font-weight: var(--input-font-weight);
1597
+ }
1598
+
1599
+ .type-input-otp {
1600
+ font-size: var(--input-otp-font-size);
1601
+ line-height: var(--input-otp-line-height);
1602
+ font-weight: var(--input-otp-font-weight);
1603
+ }
1604
+
1605
+ .type-native-select-sm {
1606
+ font-size: var(--native-select-font-size-sm);
1607
+ line-height: var(--native-select-line-height-sm);
1608
+ font-weight: var(--native-select-font-weight);
1609
+ }
1610
+
1611
+ .type-native-select-md {
1612
+ font-size: var(--native-select-font-size-md);
1613
+ line-height: var(--native-select-line-height-md);
1614
+ font-weight: var(--native-select-font-weight);
1615
+ }
1616
+
1617
+ .type-native-select-lg {
1618
+ font-size: var(--native-select-font-size-lg);
1619
+ line-height: var(--native-select-line-height-lg);
1620
+ font-weight: var(--native-select-font-weight);
1621
+ }
1622
+
1623
+ .type-select-sm {
1624
+ font-size: var(--select-font-size-sm);
1625
+ line-height: var(--select-line-height-sm);
1626
+ font-weight: var(--select-font-weight);
1627
+ }
1628
+
1629
+ .type-select-md {
1630
+ font-size: var(--select-font-size-md);
1631
+ line-height: var(--select-line-height-md);
1632
+ font-weight: var(--select-font-weight);
1633
+ }
1634
+
1635
+ .type-select-lg {
1636
+ font-size: var(--select-font-size-lg);
1637
+ line-height: var(--select-line-height-lg);
1638
+ font-weight: var(--select-font-weight);
1639
+ }
1640
+
1641
+ .type-textarea {
1642
+ font-size: var(--textarea-font-size);
1643
+ line-height: var(--textarea-line-height);
1644
+ font-weight: var(--textarea-font-weight);
1645
+ }
1646
+
1647
+ .type-sheet-title {
1648
+ font-size: var(--sheet-title-font-size);
1649
+ line-height: var(--sheet-title-line-height);
1650
+ font-weight: var(--sheet-title-font-weight);
1651
+ }
1652
+
1653
+ .type-sheet-description {
1654
+ font-size: var(--sheet-description-font-size);
1655
+ line-height: var(--sheet-description-line-height);
1656
+ font-weight: var(--sheet-description-font-weight);
1657
+ }
1658
+
1659
+ .type-table {
1660
+ font-size: var(--table-font-size);
1661
+ line-height: var(--table-line-height);
1662
+ font-weight: var(--table-font-weight);
1663
+ }
1664
+
1665
+ .type-table-head {
1666
+ font-size: var(--table-font-size);
1667
+ line-height: var(--table-line-height);
1668
+ font-weight: var(--table-head-font-weight);
1669
+ }
1670
+
1671
+ .type-bottom-navigation-label {
1672
+ font-size: var(--bottom-navigation-label-font-size);
1673
+ line-height: var(--bottom-navigation-label-line-height);
1674
+ font-weight: var(--bottom-navigation-label-font-weight);
1675
+ }
1676
+
1677
+ /* Bottom Navigation — the arriving icon pops on an overshoot spring; the
1678
+ label never moves. */
1679
+ [data-slot="bottom-navigation-item"] svg {
1680
+ transition: transform var(--motion-pop) var(--primitive-ease-overshoot);
1681
+ }
1682
+
1683
+ [data-slot="bottom-navigation-item"][data-active] svg {
1684
+ transform: translateY(-1px) scale(1.1);
1685
+ }
1686
+
1687
+ .type-sidebar-menu {
1688
+ font-size: var(--sidebar-menu-font-size);
1689
+ line-height: var(--sidebar-menu-line-height);
1690
+ font-weight: var(--sidebar-menu-font-weight);
1691
+ }
1692
+
1693
+ .type-sidebar-menu-sm {
1694
+ font-size: var(--sidebar-menu-font-size-sm);
1695
+ line-height: var(--sidebar-menu-line-height-sm);
1696
+ font-weight: var(--sidebar-menu-font-weight);
1697
+ }
1698
+
1699
+ .type-sidebar-label {
1700
+ font-size: var(--sidebar-label-font-size);
1701
+ line-height: var(--sidebar-label-line-height);
1702
+ font-weight: var(--sidebar-label-font-weight);
1703
+ }
1704
+
1705
+ /* Sidebar — active menu rows go semibold. */
1706
+ [data-sidebar="menu-button"][data-active="true"],
1707
+ [data-sidebar="menu-sub-button"][data-active="true"] {
1708
+ font-weight: var(--sidebar-menu-active-font-weight);
1709
+ }
1710
+
1711
+ /* Tabs — the list's data-size drives the trigger type; active is semibold. */
1712
+ [data-slot="tabs-list"][data-size="sm"] [data-slot="tabs-trigger"] {
1713
+ font-size: var(--tabs-trigger-font-size-sm);
1714
+ line-height: var(--tabs-trigger-line-height-sm);
1715
+ font-weight: var(--tabs-trigger-font-weight);
1716
+ }
1717
+
1718
+ [data-slot="tabs-list"][data-size="md"] [data-slot="tabs-trigger"] {
1719
+ font-size: var(--tabs-trigger-font-size-md);
1720
+ line-height: var(--tabs-trigger-line-height-md);
1721
+ font-weight: var(--tabs-trigger-font-weight);
1722
+ }
1723
+
1724
+ [data-slot="tabs-list"][data-size="lg"] [data-slot="tabs-trigger"] {
1725
+ font-size: var(--tabs-trigger-font-size-lg);
1726
+ line-height: var(--tabs-trigger-line-height-lg);
1727
+ font-weight: var(--tabs-trigger-font-weight);
1728
+ }
1729
+
1730
+ [data-slot="tabs-list"] [data-slot="tabs-trigger"][data-state="active"] {
1731
+ font-weight: var(--tabs-trigger-active-font-weight);
1732
+ }
1733
+
1734
+ .type-toggle {
1735
+ font-size: var(--toggle-font-size);
1736
+ line-height: var(--toggle-line-height);
1737
+ font-weight: var(--toggle-font-weight);
1738
+ }
1739
+
1740
+ .type-tooltip {
1741
+ font-size: var(--tooltip-font-size);
1742
+ line-height: var(--tooltip-line-height);
1743
+ font-weight: var(--tooltip-font-weight);
1744
+ }
1745
+
1746
+ .type-item-title {
1747
+ font-size: var(--item-title-font-size);
1748
+ line-height: var(--item-title-line-height);
1749
+ font-weight: var(--item-title-font-weight);
1750
+ }
1751
+
1752
+ .type-item-description {
1753
+ font-size: var(--item-description-font-size);
1754
+ line-height: var(--item-description-line-height);
1755
+ font-weight: var(--item-description-font-weight);
1756
+ }
1757
+
1758
+
1759
+ /* Input Group — the group carries the input ladder so addons, prefixes, and
1760
+ kbd hints inherit it; the input and buttons inside set their own. */
1761
+ [data-slot="input-group"][data-size="sm"] {
1762
+ font-size: var(--input-font-size-sm);
1763
+ line-height: var(--input-line-height-sm);
1764
+ font-weight: var(--input-font-weight);
1765
+ }
1766
+
1767
+ [data-slot="input-group"][data-size="md"] {
1768
+ font-size: var(--input-font-size-md);
1769
+ line-height: var(--input-line-height-md);
1770
+ font-weight: var(--input-font-weight);
1771
+ }
1772
+
1773
+ [data-slot="input-group"][data-size="lg"] {
1774
+ font-size: var(--input-font-size-lg);
1775
+ line-height: var(--input-line-height-lg);
1776
+ font-weight: var(--input-font-weight);
1777
+ }
1778
+
1779
+ .type-menu-item {
1780
+ font-size: var(--menu-item-font-size);
1781
+ line-height: var(--menu-item-line-height);
1782
+ font-weight: var(--menu-item-font-weight);
1783
+ }
1784
+ .type-menu-heading {
1785
+ font-size: var(--menu-heading-font-size);
1786
+ line-height: var(--menu-heading-line-height);
1787
+ font-weight: var(--menu-heading-font-weight);
1788
+ }
1789
+
1790
+ .type-menu-trigger {
1791
+ font-size: var(--menu-trigger-font-size);
1792
+ line-height: var(--menu-trigger-line-height);
1793
+ font-weight: var(--menu-trigger-font-weight);
1794
+ }
1795
+
1796
+ .type-menu-shortcut {
1797
+ font-size: var(--menu-shortcut-font-size);
1798
+ line-height: var(--menu-shortcut-line-height);
1799
+ font-weight: var(--menu-shortcut-font-weight);
1800
+ }
1801
+ .type-chip-md {
1802
+ font-size: var(--chip-font-size-md);
1803
+ line-height: var(--chip-line-height-md);
1804
+ font-weight: var(--chip-font-weight);
1805
+ }
1806
+ .type-chip-sm {
1807
+ font-size: var(--chip-font-size-sm);
1808
+ line-height: var(--chip-line-height-sm);
1809
+ font-weight: var(--chip-font-weight);
1810
+ }
1811
+ .type-calendar-caption {
1812
+ font-size: var(--calendar-caption-font-size);
1813
+ line-height: var(--calendar-caption-line-height);
1814
+ font-weight: var(--calendar-caption-font-weight);
1815
+ }
1816
+ .type-calendar-weekday {
1817
+ font-size: var(--calendar-weekday-font-size);
1818
+ line-height: var(--calendar-weekday-line-height);
1819
+ font-weight: var(--calendar-weekday-font-weight);
1820
+ }
1821
+ .type-calendar-day {
1822
+ font-size: var(--calendar-day-font-size);
1823
+ line-height: var(--calendar-day-line-height);
1824
+ font-weight: var(--calendar-day-font-weight);
1825
+ }
1826
+ .type-button-lg {
1827
+ font-size: var(--button-font-size-lg);
1828
+ line-height: var(--button-line-height-lg);
1829
+ font-weight: var(--button-font-weight);
1830
+ }
1831
+ .type-button-md {
1832
+ font-size: var(--button-font-size-md);
1833
+ line-height: var(--button-line-height-md);
1834
+ font-weight: var(--button-font-weight);
1835
+ }
1836
+ .type-button-sm {
1837
+ font-size: var(--button-font-size-sm);
1838
+ line-height: var(--button-line-height-sm);
1839
+ font-weight: var(--button-font-weight);
1840
+ }
1841
+ .type-breadcrumb {
1842
+ font-size: var(--breadcrumb-font-size);
1843
+ line-height: var(--breadcrumb-line-height);
1844
+ font-weight: var(--breadcrumb-font-weight);
1845
+ }
1846
+ .type-breadcrumb-page {
1847
+ font-weight: var(--breadcrumb-page-font-weight);
1848
+ }
1849
+ .type-banner-title {
1850
+ font-size: var(--banner-title-font-size);
1851
+ line-height: var(--banner-title-line-height);
1852
+ font-weight: var(--banner-title-font-weight);
1853
+ letter-spacing: var(--primitive-tracking-tight);
1854
+ }
1855
+ .type-banner-description {
1856
+ font-size: var(--banner-description-font-size);
1857
+ line-height: var(--banner-description-line-height);
1858
+ font-weight: var(--banner-description-font-weight);
1859
+ }
1860
+ .type-banner-action {
1861
+ font-size: var(--banner-action-font-size);
1862
+ line-height: var(--banner-action-line-height);
1863
+ font-weight: var(--banner-action-font-weight);
1864
+ }
1865
+ .type-section-message-title {
1866
+ font-size: var(--section-message-title-font-size);
1867
+ line-height: var(--section-message-title-line-height);
1868
+ font-weight: var(--section-message-title-font-weight);
1869
+ }
1870
+
1871
+ .type-section-message-description {
1872
+ font-size: var(--section-message-description-font-size);
1873
+ line-height: var(--section-message-description-line-height);
1874
+ font-weight: var(--section-message-description-font-weight);
1875
+ }
1876
+ .type-section-message-title-sm {
1877
+ font-size: var(--section-message-title-font-size-sm);
1878
+ line-height: var(--section-message-title-line-height-sm);
1879
+ font-weight: var(--section-message-title-font-weight);
1880
+ }
1881
+ .type-section-message-description-sm {
1882
+ font-size: var(--section-message-description-font-size-sm);
1883
+ line-height: var(--section-message-description-line-height-sm);
1884
+ font-weight: var(--section-message-description-font-weight);
1885
+ }
1886
+
1887
+ .overline {
529
1888
  font-family: var(--font-plus-jakarta-sans);
530
- font-weight: 600;
531
- font-size: 8px;
532
- line-height: 12px;
1889
+ font-weight: var(--type-overline-weight);
1890
+ font-size: var(--type-overline-size);
1891
+ line-height: var(--type-overline-line);
1892
+ letter-spacing: var(--type-overline-tracking);
1893
+ text-transform: uppercase;
1894
+ /* `overline` is also a built-in Tailwind text-decoration utility, which
1895
+ would draw a literal line above the text. Explicitly clear it — this is
1896
+ a type token (eyebrow/tag label), not a decoration. */
1897
+ text-decoration: none;
533
1898
  }
534
1899
 
535
1900
  /* ── Result block — icon motion ─────────────────────────────── */