@faqir-ui/core 1.0.0 → 1.1.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 (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +121 -57
  4. package/dist/faqir-core.min.js +3 -3
  5. package/dist/faqir-core.min.js.map +3 -3
  6. package/dist/faqir-core.mjs +75 -59
  7. package/dist/faqir.aurora.css +1209 -507
  8. package/dist/faqir.brutalist.css +1184 -489
  9. package/dist/faqir.candy.css +14152 -0
  10. package/dist/faqir.clinical.css +14152 -0
  11. package/dist/faqir.contrast.css +1198 -526
  12. package/dist/faqir.default.css +1261 -588
  13. package/dist/faqir.document-serif.css +1211 -491
  14. package/dist/faqir.document.css +1193 -490
  15. package/dist/faqir.editorial-document.css +14116 -0
  16. package/dist/faqir.editorial.css +14152 -0
  17. package/dist/faqir.fintech.css +14152 -0
  18. package/dist/faqir.glass.css +1214 -517
  19. package/dist/faqir.ink-document.css +14116 -0
  20. package/dist/faqir.ink.css +14127 -0
  21. package/dist/faqir.luxe.css +14211 -0
  22. package/dist/faqir.midnight.css +1229 -507
  23. package/dist/faqir.neo.css +14153 -0
  24. package/dist/faqir.neumorph.css +14151 -0
  25. package/dist/faqir.nordic.css +14151 -0
  26. package/dist/faqir.organic.css +14152 -0
  27. package/dist/faqir.paper.css +1200 -508
  28. package/dist/faqir.slate.css +1296 -564
  29. package/dist/faqir.soft.css +1180 -494
  30. package/dist/faqir.sunset.css +14153 -0
  31. package/dist/faqir.swiss-document.css +14116 -0
  32. package/dist/faqir.swiss.css +14153 -0
  33. package/dist/faqir.terminal.css +1187 -491
  34. package/dist/plugins/faqir-collapse.js +1 -1
  35. package/dist/plugins/faqir-intersect.js +2 -0
  36. package/dist/plugins/faqir-mask.js +27 -17
  37. package/dist/plugins/faqir-rules.js +63 -0
  38. package/dist/plugins/faqir-validate.js +471 -58
  39. package/dist/sri.json +36 -20
  40. package/faqir-core.d.ts +119 -6
  41. package/package.json +1 -1
@@ -131,6 +131,18 @@
131
131
  --font-mono: ui-monospace, 'Cascadia Code', 'JetBrains Mono', monospace;
132
132
  --font-serif: 'Georgia', 'Times New Roman', serif;
133
133
 
134
+ /* ── Font Roles (task 1.1A-01) ──
135
+ The three families above are the PALETTE; these three are the ROLES that
136
+ components actually read. A theme re-points a role once and every heading,
137
+ every paragraph and every control follows — "serif headings on a sans body"
138
+ is one declaration rather than sixty-four stylesheet edits. Components never
139
+ read --font-sans / --font-serif directly (gated by
140
+ tests/tokens/role-tokens.test.ts); --font-mono stays readable by name,
141
+ because "this is code" is a semantic choice, not a stylistic one. */
142
+ --font-heading: var(--font-sans); /* h1–h6, hero headline, card/dialog titles, stat values, doc headings */
143
+ --font-body: var(--font-sans); /* prose, text, document body, descriptions */
144
+ --font-ui: var(--font-sans); /* controls: button, input, select, badge, chip, tabs, menus */
145
+
134
146
  /* ── Font Sizes ── */
135
147
  --text-xs: 0.75rem; /* 12px */
136
148
  --text-sm: 0.875rem; /* 14px */
@@ -153,10 +165,29 @@
153
165
  --weight-medium: 500;
154
166
  --weight-semibold: 600;
155
167
  --weight-bold: 700;
168
+
169
+ /* ── Heading Voice (task 1.1A-01) ──
170
+ What makes a heading sound like the theme rather than like the body text one
171
+ size up: how heavy it is, how tightly the letters sit, whether it shouts, and
172
+ how close its own lines run. The defaults reproduce today's primary heading
173
+ exactly, so a project that sets none of them renders unchanged. A heading
174
+ that deliberately steps DOWN from the primary voice (prose h2–h4, a semibold
175
+ step below h1) keeps its own weight and leading and takes family, tracking
176
+ and case from the voice — the step is the design, not a value to re-derive. */
177
+ --heading-weight: var(--weight-bold);
178
+ --heading-tracking: 0em; /* letter-spacing — carries a unit so it
179
+ composes inside calc() where a heading
180
+ already has its own optical tightening */
181
+ --heading-transform: none; /* text-transform */
182
+ --heading-caps: normal; /* font-variant-caps — small caps are a
183
+ variant, not a transform (1.1A-25), so
184
+ they get a knob of their own that sits
185
+ beside --heading-transform */
186
+ --heading-leading: var(--leading-tight);
156
187
  }
157
188
 
158
189
  /* === tokens/effects.css === */
159
- /* @ui:tokens effects — radii, shadows, z-index */
190
+ /* @ui:tokens effects — radii, shape, shadows, focus, z-index */
160
191
 
161
192
  :root {
162
193
  /* ── Radii ── */
@@ -168,12 +199,49 @@
168
199
  --radius-2xl: 1rem; /* 16px */
169
200
  --radius-full: 9999px;
170
201
 
171
- /* ── Shadows ── */
172
- --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.04);
173
- --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
174
- --shadow-md: 0 4px 6px oklch(0 0 0 / 0.05), 0 2px 4px oklch(0 0 0 / 0.04);
175
- --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.06), 0 4px 6px oklch(0 0 0 / 0.04);
176
- --shadow-xl: 0 20px 25px oklch(0 0 0 / 0.08), 0 8px 10px oklch(0 0 0 / 0.04);
202
+ /* ── Shape ── */
203
+ /* The weight of an edge. A component names the ROLE (--border-width, or
204
+ --border-width-strong where the design leans on a thicker rule), never a
205
+ step, so a theme re-points every edge it ships with one declaration. */
206
+ --border-width-sm: 1px;
207
+ --border-width-md: 2px;
208
+ --border-width-lg: 3px;
209
+ --border-width: var(--border-width-sm); /* the default component border */
210
+ --border-width-strong: var(--border-width-md); /* emphasis: keycap, thick rule, active tab */
211
+ /* Progressive: CSS Borders 4. A browser without the property ignores it; a
212
+ value it does not know resolves to `round`, which is today's rendering. */
213
+ --corner-shape: round; /* bevel | scoop | notch where supported */
214
+
215
+ /* ── Depth ── */
216
+ /* The colour every shadow is cast in, as BARE OKLCH channels (L C H, no
217
+ `oklch()` around them) so each step can still set its own alpha:
218
+ `oklch(var(--shadow-color) / 0.06)`. A theme tints its depth warm, or
219
+ removes it entirely, with one declaration instead of rewriting five
220
+ multi-layer values. `0 0 0` is black — today's rendering, exactly. */
221
+ --shadow-color: 0 0 0;
222
+
223
+ --shadow-xs: 0 1px 2px oklch(var(--shadow-color) / 0.04);
224
+ --shadow-sm: 0 1px 3px oklch(var(--shadow-color) / 0.06), 0 1px 2px oklch(var(--shadow-color) / 0.04);
225
+ --shadow-md: 0 4px 6px oklch(var(--shadow-color) / 0.05), 0 2px 4px oklch(var(--shadow-color) / 0.04);
226
+ --shadow-lg: 0 10px 15px oklch(var(--shadow-color) / 0.06), 0 4px 6px oklch(var(--shadow-color) / 0.04);
227
+ --shadow-xl: 0 20px 25px oklch(var(--shadow-color) / 0.08), 0 8px 10px oklch(var(--shadow-color) / 0.04);
228
+
229
+ /* What an elevated surface does to whatever shows through it. Every surface
230
+ that can float — card, surface[data-variant="overlay"] and the seven
231
+ floating recipes — declares `backdrop-filter: var(--surface-backdrop)`
232
+ inside the same `@supports` guard, so a frosted theme is a token rather
233
+ than a stylesheet that reaches into seven components by selector.
234
+ `none` is the initial value of the property: no-op until a theme speaks. */
235
+ --surface-backdrop: none;
236
+
237
+ /* ── Focus ── */
238
+ /* base/reset.css owns the default ring and reads only these. Every control
239
+ that draws its own ring reads them too, so a theme changes focus once. */
240
+ --focus-ring-width: 2px;
241
+ --focus-ring-offset: 2px;
242
+ --focus-ring-style: solid;
243
+ --focus-ring-color: var(--color-ring);
244
+ --focus-shadow: none; /* a glow theme puts a shadow behind the ring */
177
245
 
178
246
  /* ── Z-Index ── */
179
247
  --z-base: 0;
@@ -186,8 +254,74 @@
186
254
  --z-max: 9999;
187
255
  }
188
256
 
257
+ /* ── Scheme islands ── */
258
+ /* The ring colour, restated where a scheme can change below the root: declared
259
+ on `:root` alone it resolves `--color-ring` once, from the page, and a nested
260
+ `data-theme="dark"` region would draw the light ring. See the same block in
261
+ tokens/aliases.css. `--focus-shadow` is deliberately NOT restated — it is a
262
+ depth value a theme owns, and restating it would replace the theme's glow
263
+ with `none` inside every island. */
264
+ [data-theme],
265
+ [data-skin] {
266
+ --focus-ring-color: var(--color-ring);
267
+ }
268
+
269
+ /* === tokens/textures.css === */
270
+ /* @ui:tokens textures — named surface materials (SVG data URIs) */
271
+
272
+ /* ══════════════════════════════════════════════════════════════════════════
273
+ The material palette.
274
+ ══════════════════════════════════════════════════════════════════════════
275
+ Six named textures, each a self-contained `url("data:image/svg+xml,…")` that
276
+ tiles. Nothing here is consumed directly: components read the two ROLE tokens
277
+ in `aliases.css` — `--texture-page` (body, document) and `--texture-surface`
278
+ (surface, card, hero) — both `none` by default, so the registry renders
279
+ exactly as it did before this file existed. A theme opts in with one
280
+ declaration:
281
+
282
+ --texture-page: var(--texture-grain);
283
+
284
+ This file is deliberately OUTSIDE the themeable surface (see
285
+ `NON_SURFACE_TOKEN_FILES` in `src/theme-manifest.ts`): a theme re-points the
286
+ two role tokens, it does not inherit six data URIs into its manifest.
287
+
288
+ On `currentColor`: the tint is written as `currentColor` so the markup states
289
+ its intent and a theme can re-point the whole token, but a data-URI SVG used
290
+ as `background-image` is its own document — `currentColor` there resolves to
291
+ that document's initial colour (black), not to the host element's `color`.
292
+ That IS the intended neutral for grain and paper, which are meant to darken a
293
+ surface slightly; the alpha in each texture, not the hue, is what carries the
294
+ effect. A theme wanting a different tint ships its own URI.
295
+
296
+ Every texture keeps its alpha low enough to survive on both schemes, and each
297
+ `<svg>` carries explicit `width`/`height` so the tile size is the token's,
298
+ not the browser's default 300×150.
299
+ ══════════════════════════════════════════════════════════════════════════ */
300
+
301
+ :root {
302
+ /* Film grain — fractal noise masking a flat currentColor fill. The mask is
303
+ what makes this a tint rather than the turbulence's own rainbow. */
304
+ --texture-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/mask%3E%3Crect width='160' height='160' fill='currentColor' mask='url(%23m)' opacity='0.14'/%3E%3C/svg%3E");
305
+
306
+ /* Paper fibre — lower frequency, more octaves, softer than grain. */
307
+ --texture-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.04 0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='200' height='200' filter='url(%23p)'/%3E%3C/mask%3E%3Crect width='200' height='200' fill='currentColor' mask='url(%23m)' opacity='0.1'/%3E%3C/svg%3E");
308
+
309
+ /* Dot field — one dot per 16px cell. */
310
+ --texture-dots: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='2' cy='2' r='1' fill='currentColor' opacity='0.18'/%3E%3C/svg%3E");
311
+
312
+ /* Graph-paper grid — hairlines on a 24px cell. */
313
+ --texture-grid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M24 0H0v24' fill='none' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
314
+
315
+ /* Diagonal hatching — 45°, 8px pitch. */
316
+ --texture-stripes: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M-2 2 2-2M0 8 8 0M6 10l4-4' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
317
+
318
+ /* Soft gradient mesh — three offset radial blooms, the only non-tiling
319
+ texture here (it is sized to cover, not to repeat). */
320
+ --texture-mesh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3CradialGradient id='a' cx='20%25' cy='20%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.18'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='b' cx='80%25' cy='30%25' r='55%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.14'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='c' cx='50%25' cy='90%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.12'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3Crect width='640' height='640' fill='url(%23a)'/%3E%3Crect width='640' height='640' fill='url(%23b)'/%3E%3Crect width='640' height='640' fill='url(%23c)'/%3E%3C/svg%3E");
321
+ }
322
+
189
323
  /* === tokens/motion.css === */
190
- /* @ui:tokens motion — easings and durations */
324
+ /* @ui:tokens motion — easings, durations and motion personality */
191
325
 
192
326
  :root {
193
327
  /* ── Easings ── */
@@ -216,6 +350,35 @@
216
350
  /* Preset geometry */
217
351
  --motion-slide-distance: 0.5rem; /* slide-up travel */
218
352
  --motion-scale-from: 0.95; /* scale start/end factor */
353
+
354
+ /* ── Personality (1.1A-05 · §5.2 `motion`) ── */
355
+ /* The easing PALETTE gained a spring. Like --ease-bounce it has no consumer
356
+ of its own: a theme that wants everything to overshoot re-points
357
+ --ease-default at it, exactly as a serif theme re-points --font-body.
358
+ The declaration here is the cubic-bezier APPROXIMATION, because a custom
359
+ property stores whatever tokens it is given — a browser without `linear()`
360
+ would accept the spring happily and then drop every `transition` that used
361
+ it, landing on the initial easing rather than on a fallback. The @supports
362
+ block below is what makes the upgrade conditional. The approximation is
363
+ the bounce curve, deliberately: an overshoot-and-settle cubic-bezier is the
364
+ closest a browser without `linear()` can come to a spring. */
365
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
366
+
367
+ /* How far an interactive surface rises under the pointer. A `translate`
368
+ VALUE, not a length: `none` is the initial value of that property, so the
369
+ default registry computes exactly what it computed before this token
370
+ existed, and a theme states the lift as `0 -1px`. `translate` rather than
371
+ `transform` so a component's own transform is never clobbered. */
372
+ --motion-hover-lift: none;
373
+ }
374
+
375
+ /* The real spring, where `linear()` is understood (Chrome 113+, Safari 17.2+,
376
+ Firefox 112+). Declared second so it wins; guarded so it is never declared at
377
+ all where it would be meaningless. */
378
+ @supports (animation-timing-function: linear(0, 1)) {
379
+ :root {
380
+ --ease-spring: linear(0, 0.3 6%, 0.7 13%, 0.95 20%, 1.03 27%, 1 40%, 1);
381
+ }
219
382
  }
220
383
 
221
384
  /* === tokens/semantic.css === */
@@ -307,27 +470,123 @@
307
470
  --section-gap-lg: var(--space-32); /* 8rem — spacious, one idea per screen */
308
471
  --content-gutter: var(--space-6); /* 1.5rem — page padding-inline */
309
472
 
473
+ /* ── Material ── */
474
+ /* The two textures a theme actually points at. Components never name a
475
+ texture from `tokens/textures.css` directly — they read one of these, so a
476
+ theme re-points two tokens rather than every surface in the registry.
477
+ `--texture-page` dresses the page itself (body, document);
478
+ `--texture-surface` dresses the things that sit ON it (surface, card,
479
+ hero). Both `none`: the initial value of `background-image`, so the
480
+ default registry renders exactly as it did before they existed. */
481
+ --texture-page: none;
482
+ --texture-surface: none;
483
+
484
+ /* ── Decoration (1.1A-05 · §5.2 `decoration`) ── */
485
+ /* The marks a theme draws that are not edges, fills or type: how a link is
486
+ underlined, how a divider is dashed, what selected text looks like, what
487
+ colour a list bullet is. Every default is the value the registry already
488
+ rendered, so this section is a set of handles, not a restyle.
489
+ `--marker-color` is `currentColor` — the initial value of `::marker`'s
490
+ colour — rather than the accent, so a list only changes when a theme says
491
+ it should. */
492
+ --link-decoration: underline;
493
+ --link-underline-offset: 0.2em;
494
+ --link-thickness: 1px;
495
+ --divider-style: solid;
496
+ /* The divider's own width, following the edge by default (1.1A-26). A theme
497
+ that asks for a `double` divider raises it to at least 3px: a double rule
498
+ only splits into two lines from 3px, and the family's 1px hairline would
499
+ paint it as one. */
500
+ --divider-width: var(--border-width);
501
+ /* The zebra, so a theme dials the stripe without restating the four selectors
502
+ the table's striped variant needs (stamped and nth-child, each with a hover
503
+ twin). Deliberately NOT `--table-stripe`: `--table-level`,
504
+ `--table-thead-h` and `--table-pin-offset` are stamped and MEASURED per
505
+ element by the table controller, so claiming the `--table-*` namespace for
506
+ a theme token would put runtime state on the themeable surface. */
507
+ --stripe-bg: var(--color-bg-subtle);
508
+ --selection-bg: var(--color-primary-subtle);
509
+ --selection-fg: var(--color-fg);
510
+ --marker-color: currentColor;
511
+ /* How far a disabled control is dimmed. Seventeen rules across the primitives
512
+ and recipes each spelled `opacity: 0.5`, which left a theme with an opinion
513
+ about disabled legibility no way to state it except by out-specifying every
514
+ one of them — which is exactly what `themes/contrast.css` did, with a
515
+ blanket `:root [data-ui]:disabled` rule, until 1.1A-15 turned it into this
516
+ one declaration. `0.5` is the value those seventeen rules already held. */
517
+ --disabled-opacity: 0.5;
518
+
310
519
  /* ── Button ── */
311
520
  --button-radius: var(--radius-md);
312
521
  --button-height-sm: var(--control-height-sm);
313
522
  --button-height-md: var(--control-height-md);
314
523
  --button-height-lg: var(--control-height-lg);
315
- --button-font: var(--font-sans);
524
+ --button-font: var(--font-ui);
316
525
  --button-weight: var(--weight-medium);
526
+ --button-text-transform: none;
317
527
 
318
528
  /* ── Card ── */
319
529
  --card-radius: var(--radius-lg);
320
530
  --card-shadow: var(--shadow-sm);
321
531
  --card-border: var(--color-surface-1-border);
532
+ --card-border-width: var(--border-width);
322
533
  --card-bg: var(--color-surface-1);
323
534
  --card-padding: var(--space-6);
324
535
 
325
536
  /* ── Input ── */
326
- --input-radius: var(--radius-md);
327
- --input-height: var(--control-height-md);
328
- --input-border: var(--color-border);
329
- --input-bg: var(--color-bg);
330
- --input-font: var(--font-sans);
537
+ /* The text-control silhouette. `--input-border-width` (1.1A-02) is the edge;
538
+ `--input-fill` is what the control paints, and `input`, `textarea` and
539
+ `select` all read it, so one declaration fills every text control.
540
+ `--input-fill` defaults to `--input-bg`, so a project that sets `--input-bg`
541
+ on `:root` — the 1.0 way to fill every input — still gets it. Set BELOW the
542
+ root, `--input-bg` no longer reaches the control: `--input-fill` has already
543
+ resolved it on `:root`, which is where a theme flips the fill, and a
544
+ per-element `--input-bg` winning over that would need the component to tell
545
+ "set here" from "inherited", which CSS cannot. To fill one input, or every
546
+ input in a region, set `--input-fill` there instead. `--input-bg-filled` is
547
+ the value a "filled" theme points `--input-fill` at — named here so the
548
+ silhouette is a token a theme flips rather than a colour it has to pick. */
549
+ --input-radius: var(--radius-md);
550
+ --input-height: var(--control-height-md);
551
+ --input-border: var(--color-border);
552
+ --input-border-width: var(--border-width);
553
+ --input-bg: var(--color-bg);
554
+ --input-bg-filled: var(--color-bg-subtle);
555
+ --input-fill: var(--input-bg);
556
+ --input-font: var(--font-ui);
557
+
558
+ /* ── Checkbox / Switch ── */
559
+ /* The two control shapes that do not follow `--radius-md`: a checkbox is a
560
+ small square with a small radius, a switch is a pill. Both were literal
561
+ `var(--radius-*)` reads in the components; named here, a theme squares its
562
+ switches without touching the radius ladder every other surface uses.
563
+
564
+ The geometry beside them is not decoration — it is the rest of the
565
+ namespace. Naming ONE token `--checkbox-radius` makes `--checkbox-*` a
566
+ token family, and the registry audit then (rightly) reads every other
567
+ `--checkbox-…`/`--switch-…` the components carried as a token wearing a
568
+ fallback as a disguise. They were always the default geometry; these are
569
+ the values the fallbacks already held, said once. */
570
+ --checkbox-size: 18px;
571
+ --checkbox-radius: var(--radius-sm);
572
+ --switch-width: 44px;
573
+ --switch-height: 24px;
574
+ --switch-thumb: 18px;
575
+ --switch-travel: 20px;
576
+ --switch-radius: var(--radius-full);
577
+ --switch-bg: var(--color-bg-muted);
578
+ --switch-thumb-shadow: var(--shadow-xs);
579
+
580
+ /* ── Floating panels ── */
581
+ /* What a panel that floats above the page is filled with: the dialog and
582
+ sheet panels, the drawer, the popover content (and its arrow), the dropdown
583
+ menu and the toast. They all painted `var(--color-bg)` directly, which left
584
+ a theme no way to make a floating surface differ from the page — the frost
585
+ half of that pairing is `--surface-backdrop` (1.1A-04), and a blur behind an
586
+ opaque fill renders nothing, so the fill has to be a token too. `card` has
587
+ had `--card-bg` since 1.0; this is the same handle for the things that have
588
+ no surface of their own. [1.1A-14] */
589
+ --panel-bg: var(--color-bg);
331
590
 
332
591
  /* ── Dialog ── */
333
592
  --dialog-radius: var(--radius-xl);
@@ -336,7 +595,7 @@
336
595
 
337
596
  /* ── Badge ── */
338
597
  --badge-radius: var(--radius-full);
339
- --badge-font: var(--font-sans);
598
+ --badge-font: var(--font-ui);
340
599
 
341
600
  /* ── Avatar ── */
342
601
  --avatar-radius: var(--radius-full);
@@ -345,6 +604,39 @@
345
604
  --avatar-size-lg: 56px;
346
605
  }
347
606
 
607
+ /* ── Scheme islands ── */
608
+ /* The colour aliases above, restated wherever a scheme can change below the
609
+ root. A custom property resolves its var() on the element that DECLARES it,
610
+ so `--panel-bg: var(--color-bg)` on `:root` is computed once, from the page's
611
+ colours, and a nested `<div data-theme="dark">` inherits that light value
612
+ even though its own `--color-bg` is dark — a white dialog on a dark island.
613
+ Components that read `var(--color-bg)` directly never had the problem; the
614
+ aliases 1.1 routed them through did. Restating the declaration on
615
+ `[data-theme]` and `[data-skin]` makes it resolve again there.
616
+
617
+ Only colours are restated. Geometry does not change with the scheme, and
618
+ shadows are the depth axis every theme owns on `:root`: restating either here
619
+ would replace a theme's own value with the default inside every island. A
620
+ theme that overrides one of THESE on `:root` and wants it honoured in an
621
+ island says so on the same selectors.
622
+
623
+ The values must match the `:root` declarations above exactly;
624
+ `tests/tokens/scheme-islands.test.ts` fails if they drift. */
625
+ [data-theme],
626
+ [data-skin] {
627
+ --stripe-bg: var(--color-bg-subtle);
628
+ --selection-bg: var(--color-primary-subtle);
629
+ --selection-fg: var(--color-fg);
630
+ --card-border: var(--color-surface-1-border);
631
+ --card-bg: var(--color-surface-1);
632
+ --input-border: var(--color-border);
633
+ --input-bg: var(--color-bg);
634
+ --input-bg-filled: var(--color-bg-subtle);
635
+ --input-fill: var(--input-bg);
636
+ --switch-bg: var(--color-bg-muted);
637
+ --panel-bg: var(--color-bg);
638
+ }
639
+
348
640
  /* === tokens/document.css === */
349
641
  /* @ui:tokens document — structural tokens for document/print rendering */
350
642
  /* These tokens control page geometry, document typography, table density,
@@ -376,10 +668,10 @@
376
668
  Separate from the base typography tokens because documents have
377
669
  different optimal sizes than screen UIs. 14px body + 12px legal
378
670
  is standard for A4 business documents. */
379
- --doc-font: var(--font-sans);
671
+ --doc-font: var(--font-body);
380
672
  --doc-font-size: var(--text-sm); /* 14px — optimal for A4 */
381
673
  --doc-line-height: var(--leading-normal); /* 1.5 */
382
- --doc-heading-font: var(--font-sans);
674
+ --doc-heading-font: var(--font-heading);
383
675
  --doc-heading-weight: var(--weight-bold);
384
676
  --doc-heading-size: var(--text-xl); /* 20px for doc titles */
385
677
  --doc-subheading-size: var(--text-lg); /* 18px for section titles */
@@ -430,6 +722,16 @@
430
722
  --doc-print-border-color: oklch(0.60 0 0); /* medium gray borders in print */
431
723
  }
432
724
 
725
+ /* ── Scheme islands ── */
726
+ /* `--doc-legal-color` is the one document colour screen components read (the
727
+ key-value label and the image caption), so it is restated where a scheme can
728
+ change below the root — see the same block in tokens/aliases.css. The rest
729
+ of this file is print ink, which does not follow the scheme. */
730
+ [data-theme],
731
+ [data-skin] {
732
+ --doc-legal-color: var(--color-fg-muted);
733
+ }
734
+
433
735
  /* === tokens/doc-aliases.css === */
