@trading-game/design-intelligence-layer 0.17.4 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/AGENTS.md +105 -231
  2. package/README.md +50 -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 +110 -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 +1634 -252
  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,372 @@
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
+ /* Tinted canvas — the screen background: a blue tint melting into the
548
+ canvas with a soft centred aurora — the Refined composition, in token math. One token, two layers; consume via
549
+ `background: var(--background-tinted-canvas)` on the page root (an
550
+ app-shell decision — components never paint it). Every stop is token
551
+ math (blue primitives mixed into the canvas), and both themes end on
552
+ background-primary-canvas so long pages melt in without a seam. */
553
+ --background-tinted-canvas:
554
+ radial-gradient(circle at 50% -10%, color-mix(in srgb, var(--primitive-blue-400) 24%, transparent), transparent 55%),
555
+ linear-gradient(180deg,
556
+ color-mix(in srgb, var(--primitive-blue-600) 12%, var(--background-primary-canvas)) 0%,
557
+ color-mix(in srgb, var(--primitive-blue-600) 4%, var(--background-primary-canvas)) 55%,
558
+ var(--background-primary-canvas) 100%);
559
+ --background-brand-container:
560
+ linear-gradient(rgb(255 255 255 / 92%), rgb(255 255 255 / 92%)),
561
+ var(--primitive-blue-600);
562
+ /* Two layers, not a flattened colour: brand base + white 92% glaze on top,
563
+ exactly like a Figma fill stack. Static — same in both themes. Layered
564
+ values paint via `background`, not `background-color`. */
565
+ --background-inverse-surface: var(--primitive-mono-1100);
566
+
567
+ /* Status backgrounds — pale tint surfaces for Alert / Section Message */
568
+ /* Solid status fills + their shared static ink (badges, chips) */
569
+ /* Demo badge role — rides the ember scale, static in both themes */
570
+ /* Static pair — never flips; for elements on fixed-colour art panels */
571
+ --background-static-white: var(--primitive-mono-50);
572
+ --text-static-black: var(--primitive-mono-1100);
573
+ --background-demo-solid: var(--primitive-ember-500);
574
+ --background-demo-default: var(--primitive-ember-50);
575
+ --text-demo-default: var(--primitive-ember-500);
576
+ --background-success-solid: var(--primitive-green-600);
577
+ --background-error-solid: var(--primitive-red-600);
578
+ --background-warning-solid: var(--primitive-amber-600);
579
+ --text-on-status-static: var(--primitive-mono-50);
580
+ /* white on the bright 600 fills — deliberate style call, below AA on green/amber */
581
+ /* Brand-coloured text on the canvas (links, ghost badges) */
582
+ --text-brand-default: var(--primitive-blue-600);
583
+ --text-brand-hover: var(--primitive-blue-700);
584
+ /* Selection — brand-selected states (active nav, chosen chip, current page).
585
+ Light: a 10% brand tint, solid-mixed over the surface. Dark deliberately
586
+ diverges (not a mirror): stronger solid fill, lighter ink and border,
587
+ because a 10% wash vanishes on near-black and blue-400 ink loses AA. */
588
+ --background-brand-selected: color-mix(in srgb, var(--primitive-blue-600) 10%, var(--primitive-mono-50));
589
+ --text-brand-selected: var(--primitive-blue-600);
590
+ --border-brand-selected: var(--primitive-blue-600);
591
+ /* Chrome — floating mobile chrome (Bottom Navigation), straight from the
592
+ Refined Mobile file: heavy near-solid frost + a soft ambient lift. The
593
+ ambient shadow is the ONE sanctioned exception to the no-shadow rule:
594
+ floating chrome over scrolling content needs separation; inline
595
+ components still never carry shadows. The bubble is a top-lit gloss
596
+ over the brand-selected fill; layered values paint via `background:`.
597
+ Chrome ink resolves through text-subtle-default (2026-09-03, AA fix —
598
+ was the Refined file's #8A8AA0/#9A9AC4 literals, 3.4:1 on the light
599
+ frost); the frost/border/shadow literals remain until an ink scale
600
+ joins the palette. */
601
+ --background-chrome-default: rgb(255 255 255 / 78%);
602
+ --border-chrome-default: rgb(10 10 60 / 8%);
603
+ --shadow-chrome-default: 0 12px 30px rgb(10 10 60 / 14%);
604
+ --text-chrome-subtle: var(--text-subtle-default);
605
+ --background-chrome-selected:
606
+ linear-gradient(rgb(255 255 255 / 55%), rgb(255 255 255 / 15%)),
607
+ var(--background-brand-selected);
608
+ --chrome-highlight-default: var(--primitive-white-alpha-80);
609
+ --text-chrome-selected: var(--primitive-blue-600);
610
+ --background-success-default: var(--primitive-green-50);
611
+ --background-error-default: var(--primitive-red-50);
612
+ --background-warning-default: var(--primitive-amber-50);
613
+ --background-information-default: var(--primitive-azure-50);
614
+ --background-overlay-default: var(--primitive-black-alpha-50);
615
+
616
+ /* Border */
617
+ --border-default-default: var(--primitive-mono-200);
618
+ --border-prominent-default: var(--primitive-mono-1100);
619
+
620
+ /* Status borders — solid status-600 outline, same in both themes */
621
+ --border-neutral-default: var(--primitive-mono-500);
622
+ /* soft hairline for neutral tint chips */
623
+ --border-success-default: var(--primitive-green-600);
624
+ --border-error-default: var(--primitive-red-600);
625
+ --border-warning-default: var(--primitive-amber-600);
626
+ --border-information-default: var(--primitive-azure-600);
627
+
628
+ /* Text */
629
+ --text-prominent-default: var(--primitive-mono-1100);
630
+ --text-subtle-default: var(--primitive-mono-900);
631
+ --text-disabled-default: var(--primitive-mono-500);
632
+ --text-prominent-inverse: var(--primitive-mono-50);
633
+ --text-subtle-inverse: color-mix(in srgb, var(--text-prominent-inverse) 78%, var(--background-inverse-surface));
634
+ /* supporting copy on the inverse surface (Toast description) — a real
635
+ mixed ink, not an opacity hack; the ingredients flip per theme. */
636
+ --text-on-brand-static: var(--primitive-mono-50);
637
+ --text-brand-container-static: var(--primitive-blue-600);
638
+ --text-success-default: var(--primitive-green-600);
639
+ --text-error-default: var(--primitive-red-600);
640
+ --text-warning-default: var(--primitive-amber-600);
641
+ --text-information-default: var(--primitive-azure-600);
642
+
643
+ /* Icon — aliases of text today; a separate namespace so icons can diverge
644
+ later (icons only need 3:1, so they may one day get brighter steps). */
645
+ --icon-prominent-default: var(--text-prominent-default);
646
+ --icon-subtle-default: var(--text-subtle-default);
647
+ --icon-disabled-default: var(--text-disabled-default);
648
+ --icon-success-default: var(--text-success-default);
649
+ --icon-error-default: var(--text-error-default);
650
+ --icon-warning-default: var(--text-warning-default);
651
+ --icon-information-default: var(--text-information-default);
652
+
653
+ /* Ring */
654
+ --ring-focus-default: var(--primitive-blue-600);
655
+ --ring-focus-strong: color-mix(in srgb, var(--ring-focus-default) 50%, transparent);
656
+ /* the 3px control focus ring */
657
+ --ring-focus-soft: color-mix(in srgb, var(--ring-focus-default) 8%, transparent);
658
+ /* the soft text-field focus ring */
659
+ --ring-error-default: var(--text-error-default);
660
+ --ring-error-soft: color-mix(in srgb, var(--ring-error-default) 20%, transparent);
661
+ /* invalid-field ring */
662
+ --ring-brand-soft: color-mix(in srgb, var(--background-brand-default) 40%, transparent);
663
+ /* brand hairline ring — sidebar icon-rail hover/active */
664
+
665
+ /* ── @deprecated aliases — the old semantic layer, repointed at the new
666
+ tokens. Each is deleted when the last component using it migrates. ── */
667
+ --prominent: var(--background-primary-canvas);
668
+ --on-prominent: var(--text-prominent-default);
669
+ --prominent-inverse: var(--background-inverse-surface);
670
+ --on-prominent-inverse: var(--text-prominent-inverse);
671
+ --primary: var(--background-brand-default);
672
+ --on-primary: var(--text-on-brand-static);
277
673
  --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);
674
+ --on-primary-inverse: var(--text-brand-container-static);
675
+ --primary-hover: var(--background-brand-hover);
676
+ --on-prominent-static-inverse: var(--text-prominent-inverse);
677
+ --surface-inverse-static: var(--primitive-mono-50);
678
+ --subtle: var(--primitive-mono-100);
679
+ --on-subtle: var(--text-subtle-default);
680
+ --on-disabled: var(--text-disabled-default);
681
+
682
+ --border-subtle: var(--border-default-default);
683
+ --border: var(--border-default-default);
684
+ --border-prominent: var(--border-prominent-default);
685
+ --secondary-hover: var(--background-hover-default);
686
+ --ring: var(--ring-focus-default);
687
+ --overlay: var(--background-overlay-default);
688
+ --semantic-win: var(--text-success-default);
299
689
  --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);