434
736
  /* @ui:tokens doc-aliases — component-level document tokens */
435
737
  /* Maps document-layer tokens to specific primitive/recipe attribute selectors.
@@ -476,7 +778,10 @@
476
778
  --field-error-size: var(--doc-legal-size);
477
779
  --field-error-color: var(--color-destructive);
478
780
  --field-validating-color: var(--color-fg-muted); /* async validation in flight */
479
- --field-disabled-opacity: 0.55; /* honest disabled affordance */
781
+ /* The role `--disabled-opacity` sets for every control, nudged 10% lighter:
782
+ 0.55 at the 0.5 default, which is the value this alias always held, and it
783
+ follows a theme that states the role (1.1A-27). */
784
+ --field-disabled-opacity: calc(var(--disabled-opacity) * 1.1);
480
785
  --field-required-color: var(--color-destructive);
481
786
  --field-required-marker: ' *'; /* appended to required labels */
482
787
 
@@ -496,15 +801,47 @@
496
801
  --stat-change-negative: var(--color-destructive);
497
802
  }
498
803
 
804
+ /* ── Scheme islands ── */
805
+ /* The colour aliases above, restated where a scheme can change below the root —
806
+ a custom property resolves its var() on the element that declares it, so a
807
+ `:root`-only alias would carry the page's light value into a nested
808
+ `data-theme="dark"` region. See the same block in tokens/aliases.css; the
809
+ values must match the `:root` declarations above exactly. */
810
+ [data-theme],
811
+ [data-skin] {
812
+ --kv-label-color: var(--doc-legal-color);
813
+ --kv-value-color: var(--color-fg);
814
+ --callout-bg: var(--color-bg-subtle);
815
+ --callout-fg: var(--color-fg);
816
+ --image-border: var(--color-border);
817
+ --image-caption-color: var(--doc-legal-color);
818
+ --field-label-color: var(--color-fg);
819
+ --field-description-color: var(--color-fg-muted);
820
+ --field-error-color: var(--color-destructive);
821
+ --field-validating-color: var(--color-fg-muted);
822
+ --field-required-color: var(--color-destructive);
823
+ --page-break-screen-color: var(--color-border);
824
+ --page-break-screen-label-color: var(--color-fg-muted);
825
+ --stat-label-color: var(--color-fg-muted);
826
+ --stat-change-positive: var(--color-success);
827
+ --stat-change-negative: var(--color-destructive);
828
+ }
829
+
499
830
  /* === tokens/density.css === */
500
- /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6)
831
+ /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6;
832
+ `spacious` added 1.1A-09, SPEC-1.0.md §4)
501
833
 
502
834
  Put `data-density="compact"` on ANY container and its whole subtree renders
503
835
  tighter: spacing steps shrink by --density-scale and interactive controls drop
504
836
  to a shorter height ramp. `data-density="comfortable"` restores the base scale,
505
- so density can be reset on an inner subtree.
837
+ so density can be reset on an inner subtree. `data-density="spacious"` is the
838
+ third point on the ladder, above comfortable: spacing grows and the control
839
+ ramp grows with it, gentler than the spacing multiplier for the same reason
840
+ compact's ramp shrinks gentler — a usable hit target has a ceiling as well as
841
+ a floor.
506
842
 
507
843
  <section data-density="compact"> … dense form / table / toolbar … </section>
844
+ <section data-density="spacious"> … roomy landing hero, kiosk UI … </section>
508
845
 
509
846
  This is 100% CSS. `data-density` is NOT a sixth protocol attribute: no
510
847
  component contract, manifest, controller or audit rule knows about it — CSS
@@ -641,6 +978,57 @@
641
978
  --content-gutter: var(--space-6);
642
979
  }
643
980
 
981
+ /* The third density: roomier than the base scale, for a landing hero or a kiosk
982
+ UI meant to be read at arm's length. Control heights grow slower than the
983
+ spacing multiplier — the same asymmetry compact's ramp has, mirrored. */
984
+ [data-density="spacious"] {
985
+ --density-scale: 1.25;
986
+
987
+ /* ── Spacing scale (× --density-scale) ── */
988
+ --space-0h: calc(0.125rem * var(--density-scale));
989
+ --space-1: calc(0.25rem * var(--density-scale));
990
+ --space-1h: calc(0.375rem * var(--density-scale));
991
+ --space-2: calc(0.5rem * var(--density-scale));
992
+ --space-2h: calc(0.625rem * var(--density-scale));
993
+ --space-3: calc(0.75rem * var(--density-scale));
994
+ --space-3h: calc(0.875rem * var(--density-scale));
995
+ --space-4: calc(1rem * var(--density-scale));
996
+ --space-5: calc(1.25rem * var(--density-scale));
997
+ --space-6: calc(1.5rem * var(--density-scale));
998
+ --space-7: calc(1.75rem * var(--density-scale));
999
+ --space-8: calc(2rem * var(--density-scale));
1000
+ --space-10: calc(2.5rem * var(--density-scale));
1001
+ --space-12: calc(3rem * var(--density-scale));
1002
+ --space-16: calc(4rem * var(--density-scale));
1003
+ --space-20: calc(5rem * var(--density-scale));
1004
+ --space-24: calc(6rem * var(--density-scale));
1005
+ --space-32: calc(8rem * var(--density-scale));
1006
+ --space-40: calc(10rem * var(--density-scale));
1007
+ --space-48: calc(12rem * var(--density-scale));
1008
+ --space-64: calc(16rem * var(--density-scale));
1009
+
1010
+ /* ── Control height ramp ── */
1011
+ --control-height-sm: 36px;
1012
+ --control-height-md: 44px;
1013
+ --control-height-lg: 52px;
1014
+
1015
+ /* ── Aliases re-substituted in this scope (values identical to the base) ── */
1016
+ --button-height-sm: var(--control-height-sm);
1017
+ --button-height-md: var(--control-height-md);
1018
+ --button-height-lg: var(--control-height-lg);
1019
+ --input-height: var(--control-height-md);
1020
+ --card-padding: var(--space-6);
1021
+ --kv-pair-gap: var(--space-3);
1022
+ --kv-grid-gap: var(--space-4);
1023
+ --callout-padding-y: var(--space-3);
1024
+ --callout-padding-x: var(--space-4);
1025
+ --field-gap: var(--space-1h);
1026
+ --section-gap-sm: var(--space-12);
1027
+ --section-gap-md: var(--space-20);
1028
+ --section-gap-lg: var(--space-32);
1029
+ --content-gutter: var(--space-6);
1030
+ }
1031
+
644
1032
  /* === themes/aurora.css === */
645
1033
  /* @ui:theme aurora — vibrant gradient accents on deep neutral dark; modern SaaS */
646
1034
 
@@ -693,12 +1081,42 @@
693
1081
  /* ── Signature gradient accent (decorative; violet → cyan) ── */
694
1082
  --gradient-accent: linear-gradient(135deg, oklch(0.51 0.24 300), oklch(0.60 0.14 220));
695
1083
 
696
- /* ── Shadows (violet-tinted) ── */
697
- --shadow-xs: 0 1px 2px oklch(0.25 0.05 300 / 0.08);
698
- --shadow-sm: 0 1px 3px oklch(0.25 0.05 300 / 0.10), 0 1px 2px oklch(0.25 0.05 300 / 0.06);
699
- --shadow-md: 0 4px 6px oklch(0.25 0.05 300 / 0.08), 0 2px 4px oklch(0.25 0.05 300 / 0.06);
700
- --shadow-lg: 0 10px 15px oklch(0.25 0.05 300 / 0.10), 0 4px 6px oklch(0.25 0.05 300 / 0.06);
701
- --shadow-xl: 0 20px 25px oklch(0.25 0.05 300 / 0.12), 0 8px 10px oklch(0.25 0.05 300 / 0.06);
1084
+ /* ── Type voice: display headings, set tight ──
1085
+ The one thing every modern SaaS landing page does to its type and no token
1086
+ could say before 1.1A-01. Tracking is additive — the heading primitive keeps
1087
+ its own optical tightening and this rides on top of it. */
1088
+ --heading-tracking: -0.02em;
1089
+
1090
+ /* ── Material: the aurora itself ──
1091
+ A soft gradient mesh on the page, which is the one texture in the set that
1092
+ is a light rather than a grain. It dresses the PAGE and not `surface`/`card`
1093
+ (`--texture-surface`): a mesh behind every card would compete with the
1094
+ content sitting on it, and the theme's subject is the sky behind the app. */
1095
+ --texture-page: var(--texture-mesh);
1096
+
1097
+ /* ── Depth: layered, and tinted through the channel ──
1098
+ Every step is cast in `--shadow-color` (bare OKLCH channels), so the violet
1099
+ cast is ONE declaration per scheme instead of ten literals, and the geometry
1100
+ matches the dark ramp below: the md step blurs past the `layered` band,
1101
+ which is what a stack of floating SaaS panels looks like. */
1102
+ --shadow-color: 0.25 0.05 300;
1103
+
1104
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.08);
1105
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.10), 0 1px 2px oklch(var(--shadow-color) / 0.06);
1106
+ --shadow-md: 0 6px 12px oklch(var(--shadow-color) / 0.09), 0 2px 4px oklch(var(--shadow-color) / 0.06);
1107
+ --shadow-lg: 0 12px 24px oklch(var(--shadow-color) / 0.11), 0 4px 8px oklch(var(--shadow-color) / 0.06);
1108
+ --shadow-xl: 0 24px 48px oklch(var(--shadow-color) / 0.13), 0 8px 16px oklch(var(--shadow-color) / 0.07);
1109
+ }
1110
+
1111
+ :root,
1112
+ [data-theme] {
1113
+ /* ── Decoration: selection wears the accent ──
1114
+ The one surface of a themed page that never matched the theme.
1115
+ On `:root, [data-theme]`: the token layer re-resolves these aliases on
1116
+ every scheme island (tokens/aliases.css), so a `:root`-only override
1117
+ would fall back to the default inside a nested `data-theme` region. */
1118
+ --selection-bg: var(--color-primary);
1119
+ --selection-fg: var(--color-primary-fg);
702
1120
  }
703
1121
 
704
1122
  /* ── Dark Mode (primary design target) ── */
@@ -750,12 +1168,14 @@
750
1168
  /* ── Signature gradient accent (decorative; violet → cyan aurora) ── */
751
1169
  --gradient-accent: linear-gradient(135deg, oklch(0.72 0.18 307), oklch(0.78 0.14 195));
752
1170
 
753
- /* ── Shadows (deep, near-black violet) ── */
754
- --shadow-xs: 0 1px 3px oklch(0.06 0.02 300 / 0.4);
755
- --shadow-sm: 0 2px 6px oklch(0.06 0.02 300 / 0.5);
756
- --shadow-md: 0 6px 12px oklch(0.06 0.02 300 / 0.5), 0 2px 4px oklch(0.06 0.02 300 / 0.3);
757
- --shadow-lg: 0 12px 24px oklch(0.06 0.02 300 / 0.6), 0 4px 8px oklch(0.06 0.02 300 / 0.3);
758
- --shadow-xl: 0 24px 48px oklch(0.06 0.02 300 / 0.7), 0 8px 16px oklch(0.06 0.02 300 / 0.4);
1171
+ /* ── Shadows (deep, near-black violet — the same ramp, cast darker) ── */
1172
+ --shadow-color: 0.06 0.02 300;
1173
+
1174
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.4);
1175
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.5);
1176
+ --shadow-md: 0 6px 12px oklch(var(--shadow-color) / 0.5), 0 2px 4px oklch(var(--shadow-color) / 0.3);
1177
+ --shadow-lg: 0 12px 24px oklch(var(--shadow-color) / 0.6), 0 4px 8px oklch(var(--shadow-color) / 0.3);
1178
+ --shadow-xl: 0 24px 48px oklch(var(--shadow-color) / 0.7), 0 8px 16px oklch(var(--shadow-color) / 0.4);
759
1179
  }
760
1180
 
761
1181
  /* ── Auto Dark Mode (system preference) ── */
@@ -807,12 +1227,14 @@
807
1227
  /* ── Signature gradient accent (decorative; violet → cyan aurora) ── */
808
1228
  --gradient-accent: linear-gradient(135deg, oklch(0.72 0.18 307), oklch(0.78 0.14 195));
809
1229
 
810
- /* ── Shadows (deep, near-black violet) ── */
811
- --shadow-xs: 0 1px 3px oklch(0.06 0.02 300 / 0.4);
812
- --shadow-sm: 0 2px 6px oklch(0.06 0.02 300 / 0.5);
813
- --shadow-md: 0 6px 12px oklch(0.06 0.02 300 / 0.5), 0 2px 4px oklch(0.06 0.02 300 / 0.3);
814
- --shadow-lg: 0 12px 24px oklch(0.06 0.02 300 / 0.6), 0 4px 8px oklch(0.06 0.02 300 / 0.3);
815
- --shadow-xl: 0 24px 48px oklch(0.06 0.02 300 / 0.7), 0 8px 16px oklch(0.06 0.02 300 / 0.4);
1230
+ /* ── Shadows (deep, near-black violet — the same ramp, cast darker) ── */
1231
+ --shadow-color: 0.06 0.02 300;
1232
+
1233
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.4);
1234
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.5);
1235
+ --shadow-md: 0 6px 12px oklch(var(--shadow-color) / 0.5), 0 2px 4px oklch(var(--shadow-color) / 0.3);
1236
+ --shadow-lg: 0 12px 24px oklch(var(--shadow-color) / 0.6), 0 4px 8px oklch(var(--shadow-color) / 0.3);
1237
+ --shadow-xl: 0 24px 48px oklch(var(--shadow-color) / 0.7), 0 8px 16px oklch(var(--shadow-color) / 0.4);
816
1238
  }
817
1239
  }
818
1240
 
@@ -830,11 +1252,38 @@
830
1252
  padding: 0;
831
1253
  }
832
1254
 
1255
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1256
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1257
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1258
+ these three rules; declaring them here (rather than in each theme) is what
1259
+ makes the two authoring forms interchangeable. Nothing else in the registry
1260
+ declares `color-scheme`, so this is purely additive.
1261
+
1262
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1263
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1264
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1265
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1266
+ dark island inside a light page has always worked here. */
1267
+ :root {
1268
+ color-scheme: light;
1269
+ }
1270
+
1271
+ [data-theme="dark"] {
1272
+ color-scheme: dark;
1273
+ }
1274
+
1275
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1276
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1277
+ does for a theme authored in the three-block form. */
1278
+ [data-theme="auto"] {
1279
+ color-scheme: light dark;
1280
+ }
1281
+
833
1282
  html {
834
1283
  -webkit-text-size-adjust: 100%;
835
1284
  -moz-tab-size: 4;
836
1285
  tab-size: 4;
837
- font-family: var(--font-sans);
1286
+ font-family: var(--font-body);
838
1287
  font-size: var(--text-base);
839
1288
  line-height: var(--leading-normal);
840
1289
  color: var(--color-fg);
@@ -845,6 +1294,11 @@ html {
845
1294
 
846
1295
  body {
847
1296
  min-height: 100dvh;
1297
+ /* The page's material. `none` by default (the initial value), so this is a
1298
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1299
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1300
+ covers the viewport, so the two compose instead of overwriting. */
1301
+ background-image: var(--texture-page);
848
1302
  }
849
1303
 
850
1304
  img,
@@ -914,10 +1368,32 @@ table {
914
1368
  }
915
1369
  }
916
1370
 
917
- /* Focus visible — default ring */
1371
+ /* Text selection — the decoration axis reaching the one surface no component
1372
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1373
+ of a themed page that never matched the theme. Both values are tokens
1374
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1375
+ ::selection {
1376
+ background-color: var(--selection-bg);
1377
+ color: var(--selection-fg);
1378
+ }
1379
+
1380
+ /* Focus visible — the default ring, and the only place it is spelled out.
1381
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1382
+ focus once and every element that has not drawn its own ring follows. */
918
1383
  :focus-visible {
919
- outline: 2px solid var(--color-ring);
920
- outline-offset: 2px;
1384
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1385
+ outline-offset: var(--focus-ring-offset);
1386
+ }
1387
+
1388
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1389
+ is not a property focus owns: an element's resting shadow — a card's depth,
1390
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1391
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1392
+ sets a shadow outranks this one, so it lands only on an element nothing else
1393
+ shadows, and it never takes a shadow away. The controls that draw their own
1394
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1395
+ :where(:focus-visible) {
1396
+ box-shadow: var(--focus-shadow);
921
1397
  }
922
1398
 
923
1399
  /* Hidden but accessible */
@@ -946,7 +1422,7 @@ table {
946
1422
  /* @ui:base prose — typography defaults for long-form content */
947
1423
 
948
1424
  [data-ui="prose"] {
949
- font-family: var(--font-sans);
1425
+ font-family: var(--font-body);
950
1426
  font-size: var(--text-base);
951
1427
  line-height: var(--leading-relaxed);
952
1428
  color: var(--color-fg);
@@ -954,29 +1430,45 @@ table {
954
1430
  }
955
1431
 
956
1432
  [data-ui="prose"] h1 {
1433
+ font-family: var(--font-heading);
957
1434
  font-size: var(--text-4xl);
958
- font-weight: var(--weight-bold);
959
- line-height: var(--leading-tight);
1435
+ font-weight: var(--heading-weight);
1436
+ letter-spacing: var(--heading-tracking);
1437
+ text-transform: var(--heading-transform);
1438
+ font-variant-caps: var(--heading-caps);
1439
+ line-height: var(--heading-leading);
960
1440
  margin-block: var(--space-8) var(--space-4);
961
1441
  }
962
1442
 
963
1443
  [data-ui="prose"] h2 {
1444
+ font-family: var(--font-heading);
964
1445
  font-size: var(--text-3xl);
965
1446
  font-weight: var(--weight-semibold);
966
- line-height: var(--leading-tight);
1447
+ letter-spacing: var(--heading-tracking);
1448
+ text-transform: var(--heading-transform);
1449
+ font-variant-caps: var(--heading-caps);
1450
+ line-height: var(--heading-leading);
967
1451
  margin-block: var(--space-8) var(--space-3);
968
1452
  }
969
1453
 
970
1454
  [data-ui="prose"] h3 {
1455
+ font-family: var(--font-heading);
971
1456
  font-size: var(--text-2xl);
972
1457
  font-weight: var(--weight-semibold);
1458
+ letter-spacing: var(--heading-tracking);
1459
+ text-transform: var(--heading-transform);
1460
+ font-variant-caps: var(--heading-caps);
973
1461
  line-height: var(--leading-snug);
974
1462
  margin-block: var(--space-6) var(--space-3);
975
1463
  }
976
1464
 
977
1465
  [data-ui="prose"] h4 {
1466
+ font-family: var(--font-heading);
978
1467
  font-size: var(--text-xl);
979
1468
  font-weight: var(--weight-semibold);
1469
+ letter-spacing: var(--heading-tracking);
1470
+ text-transform: var(--heading-transform);
1471
+ font-variant-caps: var(--heading-caps);
980
1472
  line-height: var(--leading-snug);
981
1473
  margin-block: var(--space-6) var(--space-2);
982
1474
  }
@@ -987,8 +1479,8 @@ table {
987
1479
 
988
1480
  [data-ui="prose"] a {
989
1481
  color: var(--color-primary);
990
- text-decoration: underline;
991
- text-underline-offset: 2px;
1482
+ text-decoration-line: var(--link-decoration);
1483
+ text-underline-offset: var(--link-underline-offset);
992
1484
  }
993
1485
 
994
1486
  [data-ui="prose"] a:hover {
@@ -1025,7 +1517,7 @@ table {
1025
1517
  }
1026
1518
 
1027
1519
  [data-ui="prose"] blockquote {
1028
- border-inline-start: 3px solid var(--color-border-strong);
1520
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1029
1521
  padding-inline-start: var(--space-4);
1030
1522
  color: var(--color-fg-muted);
1031
1523
  margin-block: var(--space-4);
@@ -1047,9 +1539,15 @@ table {
1047
1539
  margin-block: var(--space-1);
1048
1540
  }
1049
1541
 
1542
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1543
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1544
+ [data-ui="prose"] li::marker {
1545
+ color: var(--marker-color);
1546
+ }
1547
+
1050
1548
  [data-ui="prose"] hr {
1051
1549
  border: none;
1052
- border-block-start: 1px solid var(--color-border);
1550
+ border-block-start: var(--border-width) solid var(--color-border);
1053
1551
  margin-block: var(--space-8);
1054
1552
  }
1055
1553
 
@@ -1068,12 +1566,12 @@ table {
1068
1566
  font-weight: var(--weight-semibold);
1069
1567
  text-align: start;
1070
1568
  padding: var(--space-2) var(--space-3);
1071
- border-block-end: 2px solid var(--color-border-strong);
1569
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1072
1570
  }
1073
1571
 
1074
1572
  [data-ui="prose"] td {
1075
1573
  padding: var(--space-2) var(--space-3);
1076
- border-block-end: 1px solid var(--color-border);
1574
+ border-block-end: var(--border-width) solid var(--color-border);
1077
1575
  }
1078
1576
 
1079
1577
  /* First child no top margin, last child no bottom margin */
@@ -1258,7 +1756,7 @@ table {
1258
1756
 
1259
1757
  /* === primitives/avatar.css === */
1260
1758
  /* @ui:component avatar */
1261
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1759
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1262
1760
 
1263
1761
  /* ── Base ── */
1264
1762
  [data-ui="avatar"] {
@@ -1288,7 +1786,7 @@ table {
1288
1786
  height: 100%;
1289
1787
  background: var(--color-bg-muted);
1290
1788
  color: var(--color-fg-muted);
1291
- font-family: var(--font-sans);
1789
+ font-family: var(--font-ui);
1292
1790
  font-size: var(--text-sm);
1293
1791
  font-weight: var(--weight-medium);
1294
1792
  text-transform: uppercase;
@@ -1313,7 +1811,7 @@ table {
1313
1811
 
1314
1812
  /* === primitives/badge.css === */
1315
1813
  /* @ui:component badge */
1316
- /* @ui:tokens color-bg-muted color-fg color-primary color-primary-fg color-primary-subtle color-secondary color-secondary-fg color-destructive color-destructive-fg color-destructive-subtle color-success color-success-subtle color-warning color-warning-subtle radius-full space-1 space-2 font-sans text-xs text-sm weight-medium */
1814
+ /* @ui:tokens color-bg-muted color-fg color-primary color-primary-fg color-primary-subtle color-secondary color-secondary-fg color-destructive color-destructive-fg color-destructive-subtle color-success color-success-subtle color-warning color-warning-subtle radius-full space-1 space-2 font-ui text-xs text-sm weight-medium corner-shape */
1317
1815
 
1318
1816
  /* ── Base ── */
1319
1817
  [data-ui="badge"] {
@@ -1323,9 +1821,10 @@ table {
1323
1821
  gap: var(--space-1);
1324
1822
  padding: 0.125rem var(--space-2);
1325
1823
  border-radius: var(--badge-radius, var(--radius-full));
1824
+ corner-shape: var(--corner-shape);
1326
1825
  background: var(--color-bg-muted);
1327
1826
  color: var(--color-fg);
1328
- font-family: var(--badge-font, var(--font-sans));
1827
+ font-family: var(--badge-font, var(--font-ui));
1329
1828
  font-size: var(--text-xs);
1330
1829
  font-weight: var(--weight-medium);
1331
1830
  line-height: 1.5;
@@ -1371,11 +1870,11 @@ table {
1371
1870
 
1372
1871
  /* === primitives/breadcrumb.css === */
1373
1872
  /* @ui:component breadcrumb */
1374
- /* @ui:tokens color-fg color-fg-muted color-fg-subtle color-primary-hover color-ring radius-sm space-2 text-xs text-sm text-base font-sans weight-medium duration-fast ease-default */
1873
+ /* @ui:tokens color-fg color-fg-muted color-fg-subtle color-primary-hover color-ring radius-sm space-2 text-xs text-sm text-base font-ui weight-medium duration-fast ease-default focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow link-decoration */
1375
1874
 
1376
1875
  /* ── Root ── */
1377
1876
  [data-ui="breadcrumb"] {
1378
- font-family: var(--breadcrumb-font, var(--font-sans));
1877
+ font-family: var(--breadcrumb-font, var(--font-ui));
1379
1878
  font-size: var(--breadcrumb-size, var(--text-sm));
1380
1879
  color: var(--color-fg-muted);
1381
1880
  }
@@ -1401,12 +1900,13 @@ table {
1401
1900
 
1402
1901
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1403
1902
  color: var(--color-primary-hover);
1404
- text-decoration: underline;
1903
+ text-decoration-line: var(--link-decoration);
1405
1904
  }
1406
1905
 
1407
1906
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1408
- outline: 2px solid var(--color-ring);
1409
- outline-offset: 2px;
1907
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1908
+ outline-offset: var(--focus-ring-offset);
1909
+ box-shadow: var(--focus-shadow);
1410
1910
  }
1411
1911
 
1412
1912
  /* ── Separator (presentational) ── */
@@ -1446,7 +1946,7 @@ table {
1446
1946
 
1447
1947
  /* === primitives/button.css === */
1448
1948
  /* @ui:component button */
1449
- /* @ui:tokens color-primary color-primary-hover color-primary-fg color-secondary color-secondary-hover color-secondary-fg color-destructive color-destructive-hover color-destructive-fg color-bg color-bg-muted color-bg-subtle color-fg color-border color-ring radius-md space-2 space-3 space-4 space-6 font-sans text-xs text-sm text-base weight-medium duration-fast ease-default shadow-xs radius-full */
1949
+ /* @ui:tokens color-primary color-primary-hover color-primary-fg color-secondary color-secondary-hover color-secondary-fg color-destructive color-destructive-hover color-destructive-fg color-bg color-bg-muted color-bg-subtle color-fg color-border color-ring radius-md space-2 space-3 space-4 space-6 font-ui text-xs text-sm text-base weight-medium duration-fast ease-default shadow-xs radius-full border-width border-width-strong corner-shape focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow button-text-transform motion-hover-lift link-decoration disabled-opacity */
1450
1950
 
1451
1951
  /* ── Base ── */
1452
1952
  [data-ui="button"] {
@@ -1456,18 +1956,21 @@ table {
1456
1956
  gap: var(--space-2);
1457
1957
  height: var(--button-height-md, 40px);
1458
1958
  padding-inline: var(--space-4);
1459
- border: 1px solid var(--color-border);
1959
+ border: var(--border-width) solid var(--color-border);
1460
1960
  border-radius: var(--button-radius, var(--radius-md));
1961
+ corner-shape: var(--corner-shape);
1461
1962
  background: var(--color-bg);
1462
1963
  color: var(--color-fg);
1463
- font-family: var(--font-sans);
1964
+ font-family: var(--font-ui);
1464
1965
  font-size: var(--text-sm);
1465
1966
  font-weight: var(--weight-medium);
1967
+ text-transform: var(--button-text-transform);
1466
1968
  line-height: 1;
1467
1969
  cursor: pointer;
1468
1970
  transition: background var(--duration-fast) var(--ease-default),
1469
1971
  border-color var(--duration-fast) var(--ease-default),
1470
1972
  color var(--duration-fast) var(--ease-default),
1973
+ translate var(--duration-fast) var(--ease-default),
1471
1974
  box-shadow var(--duration-fast) var(--ease-default);
1472
1975
  user-select: none;
1473
1976
  white-space: nowrap;
@@ -1476,11 +1979,16 @@ table {
1476
1979
 
1477
1980
  [data-ui="button"]:hover {
1478
1981
  background: var(--color-bg-muted);
1982
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1983
+ this rule computes what the button computed before the token existed; a
1984
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1985
+ translate: var(--motion-hover-lift);
1479
1986
  }
1480
1987
 
1481
1988
  [data-ui="button"]:focus-visible {
1482
- outline: 2px solid var(--color-ring);
1483
- outline-offset: 2px;
1989
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1990
+ outline-offset: var(--focus-ring-offset);
1991
+ box-shadow: var(--focus-shadow);
1484
1992
  }
1485
1993
 
1486
1994
  /* ── Variants ── */
@@ -1536,7 +2044,7 @@ table {
1536
2044
  padding: 0;
1537
2045
  }
1538
2046
  [data-ui="button"][data-variant="link"]:hover {
1539
- text-decoration: underline;
2047
+ text-decoration-line: var(--link-decoration);
1540
2048
  }
1541
2049
 
1542
2050
  /* ── Sizes ── */
@@ -1555,7 +2063,7 @@ table {
1555
2063
  /* ── States ── */
1556
2064
  [data-ui="button"]:disabled,
1557
2065
  [data-ui="button"][data-state="disabled"] {
1558
- opacity: 0.5;
2066
+ opacity: var(--disabled-opacity);
1559
2067
  cursor: not-allowed;
1560
2068
  pointer-events: none;
1561
2069
  }
@@ -1570,7 +2078,7 @@ table {
1570
2078
  position: absolute;
1571
2079
  width: 1em;
1572
2080
  height: 1em;
1573
- border: 2px solid currentColor;
2081
+ border: var(--border-width-strong) solid currentColor;
1574
2082
  border-inline-end-color: transparent;
1575
2083
  border-radius: var(--radius-full);
1576
2084
  animation: faqir-spin 0.6s linear infinite;
@@ -1617,7 +2125,7 @@ table {
1617
2125
 
1618
2126
  /* === primitives/callout.css === */
1619
2127
  /* @ui:component callout */
1620
- /* @ui:tokens callout-radius callout-padding-y callout-padding-x callout-border-left-width callout-font-size callout-icon-size callout-fg color-fg color-fg-muted color-info color-info-subtle color-warning color-warning-subtle color-destructive color-destructive-subtle color-success color-success-subtle color-bg-muted color-border color-ring space-1 radius-sm font-sans weight-semibold */
2128
+ /* @ui:tokens callout-radius callout-padding-y callout-padding-x callout-border-left-width callout-font-size callout-icon-size callout-fg color-fg color-fg-muted color-info color-info-subtle color-warning color-warning-subtle color-destructive color-destructive-subtle color-success color-success-subtle color-bg-muted color-border color-ring space-1 radius-sm font-heading font-body weight-semibold focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
1621
2129
 
1622
2130
  /* ── Base ── */
1623
2131
  [data-ui="callout"] {
@@ -1626,7 +2134,7 @@ table {
1626
2134
  padding: var(--callout-padding-y) var(--callout-padding-x);
1627
2135
  border-radius: var(--callout-radius);
1628
2136
  border-inline-start: var(--callout-border-left-width) solid;
1629
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2137
+ font-family: var(--doc-font, var(--font-body));
1630
2138
  font-size: var(--callout-font-size);
1631
2139
  line-height: var(--doc-line-height, 1.5);
1632
2140
  }
@@ -1657,6 +2165,7 @@ table {
1657
2165
  /* ── Title ── */
1658
2166
  [data-ui="callout"] [data-part="title"] {
1659
2167
  display: block;
2168
+ font-family: var(--font-heading);
1660
2169
  font-weight: var(--weight-semibold);
1661
2170
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1662
2171
  }
@@ -1683,8 +2192,9 @@ table {
1683
2192
  }
1684
2193
 
1685
2194
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1686
- outline: 2px solid var(--color-ring, var(--color-info));
1687
- outline-offset: 2px;
2195
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2196
+ outline-offset: var(--focus-ring-offset);
2197
+ box-shadow: var(--focus-shadow);
1688
2198
  opacity: 1;
1689
2199
  }
1690
2200
 
@@ -1770,17 +2280,36 @@ table {
1770
2280
 
1771
2281
  /* === primitives/card.css === */
1772
2282
  /* @ui:component card */
1773
- /* @ui:tokens color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border color-fg color-fg-muted radius-lg shadow-sm space-4 space-6 font-sans text-sm text-lg text-xl weight-semibold leading-tight */
2283
+ /* @ui:tokens color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border color-fg color-fg-muted radius-lg shadow-sm space-4 space-6 font-heading text-sm text-lg text-xl weight-semibold leading-tight border-width corner-shape card-border-width surface-backdrop texture-surface motion-hover-lift duration-fast ease-default */
1774
2284
 
1775
2285
  /* ── Base ── */
1776
2286
  [data-ui="card"] {
1777
2287
  display: flex;
1778
2288
  flex-direction: column;
1779
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2289
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1780
2290
  border-radius: var(--card-radius, var(--radius-lg));
1781
- background: var(--card-bg, var(--color-surface-1));
2291
+ corner-shape: var(--corner-shape);
2292
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2293
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2294
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2295
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1782
2296
  box-shadow: var(--card-shadow, var(--shadow-sm));
1783
2297
  overflow: hidden;
2298
+ transition: translate var(--duration-fast) var(--ease-default);
2299
+ }
2300
+
2301
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2302
+ value of `translate`), so a card sits exactly where it always sat until a
2303
+ theme says surfaces rise under the pointer. */
2304
+ [data-ui="card"]:hover {
2305
+ translate: var(--motion-hover-lift);
2306
+ }
2307
+
2308
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2309
+ [data-ui="card"] {
2310
+ -webkit-backdrop-filter: var(--surface-backdrop);
2311
+ backdrop-filter: var(--surface-backdrop);
2312
+ }
1784
2313
  }
1785
2314
 
1786
2315
  /* ── Variants ── */
@@ -1789,7 +2318,7 @@ table {
1789
2318
  }
1790
2319
 
1791
2320
  [data-ui="card"][data-variant="filled"] {
1792
- background: var(--color-surface-2);
2321
+ background: var(--texture-surface), var(--color-surface-2);
1793
2322
  border-color: var(--color-surface-2-border);
1794
2323
  box-shadow: none;
1795
2324
  }
@@ -1804,7 +2333,7 @@ table {
1804
2333
  }
1805
2334
 
1806
2335
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1807
- font-family: var(--font-sans);
2336
+ font-family: var(--font-heading);
1808
2337
  font-size: var(--text-lg);
1809
2338
  font-weight: var(--weight-semibold);
1810
2339
  line-height: var(--leading-tight);
@@ -1845,9 +2374,19 @@ table {
1845
2374
  padding-top: 0;
1846
2375
  }
1847
2376
 
2377
+ /* ── Motion ── */
2378
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2379
+ theme states one — but the house rule is that a stylesheet which transitions
2380
+ carries its own opt-out, so a reader never has to check the token first. */
2381
+ @media (prefers-reduced-motion: reduce) {
2382
+ [data-ui="card"] {
2383
+ transition: none;
2384
+ }
2385
+ }
2386
+
1848
2387
  /* === primitives/checkbox.css === */
1849
2388
  /* @ui:component checkbox */
1850
- /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-sm space-1 space-2 duration-fast ease-default */
2389
+ /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring space-1 space-2 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow checkbox-radius checkbox-size disabled-opacity */
1851
2390
 
1852
2391
  /* -- Label wrapper -- */
1853
2392
  [data-ui="checkbox-label"] {
@@ -1859,7 +2398,7 @@ table {
1859
2398
 
1860
2399
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1861
2400
  cursor: not-allowed;
1862
- opacity: 0.5;
2401
+ opacity: var(--disabled-opacity);
1863
2402
  }
1864
2403
 
1865
2404
  /* -- Base -- */
@@ -1871,8 +2410,8 @@ table {
1871
2410
  width: var(--checkbox-size, 18px);
1872
2411
  height: var(--checkbox-size, 18px);
1873
2412
  flex-shrink: 0;
1874
- border: 1px solid var(--color-border);
1875
- border-radius: var(--checkbox-radius, var(--radius-sm));
2413
+ border: var(--border-width) solid var(--color-border);
2414
+ border-radius: var(--checkbox-radius);
1876
2415
  background: var(--color-bg);
1877
2416
  cursor: pointer;
1878
2417
  transition: background var(--duration-fast) var(--ease-default),
@@ -1885,8 +2424,9 @@ table {
1885
2424
  }
1886
2425
 
1887
2426
  [data-ui="checkbox"]:focus-visible {
1888
- outline: 2px solid var(--color-ring);
1889
- outline-offset: 2px;
2427
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2428
+ outline-offset: var(--focus-ring-offset);
2429
+ box-shadow: var(--focus-shadow);
1890
2430
  }
1891
2431
 
1892
2432
  /* -- Checked -- */
@@ -1977,7 +2517,7 @@ table {
1977
2517
  The mask has to opt out of the substitution to stay readable. [W3-3] */
1978
2518
  @media (forced-colors: active) {
1979
2519
  [data-ui="checkbox"] {
1980
- border: 1px solid ButtonText;
2520
+ border: var(--border-width) solid ButtonText;
1981
2521
  }
1982
2522
 
1983
2523
  [data-ui="checkbox"]:checked,
@@ -2001,7 +2541,7 @@ table {
2001
2541
 
2002
2542
  /* === primitives/chip.css === */
2003
2543
  /* @ui:component chip */
2004
- /* @ui:tokens color-bg-muted color-fg color-fg-muted color-primary color-primary-subtle color-destructive color-destructive-subtle color-border color-ring radius-full space-1 space-2 space-3 font-sans text-xs text-sm weight-medium */
2544
+ /* @ui:tokens color-bg-muted color-fg color-fg-muted color-primary color-primary-subtle color-destructive color-destructive-subtle color-border color-ring radius-full space-1 space-2 space-3 font-ui text-xs text-sm weight-medium border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
2005
2545
 
2006
2546
  /* ── Base ── */
2007
2547
  [data-ui="chip"] {
@@ -2009,11 +2549,11 @@ table {
2009
2549
  align-items: center;
2010
2550
  gap: var(--space-1);
2011
2551
  padding: var(--space-1) var(--space-2);
2012
- border: 1px solid transparent;
2552
+ border: var(--border-width) solid transparent;
2013
2553
  border-radius: var(--chip-radius, var(--radius-full));
2014
2554
  background: var(--color-bg-muted);
2015
2555
  color: var(--color-fg);
2016
- font-family: var(--chip-font, var(--font-sans));
2556
+ font-family: var(--chip-font, var(--font-ui));
2017
2557
  font-size: var(--text-sm);
2018
2558
  font-weight: var(--weight-medium);
2019
2559
  line-height: 1.2;
@@ -2049,8 +2589,11 @@ table {
2049
2589
  }
2050
2590
 
2051
2591
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2052
- outline: 2px solid var(--color-ring);
2053
- outline-offset: 1px;
2592
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2593
+ /* Half the default gap — the dismiss target is small, and the full ring
2594
+ would collide with the chip's own edge. */
2595
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2596
+ box-shadow: var(--focus-shadow);
2054
2597
  }
2055
2598
 
2056
2599
  /* ── Variants ── */
@@ -2273,12 +2816,12 @@ table {
2273
2816
 
2274
2817
  /* === primitives/collapsible.css === */
2275
2818
  /* @ui:component collapsible */
2276
- /* @ui:tokens color-fg color-fg-muted color-bg-subtle color-border color-ring radius-md space-2 space-3 text-sm text-base font-sans weight-medium duration-fast duration-normal ease-default */
2819
+ /* @ui:tokens color-fg color-fg-muted color-bg-subtle color-border color-ring radius-md space-2 space-3 text-sm text-base font-ui weight-medium duration-fast duration-normal ease-default border-width border-width-strong focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
2277
2820
 
2278
2821
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2279
2822
  [data-ui="collapsible"] {
2280
2823
  border-radius: var(--collapsible-radius, var(--radius-md));
2281
- font-family: var(--collapsible-font, var(--font-sans));
2824
+ font-family: var(--collapsible-font, var(--font-ui));
2282
2825
  color: var(--color-fg);
2283
2826
  }
2284
2827
 
@@ -2308,8 +2851,9 @@ table {
2308
2851
  }
2309
2852
 
2310
2853
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2311
- outline: 2px solid var(--color-ring);
2312
- outline-offset: 2px;
2854
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2855
+ outline-offset: var(--focus-ring-offset);
2856
+ box-shadow: var(--focus-shadow);
2313
2857
  }
2314
2858
 
2315
2859
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2318,8 +2862,8 @@ table {
2318
2862
  flex: none;
2319
2863
  width: 0.5em;
2320
2864
  height: 0.5em;
2321
- border-inline-end: 2px solid var(--color-fg-muted);
2322
- border-block-end: 2px solid var(--color-fg-muted);
2865
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2866
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2323
2867
  transform: rotate(45deg);
2324
2868
  transition: transform var(--duration-normal) var(--ease-default);
2325
2869
  }
@@ -2338,7 +2882,7 @@ table {
2338
2882
 
2339
2883
  /* ── Bordered variant ── */
2340
2884
  [data-ui="collapsible"][data-variant="bordered"] {
2341
- border: 1px solid var(--color-border);
2885
+ border: var(--border-width) solid var(--color-border);
2342
2886
  }
2343
2887
 
2344
2888
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2471,13 +3015,13 @@ table {
2471
3015
 
2472
3016
  /* === primitives/description-list.css === */
2473
3017
  /* @ui:component description-list */
2474
- /* @ui:tokens color-fg color-fg-muted color-border doc-font doc-line-height space-1 space-2 space-3 space-4 space-6 text-xs text-sm text-base font-sans weight-semibold */
3018
+ /* @ui:tokens color-fg color-fg-muted color-border doc-font doc-line-height space-1 space-2 space-3 space-4 space-6 text-xs text-sm text-base font-body weight-semibold border-width */
2475
3019
 
2476
3020
  /* ── Base ── */
2477
3021
  [data-ui="description-list"] {
2478
3022
  margin: 0;
2479
3023
  padding: 0;
2480
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3024
+ font-family: var(--doc-font, var(--font-body));
2481
3025
  }
2482
3026
 
2483
3027
  /* ── Term ── */
@@ -2533,7 +3077,7 @@ table {
2533
3077
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2534
3078
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2535
3079
  padding-bottom: var(--space-4);
2536
- border-bottom: 1px solid var(--color-border);
3080
+ border-bottom: var(--border-width) solid var(--color-border);
2537
3081
  }
2538
3082
 
2539
3083
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2545,7 +3089,7 @@ table {
2545
3089
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2546
3090
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2547
3091
  padding-bottom: var(--space-3);
2548
- border-bottom: 1px solid var(--color-border);
3092
+ border-bottom: var(--border-width) solid var(--color-border);
2549
3093
  }
2550
3094
 
2551
3095
  /* ── Size: Small ── */
@@ -2583,7 +3127,7 @@ table {
2583
3127
 
2584
3128
  /* === primitives/empty-state.css === */
2585
3129
  /* @ui:component empty-state */
2586
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3130
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2587
3131
 
2588
3132
  /* ── Base ── */
2589
3133
  [data-ui="empty-state"] {
@@ -2604,6 +3148,7 @@ table {
2604
3148
 
2605
3149
  /* ── Title ── */
2606
3150
  [data-ui="empty-state"] [data-part="title"] {
3151
+ font-family: var(--font-heading);
2607
3152
  font-size: var(--text-lg);
2608
3153
  font-weight: var(--weight-medium);
2609
3154
  color: var(--color-fg);
@@ -2651,7 +3196,7 @@ table {
2651
3196
 
2652
3197
  /* === primitives/field-group.css === */
2653
3198
  /* @ui:component field-group */
2654
- /* @ui:tokens field-label-size field-label-weight field-label-color field-description-size field-description-color field-error-size field-error-color field-required-color field-required-marker field-validating-color field-disabled-opacity color-destructive color-success space-1 space-2 space-3 space-4 text-xs text-sm font-sans */
3199
+ /* @ui:tokens field-label-size field-label-weight field-label-color field-description-size field-description-color field-error-size field-error-color field-required-color field-required-marker field-validating-color field-disabled-opacity color-destructive color-success space-1 space-2 space-3 space-4 text-xs text-sm font-body border-width */
2655
3200
 
2656
3201
  /* ── Base / spacing ownership ──
2657
3202
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2663,7 +3208,7 @@ table {
2663
3208
  display: flex;
2664
3209
  flex-direction: column;
2665
3210
  gap: var(--space-2);
2666
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3211
+ font-family: var(--doc-font, var(--font-body));
2667
3212
  }
2668
3213
 
2669
3214
  /* ── Label ── */
@@ -2733,7 +3278,7 @@ table {
2733
3278
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2734
3279
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2735
3280
  border-color: var(--field-error-color);
2736
- box-shadow: 0 0 0 1px var(--field-error-color);
3281
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2737
3282
  }
2738
3283
 
2739
3284
  /* ── State: Validating ──
@@ -2743,7 +3288,7 @@ table {
2743
3288
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2744
3289
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2745
3290
  border-color: var(--field-validating-color);
2746
- box-shadow: 0 0 0 1px var(--field-validating-color);
3291
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2747
3292
  }
2748
3293
 
2749
3294
  /* ── State: Disabled ──
@@ -2762,8 +3307,8 @@ table {
2762
3307
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2763
3308
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2764
3309
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2765
- border-color: var(--color-success, oklch(0.62 0.19 145));
2766
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3310
+ border-color: var(--color-success);
3311
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2767
3312
  }
2768
3313
 
2769
3314
  /* ── Variant: Horizontal ── */
@@ -3068,7 +3613,7 @@ table {
3068
3613
 
3069
3614
  /* === primitives/image.css === */
3070
3615
  /* @ui:component image */
3071
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3616
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3072
3617
 
3073
3618
  /* ── Base ── */
3074
3619
  [data-ui="image"] {
@@ -3092,7 +3637,7 @@ table {
3092
3637
  [data-ui="image"] [data-part="caption"] {
3093
3638
  display: block;
3094
3639
  margin-top: var(--space-2);
3095
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3640
+ font-family: var(--doc-font, var(--font-body));
3096
3641
  font-size: var(--image-caption-size);
3097
3642
  color: var(--image-caption-color);
3098
3643
  line-height: 1.4;
@@ -3189,7 +3734,7 @@ table {
3189
3734
 
3190
3735
  /* === primitives/input.css === */
3191
3736
  /* @ui:component input */
3192
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
3737
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width corner-shape focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
3193
3738
 
3194
3739
  /* ── Base ── */
3195
3740
  [data-ui="input"] {
@@ -3197,11 +3742,18 @@ table {
3197
3742
  width: 100%;
3198
3743
  height: var(--input-height, 40px);
3199
3744
  padding-inline: var(--space-3);
3200
- border: 1px solid var(--color-border);
3745
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3746
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3747
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3748
+ is drawn. Identical to the shorthand at every other value of the token. */
3749
+ border-style: solid;
3750
+ border-color: var(--color-border);
3751
+ border-width: var(--input-border-width);
3201
3752
  border-radius: var(--input-radius, var(--radius-md));
3202
- background: var(--input-bg, var(--color-bg));
3753
+ corner-shape: var(--corner-shape);
3754
+ background: var(--input-fill);
3203
3755
  color: var(--color-fg);
3204
- font-family: var(--input-font, var(--font-sans));
3756
+ font-family: var(--input-font, var(--font-ui));
3205
3757
  font-size: var(--text-sm);
3206
3758
  line-height: 1;
3207
3759
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3217,8 +3769,11 @@ table {
3217
3769
  }
3218
3770
 
3219
3771
  [data-ui="input"]:focus {
3220
- outline: 2px solid var(--color-ring);
3221
- outline-offset: -1px;
3772
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3773
+ /* The ring replaces the border rather than sitting outside it: inset by
3774
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3775
+ outline-offset: calc(-1 * var(--input-border-width));
3776
+ box-shadow: var(--focus-shadow);
3222
3777
  border-color: transparent;
3223
3778
  }
3224
3779
 
@@ -3246,7 +3801,7 @@ table {
3246
3801
  }
3247
3802
 
3248
3803
  [data-ui="input"]:disabled {
3249
- opacity: 0.5;
3804
+ opacity: var(--disabled-opacity);
3250
3805
  cursor: not-allowed;
3251
3806
  }
3252
3807
 
@@ -3309,7 +3864,7 @@ table {
3309
3864
 
3310
3865
  /* === primitives/kbd.css === */
3311
3866
  /* @ui:component kbd */
3312
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3867
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3313
3868
 
3314
3869
  /* ── Base ── */
3315
3870
  [data-ui="kbd"] {
@@ -3319,8 +3874,8 @@ table {
3319
3874
  height: 20px;
3320
3875
  min-width: 20px;
3321
3876
  padding-inline: var(--space-1h);
3322
- border: 1px solid var(--color-border);
3323
- border-bottom-width: 2px;
3877
+ border: var(--border-width) solid var(--color-border);
3878
+ border-bottom-width: var(--border-width-strong);
3324
3879
  border-radius: var(--radius-sm);
3325
3880
  background: var(--color-bg-subtle);
3326
3881
  color: var(--color-fg);
@@ -3333,7 +3888,7 @@ table {
3333
3888
 
3334
3889
  /* === primitives/key-value.css === */
3335
3890
  /* @ui:component key-value */
3336
- /* @ui:tokens kv-label-color kv-label-weight kv-label-size kv-value-color kv-value-size kv-value-weight kv-gap kv-pair-gap kv-grid-gap text-xs text-sm text-base font-sans */
3891
+ /* @ui:tokens kv-label-color kv-label-weight kv-label-size kv-value-color kv-value-size kv-value-weight kv-gap kv-pair-gap kv-grid-gap text-xs text-sm text-base font-body */
3337
3892
 
3338
3893
  /* ── Base ── */
3339
3894
  [data-ui="key-value"] {
@@ -3342,7 +3897,7 @@ table {
3342
3897
  gap: var(--kv-pair-gap);
3343
3898
  margin: 0;
3344
3899
  padding: 0;
3345
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3900
+ font-family: var(--doc-font, var(--font-body));
3346
3901
  }
3347
3902
 
3348
3903
  /* ── Label ── */
@@ -3472,12 +4027,12 @@ table {
3472
4027
 
3473
4028
  /* === primitives/label.css === */
3474
4029
  /* @ui:component label */
3475
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4030
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3476
4031
 
3477
4032
  /* ── Base ── */
3478
4033
  [data-ui="label"] {
3479
4034
  display: block;
3480
- font-family: var(--font-sans);
4035
+ font-family: var(--font-ui);
3481
4036
  font-size: var(--text-sm);
3482
4037
  font-weight: var(--weight-medium);
3483
4038
  color: var(--color-fg);
@@ -3510,21 +4065,21 @@ table {
3510
4065
 
3511
4066
  /* ── States ── */
3512
4067
  [data-ui="label"][data-state="disabled"] {
3513
- opacity: 0.5;
4068
+ opacity: var(--disabled-opacity);
3514
4069
  cursor: not-allowed;
3515
4070
  }
3516
4071
 
3517
4072
  /* === primitives/link.css === */
3518
4073
  /* @ui:component link */
3519
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4074
+ /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow link-decoration link-thickness link-underline-offset */
3520
4075
 
3521
4076
  /* ── Base ── */
3522
4077
  [data-ui="link"] {
3523
4078
  color: var(--color-primary);
3524
4079
  font-family: inherit;
3525
- text-decoration: underline;
3526
- text-decoration-thickness: 1px;
3527
- text-underline-offset: 0.2em;
4080
+ text-decoration-line: var(--link-decoration);
4081
+ text-decoration-thickness: var(--link-thickness);
4082
+ text-underline-offset: var(--link-underline-offset);
3528
4083
  border-radius: var(--radius-sm);
3529
4084
  cursor: pointer;
3530
4085
  }
@@ -3538,8 +4093,9 @@ table {
3538
4093
  }
3539
4094
 
3540
4095
  [data-ui="link"]:focus-visible {
3541
- outline: 2px solid var(--color-ring);
3542
- outline-offset: 2px;
4096
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4097
+ outline-offset: var(--focus-ring-offset);
4098
+ box-shadow: var(--focus-shadow);
3543
4099
  }
3544
4100
 
3545
4101
  /* ── Variants ── */
@@ -3563,7 +4119,7 @@ table {
3563
4119
 
3564
4120
  /* === primitives/nav.css === */
3565
4121
  /* @ui:component nav */
3566
- /* @ui:tokens color-fg color-fg-muted color-primary color-primary-subtle color-bg-subtle color-border text-sm weight-medium radius-md space-1 space-2 space-3 space-4 duration-fast ease-default */
4122
+ /* @ui:tokens color-fg color-fg-muted color-primary color-primary-subtle color-bg-subtle color-border text-sm weight-medium radius-md space-1 space-2 space-3 space-4 duration-fast ease-default border-width border-width-strong */
3567
4123
 
3568
4124
  /* ── Base ── */
3569
4125
  [data-ui="nav"] {
@@ -3613,14 +4169,14 @@ table {
3613
4169
 
3614
4170
  /* ── Underline variant ── */
3615
4171
  [data-ui="nav"][data-variant="underline"] {
3616
- border-bottom: 1px solid var(--color-border);
4172
+ border-bottom: var(--border-width) solid var(--color-border);
3617
4173
  gap: 0;
3618
4174
  }
3619
4175
 
3620
4176
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3621
4177
  border-radius: 0;
3622
4178
  padding: var(--space-2) var(--space-4);
3623
- border-bottom: 2px solid transparent;
4179
+ border-bottom: var(--border-width-strong) solid transparent;
3624
4180
  margin-bottom: -1px;
3625
4181
  }
3626
4182
 
@@ -3676,7 +4232,7 @@ table {
3676
4232
 
3677
4233
  /* === primitives/page-break.css === */
3678
4234
  /* @ui:component page-break */
3679
- /* @ui:tokens page-break-screen-color page-break-screen-style page-break-screen-label-color page-break-screen-label-size doc-font font-sans space-4 space-6 */
4235
+ /* @ui:tokens page-break-screen-color page-break-screen-style page-break-screen-label-color page-break-screen-label-size doc-font font-body space-4 space-6 border-width */
3680
4236
 
3681
4237
  /* ── Base (Screen) ── */
3682
4238
  [data-ui="page-break"] {
@@ -3691,12 +4247,12 @@ table {
3691
4247
  [data-ui="page-break"]::after {
3692
4248
  content: "";
3693
4249
  flex: 1;
3694
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4250
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3695
4251
  }
3696
4252
 
3697
4253
  /* ── Label (Screen) ── */
3698
4254
  [data-ui="page-break"] {
3699
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4255
+ font-family: var(--doc-font, var(--font-body));
3700
4256
  font-size: var(--page-break-screen-label-size);
3701
4257
  color: var(--page-break-screen-label-color);
3702
4258
  letter-spacing: 0.05em;
@@ -3738,7 +4294,7 @@ table {
3738
4294
 
3739
4295
  /* === primitives/progress.css === */
3740
4296
  /* @ui:component progress */
3741
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4297
+ /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default border-width */
3742
4298
 
3743
4299
  /* ── Base ── */
3744
4300
  [data-ui="progress"] {
@@ -3813,7 +4369,7 @@ table {
3813
4369
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3814
4370
  @media (forced-colors: active) {
3815
4371
  [data-ui="progress"] [data-part="track"] {
3816
- border: 1px solid ButtonText;
4372
+ border: var(--border-width) solid ButtonText;
3817
4373
  }
3818
4374
 
3819
4375
  [data-ui="progress"] [data-part="fill"],
@@ -3827,7 +4383,7 @@ table {
3827
4383
 
3828
4384
  /* === primitives/radio.css === */
3829
4385
  /* @ui:component radio */
3830
- /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-full space-1 space-2 duration-fast ease-default */
4386
+ /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-full space-1 space-2 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow disabled-opacity */
3831
4387
 
3832
4388
  /* -- Radio group -- */
3833
4389
  [data-ui="radio-group"] {
@@ -3849,7 +4405,7 @@ table {
3849
4405
 
3850
4406
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3851
4407
  cursor: not-allowed;
3852
- opacity: 0.5;
4408
+ opacity: var(--disabled-opacity);
3853
4409
  }
3854
4410
 
3855
4411
  /* -- Base -- */
@@ -3861,7 +4417,7 @@ table {
3861
4417
  width: var(--radio-size, 18px);
3862
4418
  height: var(--radio-size, 18px);
3863
4419
  flex-shrink: 0;
3864
- border: 1px solid var(--color-border);
4420
+ border: var(--border-width) solid var(--color-border);
3865
4421
  border-radius: var(--radius-full);
3866
4422
  background: var(--color-bg);
3867
4423
  cursor: pointer;
@@ -3875,8 +4431,9 @@ table {
3875
4431
  }
3876
4432
 
3877
4433
  [data-ui="radio"]:focus-visible {
3878
- outline: 2px solid var(--color-ring);
3879
- outline-offset: 2px;
4434
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4435
+ outline-offset: var(--focus-ring-offset);
4436
+ box-shadow: var(--focus-shadow);
3880
4437
  }
3881
4438
 
3882
4439
  /* -- Checked -- */
@@ -3929,7 +4486,7 @@ table {
3929
4486
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3930
4487
  @media (forced-colors: active) {
3931
4488
  [data-ui="radio"] {
3932
- border: 1px solid ButtonText;
4489
+ border: var(--border-width) solid ButtonText;
3933
4490
  }
3934
4491
 
3935
4492
  [data-ui="radio"]:checked {
@@ -3949,7 +4506,7 @@ table {
3949
4506
 
3950
4507
  /* === primitives/select.css === */
3951
4508
  /* @ui:component select */
3952
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
4509
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
3953
4510
 
3954
4511
  /* -- Base -- */
3955
4512
  [data-ui="select"] {
@@ -3958,11 +4515,17 @@ table {
3958
4515
  height: var(--select-height, 40px);
3959
4516
  padding-inline: var(--space-3);
3960
4517
  padding-inline-end: var(--space-8, 2rem);
3961
- border: 1px solid var(--color-border);
4518
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4519
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4520
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4521
+ is drawn. Identical to the shorthand at every other value of the token. */
4522
+ border-style: solid;
4523
+ border-color: var(--color-border);
4524
+ border-width: var(--input-border-width);
3962
4525
  border-radius: var(--select-radius, var(--radius-md));
3963
- background: var(--select-bg, var(--color-bg));
4526
+ background: var(--select-bg, var(--input-fill));
3964
4527
  color: var(--color-fg);
3965
- font-family: var(--select-font, var(--font-sans));
4528
+ font-family: var(--select-font, var(--font-ui));
3966
4529
  font-size: var(--text-sm);
3967
4530
  line-height: 1;
3968
4531
  cursor: pointer;
@@ -3992,8 +4555,11 @@ table {
3992
4555
  }
3993
4556
 
3994
4557
  [data-ui="select"]:focus {
3995
- outline: 2px solid var(--color-ring);
3996
- outline-offset: -1px;
4558
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4559
+ /* The ring replaces the border rather than sitting outside it: inset by
4560
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4561
+ outline-offset: calc(-1 * var(--input-border-width));
4562
+ box-shadow: var(--focus-shadow);
3997
4563
  border-color: transparent;
3998
4564
  }
3999
4565
 
@@ -4026,7 +4592,7 @@ table {
4026
4592
  }
4027
4593
 
4028
4594
  [data-ui="select"]:disabled {
4029
- opacity: 0.5;
4595
+ opacity: var(--disabled-opacity);
4030
4596
  cursor: not-allowed;
4031
4597
  }
4032
4598
 
@@ -4039,12 +4605,12 @@ table {
4039
4605
 
4040
4606
  /* === primitives/separator.css === */
4041
4607
  /* @ui:component separator */
4042
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4608
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4043
4609
 
4044
4610
  /* ── Base (horizontal) ── */
4045
4611
  [data-ui="separator"] {
4046
4612
  border: none;
4047
- border-top: 1px solid var(--color-border);
4613
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4048
4614
  margin: 0;
4049
4615
  width: 100%;
4050
4616
  }
@@ -4052,7 +4618,7 @@ table {
4052
4618
  /* ── Vertical ── */
4053
4619
  [data-ui="separator"][data-variant="vertical"] {
4054
4620
  border-top: none;
4055
- border-inline-start: 1px solid var(--color-border);
4621
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4056
4622
  width: auto;
4057
4623
  height: 100%;
4058
4624
  align-self: stretch;
@@ -4070,11 +4636,11 @@ div[data-ui="separator"]::before,
4070
4636
  div[data-ui="separator"]::after {
4071
4637
  content: "";
4072
4638
  flex: 1;
4073
- border-top: 1px solid var(--color-border);
4639
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4074
4640
  }
4075
4641
 
4076
4642
  [data-ui="separator"] [data-part="label"] {
4077
- font-family: var(--font-sans);
4643
+ font-family: var(--font-ui);
4078
4644
  font-size: var(--text-xs);
4079
4645
  color: var(--color-fg-muted);
4080
4646
  white-space: nowrap;
@@ -4112,17 +4678,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4112
4678
 
4113
4679
  /* ── Style: Thick ── */
4114
4680
  [data-ui="separator"][data-style="thick"] {
4115
- border-top-width: 2px;
4681
+ border-top-width: var(--border-width-strong);
4116
4682
  }
4117
4683
 
4118
4684
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4119
4685
  border-top-width: 0;
4120
- border-inline-start-width: 2px;
4686
+ border-inline-start-width: var(--border-width-strong);
4121
4687
  }
4122
4688
 
4123
4689
  div[data-ui="separator"][data-style="thick"]::before,
4124
4690
  div[data-ui="separator"][data-style="thick"]::after {
4125
- border-top-width: 2px;
4691
+ border-top-width: var(--border-width-strong);
4126
4692
  }
4127
4693
 
4128
4694
  /* ── Vertical Sizes ── */
@@ -4140,20 +4706,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4140
4706
 
4141
4707
  /* === primitives/signature.css === */
4142
4708
  /* @ui:component signature */
4143
- /* @ui:tokens doc-signature-width doc-signature-gap doc-signature-line-color doc-signature-label-size doc-signature-label-color doc-font font-sans space-2 space-12 */
4709
+ /* @ui:tokens doc-signature-width doc-signature-gap doc-signature-line-color doc-signature-label-size doc-signature-label-color doc-font font-body space-2 space-12 border-width */
4144
4710
 
4145
4711
  /* ── Base ── */
4146
4712
  [data-ui="signature"] {
4147
4713
  display: flex;
4148
4714
  flex-direction: column;
4149
4715
  gap: var(--space-2);
4150
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4716
+ font-family: var(--doc-font, var(--font-body));
4151
4717
  margin-top: var(--doc-signature-gap);
4152
4718
  }
4153
4719
 
4154
4720
  /* ── Line ── */
4155
4721
  [data-ui="signature"] [data-part="line"] {
4156
- border-top: 1px solid var(--doc-signature-line-color);
4722
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4157
4723
  min-height: 1px;
4158
4724
  }
4159
4725
 
@@ -4256,14 +4822,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4256
4822
 
4257
4823
  /* === primitives/spinner.css === */
4258
4824
  /* @ui:component spinner */
4259
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4825
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4260
4826
 
4261
4827
  /* ── Base ── */
4262
4828
  [data-ui="spinner"] {
4263
4829
  display: inline-block;
4264
4830
  width: 24px;
4265
4831
  height: 24px;
4266
- border: 2px solid var(--color-border);
4832
+ border: var(--border-width-strong) solid var(--color-border);
4267
4833
  border-top-color: var(--color-primary);
4268
4834
  border-radius: var(--radius-full);
4269
4835
  animation: faqir-spin 0.75s linear infinite;
@@ -4279,13 +4845,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4279
4845
  [data-ui="spinner"][data-size="lg"] {
4280
4846
  width: 32px;
4281
4847
  height: 32px;
4282
- border-width: 3px;
4848
+ border-width: var(--border-width-lg);
4283
4849
  }
4284
4850
 
4285
4851
  [data-ui="spinner"][data-size="xl"] {
4286
4852
  width: 48px;
4287
4853
  height: 48px;
4288
- border-width: 3px;
4854
+ border-width: var(--border-width-lg);
4289
4855
  }
4290
4856
 
4291
4857
  /* ── Motion ── */
@@ -4867,14 +5433,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4867
5433
 
4868
5434
  /* === primitives/stat.css === */
4869
5435
  /* @ui:component stat */
4870
- /* @ui:tokens stat-value-size stat-value-weight stat-value-num-font stat-label-size stat-label-color stat-change-positive stat-change-negative color-fg color-fg-muted color-bg color-border space-1 space-2 space-4 radius-md shadow-sm font-sans text-xs text-sm text-lg text-3xl weight-semibold */
5436
+ /* @ui:tokens stat-value-size stat-value-weight stat-value-num-font stat-label-size stat-label-color stat-change-positive stat-change-negative color-fg color-fg-muted color-bg color-border space-1 space-2 space-4 radius-md shadow-sm font-heading font-body text-xs text-sm text-lg text-3xl weight-semibold border-width */
4871
5437
 
4872
5438
  /* ── Base ── */
4873
5439
  [data-ui="stat"] {
4874
5440
  display: flex;
4875
5441
  flex-direction: column;
4876
5442
  gap: var(--space-1);
4877
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5443
+ font-family: var(--doc-font, var(--font-body));
4878
5444
  }
4879
5445
 
4880
5446
  /* ── Label ── */
@@ -4888,6 +5454,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4888
5454
 
4889
5455
  /* ── Value ── */
4890
5456
  [data-ui="stat"] [data-part="value"] {
5457
+ font-family: var(--font-heading);
4891
5458
  font-size: var(--stat-value-size);
4892
5459
  font-weight: var(--stat-value-weight);
4893
5460
  color: var(--color-fg);
@@ -4946,10 +5513,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4946
5513
  /* ── Variant: Card ── */
4947
5514
  [data-ui="stat"][data-variant="card"] {
4948
5515
  padding: var(--space-4);
4949
- border: 1px solid var(--color-border);
5516
+ border: var(--border-width) solid var(--color-border);
4950
5517
  border-radius: var(--radius-md, 0.375rem);
4951
5518
  background: var(--color-bg);
4952
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5519
+ box-shadow: var(--shadow-sm);
4953
5520
  }
4954
5521
 
4955
5522
  /* ── Value + Change Inline ── */
@@ -4961,7 +5528,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4961
5528
  @media print {
4962
5529
  [data-ui="stat"][data-variant="card"] {
4963
5530
  box-shadow: none;
4964
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5531
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
4965
5532
  }
4966
5533
 
4967
5534
  [data-ui="stat"] {
@@ -4971,7 +5538,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4971
5538
 
4972
5539
  /* === primitives/stepper.css === */
4973
5540
  /* @ui:component stepper */
4974
- /* @ui:tokens color-primary color-primary-fg color-bg-muted color-fg-muted color-success color-success-subtle color-border text-sm text-xs weight-medium radius-full space-2 space-3 space-1 */
5541
+ /* @ui:tokens color-primary color-primary-fg color-bg-muted color-fg-muted color-success color-success-subtle color-border text-sm text-xs weight-medium radius-full space-2 space-3 space-1 border-width-strong */
4975
5542
 
4976
5543
  /* ── Base ── */
4977
5544
  [data-ui="stepper"] {
@@ -5050,7 +5617,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5050
5617
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5051
5618
  [data-ui="stepper"] [data-part="connector"] {
5052
5619
  flex: 1;
5053
- height: 2px;
5620
+ height: var(--border-width-strong);
5054
5621
  background: var(--color-border);
5055
5622
  margin: 0 var(--space-1);
5056
5623
  min-width: var(--space-2);
@@ -5118,18 +5685,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5118
5685
 
5119
5686
  /* === primitives/surface.css === */
5120
5687
  /* @ui:component surface */
5121
- /* @ui:tokens color-bg color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border measure-content measure-narrow measure-prose measure-wide radius-lg shadow-sm shadow-md shadow-lg space-3 space-4 space-6 */
5688
+ /* @ui:tokens color-bg color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border measure-content measure-narrow measure-prose measure-wide radius-lg shadow-sm shadow-md shadow-lg space-3 space-4 space-6 border-width corner-shape surface-backdrop texture-surface */
5122
5689
 
5123
5690
  /* ── Base ── */
5124
5691
  [data-ui="surface"] {
5125
- background: var(--color-surface-1);
5692
+ background-color: var(--color-surface-1);
5693
+ background-image: var(--texture-surface);
5126
5694
  border-radius: var(--radius-lg);
5127
- border: 1px solid var(--color-surface-1-border);
5695
+ corner-shape: var(--corner-shape);
5696
+ border: var(--border-width) solid var(--color-surface-1-border);
5128
5697
  }
5129
5698
 
5130
5699
  /* ── Elevation Variants ── */
5131
5700
  [data-ui="surface"][data-variant="flat"] {
5132
- background: var(--color-bg);
5701
+ background-color: var(--color-bg);
5133
5702
  border: none;
5134
5703
  box-shadow: none;
5135
5704
  }
@@ -5139,11 +5708,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5139
5708
  }
5140
5709
 
5141
5710
  [data-ui="surface"][data-variant="overlay"] {
5142
- background: var(--color-surface-2);
5711
+ background-color: var(--color-surface-2);
5143
5712
  box-shadow: var(--shadow-lg);
5144
5713
  border-color: var(--color-surface-2-border);
5145
5714
  }
5146
5715
 
5716
+ /* An overlay is the one surface variant that floats over other content, so it
5717
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5718
+ its own: a browser without backdrop-filter renders the solid surface above
5719
+ and never sees this rule. */
5720
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5721
+ [data-ui="surface"][data-variant="overlay"] {
5722
+ -webkit-backdrop-filter: var(--surface-backdrop);
5723
+ backdrop-filter: var(--surface-backdrop);
5724
+ }
5725
+ }
5726
+
5147
5727
  /* ── Padding Sizes ── */
5148
5728
  [data-ui="surface"][data-size="sm"] {
5149
5729
  padding: var(--space-3);
@@ -5199,7 +5779,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5199
5779
 
5200
5780
  /* === primitives/switch.css === */
5201
5781
  /* @ui:component switch */
5202
- /* @ui:tokens color-bg-muted color-primary color-primary-fg color-border color-ring shadow-xs radius-full space-0h space-1 duration-fast ease-default */
5782
+ /* @ui:tokens color-bg-muted color-primary color-primary-fg color-border color-ring shadow-xs space-0h space-1 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow switch-radius switch-width switch-height switch-thumb switch-travel switch-bg switch-thumb-shadow disabled-opacity */
5203
5783
 
5204
5784
  /* -- Label wrapper -- */
5205
5785
  [data-ui="switch-label"] {
@@ -5211,7 +5791,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5211
5791
 
5212
5792
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5213
5793
  cursor: not-allowed;
5214
- opacity: 0.5;
5794
+ opacity: var(--disabled-opacity);
5215
5795
  }
5216
5796
 
5217
5797
  /* -- Base (track) -- */
@@ -5239,8 +5819,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5239
5819
  width: var(--switch-width, 44px);
5240
5820
  height: var(--switch-height, 24px);
5241
5821
  padding: var(--space-0h, 2px);
5242
- border: 1px solid var(--color-border);
5243
- border-radius: var(--radius-full);
5822
+ border: var(--border-width) solid var(--color-border);
5823
+ border-radius: var(--switch-radius);
5244
5824
  background: var(--switch-bg, var(--color-bg-muted));
5245
5825
  cursor: pointer;
5246
5826
  position: relative;
@@ -5250,8 +5830,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5250
5830
  }
5251
5831
 
5252
5832
  [data-ui="switch"]:focus-visible {
5253
- outline: 2px solid var(--color-ring);
5254
- outline-offset: 2px;
5833
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5834
+ outline-offset: var(--focus-ring-offset);
5835
+ box-shadow: var(--focus-shadow);
5255
5836
  }
5256
5837
 
5257
5838
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5260,7 +5841,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5260
5841
  display: block;
5261
5842
  width: var(--switch-thumb, 18px);
5262
5843
  height: var(--switch-thumb, 18px);
5263
- border-radius: var(--radius-full);
5844
+ border-radius: var(--switch-radius);
5264
5845
  background: var(--color-primary-fg);
5265
5846
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5266
5847
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5272,7 +5853,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5272
5853
  display: block;
5273
5854
  width: var(--switch-thumb, 18px);
5274
5855
  height: var(--switch-thumb, 18px);
5275
- border-radius: var(--radius-full);
5856
+ border-radius: var(--switch-radius);
5276
5857
  background: var(--color-primary-fg);
5277
5858
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5278
5859
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5354,7 +5935,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5354
5935
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5355
5936
  @media (forced-colors: active) {
5356
5937
  [data-ui="switch"] {
5357
- border: 1px solid ButtonText;
5938
+ border: var(--border-width) solid ButtonText;
5358
5939
  background: ButtonFace;
5359
5940
  }
5360
5941
 
@@ -5511,25 +6092,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5511
6092
 
5512
6093
  /* === primitives/text.css === */
5513
6094
  /* @ui:component text */
5514
- /* @ui:tokens color-fg color-fg-muted color-primary text-xs text-sm text-base text-lg text-xl text-2xl text-3xl text-4xl weight-normal weight-medium weight-semibold weight-bold leading-tight leading-snug leading-normal leading-relaxed font-sans font-mono */
6095
+ /* @ui:tokens color-fg color-fg-muted color-primary text-xs text-sm text-base text-lg text-xl text-2xl text-3xl text-4xl weight-normal weight-medium weight-semibold weight-bold leading-tight leading-snug leading-normal leading-relaxed font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading font-mono */
5515
6096
 
5516
6097
  /* ── Heading ── */
5517
6098
  [data-ui="heading"] {
5518
- font-family: var(--font-sans);
5519
- font-weight: var(--weight-bold);
6099
+ font-family: var(--font-heading);
6100
+ font-weight: var(--heading-weight);
5520
6101
  color: var(--color-fg);
5521
- line-height: var(--leading-tight);
5522
- letter-spacing: -0.01em;
6102
+ line-height: var(--heading-leading);
6103
+ text-transform: var(--heading-transform);
6104
+ font-variant-caps: var(--heading-caps);
6105
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6106
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6107
+ headings sets --heading-tracking once and every size follows, instead of
6108
+ each size having to re-derive its own number. */
6109
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5523
6110
  }
5524
6111
 
5525
6112
  [data-ui="heading"][data-size="1"] {
5526
6113
  font-size: var(--text-4xl);
5527
- letter-spacing: -0.02em;
6114
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5528
6115
  }
5529
6116
 
5530
6117
  [data-ui="heading"][data-size="2"] {
5531
6118
  font-size: var(--text-3xl);
5532
- letter-spacing: -0.02em;
6119
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5533
6120
  }
5534
6121
 
5535
6122
  [data-ui="heading"][data-size="3"] {
@@ -5553,7 +6140,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5553
6140
 
5554
6141
  /* ── Text ── */
5555
6142
  [data-ui="text"] {
5556
- font-family: var(--font-sans);
6143
+ font-family: var(--font-body);
5557
6144
  color: var(--color-fg);
5558
6145
  }
5559
6146
 
@@ -5631,7 +6218,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5631
6218
 
5632
6219
  /* === primitives/textarea.css === */
5633
6220
  /* @ui:component textarea */
5634
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
6221
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
5635
6222
 
5636
6223
  /* -- Base -- */
5637
6224
  [data-ui="textarea"] {
@@ -5639,11 +6226,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5639
6226
  width: 100%;
5640
6227
  min-height: var(--textarea-min-height, 80px);
5641
6228
  padding: var(--space-2) var(--space-3);
5642
- border: 1px solid var(--color-border);
6229
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6230
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6231
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6232
+ is drawn. Identical to the shorthand at every other value of the token. */
6233
+ border-style: solid;
6234
+ border-color: var(--color-border);
6235
+ border-width: var(--input-border-width);
5643
6236
  border-radius: var(--textarea-radius, var(--radius-md));
5644
- background: var(--textarea-bg, var(--color-bg));
6237
+ background: var(--textarea-bg, var(--input-fill));
5645
6238
  color: var(--color-fg);
5646
- font-family: var(--textarea-font, var(--font-sans));
6239
+ font-family: var(--textarea-font, var(--font-ui));
5647
6240
  font-size: var(--text-sm);
5648
6241
  line-height: 1.5;
5649
6242
  resize: vertical;
@@ -5660,8 +6253,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5660
6253
  }
5661
6254
 
5662
6255
  [data-ui="textarea"]:focus {
5663
- outline: 2px solid var(--color-ring);
5664
- outline-offset: -1px;
6256
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6257
+ /* The ring replaces the border rather than sitting outside it: inset by
6258
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6259
+ outline-offset: calc(-1 * var(--input-border-width));
6260
+ box-shadow: var(--focus-shadow);
5665
6261
  border-color: transparent;
5666
6262
  }
5667
6263
 
@@ -5689,7 +6285,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5689
6285
  }
5690
6286
 
5691
6287
  [data-ui="textarea"]:disabled {
5692
- opacity: 0.5;
6288
+ opacity: var(--disabled-opacity);
5693
6289
  cursor: not-allowed;
5694
6290
  resize: none;
5695
6291
  }
@@ -5703,7 +6299,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5703
6299
 
5704
6300
  /* === primitives/toggle.css === */
5705
6301
  /* @ui:component toggle */
5706
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 space-4 text-xs text-sm text-base font-sans weight-medium duration-fast ease-default */
6302
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 space-4 text-xs text-sm text-base font-ui weight-medium duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow disabled-opacity */
5707
6303
 
5708
6304
  /* ── Base (off / unpressed) ── */
5709
6305
  [data-ui="toggle"] {
@@ -5712,11 +6308,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5712
6308
  justify-content: center;
5713
6309
  gap: var(--space-1h);
5714
6310
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5715
- border: 1px solid var(--color-border);
6311
+ border: var(--border-width) solid var(--color-border);
5716
6312
  border-radius: var(--toggle-radius, var(--radius-md));
5717
6313
  background: var(--color-bg);
5718
6314
  color: var(--color-fg-muted);
5719
- font-family: var(--toggle-font, var(--font-sans));
6315
+ font-family: var(--toggle-font, var(--font-ui));
5720
6316
  font-size: var(--text-sm);
5721
6317
  font-weight: var(--weight-medium);
5722
6318
  line-height: 1;
@@ -5733,8 +6329,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5733
6329
  }
5734
6330
 
5735
6331
  [data-ui="toggle"]:focus-visible {
5736
- outline: 2px solid var(--color-ring);
5737
- outline-offset: 2px;
6332
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6333
+ outline-offset: var(--focus-ring-offset);
6334
+ box-shadow: var(--focus-shadow);
5738
6335
  }
5739
6336
 
5740
6337
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5751,7 +6348,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5751
6348
 
5752
6349
  /* ── Disabled ── */
5753
6350
  [data-ui="toggle"]:disabled {
5754
- opacity: 0.5;
6351
+ opacity: var(--disabled-opacity);
5755
6352
  cursor: not-allowed;
5756
6353
  }
5757
6354
 
@@ -5775,7 +6372,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5775
6372
 
5776
6373
  /* === primitives/watermark.css === */
5777
6374
  /* @ui:component watermark */
5778
- /* @ui:tokens color-fg-muted doc-font font-sans text-xl text-2xl text-4xl weight-bold leading-tight space-8 space-20 z-raised */
6375
+ /* @ui:tokens color-fg-muted doc-font font-body text-xl text-2xl text-4xl weight-bold leading-tight space-8 space-20 z-raised */
5779
6376
 
5780
6377
  [data-ui="watermark"] {
5781
6378
  position: fixed;
@@ -5794,7 +6391,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5794
6391
 
5795
6392
  [data-ui="watermark"] > [data-part="mark"] {
5796
6393
  color: var(--color-fg-muted);
5797
- font-family: var(--doc-font, var(--font-sans));
6394
+ font-family: var(--doc-font, var(--font-body));
5798
6395
  font-size: var(--text-4xl);
5799
6396
  font-weight: var(--weight-bold);
5800
6397
  line-height: var(--leading-tight);
@@ -5852,7 +6449,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5852
6449
 
5853
6450
  /* === recipes/accordion.css === */
5854
6451
  /* @ui:component accordion */
5855
- /* @ui:tokens color-bg color-fg color-fg-muted color-border space-3 space-4 text-sm text-base weight-medium duration-normal ease-default radius-lg */
6452
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border space-3 space-4 text-sm text-base weight-medium duration-normal ease-default radius-lg font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
5856
6453
 
5857
6454
  /* ── Root ── */
5858
6455
  [data-ui="accordion"] {
@@ -5861,7 +6458,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5861
6458
 
5862
6459
  /* ── Item ── */
5863
6460
  [data-ui="accordion"] [data-part="item"] {
5864
- border-bottom: 1px solid var(--color-border);
6461
+ border-bottom: var(--border-width) solid var(--color-border);
5865
6462
  }
5866
6463
 
5867
6464
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5878,7 +6475,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5878
6475
  border: none;
5879
6476
  background: transparent;
5880
6477
  color: var(--color-fg);
5881
- font-family: var(--font-sans, system-ui, sans-serif);
6478
+ font-family: var(--font-ui);
5882
6479
  font-size: var(--text-base);
5883
6480
  font-weight: var(--weight-medium);
5884
6481
  text-align: start;
@@ -5892,8 +6489,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5892
6489
  }
5893
6490
 
5894
6491
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5895
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5896
- outline-offset: -2px;
6492
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6493
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5897
6494
  border-radius: var(--radius-sm, 0.25rem);
5898
6495
  }
5899
6496
 
@@ -5925,13 +6522,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5925
6522
 
5926
6523
  /* ── Bordered Variant ── */
5927
6524
  [data-ui="accordion"][data-bordered="true"] {
5928
- border: 1px solid var(--color-border);
6525
+ border: var(--border-width) solid var(--color-border);
5929
6526
  border-radius: var(--radius-lg);
5930
6527
  overflow: hidden;
5931
6528
  }
5932
6529
 
5933
6530
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5934
- border-bottom: 1px solid var(--color-border);
6531
+ border-bottom: var(--border-width) solid var(--color-border);
5935
6532
  }
5936
6533
 
5937
6534
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5948,7 +6545,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5948
6545
 
5949
6546
  /* === recipes/alert-dialog.css === */
5950
6547
  /* @ui:component alert-dialog */
5951
- /* @ui:tokens radius-xl shadow-xl space-2 space-3 space-6 color-bg color-fg color-border color-fg-muted color-destructive duration-normal ease-default ease-out z-overlay z-modal */
6548
+ /* @ui:tokens radius-xl shadow-xl space-2 space-3 space-6 color-bg color-fg color-border color-fg-muted color-destructive duration-normal ease-default ease-out z-overlay z-modal font-heading border-width */
5952
6549
 
5953
6550
  /* ── Root ── */
5954
6551
  [data-ui="alert-dialog"] {
@@ -5984,7 +6581,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5984
6581
  max-height: 85vh;
5985
6582
  overflow-y: auto;
5986
6583
  background: var(--color-bg);
5987
- border: 1px solid var(--color-border);
6584
+ border: var(--border-width) solid var(--color-border);
5988
6585
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
5989
6586
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
5990
6587
  opacity: 0;
@@ -6030,6 +6627,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6030
6627
  /* ── Title ── */
6031
6628
  [data-ui="alert-dialog"] [data-part="title"] {
6032
6629
  margin: 0;
6630
+ font-family: var(--font-heading);
6033
6631
  font-size: var(--text-lg, 1.125rem);
6034
6632
  font-weight: var(--weight-semibold, 600);
6035
6633
  color: var(--color-fg);
@@ -6069,7 +6667,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6069
6667
 
6070
6668
  /* === recipes/barcode.css === */
6071
6669
  /* @ui:component barcode */
6072
- /* @ui:tokens color-fg color-bg color-fg-muted doc-font doc-legal-color doc-legal-size font-mono font-sans space-2 space-12 space-16 space-20 */
6670
+ /* @ui:tokens color-fg color-bg color-fg-muted doc-font doc-legal-color doc-legal-size font-mono font-body space-2 space-12 space-16 space-20 */
6073
6671
 
6074
6672
  [data-ui="barcode"] {
6075
6673
  display: inline-flex;
@@ -6096,7 +6694,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6096
6694
 
6097
6695
  [data-ui="barcode"] > [data-part="caption"] {
6098
6696
  color: var(--doc-legal-color, var(--color-fg-muted));
6099
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6697
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6100
6698
  font-size: var(--doc-legal-size);
6101
6699
  line-height: var(--leading-normal);
6102
6700
  text-align: center;
@@ -6116,7 +6714,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6116
6714
 
6117
6715
  /* === recipes/calendar.css === */
6118
6716
  /* @ui:component calendar */
6119
- /* @ui:tokens color-bg color-fg color-fg-muted color-fg-subtle color-border color-primary color-primary-fg color-primary-subtle color-ring radius-md radius-full space-0 space-1 space-2 text-xs text-sm text-base weight-medium duration-fast ease-default */
6717
+ /* @ui:tokens color-bg color-fg color-fg-muted color-fg-subtle color-border color-primary color-primary-fg color-primary-subtle color-ring radius-md radius-full space-0 space-1 space-2 text-xs text-sm text-base weight-medium duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6120
6718
 
6121
6719
  /* ── Root ── */
6122
6720
  [data-ui="calendar"] {
@@ -6149,7 +6747,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6149
6747
  width: 28px;
6150
6748
  height: 28px;
6151
6749
  padding: 0;
6152
- border: 1px solid var(--color-border);
6750
+ border: var(--border-width) solid var(--color-border);
6153
6751
  border-radius: var(--radius-md);
6154
6752
  background: var(--color-bg);
6155
6753
  color: var(--color-fg);
@@ -6165,13 +6763,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6165
6763
 
6166
6764
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6167
6765
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6168
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6169
- outline-offset: 2px;
6766
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6767
+ outline-offset: var(--focus-ring-offset);
6170
6768
  }
6171
6769
 
6172
6770
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6173
6771
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6174
- opacity: 0.4;
6772
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6773
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6774
+ opacity: calc(var(--disabled-opacity) * 0.8);
6175
6775
  cursor: not-allowed;
6176
6776
  }
6177
6777
 
@@ -6206,11 +6806,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6206
6806
  width: 36px;
6207
6807
  height: 36px;
6208
6808
  padding: 0;
6209
- border: 1px solid transparent;
6809
+ border: var(--border-width) solid transparent;
6210
6810
  border-radius: var(--radius-full);
6211
6811
  background: transparent;
6212
6812
  color: var(--color-fg);
6213
- font-family: var(--font-sans, system-ui, sans-serif);
6813
+ font-family: var(--font-ui);
6214
6814
  font-size: var(--text-sm);
6215
6815
  cursor: pointer;
6216
6816
  transition: background var(--duration-fast) var(--ease-default),
@@ -6223,8 +6823,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6223
6823
  }
6224
6824
 
6225
6825
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6226
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6227
- outline-offset: 2px;
6826
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6827
+ outline-offset: var(--focus-ring-offset);
6228
6828
  }
6229
6829
 
6230
6830
  /* ── Today ── */
@@ -6259,7 +6859,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6259
6859
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6260
6860
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6261
6861
  [data-ui="calendar"] [data-part="day"]:disabled {
6262
- opacity: 0.5;
6862
+ opacity: var(--disabled-opacity);
6263
6863
  cursor: not-allowed;
6264
6864
  text-decoration: line-through;
6265
6865
  }
@@ -6323,7 +6923,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6323
6923
 
6324
6924
  /* === recipes/carousel.css === */
6325
6925
  /* @ui:component carousel */
6326
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-ring radius-md radius-lg space-1 space-2 space-3 space-4 text-sm font-sans duration-fast ease-default */
6926
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-ring radius-md radius-lg space-1 space-2 space-3 space-4 text-sm font-ui duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6327
6927
 
6328
6928
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6329
6929
  every slide is a snap target. Everything below works with no controller
@@ -6337,7 +6937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6337
6937
  inline-size: 100%;
6338
6938
  min-inline-size: 0;
6339
6939
  max-inline-size: 100%;
6340
- font-family: var(--carousel-font, var(--font-sans));
6940
+ font-family: var(--carousel-font, var(--font-ui));
6341
6941
  }
6342
6942
 
6343
6943
  /* ── Viewport: the scroll-snap strip ── */
@@ -6363,8 +6963,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6363
6963
  }
6364
6964
 
6365
6965
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6366
- outline: 2px solid var(--color-ring);
6367
- outline-offset: 2px;
6966
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6967
+ outline-offset: var(--focus-ring-offset);
6368
6968
  }
6369
6969
 
6370
6970
  /* ── Slide: one full-width snap target ── */
@@ -6372,7 +6972,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6372
6972
  flex: 0 0 var(--carousel-slide-size, 100%);
6373
6973
  min-inline-size: 0;
6374
6974
  padding: var(--space-4);
6375
- border: 1px solid var(--color-border);
6975
+ border: var(--border-width) solid var(--color-border);
6376
6976
  border-radius: var(--radius-lg);
6377
6977
  background: var(--color-bg);
6378
6978
  color: var(--color-fg);
@@ -6401,7 +7001,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6401
7001
  min-inline-size: 2rem;
6402
7002
  min-block-size: 2rem;
6403
7003
  padding: var(--space-1) var(--space-2);
6404
- border: 1px solid var(--color-border);
7004
+ border: var(--border-width) solid var(--color-border);
6405
7005
  border-radius: var(--radius-md);
6406
7006
  background: var(--color-bg);
6407
7007
  color: var(--color-fg);
@@ -6420,14 +7020,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6420
7020
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6421
7021
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6422
7022
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6423
- outline: 2px solid var(--color-ring);
6424
- outline-offset: 2px;
7023
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7024
+ outline-offset: var(--focus-ring-offset);
6425
7025
  }
6426
7026
 
6427
7027
  /* Boundary contract "stop" — the controller disables the end button. */
6428
7028
  [data-ui="carousel"] [data-part="prev"]:disabled,
6429
7029
  [data-ui="carousel"] [data-part="next"]:disabled {
6430
- opacity: 0.4;
7030
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7031
+ opacity: calc(var(--disabled-opacity) * 0.8);
6431
7032
  cursor: not-allowed;
6432
7033
  }
6433
7034
 
@@ -6436,7 +7037,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6436
7037
  inline-size: 0.625rem;
6437
7038
  block-size: 0.625rem;
6438
7039
  padding: 0;
6439
- border: 1px solid var(--color-border);
7040
+ border: var(--border-width) solid var(--color-border);
6440
7041
  border-radius: 50%;
6441
7042
  background: var(--color-bg-muted);
6442
7043
  cursor: pointer;
@@ -6472,7 +7073,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6472
7073
 
6473
7074
  /* === recipes/combobox.css === */
6474
7075
  /* @ui:component combobox */
6475
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 text-sm text-base z-dropdown duration-fast ease-default */
7076
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle radius-md radius-lg shadow-md space-1 space-2 space-3 text-sm text-base z-dropdown duration-fast ease-default font-ui border-width focus-ring-color focus-ring-width */
6476
7077
 
6477
7078
  /* ── Root ── */
6478
7079
  [data-ui="combobox"] {
@@ -6486,11 +7087,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6486
7087
  display: block;
6487
7088
  width: 100%;
6488
7089
  padding: var(--space-2) var(--space-3);
6489
- border: 1px solid var(--color-border);
7090
+ border: var(--border-width) solid var(--color-border);
6490
7091
  border-radius: var(--radius-md);
6491
7092
  background: var(--color-bg);
6492
7093
  color: var(--color-fg);
6493
- font-family: var(--font-sans, system-ui, sans-serif);
7094
+ font-family: var(--font-ui);
6494
7095
  font-size: var(--text-sm);
6495
7096
  line-height: 1.5;
6496
7097
  outline: none;
@@ -6503,8 +7104,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6503
7104
  }
6504
7105
 
6505
7106
  [data-ui="combobox"] [data-part="input"]:focus {
6506
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6507
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7107
+ border-color: var(--focus-ring-color);
7108
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6508
7109
  }
6509
7110
 
6510
7111
  /* ── Listbox ── */
@@ -6516,7 +7117,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6516
7117
  z-index: var(--z-dropdown);
6517
7118
  margin-top: var(--space-1);
6518
7119
  padding: var(--space-1);
6519
- border: 1px solid var(--color-border);
7120
+ border: var(--border-width) solid var(--color-border);
6520
7121
  border-radius: var(--radius-lg);
6521
7122
  background: var(--color-bg);
6522
7123
  box-shadow: var(--shadow-md);
@@ -6601,7 +7202,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6601
7202
 
6602
7203
  /* === recipes/command-palette.css === */
6603
7204
  /* @ui:component command-palette */
6604
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-bg-muted shadow-xl radius-xl space-2 space-3 space-4 text-sm text-xs text-base weight-medium font-mono z-overlay z-modal duration-fast duration-normal ease-out */
7205
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-bg-muted shadow-xl radius-xl space-2 space-3 space-4 text-sm text-xs text-base weight-medium font-mono z-overlay z-modal duration-fast duration-normal ease-out font-ui border-width */
6605
7206
 
6606
7207
  /* ── Root ── */
6607
7208
  [data-ui="command-palette"] {
@@ -6634,7 +7235,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6634
7235
  display: flex;
6635
7236
  flex-direction: column;
6636
7237
  background: var(--color-bg);
6637
- border: 1px solid var(--color-border);
7238
+ border: var(--border-width) solid var(--color-border);
6638
7239
  border-radius: var(--radius-xl);
6639
7240
  box-shadow: var(--shadow-xl);
6640
7241
  overflow: hidden;
@@ -6666,7 +7267,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6666
7267
  display: flex;
6667
7268
  align-items: center;
6668
7269
  padding: var(--space-3) var(--space-4);
6669
- border-bottom: 1px solid var(--color-border);
7270
+ border-bottom: var(--border-width) solid var(--color-border);
6670
7271
  }
6671
7272
 
6672
7273
  /* ── Search Input ── */
@@ -6676,7 +7277,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6676
7277
  border: none;
6677
7278
  background: transparent;
6678
7279
  color: var(--color-fg);
6679
- font-family: var(--font-sans, system-ui, sans-serif);
7280
+ font-family: var(--font-ui);
6680
7281
  font-size: var(--text-base);
6681
7282
  outline: none;
6682
7283
  }
@@ -6760,7 +7361,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6760
7361
  align-items: center;
6761
7362
  gap: var(--space-1, 0.25rem);
6762
7363
  padding: var(--space-1, 0.25rem) var(--space-2);
6763
- border: 1px solid var(--color-border);
7364
+ border: var(--border-width) solid var(--color-border);
6764
7365
  border-radius: var(--radius-sm, 0.25rem);
6765
7366
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6766
7367
  color: var(--color-fg-muted);
@@ -6789,7 +7390,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6789
7390
 
6790
7391
  /* === recipes/context-menu.css === */
6791
7392
  /* @ui:component context-menu */
6792
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-sm weight-medium font-sans duration-fast ease-out z-dropdown */
7393
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-sm weight-medium font-ui duration-fast ease-out z-dropdown focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6793
7394
 
6794
7395
  [data-ui="context-menu"] {
6795
7396
  position: relative;
@@ -6802,12 +7403,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6802
7403
  border-radius: var(--radius-lg);
6803
7404
  background: var(--color-bg-muted);
6804
7405
  color: var(--color-fg);
6805
- font-family: var(--font-sans, system-ui, sans-serif);
7406
+ font-family: var(--font-ui);
6806
7407
  }
6807
7408
 
6808
7409
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6809
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6810
- outline-offset: var(--space-1);
7410
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7411
+ outline-offset: var(--focus-ring-offset);
6811
7412
  }
6812
7413
 
6813
7414
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6839,7 +7440,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6839
7440
  border-radius: var(--radius-md);
6840
7441
  background: transparent;
6841
7442
  color: var(--color-fg);
6842
- font-family: var(--font-sans, system-ui, sans-serif);
7443
+ font-family: var(--font-ui);
6843
7444
  font-size: var(--text-sm);
6844
7445
  font-weight: var(--weight-medium);
6845
7446
  text-align: start;
@@ -6863,15 +7464,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6863
7464
  focus additionally draws the ring, inset so it does not overlap the item
6864
7465
  above. [W3-3] */
6865
7466
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6866
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6867
- outline-offset: calc(var(--space-px) * -2);
7467
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7468
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6868
7469
  }
6869
7470
 
6870
7471
  [data-ui="context-menu"] [data-part="item"]:disabled,
6871
7472
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6872
7473
  color: var(--color-fg-muted);
6873
7474
  cursor: not-allowed;
6874
- opacity: 0.5;
7475
+ opacity: var(--disabled-opacity);
6875
7476
  }
6876
7477
 
6877
7478
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6890,7 +7491,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6890
7491
 
6891
7492
  /* === recipes/date-picker.css === */
6892
7493
  /* @ui:component date-picker */
6893
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-ring shadow-lg radius-md radius-lg space-1 space-2 space-3 space-4 text-xs text-sm z-dropdown duration-fast ease-default */
7494
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-ring shadow-lg radius-md radius-lg space-1 space-2 space-3 space-4 text-xs text-sm z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
6894
7495
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6895
7496
 
6896
7497
  /* ── Root ── */
@@ -6911,11 +7512,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6911
7512
  width: 100%;
6912
7513
  padding: var(--space-2, 0.5rem) var(--space-3);
6913
7514
  padding-inline-end: var(--space-8, 2.5rem);
6914
- border: 1px solid var(--color-border);
7515
+ border: var(--border-width) solid var(--color-border);
6915
7516
  border-radius: var(--radius-md);
6916
7517
  background: var(--color-bg);
6917
7518
  color: var(--color-fg);
6918
- font-family: var(--font-sans, system-ui, sans-serif);
7519
+ font-family: var(--font-ui);
6919
7520
  font-size: var(--text-sm);
6920
7521
  line-height: 1.5;
6921
7522
  cursor: pointer;
@@ -6927,8 +7528,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6927
7528
  }
6928
7529
 
6929
7530
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6930
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6931
- outline-offset: 2px;
7531
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7532
+ outline-offset: var(--focus-ring-offset);
6932
7533
  border-color: var(--color-primary);
6933
7534
  }
6934
7535
 
@@ -6951,7 +7552,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6951
7552
  z-index: var(--z-dropdown);
6952
7553
  margin-top: var(--space-1);
6953
7554
  padding: var(--space-3);
6954
- border: 1px solid var(--color-border);
7555
+ border: var(--border-width) solid var(--color-border);
6955
7556
  border-radius: var(--radius-lg);
6956
7557
  background: var(--color-bg);
6957
7558
  box-shadow: var(--shadow-lg);
@@ -6990,7 +7591,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6990
7591
 
6991
7592
  /* === recipes/dialog.css === */
6992
7593
  /* @ui:component dialog */
6993
- /* @ui:tokens radius-xl shadow-xl space-4 space-6 space-8 color-bg color-fg color-border color-fg-muted duration-normal duration-slow ease-default ease-out z-overlay z-modal */
7594
+ /* @ui:tokens radius-xl shadow-xl space-4 space-6 space-8 color-bg panel-bg color-fg color-border color-fg-muted duration-normal duration-slow ease-default ease-out z-overlay z-modal font-heading corner-shape border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
6994
7595
 
6995
7596
  /* ── Root ── */
6996
7597
  [data-ui="dialog"] {
@@ -7025,15 +7626,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7025
7626
  width: 90%;
7026
7627
  max-height: 85vh;
7027
7628
  overflow-y: auto;
7028
- background: var(--color-bg);
7029
- border: 1px solid var(--color-border);
7629
+ background: var(--panel-bg);
7630
+ border: var(--border-width) solid var(--color-border);
7030
7631
  border-radius: var(--dialog-radius, var(--radius-xl));
7632
+ corner-shape: var(--corner-shape);
7031
7633
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7032
7634
  opacity: 0;
7033
7635
  transition: opacity var(--duration-normal) var(--ease-out),
7034
7636
  transform var(--duration-normal) var(--ease-out);
7035
7637
  }
7036
7638
 
7639
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7640
+ [data-ui="dialog"] [data-part="panel"] {
7641
+ -webkit-backdrop-filter: var(--surface-backdrop);
7642
+ backdrop-filter: var(--surface-backdrop);
7643
+ }
7644
+ }
7645
+
7037
7646
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7038
7647
  opacity: 1;
7039
7648
  transform: translate(-50%, -50%) scale(1);
@@ -7082,6 +7691,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7082
7691
  /* ── Title ── */
7083
7692
  [data-ui="dialog"] [data-part="title"] {
7084
7693
  margin: 0;
7694
+ font-family: var(--font-heading);
7085
7695
  font-size: var(--text-lg, 1.125rem);
7086
7696
  font-weight: var(--weight-semibold, 600);
7087
7697
  color: var(--color-fg);
@@ -7116,8 +7726,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7116
7726
  }
7117
7727
 
7118
7728
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7119
- outline: 2px solid var(--color-ring);
7120
- outline-offset: 2px;
7729
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7730
+ outline-offset: var(--focus-ring-offset);
7121
7731
  }
7122
7732
 
7123
7733
  /* ── Description ── */
@@ -7153,7 +7763,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7153
7763
 
7154
7764
  /* === recipes/drawer.css === */
7155
7765
  /* @ui:component drawer */
7156
- /* @ui:tokens color-bg color-fg color-border shadow-xl space-4 space-6 radius-none z-overlay z-modal duration-normal duration-slow ease-out ease-default */
7766
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-xl space-4 space-6 radius-none z-overlay z-modal duration-normal duration-slow ease-out ease-default font-heading border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
7157
7767
 
7158
7768
  /* ── Root ── */
7159
7769
  [data-ui="drawer"] {
@@ -7188,17 +7798,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7188
7798
  flex-direction: column;
7189
7799
  width: var(--drawer-width, 400px);
7190
7800
  max-width: 100vw;
7191
- background: var(--color-bg);
7801
+ background: var(--panel-bg);
7192
7802
  border: none;
7193
7803
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7194
7804
  transition: transform var(--duration-slow) var(--ease-out);
7195
7805
  }
7196
7806
 
7807
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7808
+ [data-ui="drawer"] [data-part="panel"] {
7809
+ -webkit-backdrop-filter: var(--surface-backdrop);
7810
+ backdrop-filter: var(--surface-backdrop);
7811
+ }
7812
+ }
7813
+
7197
7814
  /* ── Side Variants ── */
7198
7815
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7199
7816
  inset-inline-start: 0;
7200
7817
  inset-inline-end: auto;
7201
- border-inline-end: 1px solid var(--color-border);
7818
+ border-inline-end: var(--border-width) solid var(--color-border);
7202
7819
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7203
7820
  transform: translateX(-100%);
7204
7821
  }
@@ -7206,7 +7823,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7206
7823
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7207
7824
  inset-inline-end: 0;
7208
7825
  inset-inline-start: auto;
7209
- border-inline-start: 1px solid var(--color-border);
7826
+ border-inline-start: var(--border-width) solid var(--color-border);
7210
7827
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7211
7828
  transform: translateX(100%);
7212
7829
  }
@@ -7260,6 +7877,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7260
7877
  /* ── Title ── */
7261
7878
  [data-ui="drawer"] [data-part="title"] {
7262
7879
  margin: 0;
7880
+ font-family: var(--font-heading);
7263
7881
  font-size: var(--text-lg, 1.125rem);
7264
7882
  font-weight: var(--weight-semibold, 600);
7265
7883
  color: var(--color-fg);
@@ -7294,8 +7912,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7294
7912
  }
7295
7913
 
7296
7914
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7297
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7298
- outline-offset: 2px;
7915
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7916
+ outline-offset: var(--focus-ring-offset);
7299
7917
  }
7300
7918
 
7301
7919
  /* ── Body ── */
@@ -7314,7 +7932,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7314
7932
  gap: var(--space-3, 0.75rem);
7315
7933
  padding: var(--space-6);
7316
7934
  padding-top: var(--space-4);
7317
- border-top: 1px solid var(--color-border);
7935
+ border-top: var(--border-width) solid var(--color-border);
7318
7936
  flex-shrink: 0;
7319
7937
  }
7320
7938
 
@@ -7328,7 +7946,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7328
7946
 
7329
7947
  /* === recipes/dropdown.css === */
7330
7948
  /* @ui:component dropdown */
7331
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-primary space-1 space-2 space-3 space-4 radius-md radius-lg shadow-md text-sm weight-medium duration-fast ease-default ease-out z-dropdown */
7949
+ /* @ui:tokens color-bg panel-bg color-fg color-fg-muted color-border color-primary-subtle color-primary space-1 space-2 space-3 space-4 radius-md radius-lg shadow-md text-sm weight-medium duration-fast ease-default ease-out z-dropdown font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop disabled-opacity */
7332
7950
 
7333
7951
  /* ── Root ── */
7334
7952
  [data-ui="dropdown"] {
@@ -7342,11 +7960,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7342
7960
  align-items: center;
7343
7961
  gap: var(--space-2);
7344
7962
  padding: var(--space-2) var(--space-3);
7345
- border: 1px solid var(--color-border);
7963
+ border: var(--border-width) solid var(--color-border);
7346
7964
  border-radius: var(--radius-md);
7347
7965
  background: var(--color-bg);
7348
7966
  color: var(--color-fg);
7349
- font-family: var(--font-sans, system-ui, sans-serif);
7967
+ font-family: var(--font-ui);
7350
7968
  font-size: var(--text-sm);
7351
7969
  font-weight: var(--weight-medium);
7352
7970
  cursor: pointer;
@@ -7360,8 +7978,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7360
7978
  }
7361
7979
 
7362
7980
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7363
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7364
- outline-offset: 2px;
7981
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7982
+ outline-offset: var(--focus-ring-offset);
7365
7983
  }
7366
7984
 
7367
7985
  /* ── Menu ── */
@@ -7373,9 +7991,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7373
7991
  min-width: 180px;
7374
7992
  margin-top: var(--space-1);
7375
7993
  padding: var(--space-1);
7376
- border: 1px solid var(--color-border);
7994
+ border: var(--border-width) solid var(--color-border);
7377
7995
  border-radius: var(--radius-lg);
7378
- background: var(--color-bg);
7996
+ background: var(--panel-bg);
7379
7997
  box-shadow: var(--shadow-md);
7380
7998
  opacity: 0;
7381
7999
  transform: translateY(-4px);
@@ -7383,6 +8001,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7383
8001
  transform var(--duration-fast) var(--ease-out);
7384
8002
  }
7385
8003
 
8004
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8005
+ [data-ui="dropdown"] [data-part="menu"] {
8006
+ -webkit-backdrop-filter: var(--surface-backdrop);
8007
+ backdrop-filter: var(--surface-backdrop);
8008
+ }
8009
+ }
8010
+
7386
8011
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7387
8012
  opacity: 1;
7388
8013
  transform: translateY(0);
@@ -7405,7 +8030,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7405
8030
  border-radius: var(--radius-md);
7406
8031
  background: transparent;
7407
8032
  color: var(--color-fg);
7408
- font-family: var(--font-sans, system-ui, sans-serif);
8033
+ font-family: var(--font-ui);
7409
8034
  font-size: var(--text-sm);
7410
8035
  text-align: start;
7411
8036
  cursor: pointer;
@@ -7427,12 +8052,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7427
8052
  focus additionally draws the ring, inset so it does not overlap the item
7428
8053
  above. [W3-3] */
7429
8054
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7430
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7431
- outline-offset: -2px;
8055
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8056
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7432
8057
  }
7433
8058
 
7434
8059
  [data-ui="dropdown"] [data-part="item"]:disabled {
7435
- opacity: 0.5;
8060
+ opacity: var(--disabled-opacity);
7436
8061
  cursor: not-allowed;
7437
8062
  pointer-events: none;
7438
8063
  }
@@ -7485,14 +8110,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7485
8110
 
7486
8111
  /* === recipes/file-upload.css === */
7487
8112
  /* @ui:component file-upload */
7488
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-px space-1 space-2 space-3 space-4 space-8 radius-md radius-lg text-xs text-sm text-base weight-semibold font-sans duration-fast ease-default */
8113
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-px space-1 space-2 space-3 space-4 space-8 radius-md radius-lg text-xs text-sm text-base weight-semibold font-ui duration-fast ease-default focus-ring-width focus-ring-style focus-ring-color focus-ring-offset border-width disabled-opacity */
7489
8114
 
7490
8115
  [data-ui="file-upload"] {
7491
8116
  display: grid;
7492
8117
  gap: var(--space-4);
7493
8118
  inline-size: 100%;
7494
8119
  color: var(--color-fg);
7495
- font-family: var(--font-sans);
8120
+ font-family: var(--font-ui);
7496
8121
  }
7497
8122
 
7498
8123
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7527,14 +8152,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7527
8152
  }
7528
8153
 
7529
8154
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7530
- outline: var(--space-px) solid var(--color-ring);
7531
- outline-offset: var(--space-1);
8155
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8156
+ outline-offset: var(--focus-ring-offset);
7532
8157
  }
7533
8158
 
7534
8159
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7535
8160
  border-color: var(--color-primary);
7536
8161
  background: var(--color-primary-subtle);
7537
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8162
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7538
8163
  }
7539
8164
 
7540
8165
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7608,8 +8233,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7608
8233
  }
7609
8234
 
7610
8235
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7611
- outline: var(--space-px) solid var(--color-ring);
7612
- outline-offset: var(--space-1);
8236
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8237
+ outline-offset: var(--focus-ring-offset);
7613
8238
  }
7614
8239
 
7615
8240
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7631,7 +8256,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7631
8256
  }
7632
8257
 
7633
8258
  [data-ui="file-upload"][data-disabled] {
7634
- opacity: 0.5;
8259
+ opacity: var(--disabled-opacity);
7635
8260
  }
7636
8261
 
7637
8262
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7647,7 +8272,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7647
8272
 
7648
8273
  /* === recipes/input-otp.css === */
7649
8274
  /* @ui:component input-otp */
7650
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-destructive radius-md space-2 space-3 text-base text-lg font-sans duration-fast ease-default */
8275
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-destructive radius-md space-2 space-3 text-base text-lg font-ui duration-fast ease-default border-width disabled-opacity */
7651
8276
 
7652
8277
  /* ── Root ── */
7653
8278
  [data-ui="input-otp"] {
@@ -7662,7 +8287,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7662
8287
  gutter. The transparent input is `inset: 0`, so it follows the box the
7663
8288
  segments settle into however many rows that takes. */
7664
8289
  max-inline-size: 100%;
7665
- font-family: var(--font-sans, system-ui, sans-serif);
8290
+ font-family: var(--font-ui);
7666
8291
  }
7667
8292
 
7668
8293
  /* ── Real input ──
@@ -7707,14 +8332,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7707
8332
  justify-content: center;
7708
8333
  inline-size: var(--input-otp-segment-size);
7709
8334
  block-size: var(--input-otp-segment-size);
7710
- border: 1px solid var(--color-border);
8335
+ border: var(--border-width) solid var(--color-border);
7711
8336
  border-radius: var(--radius-md);
7712
8337
  background: var(--color-bg);
7713
8338
  color: var(--color-fg);
7714
8339
  font-size: var(--text-lg, 1.125rem);
7715
8340
  font-variant-numeric: tabular-nums;
7716
8341
  line-height: 1;
7717
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8342
+ transition: border-color var(--duration-fast) var(--ease-default),
7718
8343
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7719
8344
  }
7720
8345
 
@@ -7726,7 +8351,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7726
8351
  /* Active (caret / selected) segment while focused */
7727
8352
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7728
8353
  border-color: var(--color-ring);
7729
- box-shadow: 0 0 0 1px var(--color-ring);
8354
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7730
8355
  }
7731
8356
 
7732
8357
  /* Blinking caret in the next-to-fill empty slot */
@@ -7774,7 +8399,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7774
8399
 
7775
8400
  /* ── Disabled ── */
7776
8401
  [data-ui="input-otp"][data-disabled] {
7777
- opacity: 0.5;
8402
+ opacity: var(--disabled-opacity);
7778
8403
  cursor: not-allowed;
7779
8404
  }
7780
8405
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7798,7 +8423,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7798
8423
 
7799
8424
  /* === recipes/menubar.css === */
7800
8425
  /* @ui:component menubar */
7801
- /* @ui:tokens color-bg color-border color-fg color-fg-muted color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-xs text-sm text-base weight-medium duration-fast ease-out z-dropdown font-sans */
8426
+ /* @ui:tokens color-bg color-border color-fg color-fg-muted color-primary color-primary-subtle space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-xs text-sm text-base weight-medium duration-fast ease-out z-dropdown font-ui focus-ring-color focus-ring-width disabled-opacity */
7802
8427
 
7803
8428
  [data-ui="menubar"] {
7804
8429
  position: relative;
@@ -7816,7 +8441,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7816
8441
  border-radius: var(--radius-lg);
7817
8442
  background: var(--color-bg);
7818
8443
  color: var(--color-fg);
7819
- font-family: var(--font-sans);
8444
+ font-family: var(--font-ui);
7820
8445
  }
7821
8446
 
7822
8447
  [data-ui="menubar"] [data-part="group"] {
@@ -7858,7 +8483,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7858
8483
 
7859
8484
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7860
8485
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7861
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8486
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7862
8487
  }
7863
8488
 
7864
8489
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7893,7 +8518,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7893
8518
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7894
8519
  color: var(--color-fg-muted);
7895
8520
  cursor: not-allowed;
7896
- opacity: 0.6;
8521
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8522
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8523
+ it (1.1A-27). */
8524
+ opacity: calc(var(--disabled-opacity) * 1.2);
7897
8525
  }
7898
8526
 
7899
8527
  [data-ui="menubar"] [data-part="separator"] {
@@ -7925,7 +8553,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7925
8553
 
7926
8554
  /* === recipes/pagination.css === */
7927
8555
  /* @ui:component pagination */
7928
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-primary color-primary-fg color-border radius-md space-1 space-2 space-3 text-xs text-sm text-base weight-medium duration-fast ease-default */
8556
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-primary color-primary-fg color-border radius-md space-1 space-2 space-3 text-xs text-sm text-base weight-medium duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
7929
8557
 
7930
8558
  /* ── Root ── */
7931
8559
  [data-ui="pagination"] {
@@ -7961,11 +8589,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7961
8589
  min-width: 36px;
7962
8590
  height: 36px;
7963
8591
  padding: 0 var(--space-2);
7964
- border: 1px solid var(--color-border);
8592
+ border: var(--border-width) solid var(--color-border);
7965
8593
  border-radius: var(--radius-md);
7966
8594
  background: var(--color-bg);
7967
8595
  color: var(--color-fg);
7968
- font-family: var(--font-sans, system-ui, sans-serif);
8596
+ font-family: var(--font-ui);
7969
8597
  font-size: var(--text-sm);
7970
8598
  font-weight: var(--weight-medium);
7971
8599
  cursor: pointer;
@@ -7986,8 +8614,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7986
8614
  [data-ui="pagination"] [data-part="page"]:focus-visible,
7987
8615
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
7988
8616
  [data-ui="pagination"] [data-part="next"]:focus-visible {
7989
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7990
- outline-offset: 2px;
8617
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8618
+ outline-offset: var(--focus-ring-offset);
7991
8619
  }
7992
8620
 
7993
8621
  /* ── Active page ── */
@@ -8011,7 +8639,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8011
8639
  /* ── Disabled ── */
8012
8640
  [data-ui="pagination"] [data-part="prev"]:disabled,
8013
8641
  [data-ui="pagination"] [data-part="next"]:disabled {
8014
- opacity: 0.5;
8642
+ opacity: var(--disabled-opacity);
8015
8643
  cursor: not-allowed;
8016
8644
  pointer-events: none;
8017
8645
  }
@@ -8081,7 +8709,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8081
8709
 
8082
8710
  /* === recipes/popover.css === */
8083
8711
  /* @ui:component popover */
8084
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8712
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
8085
8713
 
8086
8714
  /* ── Root ── */
8087
8715
  [data-ui="popover"] {
@@ -8095,11 +8723,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8095
8723
  align-items: center;
8096
8724
  gap: var(--space-2, 0.5rem);
8097
8725
  padding: var(--space-2, 0.5rem) var(--space-3);
8098
- border: 1px solid var(--color-border);
8726
+ border: var(--border-width) solid var(--color-border);
8099
8727
  border-radius: var(--radius-md, 0.375rem);
8100
8728
  background: var(--color-bg);
8101
8729
  color: var(--color-fg);
8102
- font-family: var(--font-sans, system-ui, sans-serif);
8730
+ font-family: var(--font-ui);
8103
8731
  font-size: var(--text-sm, 0.875rem);
8104
8732
  font-weight: var(--weight-medium, 500);
8105
8733
  cursor: pointer;
@@ -8113,8 +8741,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8113
8741
  }
8114
8742
 
8115
8743
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8116
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8117
- outline-offset: 2px;
8744
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8745
+ outline-offset: var(--focus-ring-offset);
8118
8746
  }
8119
8747
 
8120
8748
  /* ── Content ── */
@@ -8123,9 +8751,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8123
8751
  z-index: var(--z-dropdown);
8124
8752
  min-width: 200px;
8125
8753
  padding: var(--space-4);
8126
- border: 1px solid var(--color-border);
8754
+ border: var(--border-width) solid var(--color-border);
8127
8755
  border-radius: var(--radius-lg);
8128
- background: var(--color-bg);
8756
+ background: var(--panel-bg);
8129
8757
  color: var(--color-fg);
8130
8758
  box-shadow: var(--shadow-md);
8131
8759
  opacity: 0;
@@ -8134,6 +8762,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8134
8762
  transform var(--duration-fast) var(--ease-default);
8135
8763
  }
8136
8764
 
8765
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8766
+ [data-ui="popover"] [data-part="content"] {
8767
+ -webkit-backdrop-filter: var(--surface-backdrop);
8768
+ backdrop-filter: var(--surface-backdrop);
8769
+ }
8770
+ }
8771
+
8137
8772
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8138
8773
  opacity: 1;
8139
8774
  transform: scale(1);
@@ -8221,8 +8856,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8221
8856
  position: absolute;
8222
8857
  width: 8px;
8223
8858
  height: 8px;
8224
- background: var(--color-bg);
8225
- border: 1px solid var(--color-border);
8859
+ background: var(--panel-bg);
8860
+ border: var(--border-width) solid var(--color-border);
8226
8861
  transform: rotate(45deg);
8227
8862
  }
8228
8863
 
@@ -8323,8 +8958,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8323
8958
  }
8324
8959
 
8325
8960
  [data-ui="popover"] [data-part="close"]:focus-visible {
8326
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8327
- outline-offset: 2px;
8961
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8962
+ outline-offset: var(--focus-ring-offset);
8328
8963
  }
8329
8964
 
8330
8965
  /* ── Motion ── */
@@ -8337,7 +8972,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8337
8972
 
8338
8973
  /* === recipes/qr-code.css === */
8339
8974
  /* @ui:component qr-code */
8340
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8975
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8341
8976
 
8342
8977
  /* ── Base ── */
8343
8978
  [data-ui="qr-code"] {
@@ -8355,7 +8990,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8355
8990
 
8356
8991
  /* ── Caption ── */
8357
8992
  [data-ui="qr-code"] [data-part="caption"] {
8358
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
8993
+ font-family: var(--doc-font, var(--font-body));
8359
8994
  font-size: var(--doc-legal-size, var(--text-xs));
8360
8995
  color: var(--doc-legal-color, var(--color-fg-muted));
8361
8996
  text-align: center;
@@ -8396,7 +9031,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8396
9031
 
8397
9032
  /* === recipes/select-custom.css === */
8398
9033
  /* @ui:component select-custom */
8399
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 space-4 text-sm text-xs z-dropdown duration-fast ease-default */
9034
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 space-4 text-sm text-xs z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
8400
9035
 
8401
9036
  /* ── Root ── */
8402
9037
  [data-ui="select-custom"] {
@@ -8413,11 +9048,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8413
9048
  width: 100%;
8414
9049
  min-width: 180px;
8415
9050
  padding: var(--space-2) var(--space-3);
8416
- border: 1px solid var(--color-border);
9051
+ border: var(--border-width) solid var(--color-border);
8417
9052
  border-radius: var(--radius-md);
8418
9053
  background: var(--color-bg);
8419
9054
  color: var(--color-fg);
8420
- font-family: var(--font-sans, system-ui, sans-serif);
9055
+ font-family: var(--font-ui);
8421
9056
  font-size: var(--text-sm);
8422
9057
  cursor: pointer;
8423
9058
  white-space: nowrap;
@@ -8430,8 +9065,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8430
9065
  }
8431
9066
 
8432
9067
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8433
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8434
- outline-offset: 2px;
9068
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9069
+ outline-offset: var(--focus-ring-offset);
8435
9070
  }
8436
9071
 
8437
9072
  /* ── Value ── */
@@ -8467,7 +9102,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8467
9102
  z-index: var(--z-dropdown);
8468
9103
  margin-top: var(--space-1);
8469
9104
  padding: var(--space-1);
8470
- border: 1px solid var(--color-border);
9105
+ border: var(--border-width) solid var(--color-border);
8471
9106
  border-radius: var(--radius-lg);
8472
9107
  background: var(--color-bg);
8473
9108
  box-shadow: var(--shadow-md);
@@ -8491,11 +9126,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8491
9126
  padding: var(--space-2) var(--space-3);
8492
9127
  margin-bottom: var(--space-1);
8493
9128
  border: none;
8494
- border-bottom: 1px solid var(--color-border);
9129
+ border-bottom: var(--border-width) solid var(--color-border);
8495
9130
  border-radius: 0;
8496
9131
  background: transparent;
8497
9132
  color: var(--color-fg);
8498
- font-family: var(--font-sans, system-ui, sans-serif);
9133
+ font-family: var(--font-ui);
8499
9134
  font-size: var(--text-sm);
8500
9135
  outline: none;
8501
9136
  }
@@ -8589,7 +9224,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8589
9224
 
8590
9225
  /* === recipes/sheet.css === */
8591
9226
  /* @ui:component sheet */
8592
- /* @ui:tokens color-bg color-fg color-border shadow-xl radius-xl space-4 space-6 z-overlay z-modal duration-normal duration-slow ease-out */
9227
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-xl radius-xl space-4 space-6 z-overlay z-modal duration-normal duration-slow ease-out font-heading border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
8593
9228
 
8594
9229
  /* ── Root ── */
8595
9230
  [data-ui="sheet"] {
@@ -8620,11 +9255,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8620
9255
  z-index: var(--z-modal);
8621
9256
  display: flex;
8622
9257
  flex-direction: column;
8623
- background: var(--color-bg);
9258
+ background: var(--panel-bg);
8624
9259
  box-shadow: var(--shadow-xl);
8625
9260
  transition: transform var(--duration-slow) var(--ease-out);
8626
9261
  }
8627
9262
 
9263
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9264
+ [data-ui="sheet"] [data-part="panel"] {
9265
+ -webkit-backdrop-filter: var(--surface-backdrop);
9266
+ backdrop-filter: var(--surface-backdrop);
9267
+ }
9268
+ }
9269
+
8628
9270
  /* ── Side: Bottom ── */
8629
9271
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8630
9272
  bottom: 0;
@@ -8652,7 +9294,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8652
9294
  bottom: 0;
8653
9295
  max-width: 100vw;
8654
9296
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8655
- border-inline-end: 1px solid var(--color-border);
9297
+ border-inline-end: var(--border-width) solid var(--color-border);
8656
9298
  transform: translateX(-100%);
8657
9299
  }
8658
9300
 
@@ -8663,7 +9305,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8663
9305
  bottom: 0;
8664
9306
  max-width: 100vw;
8665
9307
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8666
- border-inline-start: 1px solid var(--color-border);
9308
+ border-inline-start: var(--border-width) solid var(--color-border);
8667
9309
  transform: translateX(100%);
8668
9310
  }
8669
9311
 
@@ -8740,6 +9382,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8740
9382
  /* ── Title ── */
8741
9383
  [data-ui="sheet"] [data-part="title"] {
8742
9384
  margin: 0;
9385
+ font-family: var(--font-heading);
8743
9386
  font-size: var(--text-lg, 1.125rem);
8744
9387
  font-weight: var(--weight-semibold, 600);
8745
9388
  color: var(--color-fg);
@@ -8774,8 +9417,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8774
9417
  }
8775
9418
 
8776
9419
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8777
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8778
- outline-offset: 2px;
9420
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9421
+ outline-offset: var(--focus-ring-offset);
8779
9422
  }
8780
9423
 
8781
9424
  /* ── Body ── */
@@ -8796,7 +9439,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8796
9439
 
8797
9440
  /* === recipes/sidebar.css === */
8798
9441
  /* @ui:component sidebar */
8799
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-bg-muted color-ring shadow-xl space-1 space-2 space-3 space-4 radius-md radius-lg z-overlay z-modal text-sm text-lg weight-medium weight-semibold duration-normal duration-slow ease-out ease-default */
9442
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-bg-muted color-ring shadow-xl space-1 space-2 space-3 space-4 radius-md radius-lg z-overlay z-modal text-sm text-lg weight-medium weight-semibold duration-normal duration-slow ease-out ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
8800
9443
 
8801
9444
  /* ── Root ──
8802
9445
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8840,7 +9483,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8840
9483
  flex-direction: column;
8841
9484
  gap: var(--space-2);
8842
9485
  background: var(--sidebar-bg);
8843
- border-inline-end: 1px solid var(--color-border);
9486
+ border-inline-end: var(--border-width) solid var(--color-border);
8844
9487
  border-start-end-radius: var(--radius-lg, 0.5rem);
8845
9488
  border-end-end-radius: var(--radius-lg, 0.5rem);
8846
9489
  box-shadow: var(--shadow-xl);
@@ -8921,8 +9564,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8921
9564
  }
8922
9565
 
8923
9566
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8924
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8925
- outline-offset: 2px;
9567
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9568
+ outline-offset: var(--focus-ring-offset);
8926
9569
  }
8927
9570
 
8928
9571
  /* ── Navigation ── */
@@ -8958,8 +9601,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8958
9601
  }
8959
9602
 
8960
9603
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
8961
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8962
- outline-offset: -2px;
9604
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9605
+ outline-offset: calc(-1 * var(--focus-ring-offset));
8963
9606
  }
8964
9607
 
8965
9608
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -8986,7 +9629,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8986
9629
  [data-ui="sidebar"] [data-part="footer"] {
8987
9630
  flex-shrink: 0;
8988
9631
  padding: var(--space-3) var(--space-4);
8989
- border-block-start: 1px solid var(--color-border);
9632
+ border-block-start: var(--border-width) solid var(--color-border);
8990
9633
  }
8991
9634
 
8992
9635
  /* ── Rail (icons only) ── */
@@ -9079,7 +9722,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9079
9722
 
9080
9723
  /* === recipes/slider.css === */
9081
9724
  /* @ui:component slider */
9082
- /* @ui:tokens color-bg color-fg-muted color-border color-primary color-primary-subtle color-ring color-bg-muted space-2 space-3 space-4 radius-full text-sm text-base shadow-sm duration-fast ease-default */
9725
+ /* @ui:tokens color-bg color-fg-muted color-border color-primary color-primary-subtle color-ring color-bg-muted space-2 space-3 space-4 radius-full text-sm text-base shadow-sm duration-fast ease-default font-ui border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
9083
9726
 
9084
9727
  /* ── Root ── */
9085
9728
  [data-ui="slider"] {
@@ -9129,28 +9772,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9129
9772
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9130
9773
  transform: translate(-50%, -50%);
9131
9774
  background: var(--color-bg, white);
9132
- border: 2px solid var(--color-primary);
9775
+ border: var(--border-width-strong) solid var(--color-primary);
9133
9776
  border-radius: var(--radius-full, 9999px);
9134
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9777
+ box-shadow: var(--shadow-sm);
9135
9778
  cursor: grab;
9136
9779
  touch-action: none;
9137
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9780
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9138
9781
  }
9139
9782
 
9140
9783
  [data-ui="slider"] [data-part="thumb"]:hover {
9141
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9142
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9784
+ box-shadow: var(--shadow-sm),
9785
+ 0 0 0 4px var(--color-primary-subtle);
9143
9786
  }
9144
9787
 
9145
9788
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9146
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9147
- outline-offset: 2px;
9789
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9790
+ outline-offset: var(--focus-ring-offset);
9148
9791
  }
9149
9792
 
9150
9793
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9151
9794
  cursor: grabbing;
9152
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9153
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9795
+ box-shadow: var(--shadow-sm),
9796
+ 0 0 0 5px var(--color-primary-subtle);
9154
9797
  }
9155
9798
 
9156
9799
  /* ── Value output ── */
@@ -9158,7 +9801,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9158
9801
  flex: 0 0 auto;
9159
9802
  min-inline-size: 3ch;
9160
9803
  color: var(--color-fg-muted);
9161
- font-family: var(--font-sans, system-ui, sans-serif);
9804
+ font-family: var(--font-ui);
9162
9805
  font-size: var(--text-sm);
9163
9806
  font-variant-numeric: tabular-nums;
9164
9807
  text-align: end;
@@ -9177,7 +9820,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9177
9820
 
9178
9821
  /* ── Disabled ── */
9179
9822
  [data-ui="slider"][data-disabled] {
9180
- opacity: 0.5;
9823
+ opacity: var(--disabled-opacity);
9181
9824
  cursor: not-allowed;
9182
9825
  pointer-events: none;
9183
9826
  }
@@ -9195,7 +9838,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9195
9838
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9196
9839
  @media (forced-colors: active) {
9197
9840
  [data-ui="slider"] [data-part="track"] {
9198
- border: 1px solid ButtonText;
9841
+ border: var(--border-width) solid ButtonText;
9199
9842
  }
9200
9843
 
9201
9844
  [data-ui="slider"] [data-part="range"] {
@@ -9206,7 +9849,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9206
9849
  [data-ui="slider"] [data-part="thumb"] {
9207
9850
  forced-color-adjust: none;
9208
9851
  background: ButtonText;
9209
- border: 1px solid ButtonFace;
9852
+ border: var(--border-width) solid ButtonFace;
9210
9853
  }
9211
9854
 
9212
9855
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9216,7 +9859,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9216
9859
 
9217
9860
  /* === recipes/table.css === */
9218
9861
  /* @ui:component table */
9219
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-fg-subtle color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-0h space-1 space-2 space-3 space-4 space-5 space-8 text-xs text-sm weight-semibold weight-bold radius-sm radius-md radius-full duration-fast ease-default doc-table-footer-bg doc-table-footer-weight doc-print-border-color */
9862
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-fg-subtle color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-0h space-1 space-2 space-3 space-4 space-5 space-8 text-xs text-sm weight-semibold weight-bold radius-sm radius-md radius-full duration-fast ease-default doc-table-footer-bg doc-table-footer-weight doc-print-border-color font-body border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset stripe-bg */
9220
9863
 
9221
9864
  /* ── Root ── */
9222
9865
  [data-ui="table"] {
@@ -9242,7 +9885,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9242
9885
  width: 100%;
9243
9886
  border-collapse: separate;
9244
9887
  border-spacing: 0;
9245
- font-family: var(--font-sans, system-ui, sans-serif);
9888
+ font-family: var(--font-body);
9246
9889
  }
9247
9890
 
9248
9891
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9264,7 +9907,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9264
9907
  font-weight: var(--weight-semibold);
9265
9908
  color: var(--color-fg-muted);
9266
9909
  background: var(--color-bg);
9267
- border-bottom: 2px solid var(--color-border);
9910
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9268
9911
  white-space: nowrap;
9269
9912
  user-select: none;
9270
9913
  }
@@ -9322,8 +9965,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9322
9965
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9323
9966
  [data-ui="table"] [data-part="th"]:focus-visible,
9324
9967
  [data-ui="table"] [data-part="td"]:focus-visible {
9325
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9326
- outline-offset: -2px;
9968
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9969
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9327
9970
  }
9328
9971
 
9329
9972
  /* ── Data Cell ── */
@@ -9331,7 +9974,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9331
9974
  padding: var(--space-3) var(--space-4);
9332
9975
  font-size: var(--text-sm);
9333
9976
  color: var(--color-fg);
9334
- border-bottom: 1px solid var(--color-border);
9977
+ border-bottom: var(--border-width) solid var(--color-border);
9335
9978
  background: var(--color-bg);
9336
9979
  transition: background var(--duration-fast) var(--ease-default);
9337
9980
  }
@@ -9360,31 +10003,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9360
10003
  Static fallback via nth-child; once the controller stamps data-stripe on the
9361
10004
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9362
10005
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9363
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10006
+ background: var(--stripe-bg);
9364
10007
  }
9365
10008
 
9366
10009
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]):hover [data-part="td"] {
9367
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10010
+ background: var(--stripe-bg);
9368
10011
  }
9369
10012
 
9370
10013
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9371
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10014
+ background: var(--stripe-bg);
9372
10015
  }
9373
10016
 
9374
10017
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9375
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10018
+ background: var(--stripe-bg);
9376
10019
  }
9377
10020
 
9378
10021
  /* ── Bordered Variant ── */
9379
10022
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9380
- border: 1px solid var(--color-border);
10023
+ border: var(--border-width) solid var(--color-border);
9381
10024
  border-radius: var(--radius-md, 0.375rem);
9382
10025
  overflow: hidden;
9383
10026
  }
9384
10027
 
9385
10028
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9386
10029
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9387
- border: 1px solid var(--color-border);
10030
+ border: var(--border-width) solid var(--color-border);
9388
10031
  }
9389
10032
 
9390
10033
  /* ── Size: Small ── */
@@ -9412,7 +10055,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9412
10055
  /* ── Footer ── */
9413
10056
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9414
10057
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9415
- border-top: 2px solid var(--color-border);
10058
+ border-top: var(--border-width-strong) solid var(--color-border);
9416
10059
  border-bottom: none;
9417
10060
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9418
10061
  }
@@ -9538,7 +10181,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9538
10181
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9539
10182
  padding: var(--space-1) var(--space-2);
9540
10183
  background: var(--color-bg);
9541
- border-bottom: 1px solid var(--color-border);
10184
+ border-bottom: var(--border-width) solid var(--color-border);
9542
10185
  }
9543
10186
 
9544
10187
  [data-ui="table"] [data-part="filter-input"],
@@ -9550,14 +10193,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9550
10193
  font-size: var(--text-xs);
9551
10194
  color: var(--color-fg);
9552
10195
  background: var(--color-bg);
9553
- border: 1px solid var(--color-border);
10196
+ border: var(--border-width) solid var(--color-border);
9554
10197
  border-radius: var(--radius-sm);
9555
10198
  }
9556
10199
 
9557
10200
  [data-ui="table"] [data-part="filter-input"]:focus,
9558
10201
  [data-ui="table"] [data-part="filter"]:focus {
9559
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9560
- outline-offset: -1px;
10202
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10203
+ outline-offset: calc(-1 * var(--border-width));
9561
10204
  border-color: var(--color-primary);
9562
10205
  }
9563
10206
 
@@ -9578,7 +10221,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9578
10221
  text-align: inherit;
9579
10222
  color: var(--color-fg);
9580
10223
  background: var(--color-bg);
9581
- border: 1px solid var(--color-primary);
10224
+ border: var(--border-width) solid var(--color-primary);
9582
10225
  border-radius: var(--radius-sm);
9583
10226
  outline: none;
9584
10227
  }
@@ -9631,11 +10274,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9631
10274
  }
9632
10275
 
9633
10276
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9634
- border-block-start: 2px solid var(--color-primary);
10277
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9635
10278
  }
9636
10279
 
9637
10280
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9638
- border-block-end: 2px solid var(--color-primary);
10281
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9639
10282
  }
9640
10283
 
9641
10284
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9643,11 +10286,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9643
10286
  }
9644
10287
 
9645
10288
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9646
- border-inline-start: 2px solid var(--color-primary);
10289
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9647
10290
  }
9648
10291
 
9649
10292
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9650
- border-inline-end: 2px solid var(--color-primary);
10293
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9651
10294
  }
9652
10295
 
9653
10296
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9720,11 +10363,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9720
10363
  }
9721
10364
 
9722
10365
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9723
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10366
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9724
10367
  }
9725
10368
 
9726
10369
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9727
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10370
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9728
10371
  }
9729
10372
 
9730
10373
  /* ── Column Visibility ── */
@@ -9796,7 +10439,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9796
10439
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9797
10440
  display: block;
9798
10441
  margin-block-end: var(--space-3);
9799
- border: 1px solid var(--color-border);
10442
+ border: var(--border-width) solid var(--color-border);
9800
10443
  border-radius: var(--radius-md);
9801
10444
  background: var(--color-bg);
9802
10445
  overflow: hidden;
@@ -9810,7 +10453,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9810
10453
  gap: var(--space-4);
9811
10454
  text-align: end;
9812
10455
  border-bottom: none;
9813
- border-block-end: 1px solid var(--color-border);
10456
+ border-block-end: var(--border-width) solid var(--color-border);
9814
10457
  }
9815
10458
 
9816
10459
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9907,7 +10550,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9907
10550
 
9908
10551
  /* === recipes/tabs.css === */
9909
10552
  /* @ui:component tabs */
9910
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle space-1 space-2 space-3 space-4 radius-md radius-lg text-sm text-base weight-medium duration-fast ease-default */
10553
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle space-1 space-2 space-3 space-4 radius-md radius-lg text-sm text-base weight-medium duration-fast ease-default font-ui border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
9911
10554
 
9912
10555
  /* ── Root ── */
9913
10556
  [data-ui="tabs"] {
@@ -9936,7 +10579,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9936
10579
  border: none;
9937
10580
  background: transparent;
9938
10581
  color: var(--color-fg-muted);
9939
- font-family: var(--font-sans, system-ui, sans-serif);
10582
+ font-family: var(--font-ui);
9940
10583
  font-size: var(--text-sm);
9941
10584
  font-weight: var(--weight-medium);
9942
10585
  cursor: pointer;
@@ -9951,8 +10594,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9951
10594
  }
9952
10595
 
9953
10596
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9954
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9955
- outline-offset: -2px;
10597
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10598
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9956
10599
  border-radius: var(--radius-md);
9957
10600
  }
9958
10601
 
@@ -9962,12 +10605,12 @@ div[data-ui="separator"][data-style="thick"]::after {
9962
10605
 
9963
10606
  /* ── Underline Variant ── */
9964
10607
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
9965
- border-bottom: 1px solid var(--color-border);
10608
+ border-bottom: var(--border-width) solid var(--color-border);
9966
10609
  gap: 0;
9967
10610
  }
9968
10611
 
9969
10612
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
9970
- border-bottom: 2px solid transparent;
10613
+ border-bottom: var(--border-width-strong) solid transparent;
9971
10614
  margin-bottom: -1px;
9972
10615
  border-radius: 0;
9973
10616
  }
@@ -9999,17 +10642,17 @@ div[data-ui="separator"][data-style="thick"]::after {
9999
10642
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
10000
10643
  background: var(--color-bg);
10001
10644
  color: var(--color-fg);
10002
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10645
+ box-shadow: var(--shadow-xs);
10003
10646
  }
10004
10647
 
10005
10648
  /* ── Enclosed Variant ── */
10006
10649
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
10007
- border-bottom: 1px solid var(--color-border);
10650
+ border-bottom: var(--border-width) solid var(--color-border);
10008
10651
  gap: 0;
10009
10652
  }
10010
10653
 
10011
10654
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10012
- border: 1px solid transparent;
10655
+ border: var(--border-width) solid transparent;
10013
10656
  border-bottom: none;
10014
10657
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10015
10658
  margin-bottom: -1px;
@@ -10054,8 +10697,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10054
10697
  @media (forced-colors: active) {
10055
10698
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10056
10699
  /* An outline the OS preserves, on every variant. */
10057
- outline: 2px solid Highlight;
10058
- outline-offset: -2px;
10700
+ outline: var(--border-width-strong) solid Highlight;
10701
+ outline-offset: calc(-1 * var(--border-width-strong));
10059
10702
  }
10060
10703
 
10061
10704
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10070,7 +10713,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10070
10713
 
10071
10714
  /* === recipes/tag-input.css === */
10072
10715
  /* @ui:component tag-input */
10073
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-1h space-2 space-3 text-sm z-dropdown duration-fast ease-default font-sans */
10716
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle radius-md radius-lg shadow-md space-1 space-1h space-2 space-3 text-sm z-dropdown duration-fast ease-default font-ui border-width focus-ring-color focus-ring-width */
10074
10717
 
10075
10718
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10076
10719
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10091,7 +10734,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10091
10734
  gap: var(--space-1h);
10092
10735
  width: 100%;
10093
10736
  padding: var(--space-1h) var(--space-2);
10094
- border: 1px solid var(--color-border);
10737
+ border: var(--border-width) solid var(--color-border);
10095
10738
  border-radius: var(--radius-md);
10096
10739
  background: var(--color-bg);
10097
10740
  list-style: none;
@@ -10100,8 +10743,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10100
10743
  }
10101
10744
 
10102
10745
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10103
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10104
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10746
+ border-color: var(--focus-ring-color);
10747
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10105
10748
  }
10106
10749
 
10107
10750
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10112,7 +10755,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10112
10755
  border: none;
10113
10756
  background: transparent;
10114
10757
  color: var(--color-fg);
10115
- font-family: var(--font-sans, system-ui, sans-serif);
10758
+ font-family: var(--font-ui);
10116
10759
  font-size: var(--text-sm);
10117
10760
  line-height: 1.5;
10118
10761
  outline: none;
@@ -10131,7 +10774,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10131
10774
  z-index: var(--z-dropdown);
10132
10775
  margin-top: var(--space-1);
10133
10776
  padding: var(--space-1);
10134
- border: 1px solid var(--color-border);
10777
+ border: var(--border-width) solid var(--color-border);
10135
10778
  border-radius: var(--radius-lg);
10136
10779
  background: var(--color-bg);
10137
10780
  box-shadow: var(--shadow-md);
@@ -10178,7 +10821,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10178
10821
 
10179
10822
  /* === recipes/toast.css === */
10180
10823
  /* @ui:component toast */
10181
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-success color-destructive color-warning shadow-lg radius-lg space-2 space-3 space-4 text-sm weight-medium z-toast duration-normal duration-slow ease-out */
10824
+ /* @ui:tokens color-bg panel-bg color-fg color-fg-muted color-border color-success color-destructive color-warning shadow-lg radius-lg space-2 space-3 space-4 text-sm weight-medium z-toast duration-normal duration-slow ease-out font-ui border-width border-width-lg focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
10182
10825
 
10183
10826
  /* ── Container ── */
10184
10827
  [data-ui="toast"][data-part="container"] {
@@ -10227,8 +10870,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10227
10870
  max-width: 380px;
10228
10871
  width: max-content;
10229
10872
  padding: var(--space-3) var(--space-4);
10230
- background: var(--color-bg);
10231
- border: 1px solid var(--color-border);
10873
+ background: var(--panel-bg);
10874
+ border: var(--border-width) solid var(--color-border);
10232
10875
  border-radius: var(--radius-lg);
10233
10876
  box-shadow: var(--shadow-lg);
10234
10877
  pointer-events: auto;
@@ -10238,6 +10881,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10238
10881
  transform var(--duration-normal) var(--ease-out);
10239
10882
  }
10240
10883
 
10884
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10885
+ [data-ui="toast"] [data-part="toast"] {
10886
+ -webkit-backdrop-filter: var(--surface-backdrop);
10887
+ backdrop-filter: var(--surface-backdrop);
10888
+ }
10889
+ }
10890
+
10241
10891
  /* ── State: Entering ── */
10242
10892
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10243
10893
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10277,7 +10927,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10277
10927
 
10278
10928
  /* ── Tone Variants ── */
10279
10929
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10280
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10930
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10281
10931
  }
10282
10932
 
10283
10933
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10285,7 +10935,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10285
10935
  }
10286
10936
 
10287
10937
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10288
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10938
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10289
10939
  }
10290
10940
 
10291
10941
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10293,7 +10943,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10293
10943
  }
10294
10944
 
10295
10945
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10296
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10946
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10297
10947
  }
10298
10948
 
10299
10949
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10315,7 +10965,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10315
10965
  /* ── Message ── */
10316
10966
  [data-ui="toast"] [data-part="message"] {
10317
10967
  flex: 1;
10318
- font-family: var(--font-sans, system-ui, sans-serif);
10968
+ font-family: var(--font-ui);
10319
10969
  font-size: var(--text-sm);
10320
10970
  font-weight: var(--weight-medium);
10321
10971
  color: var(--color-fg);
@@ -10326,11 +10976,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10326
10976
  [data-ui="toast"] [data-part="action"] {
10327
10977
  flex-shrink: 0;
10328
10978
  padding: var(--space-1, 0.25rem) var(--space-2);
10329
- border: 1px solid var(--color-border);
10979
+ border: var(--border-width) solid var(--color-border);
10330
10980
  border-radius: var(--radius-md, 0.375rem);
10331
10981
  background: transparent;
10332
10982
  color: var(--color-fg);
10333
- font-family: var(--font-sans, system-ui, sans-serif);
10983
+ font-family: var(--font-ui);
10334
10984
  font-size: var(--text-xs, 0.75rem);
10335
10985
  font-weight: var(--weight-medium);
10336
10986
  cursor: pointer;
@@ -10343,8 +10993,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10343
10993
  }
10344
10994
 
10345
10995
  [data-ui="toast"] [data-part="action"]:focus-visible {
10346
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10347
- outline-offset: 2px;
10996
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10997
+ outline-offset: var(--focus-ring-offset);
10348
10998
  }
10349
10999
 
10350
11000
  /* ── Close Button ── */
@@ -10370,8 +11020,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10370
11020
  }
10371
11021
 
10372
11022
  [data-ui="toast"] [data-part="close"]:focus-visible {
10373
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10374
- outline-offset: 2px;
11023
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11024
+ outline-offset: var(--focus-ring-offset);
10375
11025
  }
10376
11026
 
10377
11027
  /* ── Motion ── */
@@ -10384,14 +11034,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10384
11034
 
10385
11035
  /* === recipes/toggle-group.css === */
10386
11036
  /* @ui:component toggle-group */
10387
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 text-sm font-sans weight-medium duration-fast ease-default */
11037
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 text-sm font-ui weight-medium duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
10388
11038
 
10389
11039
  /* ── Root: a segmented row of toggle buttons ── */
10390
11040
  [data-ui="toggle-group"] {
10391
11041
  display: inline-flex;
10392
11042
  gap: var(--space-1);
10393
11043
  padding: var(--space-1);
10394
- border: 1px solid var(--color-border);
11044
+ border: var(--border-width) solid var(--color-border);
10395
11045
  border-radius: var(--radius-md);
10396
11046
  background: var(--color-bg);
10397
11047
  }
@@ -10406,7 +11056,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10406
11056
  border-radius: var(--radius-md);
10407
11057
  background: transparent;
10408
11058
  color: var(--color-fg-muted);
10409
- font-family: var(--toggle-group-font, var(--font-sans));
11059
+ font-family: var(--toggle-group-font, var(--font-ui));
10410
11060
  font-size: var(--text-sm);
10411
11061
  font-weight: var(--weight-medium);
10412
11062
  line-height: 1;
@@ -10447,13 +11097,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10447
11097
 
10448
11098
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10449
11099
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10450
- outline: 2px solid var(--color-ring);
10451
- outline-offset: 2px;
11100
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11101
+ outline-offset: var(--focus-ring-offset);
10452
11102
  }
10453
11103
 
10454
11104
  /* ── Disabled control ── */
10455
11105
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10456
- opacity: 0.5;
11106
+ opacity: var(--disabled-opacity);
10457
11107
  cursor: not-allowed;
10458
11108
  }
10459
11109
 
@@ -10466,7 +11116,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10466
11116
 
10467
11117
  /* === recipes/tooltip.css === */
10468
11118
  /* @ui:component tooltip */
10469
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11119
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10470
11120
 
10471
11121
  /* ── Root ── */
10472
11122
  [data-ui="tooltip"] {
@@ -10487,7 +11137,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10487
11137
  color: var(--color-bg);
10488
11138
  border-radius: var(--radius-md);
10489
11139
  padding: var(--space-1h, 0.375rem) var(--space-2);
10490
- font-family: var(--font-sans, system-ui, sans-serif);
11140
+ font-family: var(--font-ui);
10491
11141
  font-size: var(--text-xs, 0.75rem);
10492
11142
  line-height: 1.4;
10493
11143
  white-space: nowrap;
@@ -10498,6 +11148,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10498
11148
  transform var(--duration-fast) var(--ease-default);
10499
11149
  }
10500
11150
 
11151
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11152
+ [data-ui="tooltip"] [data-part="content"] {
11153
+ -webkit-backdrop-filter: var(--surface-backdrop);
11154
+ backdrop-filter: var(--surface-backdrop);
11155
+ }
11156
+ }
11157
+
10501
11158
  /* Default position (top) when no variant is specified */
10502
11159
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10503
11160
  bottom: 100%;
@@ -10613,7 +11270,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10613
11270
 
10614
11271
  /* === recipes/tree-view.css === */
10615
11272
  /* @ui:component tree-view */
10616
- /* @ui:tokens color-bg-muted color-fg color-fg-muted color-fg-subtle color-primary color-primary-subtle color-ring space-px space-1 space-2 space-5 radius-md text-sm font-sans weight-medium duration-fast ease-default */
11273
+ /* @ui:tokens color-bg-muted color-fg color-fg-muted color-fg-subtle color-primary color-primary-subtle color-ring space-px space-1 space-2 space-5 radius-md text-sm font-ui weight-medium duration-fast ease-default focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
10617
11274
 
10618
11275
  [data-ui="tree-view"],
10619
11276
  [data-ui="tree-view"] [data-part="group"] {
@@ -10626,7 +11283,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10626
11283
  inline-size: 100%;
10627
11284
  padding: var(--space-1);
10628
11285
  color: var(--color-fg);
10629
- font-family: var(--font-sans);
11286
+ font-family: var(--font-ui);
10630
11287
  font-size: var(--text-sm);
10631
11288
  }
10632
11289
 
@@ -10654,8 +11311,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10654
11311
  }
10655
11312
 
10656
11313
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10657
- outline: var(--space-px) solid var(--color-ring);
10658
- outline-offset: var(--space-px);
11314
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11315
+ outline-offset: var(--focus-ring-offset);
10659
11316
  }
10660
11317
 
10661
11318
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10694,7 +11351,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10694
11351
 
10695
11352
  /* === patterns/auth-form.css === */
10696
11353
  /* @ui:component auth-form */
10697
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-primary-hover color-primary-fg color-destructive color-destructive-subtle color-success color-success-subtle radius-lg radius-xl shadow-sm shadow-md space-1 space-2 space-3 space-4 space-5 space-6 space-8 font-sans text-xs text-sm text-base text-lg text-xl text-2xl weight-medium weight-semibold weight-bold leading-tight leading-normal duration-fast duration-normal ease-default */
11354
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-primary-hover color-primary-fg color-destructive color-destructive-subtle color-success color-success-subtle radius-lg radius-xl shadow-sm shadow-md space-1 space-2 space-3 space-4 space-5 space-6 space-8 font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading text-xs text-sm text-base text-lg text-xl text-2xl weight-medium weight-semibold weight-bold leading-tight leading-normal duration-fast duration-normal ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset link-decoration */
10698
11355
 
10699
11356
  /* ── Root Container ── */
10700
11357
  [data-ui="auth-form"] {
@@ -10702,7 +11359,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10702
11359
  align-items: center;
10703
11360
  justify-content: center;
10704
11361
  width: 100%;
10705
- font-family: var(--font-sans);
11362
+ font-family: var(--font-body);
10706
11363
  }
10707
11364
 
10708
11365
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10734,9 +11391,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10734
11391
 
10735
11392
  [data-ui="auth-form"] [data-part="title"] {
10736
11393
  margin: 0;
11394
+ font-family: var(--font-heading);
10737
11395
  font-size: var(--text-xl);
10738
- font-weight: var(--weight-bold);
10739
- line-height: var(--leading-tight);
11396
+ font-weight: var(--heading-weight);
11397
+ letter-spacing: var(--heading-tracking);
11398
+ text-transform: var(--heading-transform);
11399
+ font-variant-caps: var(--heading-caps);
11400
+ line-height: var(--heading-leading);
10740
11401
  color: var(--color-fg);
10741
11402
  }
10742
11403
 
@@ -10753,7 +11414,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10753
11414
  margin: var(--space-4) var(--space-6) 0;
10754
11415
  padding: var(--space-3);
10755
11416
  background: var(--color-destructive-subtle);
10756
- border: 1px solid var(--color-destructive);
11417
+ border: var(--border-width) solid var(--color-destructive);
10757
11418
  border-radius: var(--radius-lg);
10758
11419
  color: var(--color-destructive);
10759
11420
  font-size: var(--text-sm);
@@ -10831,13 +11492,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10831
11492
  }
10832
11493
 
10833
11494
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10834
- text-decoration: underline;
11495
+ text-decoration-line: var(--link-decoration);
10835
11496
  color: var(--color-primary-hover);
10836
11497
  }