690
+ --semantic-loss: var(--text-error-default);
302
691
  --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);
692
+ --semantic-info: var(--text-information-default);
693
+ --semantic-error: var(--text-error-default);
694
+ --semantic-warning: var(--text-warning-default);
307
695
  --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);
696
+ --semantic-demo: #FF6600;
697
+ /* TODO revisit with Badge — demo-account marker, outside the status set */
698
+ --semantic-demo-surface: color-mix(in srgb, var(--semantic-demo) 10%, var(--primitive-mono-50));
699
+ --semantic-boost: #F9840F;
700
+ /* TODO revisit with Badge — credit/boost marker, outside the status set */
701
+ --semantic-boost-surface: rgb(255 255 255 / 22%);
702
+ --on-semantic-boost: #521900;
703
+ /* TODO revisit with Badge */
704
+ --tabs: var(--primitive-black-alpha-4);
325
705
  --tabs-active: var(--primitive-mono-50);
326
706
 
327
707
  --semantic-layout-diagram-max-default: var(--primitive-layout-diagram-max-default);
328
708
  --semantic-layout-diagram-max-small: var(--primitive-layout-diagram-max-small);
329
709
  --semantic-layout-diagram-max-medium: var(--primitive-layout-diagram-max-medium);
330
710
 
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 */
711
+ /* ── Motion — Semantic roles ─────────────────────────────────
712
+ The duration and ease utilities resolve through these, so a
713
+ role retunes every consumer in one line. Roles never flip in
714
+ dark. Press is a pattern, not a utility: apply with
715
+ `active:duration-0` so the glaze lands the frame it happens
716
+ and fades on release. */
717
+ --motion-hover: var(--primitive-duration-fast);
718
+ /* hover tints & fills arriving (backs the duration-fast utility) */
719
+ --motion-hover-ease: var(--primitive-ease-standard);
720
+ --motion-press: 0ms;
721
+ /* pressed state lands instantly */
722
+ --motion-press-release: var(--primitive-duration-fast);
723
+ /* …and fades out on release */
724
+ --motion-surface: var(--primitive-duration-base);
725
+ /* menus, popovers, tooltips (backs the duration-base utility) */
726
+ --motion-surface-enter: var(--primitive-ease-enter);
727
+ --motion-surface-exit: var(--primitive-ease-exit);
728
+ --motion-overlay-open: 320ms;
729
+ /* dialogs, sheets, drawers entering (ease-enter) */
730
+ --motion-overlay-close: 250ms;
731
+ /* …and leaving (ease-exit) — exits are quicker */
732
+ --motion-structural: var(--primitive-duration-base);
733
+ /* sidebar collapse, accordion, chevrons */
734
+ --motion-structural-ease: var(--primitive-ease-linear);
735
+ --motion-progress: var(--primitive-duration-slow);
736
+ /* bars & timers (backs the duration-slow utility) */
737
+ --motion-progress-ease: var(--primitive-ease-linear);
738
+
739
+ /* ── Motion — Signature moves ────────────────────────────────
740
+ The liquid selection language, named. Travel pairs with
741
+ ease-spring; pop pairs with ease-overshoot. */
742
+ --motion-travel-lead: 200ms;
743
+ /* liquid indicator leading edge */
744
+ --motion-travel-trail: 380ms;
745
+ /* liquid indicator trailing edge, dragged behind */
746
+ --motion-pop: 450ms;
747
+ /* arrival pop — icon lift, chip tick, success check */
748
+ }
749
+
750
+ /* ══════════════════════════════════════════════════════════════
751
+ DARK THEME — semantic overrides only.
752
+ Primitives never change; each semantic token repoints to a
753
+ different step. Activate with class="dark" or data-theme="dark".
754
+ ══════════════════════════════════════════════════════════════ */
755
+ .dark,
756
+ [data-theme="dark"] {
757
+ /* Background */
758
+ --background-primary-canvas: var(--primitive-blue-1000);
759
+ --background-primary-surface: color-mix(in srgb, white 6%, var(--primitive-blue-1000));
760
+ --background-secondary-surface: color-mix(in srgb, white 12%, var(--primitive-blue-1000));
761
+ /* solid #1F1F3A — one glaze step above the card (6%) */
762
+ /* solid #0F0F2C — base + white glaze, flattened */
763
+ --background-hover-default: var(--primitive-white-alpha-12);
764
+ --background-pressed-default: var(--primitive-white-alpha-20);
765
+ --background-brand-default: var(--primitive-blue-400);
766
+ /* brand-hover / brand-pressed need no override — the black state layer
767
+ recipe re-derives from the dark brand automatically */
768
+ --background-inverse-surface: var(--primitive-mono-50);
769
+
770
+ /* Status backgrounds — solid base + 24% status glaze */
771
+ --background-success-default: color-mix(in srgb, var(--primitive-green-600) 24%, var(--primitive-blue-1000));
772
+ --background-error-default: color-mix(in srgb, var(--primitive-red-600) 24%, var(--primitive-blue-1000));
773
+ --background-warning-default: color-mix(in srgb, var(--primitive-amber-600) 24%, var(--primitive-blue-1000));
774
+ --background-information-default: color-mix(in srgb, var(--primitive-azure-600) 24%, var(--primitive-blue-1000));
775
+ --background-overlay-default: var(--primitive-black-alpha-64);
776
+
777
+ /* Border */
778
+ --border-default-default: var(--primitive-white-alpha-12);
779
+ --border-prominent-default: var(--primitive-mono-50);
780
+ --border-neutral-default: var(--primitive-white-alpha-12);
781
+
782
+ /* Text */
783
+ --text-prominent-default: var(--primitive-mono-50);
784
+ --text-subtle-default: var(--primitive-mono-600);
785
+ --text-disabled-default: var(--primitive-mono-800);
786
+ --text-prominent-inverse: var(--primitive-mono-1100);
787
+ /* status + on-brand + brand-container are static — no overrides */
788
+
789
+ /* Ring */
790
+ --ring-focus-default: var(--primitive-blue-400);
791
+ --text-brand-default: var(--primitive-blue-400);
792
+ --text-brand-hover: var(--primitive-blue-300);
793
+ --background-brand-selected: color-mix(in srgb, var(--primitive-blue-400) 24%, var(--primitive-blue-1000));
794
+ --background-tinted-canvas:
795
+ radial-gradient(circle at 60% 15%, color-mix(in srgb, var(--primitive-blue-400) 28%, transparent), transparent 55%),
796
+ linear-gradient(180deg,
797
+ color-mix(in srgb, var(--primitive-blue-400) 14%, var(--background-primary-canvas)) 0%,
798
+ var(--background-primary-canvas) 100%);
799
+ --text-brand-selected: var(--primitive-blue-200);
800
+ --border-brand-selected: var(--primitive-blue-300);
801
+ --background-chrome-default: rgb(20 20 44 / 72%);
802
+ --border-chrome-default: rgb(255 255 255 / 14%);
803
+ --shadow-chrome-default: 0 12px 30px rgb(0 0 20 / 50%);
804
+ --text-chrome-subtle: var(--text-subtle-default);
805
+ --background-chrome-selected:
806
+ linear-gradient(rgb(255 255 255 / 10%), rgb(255 255 255 / 0%)),
807
+ var(--background-brand-selected);
808
+ --chrome-highlight-default: var(--primitive-white-alpha-24);
809
+ --text-chrome-selected: var(--primitive-mono-50);
810
+
811
+ /* @deprecated aliases that don't resolve through a flipping token */
812
+ --primary-inverse: var(--primitive-mono-50);
813
+ --subtle: color-mix(in srgb, white 8%, var(--primitive-blue-1000));
814
+ --tabs: var(--primitive-white-alpha-8);
815
+ --tabs-active: color-mix(in srgb, white 12%, var(--primitive-blue-1000));
352
816
  }
353
817
 
818
+
354
819
  /* ══════════════════════════════════════════════════════════════
355
820
  RESPONSIVE LAYOUT — Standard grid (columns / gutter / margin)
356
821
  ══════════════════════════════════════════════════════════════ */
@@ -389,28 +854,312 @@
389
854
  Component-specific tokens. References semantics or primitives.
390
855
  ══════════════════════════════════════════════════════════════ */
391
856
  :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);
857
+ --card: var(--background-primary-surface);
858
+ --card-foreground: var(--text-prominent-default);
859
+ --popover: var(--background-primary-surface);
860
+ --popover-foreground: var(--text-prominent-default);
396
861
  --input: var(--border-subtle);
397
862
  /* Sunken dark fill for Input/InputGroup variant="inverse" — sits on
398
863
  coloured surfaces (brand-blue, etc.) where a frosted-white fill would
399
864
  blend into the surrounding chrome. 35 % black overlay deepens the
400
865
  surface enough for white text to read cleanly. */