10837
11498
 
10838
11499
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10839
- outline: 2px solid var(--color-ring);
10840
- outline-offset: 2px;
11500
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11501
+ outline-offset: var(--focus-ring-offset);
10841
11502
  border-radius: var(--radius-sm, 0.25rem);
10842
11503
  }
10843
11504
 
@@ -10965,8 +11626,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10965
11626
  max-width: var(--auth-form-max-width, 400px);
10966
11627
  border-radius: var(--card-radius, var(--radius-lg));
10967
11628
  box-shadow: var(--card-shadow, var(--shadow-sm));
10968
- border-inline-start: 1px solid var(--card-border, var(--color-border));
10969
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11629
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11630
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
10970
11631
  }
10971
11632
  }
10972
11633
 
@@ -10981,7 +11642,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10981
11642
 
10982
11643
  /* === patterns/crud-table.css === */
10983
11644
  /* @ui:component crud-table */
10984
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg color-destructive color-destructive-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-sans text-sm text-base text-lg weight-medium weight-semibold duration-fast duration-normal ease-default */
11645
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg color-destructive color-destructive-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-body text-sm text-base text-lg weight-medium weight-semibold duration-fast duration-normal ease-default border-width */
10985
11646
 
10986
11647
  /* ── Root ── */
10987
11648
  [data-ui="crud-table"] {
@@ -10989,7 +11650,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10989
11650
  flex-direction: column;
10990
11651
  gap: var(--space-4);
10991
11652
  width: 100%;
10992
- font-family: var(--font-sans, system-ui, sans-serif);
11653
+ font-family: var(--font-body);
10993
11654
  }
10994
11655
 
10995
11656
  /* ── Toolbar ── */
@@ -11047,7 +11708,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11047
11708
  gap: var(--space-3);
11048
11709
  padding: var(--space-3) var(--space-4);
11049
11710
  background: var(--color-bg-subtle);
11050
- border: 1px solid var(--color-border);
11711
+ border: var(--border-width) solid var(--color-border);
11051
11712
  border-radius: var(--radius-md);
11052
11713
  }
11053
11714
 
@@ -11062,7 +11723,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11062
11723
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11063
11724
  width: 100%;
11064
11725
  overflow-x: auto;
11065
- border: 1px solid var(--color-border);
11726
+ border: var(--border-width) solid var(--color-border);
11066
11727
  border-radius: var(--radius-lg);
11067
11728
  background: var(--color-bg);
11068
11729
  }
@@ -11092,7 +11753,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11092
11753
  padding: var(--space-8) var(--space-4);
11093
11754
  text-align: center;
11094
11755
  min-height: 240px;
11095
- border: 1px dashed var(--color-border);
11756
+ border: var(--border-width) dashed var(--color-border);
11096
11757
  border-radius: var(--radius-lg);
11097
11758
  background: var(--color-bg);
11098
11759
  }
@@ -11205,7 +11866,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11205
11866
 