401
- --input-inverse-surface: oklch(0 0 0 / 0.35);
866
+ --input-inverse-surface: rgb(0 0 0 / 35%);
867
+ /* ── Accordion — component type tokens (private) ──
868
+ Typography follows the same three-layer model as color: these reference
869
+ primitives only and are consumed by Accordion alone — retuning them
870
+ never affects any other component. */
871
+ --accordion-trigger-font-size: var(--primitive-font-size-14);
872
+ --accordion-trigger-font-weight: var(--primitive-font-weight-medium);
873
+ --accordion-trigger-line-height: var(--primitive-line-height-20);
874
+ --accordion-content-font-size: var(--primitive-font-size-14);
875
+ --accordion-content-font-weight: var(--primitive-font-weight-regular);
876
+ --accordion-content-line-height: var(--primitive-line-height-20);
877
+ /* ── Banner — component type tokens (private) ──
878
+ The editorial gradient panel: extrabold title, medium supporting line,
879
+ extrabold pill CTA — matching the design file's 800/500/800 weights. */
880
+ --banner-title-font-size: var(--primitive-font-size-18);
881
+ --banner-title-font-weight: var(--primitive-font-weight-semibold);
882
+ --banner-title-line-height: var(--primitive-line-height-24);
883
+ --banner-description-font-size: var(--primitive-font-size-12);
884
+ --banner-description-font-weight: var(--primitive-font-weight-medium);
885
+ --banner-description-line-height: var(--primitive-line-height-16);
886
+ --banner-action-font-size: var(--primitive-font-size-12);
887
+ --banner-action-font-weight: var(--primitive-font-weight-semibold);
888
+ --banner-action-line-height: var(--primitive-line-height-16);
889
+ /* ── Menu family — shared type tokens (private) ──
890
+ One deliberate shared anatomy for Command, Context Menu, Dropdown
891
+ Menu, Menubar, and Select rows: retune here, every menu follows. */
892
+ --menu-item-font-size: var(--primitive-font-size-14);
893
+ --menu-item-line-height: var(--primitive-line-height-20);
894
+ --menu-item-font-weight: var(--primitive-font-weight-regular);
895
+ --menu-heading-font-size: var(--primitive-font-size-12);
896
+ --menu-heading-line-height: var(--primitive-line-height-16);
897
+ --menu-trigger-font-size: var(--primitive-font-size-14);
898
+ --menu-trigger-font-weight: var(--primitive-font-weight-medium);
899
+ --menu-trigger-line-height: var(--primitive-line-height-20);
900
+ --menu-shortcut-font-size: var(--primitive-font-size-12);
901
+ --menu-shortcut-font-weight: var(--primitive-font-weight-regular);
902
+ --menu-shortcut-line-height: var(--primitive-line-height-16);
903
+ --menu-heading-font-weight: var(--primitive-font-weight-medium);
904
+ /* ── Chip — component type tokens (private) ── */
905
+ --chip-font-size-md: var(--primitive-font-size-14);
906
+ --chip-line-height-md: var(--primitive-line-height-20);
907
+ --chip-font-size-sm: var(--primitive-font-size-12);
908
+ --chip-line-height-sm: var(--primitive-line-height-16);
909
+ --chip-font-weight: var(--primitive-font-weight-semibold);
910
+ /* ── Calendar — component type tokens (private) ── */
911
+ --calendar-caption-font-size: var(--primitive-font-size-14);
912
+ --calendar-caption-font-weight: var(--primitive-font-weight-semibold);
913
+ --calendar-caption-line-height: var(--primitive-line-height-20);
914
+ --calendar-weekday-font-size: var(--primitive-font-size-12);
915
+ --calendar-weekday-font-weight: var(--primitive-font-weight-medium);
916
+ --calendar-weekday-line-height: var(--primitive-line-height-16);
917
+ --calendar-day-font-size: var(--primitive-font-size-14);
918
+ --calendar-day-font-weight: var(--primitive-font-weight-regular);
919
+ --calendar-day-line-height: var(--primitive-line-height-20);
920
+ /* ── Button — component type tokens (private) ──
921
+ One primitive step per size (18/16/14), icons tracking the height. */
922
+ --button-font-size-lg: var(--primitive-font-size-18);
923
+ --button-line-height-lg: var(--primitive-line-height-24);
924
+ --button-font-size-md: var(--primitive-font-size-16);
925
+ --button-line-height-md: var(--primitive-line-height-24);
926
+ --button-font-size-sm: var(--primitive-font-size-14);
927
+ --button-line-height-sm: var(--primitive-line-height-20);
928
+ --button-font-weight: var(--primitive-font-weight-semibold);
929
+ /* ── Breadcrumb — component type tokens (private) ── */
930
+ --breadcrumb-font-size: var(--primitive-font-size-14);
931
+ --breadcrumb-font-weight: var(--primitive-font-weight-regular);
932
+ --breadcrumb-line-height: var(--primitive-line-height-20);
933
+ --breadcrumb-page-font-weight: var(--primitive-font-weight-medium);
934
+ /* ── Section Message — component type tokens (private) ──
935
+ Line-heights follow the foundation's pairing for each size (14→20, 12→16),
936
+ replacing the old 1.375 ratio that rendered fractional 19.25/16.5px. */
937
+ --section-message-title-font-size: var(--primitive-font-size-14);
938
+ --section-message-title-font-weight: var(--primitive-font-weight-semibold);
939
+ --section-message-title-line-height: var(--primitive-line-height-20);
940
+ --section-message-description-font-size: var(--primitive-font-size-14);
941
+ --section-message-description-font-weight: var(--primitive-font-weight-regular);
942
+ --section-message-description-line-height: var(--primitive-line-height-20);
943
+ /* sm density — one scale step below md */
944
+ --section-message-title-font-size-sm: var(--primitive-font-size-12);
945
+ --section-message-title-line-height-sm: var(--primitive-line-height-16);
946
+ --section-message-description-font-size-sm: var(--primitive-font-size-12);
947
+ --section-message-description-line-height-sm: var(--primitive-line-height-16);
948
+ /* ── Alert Dialog — component type tokens (private) ── */
949
+ --alert-dialog-title-font-size: var(--primitive-font-size-18);
950
+ --alert-dialog-title-font-weight: var(--primitive-font-weight-semibold);
951
+ --alert-dialog-title-line-height: var(--primitive-line-height-24);
952
+ --alert-dialog-description-font-size: var(--primitive-font-size-14);
953
+ --alert-dialog-description-font-weight: var(--primitive-font-weight-regular);
954
+ --alert-dialog-description-line-height: var(--primitive-line-height-20);
955
+ /* ── Dialog — component type tokens (private) ──
956
+ Same ladder as Alert Dialog: 18/semibold/24 title, 14/regular/20 body. */
957
+ --dialog-title-font-size: var(--primitive-font-size-18);
958
+ --dialog-title-font-weight: var(--primitive-font-weight-semibold);
959
+ --dialog-title-line-height: var(--primitive-line-height-24);
960
+ --dialog-description-font-size: var(--primitive-font-size-14);
961
+ --dialog-description-font-weight: var(--primitive-font-weight-regular);
962
+ --dialog-description-line-height: var(--primitive-line-height-20);
963
+ /* ── Drawer — component type tokens (private) ──
964
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
965
+ --drawer-title-font-size: var(--primitive-font-size-18);
966
+ --drawer-title-font-weight: var(--primitive-font-weight-semibold);
967
+ --drawer-title-line-height: var(--primitive-line-height-24);
968
+ --drawer-description-font-size: var(--primitive-font-size-14);
969
+ --drawer-description-font-weight: var(--primitive-font-weight-regular);
970
+ --drawer-description-line-height: var(--primitive-line-height-20);
971
+ /* ── Empty — component type tokens (private) ──
972
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
973
+ --empty-title-font-size: var(--primitive-font-size-18);
974
+ --empty-title-font-weight: var(--primitive-font-weight-semibold);
975
+ --empty-title-line-height: var(--primitive-line-height-24);
976
+ --empty-description-font-size: var(--primitive-font-size-14);
977
+ --empty-description-font-weight: var(--primitive-font-weight-regular);
978
+ --empty-description-line-height: var(--primitive-line-height-20);
979
+ /* ── Field — component type tokens (private) ──
980
+ Legend 16/medium/24 (label variant one step down), body 14/regular/20;
981
+ FieldError rides the description ladder in error ink. */
982
+ --field-legend-font-size: var(--primitive-font-size-16);
983
+ --field-legend-font-weight: var(--primitive-font-weight-medium);
984
+ --field-legend-line-height: var(--primitive-line-height-24);
985
+ --field-legend-label-font-size: var(--primitive-font-size-14);
986
+ --field-legend-label-font-weight: var(--primitive-font-weight-medium);
987
+ --field-legend-label-line-height: var(--primitive-line-height-20);
988
+ /* Label rides the control's text step per size; helper text stays 12
989
+ at every size (help text shouldn't shout). */
990
+ --field-label-font-size-sm: var(--primitive-font-size-12);
991
+ --field-label-line-height-sm: var(--primitive-line-height-16);
992
+ --field-label-font-size-md: var(--primitive-font-size-14);
993
+ --field-label-line-height-md: var(--primitive-line-height-20);
994
+ --field-label-font-size-lg: var(--primitive-font-size-16);
995
+ --field-label-line-height-lg: var(--primitive-line-height-24);
996
+ --field-label-font-weight: var(--primitive-font-weight-medium);
997
+ --field-description-font-size: var(--primitive-font-size-12);
998
+ --field-description-font-weight: var(--primitive-font-weight-regular);
999
+ --field-description-line-height: var(--primitive-line-height-16);
1000
+ /* ── Input — component type tokens (private) ──
1001
+ One primitive step per size (12/14/16), matching the Field label ladder. */
1002
+ --input-font-size-sm: var(--primitive-font-size-12);
1003
+ --input-line-height-sm: var(--primitive-line-height-16);
1004
+ --input-font-size-md: var(--primitive-font-size-14);
1005
+ --input-line-height-md: var(--primitive-line-height-20);
1006
+ --input-font-size-lg: var(--primitive-font-size-16);
1007
+ --input-line-height-lg: var(--primitive-line-height-24);
1008
+ --input-font-weight: var(--primitive-font-weight-regular);
1009
+ /* ── Input OTP — component type tokens (private) ──
1010
+ Digits ride the input md step (14/regular/20). */
1011
+ --input-otp-font-size: var(--primitive-font-size-14);
1012
+ --input-otp-font-weight: var(--primitive-font-weight-regular);
1013
+ --input-otp-line-height: var(--primitive-line-height-20);
1014
+ /* ── Native Select — component type tokens (private) ──
1015
+ Same ladder as Input (12/14/16, regular). */
1016
+ --native-select-font-size-sm: var(--primitive-font-size-12);
1017
+ --native-select-line-height-sm: var(--primitive-line-height-16);
1018
+ --native-select-font-size-md: var(--primitive-font-size-14);
1019
+ --native-select-line-height-md: var(--primitive-line-height-20);
1020
+ --native-select-font-size-lg: var(--primitive-font-size-16);
1021
+ --native-select-line-height-lg: var(--primitive-line-height-24);
1022
+ --native-select-font-weight: var(--primitive-font-weight-regular);
1023
+ /* ── Select — component type tokens (private) ──
1024
+ Trigger rides the input ladder (12/14/16, regular); rows use the menu family. */
1025
+ --select-font-size-sm: var(--primitive-font-size-12);
1026
+ --select-line-height-sm: var(--primitive-line-height-16);
1027
+ --select-font-size-md: var(--primitive-font-size-14);
1028
+ --select-line-height-md: var(--primitive-line-height-20);
1029
+ --select-font-size-lg: var(--primitive-font-size-16);
1030
+ --select-line-height-lg: var(--primitive-line-height-24);
1031
+ --select-font-weight: var(--primitive-font-weight-regular);
1032
+ /* ── Textarea — component type tokens (private) ──
1033
+ Rides the input md step (14/regular/20). */
1034
+ --textarea-font-size: var(--primitive-font-size-14);
1035
+ --textarea-font-weight: var(--primitive-font-weight-regular);
1036
+ --textarea-line-height: var(--primitive-line-height-20);
1037
+ /* ── Sheet — component type tokens (private) ──
1038
+ Same ladder as Dialog: 18/semibold/24 title, 14/regular/20 body. */
1039
+ --sheet-title-font-size: var(--primitive-font-size-18);
1040
+ --sheet-title-font-weight: var(--primitive-font-weight-semibold);
1041
+ --sheet-title-line-height: var(--primitive-line-height-24);
1042
+ --sheet-description-font-size: var(--primitive-font-size-14);
1043
+ --sheet-description-font-weight: var(--primitive-font-weight-regular);
1044
+ --sheet-description-line-height: var(--primitive-line-height-20);
1045
+ /* ── Table — component type tokens (private) ──
1046
+ Cells 14/regular/20; header + footer 14/medium/20. */
1047
+ --table-font-size: var(--primitive-font-size-14);
1048
+ --table-font-weight: var(--primitive-font-weight-regular);
1049
+ --table-line-height: var(--primitive-line-height-20);
1050
+ --table-head-font-weight: var(--primitive-font-weight-medium);
1051
+ /* ── Bottom Navigation — component type tokens (private) ──
1052
+ 12/medium/16 labels; the active destination goes semibold. */
1053
+ --bottom-navigation-label-font-size: var(--primitive-font-size-12);
1054
+ --bottom-navigation-label-font-weight: var(--primitive-font-weight-medium);
1055
+ --bottom-navigation-label-line-height: var(--primitive-line-height-16);
1056
+ --bottom-navigation-label-active-font-weight: var(--primitive-font-weight-semibold);
1057
+ /* ── Sidebar — component type tokens (private) ──
1058
+ Menu rows 14/regular/20 (sm 12/16); labels + badges 12/medium/16.
1059
+ Active rows go semibold via the data-active rule below. */
1060
+ --sidebar-menu-font-size: var(--primitive-font-size-14);
1061
+ --sidebar-menu-line-height: var(--primitive-line-height-20);
1062
+ --sidebar-menu-font-size-sm: var(--primitive-font-size-12);
1063
+ --sidebar-menu-line-height-sm: var(--primitive-line-height-16);
1064
+ --sidebar-menu-font-weight: var(--primitive-font-weight-regular);
1065
+ --sidebar-menu-active-font-weight: var(--primitive-font-weight-semibold);
1066
+ --sidebar-label-font-size: var(--primitive-font-size-12);
1067
+ --sidebar-label-line-height: var(--primitive-line-height-16);
1068
+ --sidebar-label-font-weight: var(--primitive-font-weight-medium);
1069
+ /* ── Tabs — component type tokens (private) ──
1070
+ Trigger rides one primitive step per list size (12/14/16); active goes
1071
+ semibold via the data-state rule below. */
1072
+ --tabs-trigger-font-size-sm: var(--primitive-font-size-12);
1073
+ --tabs-trigger-line-height-sm: var(--primitive-line-height-16);
1074
+ --tabs-trigger-font-size-md: var(--primitive-font-size-14);
1075
+ --tabs-trigger-line-height-md: var(--primitive-line-height-20);
1076
+ --tabs-trigger-font-size-lg: var(--primitive-font-size-16);
1077
+ --tabs-trigger-line-height-lg: var(--primitive-line-height-24);
1078
+ --tabs-trigger-font-weight: var(--primitive-font-weight-regular);
1079
+ --tabs-trigger-active-font-weight: var(--primitive-font-weight-semibold);
1080
+ /* ── Toggle — component type tokens (private) ── */
1081
+ --toggle-font-size: var(--primitive-font-size-14);
1082
+ --toggle-font-weight: var(--primitive-font-weight-medium);
1083
+ --toggle-line-height: var(--primitive-line-height-20);
1084
+ /* ── Tooltip — component type tokens (private) ── */
1085
+ --tooltip-font-size: var(--primitive-font-size-14);
1086
+ --tooltip-font-weight: var(--primitive-font-weight-medium);
1087
+ --tooltip-line-height: var(--primitive-line-height-20);
1088
+ /* ── Item — component type tokens (private) ──
1089
+ List rows: 14/medium/20 title, 14/regular/20 body. */
1090
+ --item-title-font-size: var(--primitive-font-size-14);
1091
+ --item-title-font-weight: var(--primitive-font-weight-medium);
1092
+ --item-title-line-height: var(--primitive-line-height-20);
1093
+ --item-description-font-size: var(--primitive-font-size-14);
1094
+ --item-description-font-weight: var(--primitive-font-weight-regular);
1095
+ --item-description-line-height: var(--primitive-line-height-20);
1096
+ /* ── Numpad — component type tokens (private) ──
1097
+ Bare digit keys: 20/medium/28. */
1098
+ --numpad-font-size: var(--primitive-font-size-20);
1099
+ --numpad-font-weight: var(--primitive-font-weight-medium);
1100
+ --numpad-line-height: var(--primitive-line-height-28);
1101
+ /* ── Pagination — component type tokens (private) ── */
1102
+ --pagination-font-size: var(--primitive-font-size-14);
1103
+ --pagination-font-weight: var(--primitive-font-weight-semibold);
1104
+ --pagination-line-height: var(--primitive-line-height-20);
1105
+ /* ── Popover — component type tokens (private) ── */
1106
+ --popover-title-font-size: var(--primitive-font-size-14);
1107
+ --popover-title-font-weight: var(--primitive-font-weight-medium);
1108
+ --popover-title-line-height: var(--primitive-line-height-20);
1109
+ --popover-description-font-size: var(--primitive-font-size-14);
1110
+ --popover-description-font-weight: var(--primitive-font-weight-regular);
1111
+ --popover-description-line-height: var(--primitive-line-height-20);
1112
+ /* ── Label — component type tokens (private) ── */
1113
+ --label-font-size: var(--primitive-font-size-14);
1114
+ --label-font-weight: var(--primitive-font-weight-medium);
1115
+ --label-line-height: var(--primitive-line-height-20);
1116
+ /* ── Link — component type tokens (private) ──
1117
+ One primitive step per size (16/14/12), semibold like Button. */
1118
+ --link-font-size-lg: var(--primitive-font-size-16);
1119
+ --link-line-height-lg: var(--primitive-line-height-24);
1120
+ --link-font-size-md: var(--primitive-font-size-14);
1121
+ --link-line-height-md: var(--primitive-line-height-20);
1122
+ --link-font-size-sm: var(--primitive-font-size-12);
1123
+ --link-line-height-sm: var(--primitive-line-height-16);
1124
+ --link-font-weight: var(--primitive-font-weight-semibold);
1125
+ /* ── Avatar — component type tokens (private) ──
1126
+ The initials scale with the avatar's own size prop (not the viewport):
1127
+ 12px in a 24px circle, 16px in a 48px one. Weight stays 400, matching
1128
+ what the component rendered before it had tokens. */
1129
+ --avatar-fallback-font-size-sm: var(--primitive-font-size-12);
1130
+ --avatar-fallback-line-height-sm: var(--primitive-line-height-16);
1131
+ --avatar-fallback-font-size: var(--primitive-font-size-14);
1132
+ --avatar-fallback-line-height: var(--primitive-line-height-20);
1133
+ --avatar-fallback-font-size-xl: var(--primitive-font-size-16);
1134
+ --avatar-fallback-line-height-xl: var(--primitive-line-height-24);
1135
+ --avatar-fallback-font-weight: var(--primitive-font-weight-regular);
1136
+ --avatar-group-count-font-size: var(--primitive-font-size-14);
1137
+ --avatar-group-count-line-height: var(--primitive-line-height-20);
1138
+ --avatar-group-count-font-weight: var(--primitive-font-weight-regular);
1139
+ /* ── Badge — component type tokens (private) ──
1140
+ Four sizes; xs is the 10px stamp scale used for status and catalogue
1141
+ corner pills, below the shared type scale's 12px floor. */
1142
+ --badge-font-size-xs: var(--primitive-font-size-10);
1143
+ --badge-line-height-xs: var(--primitive-line-height-16);
1144
+ --badge-font-size-sm: var(--primitive-font-size-12);
1145
+ --badge-line-height-sm: var(--primitive-line-height-16);
1146
+ --badge-font-size-md: var(--primitive-font-size-14);
1147
+ --badge-line-height-md: var(--primitive-line-height-20);
1148
+ --badge-font-size-lg: var(--primitive-font-size-16);
1149
+ --badge-line-height-lg: var(--primitive-line-height-24);
1150
+ --badge-font-weight: var(--primitive-font-weight-semibold);
402
1151
  --alert-info-text: var(--semantic-info);