11206
11867
  /* === patterns/dashboard-shell.css === */
11207
11868
  /* @ui:component dashboard-shell */
11208
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-primary-fg space-2 space-3 space-4 space-5 space-6 space-8 space-12 space-16 radius-md radius-lg shadow-sm shadow-md font-sans text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-normal duration-slow ease-default ease-out z-sticky */
11869
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-primary-fg space-2 space-3 space-4 space-5 space-6 space-8 space-12 space-16 radius-md radius-lg shadow-sm shadow-md font-body font-ui text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-normal duration-slow ease-default ease-out z-sticky border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
11209
11870
 
11210
11871
  /* ── Shell Grid Layout ──
11211
11872
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11230,7 +11891,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11230
11891
  "footer";
11231
11892
  min-height: 100vh;
11232
11893
  background: var(--color-bg);
11233
- font-family: var(--font-sans);
11894
+ font-family: var(--font-body);
11234
11895
  color: var(--color-fg);
11235
11896
  }
11236
11897
 
@@ -11254,7 +11915,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11254
11915
  gap: var(--space-2);
11255
11916
  padding: var(--space-4);
11256
11917
  background: var(--color-bg-subtle);
11257
- border-inline-end: 1px solid var(--color-border);
11918
+ border-inline-end: var(--border-width) solid var(--color-border);
11258
11919
  overflow-y: auto;
11259
11920
  position: fixed;
11260
11921
  top: 0;
@@ -11274,7 +11935,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11274
11935
 
11275
11936
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11276
11937
  border-inline-end: none;
11277
- border-inline-start: 1px solid var(--color-border);
11938
+ border-inline-start: var(--border-width) solid var(--color-border);
11278
11939
  inset-inline-start: auto;
11279
11940
  inset-inline-end: 0;
11280
11941
  transform: translateX(100%);
@@ -11349,7 +12010,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11349
12010
  gap: var(--space-3);
11350
12011
  padding: var(--space-2) var(--space-3);
11351
12012
  border-radius: var(--radius-md);
11352
- font-family: var(--font-sans);
12013
+ font-family: var(--font-ui);
11353
12014
  font-size: var(--text-sm);
11354
12015
  font-weight: var(--weight-medium);
11355
12016
  line-height: var(--leading-normal);
@@ -11368,8 +12029,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11368
12029
  }
11369
12030
 
11370
12031
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11371
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11372
- outline-offset: -2px;
12032
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12033
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11373
12034
  }
11374
12035
 
11375
12036
  /* ── Nav Item Active ── */
@@ -11416,7 +12077,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11416
12077
  gap: var(--space-2);
11417
12078
  padding: 0 var(--space-3);
11418
12079
  background: var(--color-bg);
11419
- border-bottom: 1px solid var(--color-border);
12080
+ border-bottom: var(--border-width) solid var(--color-border);
11420
12081
  position: sticky;
11421
12082
  top: 0;
11422
12083
  z-index: var(--z-sticky);
@@ -11497,7 +12158,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11497
12158
  align-items: center;
11498
12159
  gap: var(--space-3);
11499
12160
  padding: var(--space-4) var(--space-6);
11500
- border-top: 1px solid var(--color-border);
12161
+ border-top: var(--border-width) solid var(--color-border);
11501
12162
  font-size: var(--text-xs);
11502
12163
  color: var(--color-fg-muted);
11503
12164
  }
@@ -11580,7 +12241,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11580
12241
 
11581
12242
  /* === patterns/document.css === */
11582
12243
  /* @ui:component document */
11583
- /* @ui:tokens doc-max-width doc-font doc-font-size doc-line-height doc-heading-font doc-heading-weight doc-heading-size doc-subheading-size doc-legal-size doc-legal-color doc-section-gap doc-component-gap doc-running-header-height doc-running-footer-height doc-running-gap doc-bg doc-fg doc-print-border-color doc-table-header-bg doc-table-header-fg doc-table-header-weight doc-table-border doc-table-cell-pad-y doc-table-cell-pad-x doc-table-font-size doc-table-num-font doc-table-footer-bg doc-table-footer-weight doc-table-stripe-bg page-format page-orientation page-margin page-margin-top page-margin-bottom page-margin-left page-margin-right color-bg color-fg color-fg-muted color-border space-4 space-6 space-8 space-12 shadow-lg radius-md font-serif z-raised */
12244
+ /* @ui:tokens doc-max-width doc-font doc-font-size doc-line-height doc-heading-font doc-heading-weight doc-heading-size doc-subheading-size doc-legal-size doc-legal-color doc-section-gap doc-component-gap doc-running-header-height doc-running-footer-height doc-running-gap doc-bg doc-fg doc-print-border-color doc-table-header-bg doc-table-header-fg doc-table-header-weight doc-table-border doc-table-cell-pad-y doc-table-cell-pad-x doc-table-font-size doc-table-num-font doc-table-footer-bg doc-table-footer-weight doc-table-stripe-bg page-format page-orientation page-margin page-margin-top page-margin-bottom page-margin-left page-margin-right color-bg color-fg color-fg-muted color-border space-4 space-6 space-8 space-12 shadow-lg radius-md font-body weight-bold z-raised border-width texture-page */
11584
12245
 