403
1152
  --alert-info-border: var(--semantic-info);
404
1153
  --alert-error-text: var(--semantic-error);
405
1154
  --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);
1155
+ --slider-range: var(--primitive-blue-alpha-40);
1156
+ --sidebar: var(--background-primary-surface);
1157
+ --sidebar-foreground: var(--text-prominent-default);
409
1158
  --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);
1159
+ --sidebar-primary-foreground: var(--text-on-brand-static);
1160
+ --sidebar-accent: var(--primitive-mono-100);
1161
+ --sidebar-accent-foreground: var(--text-prominent-default);
1162
+ --sidebar-border: var(--border-default-default);
414
1163
  --sidebar-ring: var(--ring);
415
1164
  }
416
1165
 
@@ -421,7 +1170,7 @@
421
1170
  }
422
1171
 
423
1172
  body {
424
- @apply bg-prominent text-on-prominent font-sans antialiased;
1173
+ @apply bg-background-primary-canvas text-text-prominent-default font-sans antialiased;
425
1174
  }
426
1175
  }
427
1176
 
@@ -446,6 +1195,12 @@
446
1195
  100% { transform: translateX(100%); opacity: 1; }
447
1196
  }
448
1197
 
1198
+ /* Skeleton — directional loading sweep (replaces the generic pulse) */
1199
+ @keyframes skeleton-sweep {
1200
+ from { transform: translateX(-100%); }
1201
+ to { transform: translateX(100%); }
1202
+ }
1203
+
449
1204
  /* Spinner — pill-style activity indicator */