11585
12246
  /* ── Page Rules ── */
11586
12247
  @page {
@@ -11620,14 +12281,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11620
12281
  max-width: var(--doc-max-width);
11621
12282
  margin: var(--space-4) auto;
11622
12283
  padding: var(--space-6) var(--space-4);
11623
- background: var(--color-bg, #fff);
12284
+ background-color: var(--color-bg, #fff);
12285
+ background-image: var(--texture-page);
11624
12286
  color: var(--color-fg);
11625
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12287
+ font-family: var(--doc-font, var(--font-body));
11626
12288
  font-size: var(--doc-font-size);
11627
12289
  line-height: var(--doc-line-height);
11628
- box-shadow: var(--shadow-lg,
11629
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11630
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12290
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12291
+ colour no theme could reach. --shadow-lg is always defined by the token
12292
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12293
+ than re-tokenised. */
12294
+ box-shadow: var(--shadow-lg);
11631
12295
  border-radius: 0;
11632
12296
  position: relative;
11633
12297
  }
@@ -11643,7 +12307,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11643
12307
  [data-ui="document"] > [data-part="header"] {
11644
12308
  margin-block-end: var(--doc-section-gap);
11645
12309
  padding-block-end: var(--doc-component-gap);
11646
- border-block-end: 1px solid var(--color-border);
12310
+ border-block-end: var(--border-width) solid var(--color-border);
11647
12311
  }
11648
12312
 
11649
12313
  /* ── Body ── */
@@ -11653,13 +12317,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11653
12317
  gap: var(--doc-section-gap);
11654
12318
  }
11655
12319
 
12320
+ /* ── Headings ──
12321
+ The document's own heading face and weight (1.1A-21): a print theme sets
12322
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12323
+ from the body copy (document-serif's Times titles over Georgia text). Both
12324
+ default to the page's heading role in tokens/document.css, and each falls
12325
+ back to what a heading rendered before the tokens had a reader. A heading
12326
+ that carries its own data-weight keeps it — that is the author asking. */
12327
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12328
+ font-family: var(--doc-heading-font, var(--font-body));
12329
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12330
+ }
12331
+
11656
12332
  /* ── Running footer ──
11657
12333
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11658
12334
  [data-ui="document"] > [data-part="doc-footer"],
11659
12335
  [data-ui="document"] > [data-part="footer"] {
11660
12336
  margin-block-start: var(--doc-section-gap);
11661
12337
  padding-block-start: var(--doc-component-gap);
11662
- border-block-start: 1px solid var(--color-border);
12338
+ border-block-start: var(--border-width) solid var(--color-border);
11663
12339
  font-size: var(--doc-legal-size);
11664
12340
  color: var(--doc-legal-color);
11665
12341
  }
@@ -11697,7 +12373,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11697
12373
 
11698
12374
  /* ── Variant: Report ── */
11699
12375
  [data-ui="document"][data-variant="report"] {
11700
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12376
+ /* A report is serif-set by definition. It re-points the document's own font
12377
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12378
+ (key-value, callout, signature — all of which read --doc-font) follows the
12379
+ report into serif instead of staying sans inside a serif page. `report` is
12380
+ the author asking for serif; a theme that wants its own document face
12381
+ declares --doc-font at :root, which this variant deliberately outranks. */
12382
+ --doc-font: Georgia, 'Times New Roman', serif;
11701
12383
  line-height: 1.6;
11702
12384
  }
11703
12385
 
@@ -11792,7 +12474,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11792
12474
  z-index: var(--z-raised);
11793
12475
  margin-block-end: 0;
11794
12476
  padding-block-end: var(--doc-running-gap);
11795
- border-block-end: 1px solid var(--doc-print-border-color);
12477
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11796
12478
  background: var(--doc-bg);
11797
12479
  transform: translateZ(0);
11798
12480
  }
@@ -11808,7 +12490,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11808
12490
  z-index: var(--z-raised);
11809
12491
  margin-block-start: 0;
11810
12492
  padding-block-start: var(--doc-running-gap);
11811
- border-block-start: 1px solid var(--doc-print-border-color);
12493
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11812
12494
  background: var(--doc-bg);
11813
12495
  transform: translateZ(0);
11814
12496
  }
@@ -11837,7 +12519,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11837
12519
 
11838
12520
  /* === patterns/empty-state.css === */
11839
12521
  /* @ui:component empty-state */
11840
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary radius-lg shadow-sm space-2 space-3 space-4 space-6 space-8 space-10 font-sans text-sm text-base text-lg text-xl text-2xl weight-semibold leading-tight leading-normal duration-normal ease-default */
12522
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary radius-lg shadow-sm space-2 space-3 space-4 space-6 space-8 space-10 font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-xl text-2xl weight-semibold leading-tight leading-normal duration-normal ease-default */
11841
12523
 
11842
12524
  /* ── Root ── */
11843
12525
  [data-ui="empty-state"] {
@@ -11848,7 +12530,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11848
12530
  text-align: center;
11849
12531
  padding: var(--space-8) var(--space-6);
11850
12532
  gap: var(--space-3);
11851
- font-family: var(--font-sans, system-ui, sans-serif);
12533
+ font-family: var(--font-body);
11852
12534
  }
11853
12535
 
11854
12536
  /* ── Icon ── */
@@ -11871,10 +12553,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11871
12553
 
11872
12554
  /* ── Title ── */
11873
12555
  [data-ui="empty-state"] [data-part="title"] {
11874
- font-family: var(--font-sans, system-ui, sans-serif);
12556
+ font-family: var(--font-heading);
11875
12557
  font-size: var(--text-lg);
11876
12558
  font-weight: var(--weight-semibold);
11877
- line-height: var(--leading-tight);
12559
+ letter-spacing: var(--heading-tracking);
12560
+ text-transform: var(--heading-transform);
12561
+ font-variant-caps: var(--heading-caps);
12562
+ line-height: var(--heading-leading);
11878
12563
  color: var(--color-fg);
11879
12564
  margin: 0;
11880
12565
  }
@@ -11972,7 +12657,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11972
12657
 
11973
12658
  /* === patterns/feature-grid.css === */
11974
12659
  /* @ui:component feature-grid */
11975
- /* @ui:tokens color-bg color-fg color-fg-muted color-primary color-primary-subtle space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-base text-lg text-xl text-3xl font-sans weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-md radius-lg */
12660
+ /* @ui:tokens color-bg color-fg color-fg-muted color-primary color-primary-subtle space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-base text-lg text-xl text-3xl font-body weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-md radius-lg */
11976
12661
 
11977
12662
  /* ── Root ──
11978
12663
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -11982,7 +12667,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11982
12667
  gap: var(--space-4);
11983
12668
  padding-block: var(--space-12);
11984
12669
  padding-inline: var(--space-4);
11985
- font-family: var(--font-sans, system-ui, sans-serif);
12670
+ font-family: var(--font-body);
11986
12671
  color: var(--color-fg);
11987
12672
  background: var(--color-bg);
11988
12673
  }
@@ -12124,7 +12809,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12124
12809
  max-inline-size: var(--measure-narrow);
12125
12810
  margin-inline: auto;
12126
12811
  padding-block: var(--space-8);
12127
- font-family: var(--font-sans);
12812
+ font-family: var(--font-body);
12128
12813
  }
12129
12814
 
12130
12815
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12144,7 +12829,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12144
12829
 
12145
12830
  /* === patterns/hero.css === */
12146
12831
  /* @ui:component hero */
12147
- /* @ui:tokens color-bg color-fg color-fg-muted space-3 space-4 space-6 space-8 space-12 space-16 space-20 text-sm text-base text-lg text-xl text-3xl text-4xl font-sans weight-bold weight-normal leading-tight leading-relaxed radius-lg */
12832
+ /* @ui:tokens color-bg color-fg color-fg-muted space-3 space-4 space-6 space-8 space-12 space-16 space-20 text-sm text-base text-lg text-xl text-3xl text-4xl font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading weight-bold weight-normal leading-tight leading-relaxed radius-lg texture-surface */
12148
12833
 
12149
12834
  /* ── Root ──
12150
12835
  A one-column grid by default; the layout variants only change how that grid
@@ -12158,9 +12843,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12158
12843
  gap: var(--space-4);
12159
12844
  padding-block: var(--space-12);
12160
12845
  padding-inline: var(--space-4);
12161
- font-family: var(--font-sans, system-ui, sans-serif);
12846
+ font-family: var(--font-body);
12162
12847
  color: var(--color-fg);
12163
- background: var(--color-bg);
12848
+ background-color: var(--color-bg);
12849
+ background-image: var(--texture-surface);
12164
12850
  }
12165
12851
 
12166
12852
  /* ── Eyebrow ── */
@@ -12172,9 +12858,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12172
12858
  /* ── Headline ── */
12173
12859
  [data-ui="hero"] [data-part="headline"] {
12174
12860
  margin: 0;
12861
+ font-family: var(--font-heading);
12175
12862
  font-size: var(--text-3xl);
12176
- font-weight: var(--weight-bold);
12177
- line-height: var(--leading-tight);
12863
+ font-weight: var(--heading-weight);
12864
+ letter-spacing: var(--heading-tracking);
12865
+ text-transform: var(--heading-transform);
12866
+ font-variant-caps: var(--heading-caps);
12867
+ line-height: var(--heading-leading);
12178
12868
  color: var(--color-fg);
12179
12869
  text-wrap: balance;
12180
12870
  }
@@ -12293,7 +12983,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12293
12983
 
12294
12984
  /* === patterns/inbox.css === */
12295
12985
  /* @ui:component inbox */
12296
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-destructive color-primary color-primary-subtle color-ring space-1 space-2 space-3 space-4 space-6 space-px font-sans text-xs text-sm text-base text-xl weight-medium weight-semibold leading-tight leading-normal leading-relaxed radius-md radius-lg */
12986
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-destructive color-primary color-primary-subtle color-ring space-1 space-2 space-3 space-4 space-6 space-px font-body text-xs text-sm text-base text-xl weight-medium weight-semibold leading-tight leading-normal leading-relaxed radius-md radius-lg focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
12297
12987
 
12298
12988
  /* ── Root ──
12299
12989
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12313,7 +13003,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12313
13003
  overflow: hidden;
12314
13004
  border: var(--space-px, 1px) solid var(--color-border);
12315
13005
  border-radius: var(--radius-lg);
12316
- font-family: var(--font-sans, system-ui, sans-serif);
13006
+ font-family: var(--font-body);
12317
13007
  color: var(--color-fg);
12318
13008
  background: var(--color-bg);
12319
13009
  }
@@ -12405,8 +13095,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12405
13095
  }
12406
13096
 
12407
13097
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12408
- outline: 2px solid var(--color-ring);
12409
- outline-offset: 2px;
13098
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13099
+ outline-offset: var(--focus-ring-offset);
12410
13100
  }
12411
13101
 
12412
13102
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12565,7 +13255,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12565
13255
 
12566
13256
  /* === patterns/pricing.css === */
12567
13257
  /* @ui:component pricing */
12568
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-sm text-base text-lg text-3xl font-sans weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-lg shadow-md */
13258
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-sm text-base text-lg text-3xl font-heading font-body heading-tracking heading-transform heading-caps heading-leading weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-lg shadow-md border-width-strong */
12569
13259
 
12570
13260
  /* ── Root ──
12571
13261
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12575,7 +13265,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12575
13265
  gap: var(--space-4);
12576
13266
  padding-block: var(--space-12);
12577
13267
  padding-inline: var(--space-4);
12578
- font-family: var(--font-sans, system-ui, sans-serif);
13268
+ font-family: var(--font-body);
12579
13269
  color: var(--color-fg);
12580
13270
  background: var(--color-bg);
12581
13271
  }
@@ -12625,9 +13315,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12625
13315
 
12626
13316
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12627
13317
  margin: 0;
13318
+ font-family: var(--font-heading);
12628
13319
  font-size: var(--text-lg);
12629
13320
  font-weight: var(--weight-semibold);
12630
- line-height: var(--leading-tight);
13321
+ letter-spacing: var(--heading-tracking);
13322
+ text-transform: var(--heading-transform);
13323
+ font-variant-caps: var(--heading-caps);
13324
+ line-height: var(--heading-leading);
12631
13325
  }
12632
13326
 
12633
13327
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12688,7 +13382,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12688
13382
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12689
13383
  border-color: var(--color-primary);
12690
13384
  box-shadow: var(--shadow-md);
12691
- outline: var(--space-px, 1px) solid var(--color-primary);
13385
+ outline: var(--border-width-strong) solid var(--color-primary);
12692
13386
  }
12693
13387
 
12694
13388
  /* ── Footnote ── */
@@ -12733,14 +13427,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12733
13427
 
12734
13428
  /* === patterns/search-results.css === */
12735
13429
  /* @ui:component search-results */
12736
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-sans text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default */
13430
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-body text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
12737
13431
 
12738
13432
  /* ── Root ── */
12739
13433
  [data-ui="search-results"] {
12740
13434
  display: flex;
12741
13435
  flex-direction: column;
12742
13436
  gap: var(--space-4);
12743
- font-family: var(--font-sans, system-ui, sans-serif);
13437
+ font-family: var(--font-body);
12744
13438
  }
12745
13439
 
12746
13440
  /* ── Search Input ── */
@@ -12768,7 +13462,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12768
13462
  justify-content: space-between;
12769
13463
  gap: var(--space-4);
12770
13464
  padding-bottom: var(--space-2);
12771
- border-bottom: 1px solid var(--color-border);
13465
+ border-bottom: var(--border-width) solid var(--color-border);
12772
13466
  }
12773
13467
 
12774
13468
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12803,7 +13497,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12803
13497
  flex-direction: column;
12804
13498
  gap: var(--space-2);
12805
13499
  padding: var(--space-4);
12806
- border: 1px solid var(--color-border);
13500
+ border: var(--border-width) solid var(--color-border);
12807
13501
  border-radius: var(--radius-md);
12808
13502
  background: var(--color-bg);
12809
13503
  transition: background var(--duration-fast) var(--ease-default),
@@ -12862,7 +13556,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12862
13556
  display: flex;
12863
13557
  justify-content: center;
12864
13558
  padding-top: var(--space-4);
12865
- border-top: 1px solid var(--color-border);
13559
+ border-top: var(--border-width) solid var(--color-border);
12866
13560
  }
12867
13561
 
12868
13562
  /* ── Loading ── */
@@ -12902,7 +13596,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12902
13596
 
12903
13597
  /* ── Error State ── */
12904
13598
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12905
- border: 1px solid var(--color-border);
13599
+ border: var(--border-width) solid var(--color-border);
12906
13600
  border-radius: var(--radius-md);
12907
13601
  padding: var(--space-6);
12908
13602
  text-align: center;
@@ -12911,8 +13605,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12911
13605
 
12912
13606
  /* ── Focus management ── */
12913
13607
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12914
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12915
- outline-offset: 2px;
13608
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13609
+ outline-offset: var(--focus-ring-offset);
12916
13610
  }
12917
13611
 
12918
13612
  /* ── Motion ── */
@@ -12928,7 +13622,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12928
13622
 
12929
13623
  /* === patterns/settings-page.css === */
12930
13624
  /* @ui:component settings-page */
12931
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-48 radius-md radius-lg shadow-sm shadow-md font-sans text-sm text-base text-lg text-xl weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default z-sticky */
13625
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-48 radius-md radius-lg shadow-sm shadow-md font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-xl weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default z-sticky border-width border-width-strong */
12932
13626
 
12933
13627
  /* ── Root ── */
12934
13628
  [data-ui="settings-page"] {
@@ -12938,7 +13632,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12938
13632
  width: 100%;
12939
13633
  max-width: 768px;
12940
13634
  margin-inline: auto;
12941
- font-family: var(--font-sans, system-ui, sans-serif);
13635
+ font-family: var(--font-body);
12942
13636
  color: var(--color-fg);
12943
13637
  }
12944
13638
 
@@ -12952,9 +13646,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12952
13646
  /* ── Title ── */
12953
13647
  [data-ui="settings-page"] [data-part="title"] {
12954
13648
  margin: 0;
13649
+ font-family: var(--font-heading);
12955
13650
  font-size: var(--text-xl, 1.25rem);
12956
13651
  font-weight: var(--weight-semibold, 600);
12957
- line-height: var(--leading-tight);
13652
+ letter-spacing: var(--heading-tracking);
13653
+ text-transform: var(--heading-transform);
13654
+ font-variant-caps: var(--heading-caps);
13655
+ line-height: var(--heading-leading);
12958
13656
  color: var(--color-fg);
12959
13657
  }
12960
13658
 
@@ -13018,7 +13716,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13018
13716
  gap: var(--space-3, 0.75rem);
13019
13717
  padding: var(--space-4);
13020
13718
  background: var(--color-bg);
13021
- border-top: 1px solid var(--color-border);
13719
+ border-top: var(--border-width) solid var(--color-border);
13022
13720
  border-radius: var(--radius-lg);
13023
13721
  box-shadow: var(--shadow-md);
13024
13722
  position: sticky;
@@ -13082,7 +13780,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13082
13780
  flex-direction: row;
13083
13781
  flex-wrap: wrap;
13084
13782
  border-inline-end: none;
13085
- border-bottom: 1px solid var(--color-border);
13783
+ border-bottom: var(--border-width) solid var(--color-border);
13086
13784
  padding-inline-end: 0;
13087
13785
  position: static;
13088
13786
  }
@@ -13101,7 +13799,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13101
13799
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13102
13800
  flex-direction: column;
13103
13801
  border-bottom: none;
13104
- border-inline-end: 1px solid var(--color-border);
13802
+ border-inline-end: var(--border-width) solid var(--color-border);
13105
13803
  padding-inline-end: var(--space-4);
13106
13804
  position: sticky;
13107
13805
  top: var(--space-4);
@@ -13119,7 +13817,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13119
13817
  justify-content: flex-start;
13120
13818
  text-align: start;
13121
13819
  border-bottom: none;
13122
- border-inline-start: 2px solid transparent;
13820
+ border-inline-start: var(--border-width-strong) solid transparent;
13123
13821
  margin-bottom: 0;
13124
13822
  margin-inline-end: -1px;
13125
13823
  padding: var(--space-2) var(--space-3);
@@ -13153,7 +13851,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13153
13851
 
13154
13852
  /* === patterns/site-footer.css === */
13155
13853
  /* @ui:component site-footer */
13156
- /* @ui:tokens color-bg-subtle color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 text-sm text-base text-lg font-sans weight-semibold weight-bold leading-normal */
13854
+ /* @ui:tokens color-bg-subtle color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 text-sm text-base text-lg font-body weight-semibold weight-bold leading-normal border-width */
13157
13855
 
13158
13856
  /* ── Root ──
13159
13857
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13163,11 +13861,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13163
13861
  gap: var(--space-8);
13164
13862
  padding-block: var(--space-10);
13165
13863
  padding-inline: var(--space-4);
13166
- font-family: var(--font-sans, system-ui, sans-serif);
13864
+ font-family: var(--font-body);
13167
13865
  font-size: var(--text-sm);
13168
13866
  color: var(--color-fg-muted);
13169
13867
  background: var(--color-bg-subtle);
13170
- border-block-start: 1px solid var(--color-border);
13868
+ border-block-start: var(--border-width) solid var(--color-border);
13171
13869
  }
13172
13870
 
13173
13871
  /* ── Brand ── */
@@ -13299,7 +13997,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13299
13997
 
13300
13998
  /* === patterns/stats-dashboard.css === */
13301
13999
  /* @ui:component stats-dashboard */
13302
- /* @ui:tokens color-bg color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-12 space-px font-sans text-sm text-base text-lg text-3xl weight-semibold weight-bold leading-tight leading-normal leading-relaxed */
14000
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-12 space-px font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-3xl weight-semibold weight-bold leading-tight leading-normal leading-relaxed */
13303
14001
 
13304
14002
  /* ── Root ──
13305
14003
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13312,7 +14010,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13312
14010
  gap: var(--space-3);
13313
14011
  padding-block: var(--space-8);
13314
14012
  padding-inline: var(--space-4);
13315
- font-family: var(--font-sans, system-ui, sans-serif);
14013
+ font-family: var(--font-body);
13316
14014
  color: var(--color-fg);
13317
14015
  background: var(--color-bg);
13318
14016
  }
@@ -13386,9 +14084,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13386
14084
 
13387
14085
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13388
14086
  margin: 0;
14087
+ font-family: var(--font-heading);
13389
14088
  font-size: var(--text-lg);
13390
14089
  font-weight: var(--weight-semibold);
13391
- line-height: var(--leading-tight);
14090
+ letter-spacing: var(--heading-tracking);
14091
+ text-transform: var(--heading-transform);
14092
+ font-variant-caps: var(--heading-caps);
14093
+ line-height: var(--heading-leading);
13392
14094
  }
13393
14095
 
13394
14096
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13479,7 +14181,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13479
14181
  gap: var(--space-6);
13480
14182
  max-inline-size: var(--measure-narrow);
13481
14183
  margin-inline: auto;
13482
- font-family: var(--font-sans);
14184
+ font-family: var(--font-body);
13483
14185
  }
13484
14186
 
13485
14187
  [data-ui="wizard"] [data-part="heading"] {