450
1205
  @keyframes spinner-fade {
451
1206
  0% {
@@ -453,83 +1208,710 @@
453
1208
  }
454
1209
 
455
1210
  100% {
456
- opacity: 0.2;
1211
+ opacity: 0.15;
1212
+ }
1213
+ }
1214
+
1215
+ /* ── GameLoadingBlock ────────────────────────────────────────────────
1216
+ Brand-blue dotted splash backdrop. The dot colour is derived from the
1217
+ --on-primary token (not a raw white) so it tracks the palette; the dot
1218
+ grid is a background-image, which Tailwind utilities can't express
1219
+ cleanly, so it lives here as a class. */
1220
+ .game-loader-backdrop {
1221
+ background-color: var(--primary);
1222
+ background-image: radial-gradient(
1223
+ color-mix(in oklch, var(--on-primary) 16%, transparent) 1px,
1224
+ transparent 1px
1225
+ );
1226
+ background-size: 14px 14px;
1227
+ }
1228
+
1229
+ /* Exit reveal — the monogram hangs, snaps outward, and the app is revealed
1230
+ behind it (X/Twitter-style). Suppressed under prefers-reduced-motion by
1231
+ the component, which falls back to a plain fade. */
1232
+ @keyframes game-loader-zoom {
1233
+ 0% {
1234
+ transform: scale(1);
1235
+ animation-timing-function: cubic-bezier(0.3, 0, 0.5, 1);
1236
+ }
1237
+
1238
+ 22% {
1239
+ transform: scale(0.85);
1240
+ animation-timing-function: cubic-bezier(0.7, 0, 0.85, 0.35);
1241
+ }
1242
+
1243
+ 100% {
1244
+ transform: scale(22);
457
1245
  }
458
1246
  }
459
1247
 
460
- /* Typography — Heading scale (Plus Jakarta Sans · Semibold 600 · LS 1.5px) */
461
- .heading-h1 {
1248
+ .game-loader-mark {
1249
+ transform-origin: center;
1250
+ will-change: transform;
1251
+ }
1252
+
1253
+ .game-loader-mark-exit {
1254
+ animation: game-loader-zoom 0.34s forwards;
1255
+ }
1256
+
1257
+ /* Progress-bar shimmer — sweeps across the filled portion while a stage is
1258
+ still loading, so a held bar still reads as "working". */
1259
+ @keyframes game-loader-sweep {
1260
+ 0% {
1261
+ left: -60%;
1262
+ }
1263
+
1264
+ 100% {
1265
+ left: 110%;
1266
+ }
1267
+ }
1268
+
1269
+ .game-loader-shimmer {
1270
+ background: linear-gradient(
1271
+ 90deg,
1272
+ transparent,
1273
+ color-mix(in oklch, var(--primary) 35%, transparent),
1274
+ transparent
1275
+ );
1276
+ animation: game-loader-sweep 1.4s ease-in-out infinite;
1277
+ }
1278
+
1279
+ /* ─────────────────────────────────────────────────────────────────
1280
+ Typography — Plus Jakarta Sans
1281
+ Sentence-case headings in mixed weights (600–800) with tight tracking,
1282
+ and a Regular-weight body. 8-point aligned; the top four heading sizes
1283
+ scale fluidly on small screens via clamp().
1284
+
1285
+ Weight roles:
1286
+ 400 Regular — body
1287
+ 500 Medium — captions, dense UI
1288
+ 600 SemiBold — subheads, emphasis
1289
+ 700 Bold — headings
1290
+ 800 ExtraBold — display
1291
+ ───────────────────────────────────────────────────────────────── */
1292
+
1293
+ /* Display & headings (600–800) — the top four scale fluidly. Both font-size
1294
+ AND line-height clamp between each style's -mobile and -desktop tokens, so
1295
+ they land on the 8-point grid at each end: e.g. display 56/64 (desktop) →
1296
+ 36/40 (mobile). Every number below is a semantic --type-* token (§ above),
1297
+ never a raw literal — the vw-based midpoint is the interpolation formula
1298
+ itself, not a "value," so it stays inline.
1299
+
1300
+ ONE CLASS PER TIER — sizes, line-heights and weights come from the
1301
+ --type-* tokens, which carry both mobile and desktop values, so a tier
1302
+ never changes name between breakpoints. h1–h6 are style names, not HTML
1303
+ tags. Changing a tier's look is a one-line token edit here and updates
1304
+ every product. */
1305
+ .display {
462
1306
  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;
1307
+ font-weight: var(--type-display-weight);
1308
+ font-size: clamp(var(--type-display-size-mobile), 1.4rem + 4vw, var(--type-display-size-desktop));
1309
+ line-height: clamp(var(--type-display-line-mobile), 1.48rem + 4.8vw, var(--type-display-line-desktop));
1310
+ letter-spacing: var(--type-display-tracking);
468
1311
  }
469
1312
 
470
- .heading-h2 {
1313
+ .h1 {
471
1314
  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;
1315
+ font-weight: var(--type-h1-weight);
1316
+ font-size: clamp(var(--type-h1-size-mobile), 1.6rem + 2vw, var(--type-h1-size-desktop));
1317
+ line-height: clamp(var(--type-h1-line-mobile), 1.92rem + 2.4vw, var(--type-h1-line-desktop));
1318
+ letter-spacing: var(--type-h1-tracking);
477
1319
  }
478
1320
 
479
- .heading-h3 {
1321
+ .h2 {
480
1322
  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;
1323
+ font-weight: var(--type-h2-weight);
1324
+ font-size: clamp(var(--type-h2-size-mobile), 1.4rem + 1.2vw, var(--type-h2-size-desktop));
1325
+ line-height: clamp(var(--type-h2-line-mobile), 1.7rem + 1.6vw, var(--type-h2-line-desktop));
1326
+ letter-spacing: var(--type-h2-tracking);
486
1327
  }
487
1328
 
488
- .heading-h4 {
1329
+ .h3 {
489
1330
  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;
1331
+ font-weight: var(--type-h3-weight);
1332
+ font-size: clamp(var(--type-h3-size-mobile), 1.3rem + 0.4vw, var(--type-h3-size-desktop));
1333
+ line-height: clamp(var(--type-h3-line-mobile), 1.6rem + 0.8vw, var(--type-h3-line-desktop));
1334
+ letter-spacing: var(--type-h3-tracking);
495
1335
  }
496
1336
 
497
- .heading-xs {
1337
+ .h4 {
498
1338
  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;
1339
+ font-weight: var(--type-h4-weight);
1340
+ font-size: var(--type-h4-size);
1341
+ line-height: var(--type-h4-line);
1342
+ letter-spacing: var(--type-h4-tracking);
1343
+ }
1344
+
1345
+ .h5 {
1346
+ font-family: var(--font-plus-jakarta-sans);
1347
+ font-weight: var(--type-h5-weight);
1348
+ font-size: var(--type-h5-size);
1349
+ line-height: var(--type-h5-line);
1350
+ letter-spacing: var(--type-h5-tracking);
504
1351
  }
505
1352
 
506
- /* Typography — Body scale (Plus Jakarta Sans · Semibold 600) */
1353
+ .h6 {
1354
+ font-family: var(--font-plus-jakarta-sans);
1355
+ font-weight: var(--type-h6-weight);
1356
+ font-size: var(--type-h6-size);
1357
+ line-height: var(--type-h6-line);
1358
+ letter-spacing: var(--type-h6-tracking);
1359
+ }
1360
+
1361
+ /* Body (400–600) */
507
1362
  .body-lg {
508
1363
  font-family: var(--font-plus-jakarta-sans);
509
- font-weight: 600;
510
- font-size: 18px;
511
- line-height: 28px;
1364
+ font-weight: var(--type-body-lg-weight);
1365
+ font-size: var(--type-body-lg-size);
1366
+ line-height: var(--type-body-lg-line);
512
1367
  }
513
1368
 
514
1369
  .body-md {
515
1370
  font-family: var(--font-plus-jakarta-sans);
516
- font-weight: 600;
517
- font-size: 16px;
518
- line-height: 24px;
1371
+ font-weight: var(--type-body-md-weight);
1372
+ font-size: var(--type-body-md-size);
1373
+ line-height: var(--type-body-md-line);
519
1374
  }
520
1375
 
521
1376
  .body-sm {
522
1377
  font-family: var(--font-plus-jakarta-sans);
523
- font-weight: 600;
524
- font-size: 12px;
525
- line-height: 16px;
1378
+ font-weight: var(--type-body-sm-weight);
1379
+ font-size: var(--type-body-sm-size);
1380
+ line-height: var(--type-body-sm-line);
1381
+ }
1382
+
1383
+ /* Label — identifying text on interactive/dense UI (form labels, item
1384
+ titles, table headers, tooltips). Medium weight for scannability. */
1385
+ .label-text {
1386
+ font-family: var(--font-plus-jakarta-sans);
1387
+ font-weight: var(--type-label-weight);
1388
+ font-size: var(--type-label-size);
1389
+ line-height: var(--type-label-line);
1390
+ letter-spacing: var(--type-label-tracking);
1391
+ }
1392
+
1393
+ .caption {
1394
+ font-family: var(--font-plus-jakarta-sans);
1395
+ font-weight: var(--type-caption-weight);
1396
+ font-size: var(--type-caption-size);
1397
+ line-height: var(--type-caption-line);
1398
+ letter-spacing: var(--type-caption-tracking);
1399
+ }
1400
+
1401
+ /* ── Component type classes ───────────────────────────────────
1402
+ Plain CSS, not Tailwind utilities: a generated `text-*` utility is
1403
+ indistinguishable from a text-colour utility to tailwind-merge, which
1404
+ strips one of them inside cn(). Named `type-*` so it is left alone.
1405
+ Each class reads only that component's own private tokens. */
1406
+ .type-accordion-trigger {
1407
+ font-size: var(--accordion-trigger-font-size);
1408
+ line-height: var(--accordion-trigger-line-height);
1409
+ font-weight: var(--accordion-trigger-font-weight);
1410
+ }
1411
+
1412
+ .type-accordion-content {
1413
+ font-size: var(--accordion-content-font-size);
1414
+ line-height: var(--accordion-content-line-height);
1415
+ font-weight: var(--accordion-content-font-weight);
1416
+ }
1417
+
1418
+ .type-badge-xs {
1419
+ font-size: var(--badge-font-size-xs);
1420
+ line-height: var(--badge-line-height-xs);
1421
+ font-weight: var(--badge-font-weight);
1422
+ }
1423
+
1424
+ .type-badge-sm {
1425
+ font-size: var(--badge-font-size-sm);
1426
+ line-height: var(--badge-line-height-sm);
1427
+ font-weight: var(--badge-font-weight);
1428
+ }
1429
+
1430
+ .type-badge-md {
1431
+ font-size: var(--badge-font-size-md);
1432
+ line-height: var(--badge-line-height-md);
1433
+ font-weight: var(--badge-font-weight);
1434
+ }
1435
+
1436
+ .type-badge-lg {
1437
+ font-size: var(--badge-font-size-lg);
1438
+ line-height: var(--badge-line-height-lg);
1439
+ font-weight: var(--badge-font-weight);
1440
+ }
1441
+
1442
+ .type-avatar-fallback {
1443
+ font-size: var(--avatar-fallback-font-size);
1444
+ line-height: var(--avatar-fallback-line-height);
1445
+ font-weight: var(--avatar-fallback-font-weight);
1446
+ }
1447
+
1448
+ /* Sizes come off the Avatar root's data-size, so the fallback follows the
1449
+ circle it sits in. sm and xl differ; default and lg share the base. */
1450
+ [data-slot="avatar"][data-size="sm"] .type-avatar-fallback {
1451
+ font-size: var(--avatar-fallback-font-size-sm);
1452
+ line-height: var(--avatar-fallback-line-height-sm);
1453
+ }
1454
+
1455
+ [data-slot="avatar"][data-size="xl"] .type-avatar-fallback {
1456
+ font-size: var(--avatar-fallback-font-size-xl);
1457
+ line-height: var(--avatar-fallback-line-height-xl);
1458
+ }
1459
+
1460
+ .type-avatar-group-count {
1461
+ font-size: var(--avatar-group-count-font-size);
1462
+ line-height: var(--avatar-group-count-line-height);
1463
+ font-weight: var(--avatar-group-count-font-weight);
1464
+ }
1465
+
1466
+ .type-alert-dialog-title {
1467
+ font-size: var(--alert-dialog-title-font-size);
1468
+ line-height: var(--alert-dialog-title-line-height);
1469
+ font-weight: var(--alert-dialog-title-font-weight);
1470
+ }
1471
+
1472
+ .type-alert-dialog-description {
1473
+ font-size: var(--alert-dialog-description-font-size);
1474
+ line-height: var(--alert-dialog-description-line-height);
1475
+ font-weight: var(--alert-dialog-description-font-weight);
1476
+ }
1477
+
1478
+ .type-dialog-title {
1479
+ font-size: var(--dialog-title-font-size);
1480
+ line-height: var(--dialog-title-line-height);
1481
+ font-weight: var(--dialog-title-font-weight);
1482
+ }
1483
+
1484
+ .type-dialog-description {
1485
+ font-size: var(--dialog-description-font-size);
1486
+ line-height: var(--dialog-description-line-height);
1487
+ font-weight: var(--dialog-description-font-weight);
1488
+ }
1489
+
1490
+ .type-drawer-title {
1491
+ font-size: var(--drawer-title-font-size);
1492
+ line-height: var(--drawer-title-line-height);
1493
+ font-weight: var(--drawer-title-font-weight);
526
1494
  }
527
1495
 
528
- .body-xs {
1496
+ .type-drawer-description {
1497
+ font-size: var(--drawer-description-font-size);
1498
+ line-height: var(--drawer-description-line-height);
1499
+ font-weight: var(--drawer-description-font-weight);
1500
+ }
1501
+
1502
+ .type-empty-title {
1503
+ font-size: var(--empty-title-font-size);
1504
+ line-height: var(--empty-title-line-height);
1505
+ font-weight: var(--empty-title-font-weight);
1506
+ }
1507
+
1508
+ .type-empty-description {
1509
+ font-size: var(--empty-description-font-size);
1510
+ line-height: var(--empty-description-line-height);
1511
+ font-weight: var(--empty-description-font-weight);
1512
+ }
1513
+
1514
+ .type-field-legend {
1515
+ font-size: var(--field-legend-font-size);
1516
+ line-height: var(--field-legend-line-height);
1517
+ font-weight: var(--field-legend-font-weight);
1518
+ }
1519
+
1520
+ .type-field-legend-label {
1521
+ font-size: var(--field-legend-label-font-size);
1522
+ line-height: var(--field-legend-label-line-height);
1523
+ font-weight: var(--field-legend-label-font-weight);
1524
+ }
1525
+
1526
+ .type-label {
1527
+ font-size: var(--label-font-size);
1528
+ line-height: var(--label-line-height);
1529
+ font-weight: var(--label-font-weight);
1530
+ }
1531
+
1532
+ .type-link-lg {
1533
+ font-size: var(--link-font-size-lg);
1534
+ line-height: var(--link-line-height-lg);
1535
+ font-weight: var(--link-font-weight);
1536
+ }
1537
+
1538
+ .type-link-md {
1539
+ font-size: var(--link-font-size-md);
1540
+ line-height: var(--link-line-height-md);
1541
+ font-weight: var(--link-font-weight);
1542
+ }
1543
+
1544
+ .type-link-sm {
1545
+ font-size: var(--link-font-size-sm);
1546
+ line-height: var(--link-line-height-sm);
1547
+ font-weight: var(--link-font-weight);
1548
+ }
1549
+
1550
+ .type-numpad {
1551
+ font-size: var(--numpad-font-size);
1552
+ line-height: var(--numpad-line-height);
1553
+ font-weight: var(--numpad-font-weight);
1554
+ }
1555
+
1556
+ .type-pagination {
1557
+ font-size: var(--pagination-font-size);
1558
+ line-height: var(--pagination-line-height);
1559
+ font-weight: var(--pagination-font-weight);
1560
+ }
1561
+
1562
+ .type-popover-title {
1563
+ font-size: var(--popover-title-font-size);
1564
+ line-height: var(--popover-title-line-height);
1565
+ font-weight: var(--popover-title-font-weight);
1566
+ }
1567
+
1568
+ .type-popover-description {
1569
+ font-size: var(--popover-description-font-size);
1570
+ line-height: var(--popover-description-line-height);
1571
+ font-weight: var(--popover-description-font-weight);
1572
+ }
1573
+
1574
+ .type-field-label-sm {
1575
+ font-size: var(--field-label-font-size-sm);
1576
+ line-height: var(--field-label-line-height-sm);
1577
+ font-weight: var(--field-label-font-weight);
1578
+ }
1579
+
1580
+ .type-field-label-md {
1581
+ font-size: var(--field-label-font-size-md);
1582
+ line-height: var(--field-label-line-height-md);
1583
+ font-weight: var(--field-label-font-weight);
1584
+ }
1585
+
1586
+ .type-field-label-lg {
1587
+ font-size: var(--field-label-font-size-lg);
1588
+ line-height: var(--field-label-line-height-lg);
1589
+ font-weight: var(--field-label-font-weight);
1590
+ }
1591
+
1592
+ .type-field-description {
1593
+ font-size: var(--field-description-font-size);
1594
+ line-height: var(--field-description-line-height);
1595
+ font-weight: var(--field-description-font-weight);
1596
+ }
1597
+
1598
+ .type-input-sm {
1599
+ font-size: var(--input-font-size-sm);
1600
+ line-height: var(--input-line-height-sm);
1601
+ font-weight: var(--input-font-weight);
1602
+ }
1603
+
1604
+ .type-input-md {
1605
+ font-size: var(--input-font-size-md);
1606
+ line-height: var(--input-line-height-md);
1607
+ font-weight: var(--input-font-weight);
1608
+ }
1609
+
1610
+ .type-input-lg {
1611
+ font-size: var(--input-font-size-lg);
1612
+ line-height: var(--input-line-height-lg);
1613
+ font-weight: var(--input-font-weight);
1614
+ }
1615
+
1616
+ .type-input-otp {
1617
+ font-size: var(--input-otp-font-size);
1618
+ line-height: var(--input-otp-line-height);
1619
+ font-weight: var(--input-otp-font-weight);
1620
+ }
1621
+
1622
+ .type-native-select-sm {
1623
+ font-size: var(--native-select-font-size-sm);
1624
+ line-height: var(--native-select-line-height-sm);
1625
+ font-weight: var(--native-select-font-weight);
1626
+ }
1627
+
1628
+ .type-native-select-md {
1629
+ font-size: var(--native-select-font-size-md);
1630
+ line-height: var(--native-select-line-height-md);
1631
+ font-weight: var(--native-select-font-weight);
1632
+ }
1633
+
1634
+ .type-native-select-lg {
1635
+ font-size: var(--native-select-font-size-lg);
1636
+ line-height: var(--native-select-line-height-lg);
1637
+ font-weight: var(--native-select-font-weight);
1638
+ }
1639
+
1640
+ .type-select-sm {
1641
+ font-size: var(--select-font-size-sm);
1642
+ line-height: var(--select-line-height-sm);
1643
+ font-weight: var(--select-font-weight);
1644
+ }
1645
+
1646
+ .type-select-md {
1647
+ font-size: var(--select-font-size-md);
1648
+ line-height: var(--select-line-height-md);
1649
+ font-weight: var(--select-font-weight);
1650
+ }
1651
+
1652
+ .type-select-lg {
1653
+ font-size: var(--select-font-size-lg);
1654
+ line-height: var(--select-line-height-lg);
1655
+ font-weight: var(--select-font-weight);
1656
+ }
1657
+
1658
+ .type-textarea {
1659
+ font-size: var(--textarea-font-size);
1660
+ line-height: var(--textarea-line-height);
1661
+ font-weight: var(--textarea-font-weight);
1662
+ }
1663
+
1664
+ .type-sheet-title {
1665
+ font-size: var(--sheet-title-font-size);
1666
+ line-height: var(--sheet-title-line-height);
1667
+ font-weight: var(--sheet-title-font-weight);
1668
+ }
1669
+
1670
+ .type-sheet-description {
1671
+ font-size: var(--sheet-description-font-size);
1672
+ line-height: var(--sheet-description-line-height);
1673
+ font-weight: var(--sheet-description-font-weight);
1674
+ }
1675
+
1676
+ .type-table {
1677
+ font-size: var(--table-font-size);
1678
+ line-height: var(--table-line-height);
1679
+ font-weight: var(--table-font-weight);
1680
+ }
1681
+
1682
+ .type-table-head {
1683
+ font-size: var(--table-font-size);
1684
+ line-height: var(--table-line-height);
1685
+ font-weight: var(--table-head-font-weight);
1686
+ }
1687
+
1688
+ .type-bottom-navigation-label {
1689
+ font-size: var(--bottom-navigation-label-font-size);
1690
+ line-height: var(--bottom-navigation-label-line-height);
1691
+ font-weight: var(--bottom-navigation-label-font-weight);
1692
+ }
1693
+
1694
+ /* Bottom Navigation — the arriving icon pops on an overshoot spring; the
1695
+ label never moves. */
1696
+ [data-slot="bottom-navigation-item"] svg {
1697
+ transition: transform var(--motion-pop) var(--primitive-ease-overshoot);
1698
+ }
1699
+
1700
+ [data-slot="bottom-navigation-item"][data-active] svg {
1701
+ transform: translateY(-1px) scale(1.1);
1702
+ }
1703
+
1704
+ .type-sidebar-menu {
1705
+ font-size: var(--sidebar-menu-font-size);
1706
+ line-height: var(--sidebar-menu-line-height);
1707
+ font-weight: var(--sidebar-menu-font-weight);
1708
+ }
1709
+
1710
+ .type-sidebar-menu-sm {
1711
+ font-size: var(--sidebar-menu-font-size-sm);
1712
+ line-height: var(--sidebar-menu-line-height-sm);
1713
+ font-weight: var(--sidebar-menu-font-weight);
1714
+ }
1715
+
1716
+ .type-sidebar-label {
1717
+ font-size: var(--sidebar-label-font-size);
1718
+ line-height: var(--sidebar-label-line-height);
1719
+ font-weight: var(--sidebar-label-font-weight);
1720
+ }
1721
+
1722
+ /* Sidebar — active menu rows go semibold. */
1723
+ [data-sidebar="menu-button"][data-active="true"],
1724
+ [data-sidebar="menu-sub-button"][data-active="true"] {
1725
+ font-weight: var(--sidebar-menu-active-font-weight);
1726
+ }
1727
+
1728
+ /* Tabs — the list's data-size drives the trigger type; active is semibold. */
1729
+ [data-slot="tabs-list"][data-size="sm"] [data-slot="tabs-trigger"] {
1730
+ font-size: var(--tabs-trigger-font-size-sm);
1731
+ line-height: var(--tabs-trigger-line-height-sm);
1732
+ font-weight: var(--tabs-trigger-font-weight);
1733
+ }
1734
+
1735
+ [data-slot="tabs-list"][data-size="md"] [data-slot="tabs-trigger"] {
1736
+ font-size: var(--tabs-trigger-font-size-md);
1737
+ line-height: var(--tabs-trigger-line-height-md);
1738
+ font-weight: var(--tabs-trigger-font-weight);
1739
+ }
1740
+
1741
+ [data-slot="tabs-list"][data-size="lg"] [data-slot="tabs-trigger"] {
1742
+ font-size: var(--tabs-trigger-font-size-lg);
1743
+ line-height: var(--tabs-trigger-line-height-lg);
1744
+ font-weight: var(--tabs-trigger-font-weight);
1745
+ }
1746
+
1747
+ [data-slot="tabs-list"] [data-slot="tabs-trigger"][data-state="active"] {
1748
+ font-weight: var(--tabs-trigger-active-font-weight);
1749
+ }
1750
+
1751
+ .type-toggle {
1752
+ font-size: var(--toggle-font-size);
1753
+ line-height: var(--toggle-line-height);
1754
+ font-weight: var(--toggle-font-weight);
1755
+ }
1756
+
1757
+ .type-tooltip {
1758
+ font-size: var(--tooltip-font-size);
1759
+ line-height: var(--tooltip-line-height);
1760
+ font-weight: var(--tooltip-font-weight);
1761
+ }
1762
+
1763
+ .type-item-title {
1764
+ font-size: var(--item-title-font-size);
1765
+ line-height: var(--item-title-line-height);
1766
+ font-weight: var(--item-title-font-weight);
1767
+ }
1768
+
1769
+ .type-item-description {
1770
+ font-size: var(--item-description-font-size);
1771
+ line-height: var(--item-description-line-height);
1772
+ font-weight: var(--item-description-font-weight);
1773
+ }
1774
+
1775
+
1776
+ /* Input Group — the group carries the input ladder so addons, prefixes, and
1777
+ kbd hints inherit it; the input and buttons inside set their own. */
1778
+ [data-slot="input-group"][data-size="sm"] {
1779
+ font-size: var(--input-font-size-sm);
1780
+ line-height: var(--input-line-height-sm);
1781
+ font-weight: var(--input-font-weight);
1782
+ }
1783
+
1784
+ [data-slot="input-group"][data-size="md"] {
1785
+ font-size: var(--input-font-size-md);
1786
+ line-height: var(--input-line-height-md);
1787
+ font-weight: var(--input-font-weight);
1788
+ }
1789
+
1790
+ [data-slot="input-group"][data-size="lg"] {
1791
+ font-size: var(--input-font-size-lg);
1792
+ line-height: var(--input-line-height-lg);
1793
+ font-weight: var(--input-font-weight);
1794
+ }
1795
+
1796
+ .type-menu-item {
1797
+ font-size: var(--menu-item-font-size);
1798
+ line-height: var(--menu-item-line-height);
1799
+ font-weight: var(--menu-item-font-weight);
1800
+ }
1801
+ .type-menu-heading {
1802
+ font-size: var(--menu-heading-font-size);
1803
+ line-height: var(--menu-heading-line-height);
1804
+ font-weight: var(--menu-heading-font-weight);
1805
+ }
1806
+
1807
+ .type-menu-trigger {
1808
+ font-size: var(--menu-trigger-font-size);
1809
+ line-height: var(--menu-trigger-line-height);
1810
+ font-weight: var(--menu-trigger-font-weight);
1811
+ }
1812
+
1813
+ .type-menu-shortcut {
1814
+ font-size: var(--menu-shortcut-font-size);
1815
+ line-height: var(--menu-shortcut-line-height);
1816
+ font-weight: var(--menu-shortcut-font-weight);
1817
+ }
1818
+ .type-chip-md {
1819
+ font-size: var(--chip-font-size-md);
1820
+ line-height: var(--chip-line-height-md);
1821
+ font-weight: var(--chip-font-weight);
1822
+ }
1823
+ .type-chip-sm {
1824
+ font-size: var(--chip-font-size-sm);
1825
+ line-height: var(--chip-line-height-sm);
1826
+ font-weight: var(--chip-font-weight);
1827
+ }
1828
+ .type-calendar-caption {
1829
+ font-size: var(--calendar-caption-font-size);
1830
+ line-height: var(--calendar-caption-line-height);
1831
+ font-weight: var(--calendar-caption-font-weight);
1832
+ }
1833
+ .type-calendar-weekday {
1834
+ font-size: var(--calendar-weekday-font-size);
1835
+ line-height: var(--calendar-weekday-line-height);
1836
+ font-weight: var(--calendar-weekday-font-weight);
1837
+ }
1838
+ .type-calendar-day {
1839
+ font-size: var(--calendar-day-font-size);
1840
+ line-height: var(--calendar-day-line-height);
1841
+ font-weight: var(--calendar-day-font-weight);
1842
+ }
1843
+ .type-button-lg {
1844
+ font-size: var(--button-font-size-lg);
1845
+ line-height: var(--button-line-height-lg);
1846
+ font-weight: var(--button-font-weight);
1847
+ }
1848
+ .type-button-md {
1849
+ font-size: var(--button-font-size-md);
1850
+ line-height: var(--button-line-height-md);
1851
+ font-weight: var(--button-font-weight);
1852
+ }
1853
+ .type-button-sm {
1854
+ font-size: var(--button-font-size-sm);
1855
+ line-height: var(--button-line-height-sm);
1856
+ font-weight: var(--button-font-weight);
1857
+ }
1858
+ .type-breadcrumb {
1859
+ font-size: var(--breadcrumb-font-size);
1860
+ line-height: var(--breadcrumb-line-height);
1861
+ font-weight: var(--breadcrumb-font-weight);
1862
+ }
1863
+ .type-breadcrumb-page {
1864
+ font-weight: var(--breadcrumb-page-font-weight);
1865
+ }
1866
+ .type-banner-title {
1867
+ font-size: var(--banner-title-font-size);
1868
+ line-height: var(--banner-title-line-height);
1869
+ font-weight: var(--banner-title-font-weight);
1870
+ letter-spacing: var(--primitive-tracking-tight);
1871
+ }
1872
+ .type-banner-description {
1873
+ font-size: var(--banner-description-font-size);
1874
+ line-height: var(--banner-description-line-height);
1875
+ font-weight: var(--banner-description-font-weight);
1876
+ }
1877
+ .type-banner-action {
1878
+ font-size: var(--banner-action-font-size);
1879
+ line-height: var(--banner-action-line-height);
1880
+ font-weight: var(--banner-action-font-weight);
1881
+ }
1882
+ .type-section-message-title {
1883
+ font-size: var(--section-message-title-font-size);
1884
+ line-height: var(--section-message-title-line-height);
1885
+ font-weight: var(--section-message-title-font-weight);
1886
+ }
1887
+
1888
+ .type-section-message-description {
1889
+ font-size: var(--section-message-description-font-size);
1890
+ line-height: var(--section-message-description-line-height);
1891
+ font-weight: var(--section-message-description-font-weight);
1892
+ }
1893
+ .type-section-message-title-sm {
1894
+ font-size: var(--section-message-title-font-size-sm);
1895
+ line-height: var(--section-message-title-line-height-sm);
1896
+ font-weight: var(--section-message-title-font-weight);
1897
+ }
1898
+ .type-section-message-description-sm {
1899
+ font-size: var(--section-message-description-font-size-sm);
1900
+ line-height: var(--section-message-description-line-height-sm);
1901
+ font-weight: var(--section-message-description-font-weight);
1902
+ }
1903
+
1904
+ .overline {
529
1905
  font-family: var(--font-plus-jakarta-sans);
530
- font-weight: 600;
531
- font-size: 8px;
532
- line-height: 12px;
1906
+ font-weight: var(--type-overline-weight);
1907
+ font-size: var(--type-overline-size);
1908
+ line-height: var(--type-overline-line);
1909
+ letter-spacing: var(--type-overline-tracking);
1910
+ text-transform: uppercase;
1911
+ /* `overline` is also a built-in Tailwind text-decoration utility, which
1912
+ would draw a literal line above the text. Explicitly clear it — this is
1913
+ a type token (eyebrow/tag label), not a decoration. */
1914
+ text-decoration: none;
533
1915
  }
534
1916
 
535
1917
  /* ── Result block — icon motion ─────────────────────────────── */