@faqir-ui/core 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +89 -52
  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 +61 -54
  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 +111 -5
  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/midnight.css === */
645
1033
  /* @ui:theme midnight — dark-first theme with deep navy/purple tones and vibrant cyan accents */
646
1034
 
@@ -690,12 +1078,62 @@
690
1078
  --color-border-strong: oklch(0.80 0.02 270);
691
1079
  --color-ring: oklch(0.50 0.24 280);
692
1080
 
693
- /* ── Shadows (cool blue-tinted) ── */
694
- --shadow-xs: 0 1px 2px oklch(0.20 0.04 270 / 0.08);
695
- --shadow-sm: 0 1px 3px oklch(0.20 0.04 270 / 0.10), 0 1px 2px oklch(0.20 0.04 270 / 0.06);
696
- --shadow-md: 0 4px 6px oklch(0.20 0.04 270 / 0.08), 0 2px 4px oklch(0.20 0.04 270 / 0.06);
697
- --shadow-lg: 0 10px 15px oklch(0.20 0.04 270 / 0.10), 0 4px 6px oklch(0.20 0.04 270 / 0.06);
698
- --shadow-xl: 0 20px 25px oklch(0.20 0.04 270 / 0.12), 0 8px 10px oklch(0.20 0.04 270 / 0.06);
1081
+ /* ══════════════════════════════════════════════════════════════════════
1082
+ The identity, in tokens. This theme's subject is a lit interface in a
1083
+ dark room; until 1.1A-15 it could only say so in colour. [1.1A-15]
1084
+ ══════════════════════════════════════════════════════════════════════ */
1085
+
1086
+ /* ── Type voice: one weight lighter than the registry's ──
1087
+ 700 blooms on a luminous accent against a near-black surface — the
1088
+ strokes thicken optically and a heading starts to smear. 600 is the
1089
+ weight a dark-first product sets its titles at, and stating it here is
1090
+ what makes `type.voice.weight` derive `semibold`. Light mode follows,
1091
+ because a theme has one voice. */
1092
+ --heading-weight: var(--weight-semibold);
1093
+
1094
+ /* ── Material: the grid behind the glass ──
1095
+ A faint rule grid on the PAGE (`--texture-page`), not on the things
1096
+ sitting on it: the subject is the instrument panel this UI is mounted in,
1097
+ and a grid behind every card would fight the data on it. `currentColor`
1098
+ at 12% alpha, so it tints itself from the page's own foreground and
1099
+ disappears entirely on paper (the print rule in `document.css`
1100
+ re-declares `background` as a shorthand). */
1101
+ --texture-page: var(--texture-grid);
1102
+
1103
+ /* ── Focus: a glow, not just a ring ──
1104
+ `--focus-shadow` is drawn BEHIND the outline by `base/reset.css` and by
1105
+ all thirteen controls that paint their own ring (1.1A-02), so this one
1106
+ declaration haloes every focusable surface. Mixed from `--color-ring`
1107
+ rather than named, so the halo is the accent in whichever scheme is on
1108
+ screen and can never drift from the ring it sits behind. */
1109
+ --focus-shadow: 0 0 0 var(--space-1) color-mix(in oklch, var(--color-ring) 35%, transparent);
1110
+
1111
+ /* ── Depth: layered, and tinted through the channel ──
1112
+ Every step is cast in `--shadow-color` (1.1A-04 — bare OKLCH channels, so
1113
+ each step keeps its own alpha), which replaces twenty literal navies with
1114
+ one declaration per scheme. The geometry is deliberately deeper than the
1115
+ base ramp's: the md step blurs past the `layered` band, which is what a
1116
+ lit panel floating over a dark room looks like, and it matches the dark
1117
+ ramp this theme was designed in rather than contradicting it. */
1118
+ --shadow-color: 0.20 0.05 275;
1119
+
1120
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.08);
1121
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.10), 0 1px 2px oklch(var(--shadow-color) / 0.06);
1122
+ --shadow-md: 0 6px 14px oklch(var(--shadow-color) / 0.10), 0 2px 4px oklch(var(--shadow-color) / 0.06);
1123
+ --shadow-lg: 0 14px 28px oklch(var(--shadow-color) / 0.12), 0 4px 8px oklch(var(--shadow-color) / 0.06);
1124
+ --shadow-xl: 0 28px 56px oklch(var(--shadow-color) / 0.14), 0 8px 16px oklch(var(--shadow-color) / 0.07);
1125
+ }
1126
+
1127
+ :root,
1128
+ [data-theme] {
1129
+ /* ── Decoration: selection wears the accent ──
1130
+ Cyan in this theme's primary design target, blue-violet in light — one
1131
+ declaration, because `--color-primary` already follows the scheme.
1132
+ On `:root, [data-theme]`: the token layer re-resolves these aliases on
1133
+ every scheme island (tokens/aliases.css), so a `:root`-only override
1134
+ would fall back to the default inside a nested `data-theme` region. */
1135
+ --selection-bg: var(--color-primary);
1136
+ --selection-fg: var(--color-primary-fg);
699
1137
  }
700
1138
 
701
1139
  /* ── Dark Mode (primary design target) ── */
@@ -744,12 +1182,14 @@
744
1182
  --color-border-strong: oklch(0.34 0.06 275);
745
1183
  --color-ring: oklch(0.75 0.16 195);
746
1184
 
747
- /* ── Shadows (deep, dramatic, purple-tinted) ── */
748
- --shadow-xs: 0 1px 3px oklch(0.08 0.06 285 / 0.4);
749
- --shadow-sm: 0 2px 6px oklch(0.08 0.06 285 / 0.5);
750
- --shadow-md: 0 6px 12px oklch(0.08 0.06 285 / 0.5), 0 2px 4px oklch(0.08 0.06 285 / 0.3);
751
- --shadow-lg: 0 12px 24px oklch(0.08 0.06 285 / 0.6), 0 4px 8px oklch(0.08 0.06 285 / 0.3);
752
- --shadow-xl: 0 24px 48px oklch(0.08 0.06 285 / 0.7), 0 8px 16px oklch(0.08 0.06 285 / 0.4);
1185
+ /* ── Shadows (deep, dramatic, purple-tinted — cast in the channel) ── */
1186
+ --shadow-color: 0.08 0.06 285;
1187
+
1188
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.4);
1189
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.5);
1190
+ --shadow-md: 0 6px 14px oklch(var(--shadow-color) / 0.5), 0 2px 4px oklch(var(--shadow-color) / 0.3);
1191
+ --shadow-lg: 0 14px 28px oklch(var(--shadow-color) / 0.6), 0 4px 8px oklch(var(--shadow-color) / 0.3);
1192
+ --shadow-xl: 0 28px 56px oklch(var(--shadow-color) / 0.7), 0 8px 16px oklch(var(--shadow-color) / 0.4);
753
1193
  }
754
1194
 
755
1195
  /* ── Auto Dark Mode (system preference) ── */
@@ -798,12 +1238,14 @@
798
1238
  --color-border-strong: oklch(0.34 0.06 275);
799
1239
  --color-ring: oklch(0.75 0.16 195);
800
1240
 
801
- /* ── Shadows (deep, dramatic, purple-tinted) ── */
802
- --shadow-xs: 0 1px 3px oklch(0.08 0.06 285 / 0.4);
803
- --shadow-sm: 0 2px 6px oklch(0.08 0.06 285 / 0.5);
804
- --shadow-md: 0 6px 12px oklch(0.08 0.06 285 / 0.5), 0 2px 4px oklch(0.08 0.06 285 / 0.3);
805
- --shadow-lg: 0 12px 24px oklch(0.08 0.06 285 / 0.6), 0 4px 8px oklch(0.08 0.06 285 / 0.3);
806
- --shadow-xl: 0 24px 48px oklch(0.08 0.06 285 / 0.7), 0 8px 16px oklch(0.08 0.06 285 / 0.4);
1241
+ /* ── Shadows (deep, dramatic, purple-tinted — cast in the channel) ── */
1242
+ --shadow-color: 0.08 0.06 285;
1243
+
1244
+ --shadow-xs: 0 1px 3px oklch(var(--shadow-color) / 0.4);
1245
+ --shadow-sm: 0 2px 6px oklch(var(--shadow-color) / 0.5);
1246
+ --shadow-md: 0 6px 14px oklch(var(--shadow-color) / 0.5), 0 2px 4px oklch(var(--shadow-color) / 0.3);
1247
+ --shadow-lg: 0 14px 28px oklch(var(--shadow-color) / 0.6), 0 4px 8px oklch(var(--shadow-color) / 0.3);
1248
+ --shadow-xl: 0 28px 56px oklch(var(--shadow-color) / 0.7), 0 8px 16px oklch(var(--shadow-color) / 0.4);
807
1249
  }
808
1250
  }
809
1251
 
@@ -821,11 +1263,38 @@
821
1263
  padding: 0;
822
1264
  }
823
1265
 
1266
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1267
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1268
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1269
+ these three rules; declaring them here (rather than in each theme) is what
1270
+ makes the two authoring forms interchangeable. Nothing else in the registry
1271
+ declares `color-scheme`, so this is purely additive.
1272
+
1273
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1274
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1275
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1276
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1277
+ dark island inside a light page has always worked here. */
1278
+ :root {
1279
+ color-scheme: light;
1280
+ }
1281
+
1282
+ [data-theme="dark"] {
1283
+ color-scheme: dark;
1284
+ }
1285
+
1286
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1287
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1288
+ does for a theme authored in the three-block form. */
1289
+ [data-theme="auto"] {
1290
+ color-scheme: light dark;
1291
+ }
1292
+
824
1293
  html {
825
1294
  -webkit-text-size-adjust: 100%;
826
1295
  -moz-tab-size: 4;
827
1296
  tab-size: 4;
828
- font-family: var(--font-sans);
1297
+ font-family: var(--font-body);
829
1298
  font-size: var(--text-base);
830
1299
  line-height: var(--leading-normal);
831
1300
  color: var(--color-fg);
@@ -836,6 +1305,11 @@ html {
836
1305
 
837
1306
  body {
838
1307
  min-height: 100dvh;
1308
+ /* The page's material. `none` by default (the initial value), so this is a
1309
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1310
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1311
+ covers the viewport, so the two compose instead of overwriting. */
1312
+ background-image: var(--texture-page);
839
1313
  }
840
1314
 
841
1315
  img,
@@ -905,10 +1379,32 @@ table {
905
1379
  }
906
1380
  }
907
1381
 
908
- /* Focus visible — default ring */
1382
+ /* Text selection — the decoration axis reaching the one surface no component
1383
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1384
+ of a themed page that never matched the theme. Both values are tokens
1385
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1386
+ ::selection {
1387
+ background-color: var(--selection-bg);
1388
+ color: var(--selection-fg);
1389
+ }
1390
+
1391
+ /* Focus visible — the default ring, and the only place it is spelled out.
1392
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1393
+ focus once and every element that has not drawn its own ring follows. */
909
1394
  :focus-visible {
910
- outline: 2px solid var(--color-ring);
911
- outline-offset: 2px;
1395
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1396
+ outline-offset: var(--focus-ring-offset);
1397
+ }
1398
+
1399
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1400
+ is not a property focus owns: an element's resting shadow — a card's depth,
1401
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1402
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1403
+ sets a shadow outranks this one, so it lands only on an element nothing else
1404
+ shadows, and it never takes a shadow away. The controls that draw their own
1405
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1406
+ :where(:focus-visible) {
1407
+ box-shadow: var(--focus-shadow);
912
1408
  }
913
1409
 
914
1410
  /* Hidden but accessible */
@@ -937,7 +1433,7 @@ table {
937
1433
  /* @ui:base prose — typography defaults for long-form content */
938
1434
 
939
1435
  [data-ui="prose"] {
940
- font-family: var(--font-sans);
1436
+ font-family: var(--font-body);
941
1437
  font-size: var(--text-base);
942
1438
  line-height: var(--leading-relaxed);
943
1439
  color: var(--color-fg);
@@ -945,29 +1441,45 @@ table {
945
1441
  }
946
1442
 
947
1443
  [data-ui="prose"] h1 {
1444
+ font-family: var(--font-heading);
948
1445
  font-size: var(--text-4xl);
949
- font-weight: var(--weight-bold);
950
- line-height: var(--leading-tight);
1446
+ font-weight: var(--heading-weight);
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);
951
1451
  margin-block: var(--space-8) var(--space-4);
952
1452
  }
953
1453
 
954
1454
  [data-ui="prose"] h2 {
1455
+ font-family: var(--font-heading);
955
1456
  font-size: var(--text-3xl);
956
1457
  font-weight: var(--weight-semibold);
957
- line-height: var(--leading-tight);
1458
+ letter-spacing: var(--heading-tracking);
1459
+ text-transform: var(--heading-transform);
1460
+ font-variant-caps: var(--heading-caps);
1461
+ line-height: var(--heading-leading);
958
1462
  margin-block: var(--space-8) var(--space-3);
959
1463
  }
960
1464
 
961
1465
  [data-ui="prose"] h3 {
1466
+ font-family: var(--font-heading);
962
1467
  font-size: var(--text-2xl);
963
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);
964
1472
  line-height: var(--leading-snug);
965
1473
  margin-block: var(--space-6) var(--space-3);
966
1474
  }
967
1475
 
968
1476
  [data-ui="prose"] h4 {
1477
+ font-family: var(--font-heading);
969
1478
  font-size: var(--text-xl);
970
1479
  font-weight: var(--weight-semibold);
1480
+ letter-spacing: var(--heading-tracking);
1481
+ text-transform: var(--heading-transform);
1482
+ font-variant-caps: var(--heading-caps);
971
1483
  line-height: var(--leading-snug);
972
1484
  margin-block: var(--space-6) var(--space-2);
973
1485
  }
@@ -978,8 +1490,8 @@ table {
978
1490
 
979
1491
  [data-ui="prose"] a {
980
1492
  color: var(--color-primary);
981
- text-decoration: underline;
982
- text-underline-offset: 2px;
1493
+ text-decoration-line: var(--link-decoration);
1494
+ text-underline-offset: var(--link-underline-offset);
983
1495
  }
984
1496
 
985
1497
  [data-ui="prose"] a:hover {
@@ -1016,7 +1528,7 @@ table {
1016
1528
  }
1017
1529
 
1018
1530
  [data-ui="prose"] blockquote {
1019
- border-inline-start: 3px solid var(--color-border-strong);
1531
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1020
1532
  padding-inline-start: var(--space-4);
1021
1533
  color: var(--color-fg-muted);
1022
1534
  margin-block: var(--space-4);
@@ -1038,9 +1550,15 @@ table {
1038
1550
  margin-block: var(--space-1);
1039
1551
  }
1040
1552
 
1553
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1554
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1555
+ [data-ui="prose"] li::marker {
1556
+ color: var(--marker-color);
1557
+ }
1558
+
1041
1559
  [data-ui="prose"] hr {
1042
1560
  border: none;
1043
- border-block-start: 1px solid var(--color-border);
1561
+ border-block-start: var(--border-width) solid var(--color-border);
1044
1562
  margin-block: var(--space-8);
1045
1563
  }
1046
1564
 
@@ -1059,12 +1577,12 @@ table {
1059
1577
  font-weight: var(--weight-semibold);
1060
1578
  text-align: start;
1061
1579
  padding: var(--space-2) var(--space-3);
1062
- border-block-end: 2px solid var(--color-border-strong);
1580
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1063
1581
  }
1064
1582
 
1065
1583
  [data-ui="prose"] td {
1066
1584
  padding: var(--space-2) var(--space-3);
1067
- border-block-end: 1px solid var(--color-border);
1585
+ border-block-end: var(--border-width) solid var(--color-border);
1068
1586
  }
1069
1587
 
1070
1588
  /* First child no top margin, last child no bottom margin */
@@ -1249,7 +1767,7 @@ table {
1249
1767
 
1250
1768
  /* === primitives/avatar.css === */
1251
1769
  /* @ui:component avatar */
1252
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1770
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1253
1771
 
1254
1772
  /* ── Base ── */
1255
1773
  [data-ui="avatar"] {
@@ -1279,7 +1797,7 @@ table {
1279
1797
  height: 100%;
1280
1798
  background: var(--color-bg-muted);
1281
1799
  color: var(--color-fg-muted);
1282
- font-family: var(--font-sans);
1800
+ font-family: var(--font-ui);
1283
1801
  font-size: var(--text-sm);
1284
1802
  font-weight: var(--weight-medium);
1285
1803
  text-transform: uppercase;
@@ -1304,7 +1822,7 @@ table {
1304
1822
 
1305
1823
  /* === primitives/badge.css === */
1306
1824
  /* @ui:component badge */
1307
- /* @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 */
1825
+ /* @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 */
1308
1826
 
1309
1827
  /* ── Base ── */
1310
1828
  [data-ui="badge"] {
@@ -1314,9 +1832,10 @@ table {
1314
1832
  gap: var(--space-1);
1315
1833
  padding: 0.125rem var(--space-2);
1316
1834
  border-radius: var(--badge-radius, var(--radius-full));
1835
+ corner-shape: var(--corner-shape);
1317
1836
  background: var(--color-bg-muted);
1318
1837
  color: var(--color-fg);
1319
- font-family: var(--badge-font, var(--font-sans));
1838
+ font-family: var(--badge-font, var(--font-ui));
1320
1839
  font-size: var(--text-xs);
1321
1840
  font-weight: var(--weight-medium);
1322
1841
  line-height: 1.5;
@@ -1362,11 +1881,11 @@ table {
1362
1881
 
1363
1882
  /* === primitives/breadcrumb.css === */
1364
1883
  /* @ui:component breadcrumb */
1365
- /* @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 */
1884
+ /* @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 */
1366
1885
 
1367
1886
  /* ── Root ── */
1368
1887
  [data-ui="breadcrumb"] {
1369
- font-family: var(--breadcrumb-font, var(--font-sans));
1888
+ font-family: var(--breadcrumb-font, var(--font-ui));
1370
1889
  font-size: var(--breadcrumb-size, var(--text-sm));
1371
1890
  color: var(--color-fg-muted);
1372
1891
  }
@@ -1392,12 +1911,13 @@ table {
1392
1911
 
1393
1912
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1394
1913
  color: var(--color-primary-hover);
1395
- text-decoration: underline;
1914
+ text-decoration-line: var(--link-decoration);
1396
1915
  }
1397
1916
 
1398
1917
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1399
- outline: 2px solid var(--color-ring);
1400
- outline-offset: 2px;
1918
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1919
+ outline-offset: var(--focus-ring-offset);
1920
+ box-shadow: var(--focus-shadow);
1401
1921
  }
1402
1922
 
1403
1923
  /* ── Separator (presentational) ── */
@@ -1437,7 +1957,7 @@ table {
1437
1957
 
1438
1958
  /* === primitives/button.css === */
1439
1959
  /* @ui:component button */
1440
- /* @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 */
1960
+ /* @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 */
1441
1961
 
1442
1962
  /* ── Base ── */
1443
1963
  [data-ui="button"] {
@@ -1447,18 +1967,21 @@ table {
1447
1967
  gap: var(--space-2);
1448
1968
  height: var(--button-height-md, 40px);
1449
1969
  padding-inline: var(--space-4);
1450
- border: 1px solid var(--color-border);
1970
+ border: var(--border-width) solid var(--color-border);
1451
1971
  border-radius: var(--button-radius, var(--radius-md));
1972
+ corner-shape: var(--corner-shape);
1452
1973
  background: var(--color-bg);
1453
1974
  color: var(--color-fg);
1454
- font-family: var(--font-sans);
1975
+ font-family: var(--font-ui);
1455
1976
  font-size: var(--text-sm);
1456
1977
  font-weight: var(--weight-medium);
1978
+ text-transform: var(--button-text-transform);
1457
1979
  line-height: 1;
1458
1980
  cursor: pointer;
1459
1981
  transition: background var(--duration-fast) var(--ease-default),
1460
1982
  border-color var(--duration-fast) var(--ease-default),
1461
1983
  color var(--duration-fast) var(--ease-default),
1984
+ translate var(--duration-fast) var(--ease-default),
1462
1985
  box-shadow var(--duration-fast) var(--ease-default);
1463
1986
  user-select: none;
1464
1987
  white-space: nowrap;
@@ -1467,11 +1990,16 @@ table {
1467
1990
 
1468
1991
  [data-ui="button"]:hover {
1469
1992
  background: var(--color-bg-muted);
1993
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1994
+ this rule computes what the button computed before the token existed; a
1995
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1996
+ translate: var(--motion-hover-lift);
1470
1997
  }
1471
1998
 
1472
1999
  [data-ui="button"]:focus-visible {
1473
- outline: 2px solid var(--color-ring);
1474
- outline-offset: 2px;
2000
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2001
+ outline-offset: var(--focus-ring-offset);
2002
+ box-shadow: var(--focus-shadow);
1475
2003
  }
1476
2004
 
1477
2005
  /* ── Variants ── */
@@ -1527,7 +2055,7 @@ table {
1527
2055
  padding: 0;
1528
2056
  }
1529
2057
  [data-ui="button"][data-variant="link"]:hover {
1530
- text-decoration: underline;
2058
+ text-decoration-line: var(--link-decoration);
1531
2059
  }
1532
2060
 
1533
2061
  /* ── Sizes ── */
@@ -1546,7 +2074,7 @@ table {
1546
2074
  /* ── States ── */
1547
2075
  [data-ui="button"]:disabled,
1548
2076
  [data-ui="button"][data-state="disabled"] {
1549
- opacity: 0.5;
2077
+ opacity: var(--disabled-opacity);
1550
2078
  cursor: not-allowed;
1551
2079
  pointer-events: none;
1552
2080
  }
@@ -1561,7 +2089,7 @@ table {
1561
2089
  position: absolute;
1562
2090
  width: 1em;
1563
2091
  height: 1em;
1564
- border: 2px solid currentColor;
2092
+ border: var(--border-width-strong) solid currentColor;
1565
2093
  border-inline-end-color: transparent;
1566
2094
  border-radius: var(--radius-full);
1567
2095
  animation: faqir-spin 0.6s linear infinite;
@@ -1608,7 +2136,7 @@ table {
1608
2136
 
1609
2137
  /* === primitives/callout.css === */
1610
2138
  /* @ui:component callout */
1611
- /* @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 */
2139
+ /* @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 */
1612
2140
 
1613
2141
  /* ── Base ── */
1614
2142
  [data-ui="callout"] {
@@ -1617,7 +2145,7 @@ table {
1617
2145
  padding: var(--callout-padding-y) var(--callout-padding-x);
1618
2146
  border-radius: var(--callout-radius);
1619
2147
  border-inline-start: var(--callout-border-left-width) solid;
1620
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2148
+ font-family: var(--doc-font, var(--font-body));
1621
2149
  font-size: var(--callout-font-size);
1622
2150
  line-height: var(--doc-line-height, 1.5);
1623
2151
  }
@@ -1648,6 +2176,7 @@ table {
1648
2176
  /* ── Title ── */
1649
2177
  [data-ui="callout"] [data-part="title"] {
1650
2178
  display: block;
2179
+ font-family: var(--font-heading);
1651
2180
  font-weight: var(--weight-semibold);
1652
2181
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1653
2182
  }
@@ -1674,8 +2203,9 @@ table {
1674
2203
  }
1675
2204
 
1676
2205
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1677
- outline: 2px solid var(--color-ring, var(--color-info));
1678
- outline-offset: 2px;
2206
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2207
+ outline-offset: var(--focus-ring-offset);
2208
+ box-shadow: var(--focus-shadow);
1679
2209
  opacity: 1;
1680
2210
  }
1681
2211
 
@@ -1761,17 +2291,36 @@ table {
1761
2291
 
1762
2292
  /* === primitives/card.css === */
1763
2293
  /* @ui:component card */
1764
- /* @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 */
2294
+ /* @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 */
1765
2295
 
1766
2296
  /* ── Base ── */
1767
2297
  [data-ui="card"] {
1768
2298
  display: flex;
1769
2299
  flex-direction: column;
1770
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2300
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1771
2301
  border-radius: var(--card-radius, var(--radius-lg));
1772
- background: var(--card-bg, var(--color-surface-1));
2302
+ corner-shape: var(--corner-shape);
2303
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2304
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2305
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2306
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1773
2307
  box-shadow: var(--card-shadow, var(--shadow-sm));
1774
2308
  overflow: hidden;
2309
+ transition: translate var(--duration-fast) var(--ease-default);
2310
+ }
2311
+
2312
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2313
+ value of `translate`), so a card sits exactly where it always sat until a
2314
+ theme says surfaces rise under the pointer. */
2315
+ [data-ui="card"]:hover {
2316
+ translate: var(--motion-hover-lift);
2317
+ }
2318
+
2319
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2320
+ [data-ui="card"] {
2321
+ -webkit-backdrop-filter: var(--surface-backdrop);
2322
+ backdrop-filter: var(--surface-backdrop);
2323
+ }
1775
2324
  }
1776
2325
 
1777
2326
  /* ── Variants ── */
@@ -1780,7 +2329,7 @@ table {
1780
2329
  }
1781
2330
 
1782
2331
  [data-ui="card"][data-variant="filled"] {
1783
- background: var(--color-surface-2);
2332
+ background: var(--texture-surface), var(--color-surface-2);
1784
2333
  border-color: var(--color-surface-2-border);
1785
2334
  box-shadow: none;
1786
2335
  }
@@ -1795,7 +2344,7 @@ table {
1795
2344
  }
1796
2345
 
1797
2346
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1798
- font-family: var(--font-sans);
2347
+ font-family: var(--font-heading);
1799
2348
  font-size: var(--text-lg);
1800
2349
  font-weight: var(--weight-semibold);
1801
2350
  line-height: var(--leading-tight);
@@ -1836,9 +2385,19 @@ table {
1836
2385
  padding-top: 0;
1837
2386
  }
1838
2387
 
2388
+ /* ── Motion ── */
2389
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2390
+ theme states one — but the house rule is that a stylesheet which transitions
2391
+ carries its own opt-out, so a reader never has to check the token first. */
2392
+ @media (prefers-reduced-motion: reduce) {
2393
+ [data-ui="card"] {
2394
+ transition: none;
2395
+ }
2396
+ }
2397
+
1839
2398
  /* === primitives/checkbox.css === */
1840
2399
  /* @ui:component checkbox */
1841
- /* @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 */
2400
+ /* @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 */
1842
2401
 
1843
2402
  /* -- Label wrapper -- */
1844
2403
  [data-ui="checkbox-label"] {
@@ -1850,7 +2409,7 @@ table {
1850
2409
 
1851
2410
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1852
2411
  cursor: not-allowed;
1853
- opacity: 0.5;
2412
+ opacity: var(--disabled-opacity);
1854
2413
  }
1855
2414
 
1856
2415
  /* -- Base -- */
@@ -1862,8 +2421,8 @@ table {
1862
2421
  width: var(--checkbox-size, 18px);
1863
2422
  height: var(--checkbox-size, 18px);
1864
2423
  flex-shrink: 0;
1865
- border: 1px solid var(--color-border);
1866
- border-radius: var(--checkbox-radius, var(--radius-sm));
2424
+ border: var(--border-width) solid var(--color-border);
2425
+ border-radius: var(--checkbox-radius);
1867
2426
  background: var(--color-bg);
1868
2427
  cursor: pointer;
1869
2428
  transition: background var(--duration-fast) var(--ease-default),
@@ -1876,8 +2435,9 @@ table {
1876
2435
  }
1877
2436
 
1878
2437
  [data-ui="checkbox"]:focus-visible {
1879
- outline: 2px solid var(--color-ring);
1880
- outline-offset: 2px;
2438
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2439
+ outline-offset: var(--focus-ring-offset);
2440
+ box-shadow: var(--focus-shadow);
1881
2441
  }
1882
2442
 
1883
2443
  /* -- Checked -- */
@@ -1968,7 +2528,7 @@ table {
1968
2528
  The mask has to opt out of the substitution to stay readable. [W3-3] */
1969
2529
  @media (forced-colors: active) {
1970
2530
  [data-ui="checkbox"] {
1971
- border: 1px solid ButtonText;
2531
+ border: var(--border-width) solid ButtonText;
1972
2532
  }
1973
2533
 
1974
2534
  [data-ui="checkbox"]:checked,
@@ -1992,7 +2552,7 @@ table {
1992
2552
 
1993
2553
  /* === primitives/chip.css === */
1994
2554
  /* @ui:component chip */
1995
- /* @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 */
2555
+ /* @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 */
1996
2556
 
1997
2557
  /* ── Base ── */
1998
2558
  [data-ui="chip"] {
@@ -2000,11 +2560,11 @@ table {
2000
2560
  align-items: center;
2001
2561
  gap: var(--space-1);
2002
2562
  padding: var(--space-1) var(--space-2);
2003
- border: 1px solid transparent;
2563
+ border: var(--border-width) solid transparent;
2004
2564
  border-radius: var(--chip-radius, var(--radius-full));
2005
2565
  background: var(--color-bg-muted);
2006
2566
  color: var(--color-fg);
2007
- font-family: var(--chip-font, var(--font-sans));
2567
+ font-family: var(--chip-font, var(--font-ui));
2008
2568
  font-size: var(--text-sm);
2009
2569
  font-weight: var(--weight-medium);
2010
2570
  line-height: 1.2;
@@ -2040,8 +2600,11 @@ table {
2040
2600
  }
2041
2601
 
2042
2602
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2043
- outline: 2px solid var(--color-ring);
2044
- outline-offset: 1px;
2603
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2604
+ /* Half the default gap — the dismiss target is small, and the full ring
2605
+ would collide with the chip's own edge. */
2606
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2607
+ box-shadow: var(--focus-shadow);
2045
2608
  }
2046
2609
 
2047
2610
  /* ── Variants ── */
@@ -2264,12 +2827,12 @@ table {
2264
2827
 
2265
2828
  /* === primitives/collapsible.css === */
2266
2829
  /* @ui:component collapsible */
2267
- /* @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 */
2830
+ /* @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 */
2268
2831
 
2269
2832
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2270
2833
  [data-ui="collapsible"] {
2271
2834
  border-radius: var(--collapsible-radius, var(--radius-md));
2272
- font-family: var(--collapsible-font, var(--font-sans));
2835
+ font-family: var(--collapsible-font, var(--font-ui));
2273
2836
  color: var(--color-fg);
2274
2837
  }
2275
2838
 
@@ -2299,8 +2862,9 @@ table {
2299
2862
  }
2300
2863
 
2301
2864
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2302
- outline: 2px solid var(--color-ring);
2303
- outline-offset: 2px;
2865
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2866
+ outline-offset: var(--focus-ring-offset);
2867
+ box-shadow: var(--focus-shadow);
2304
2868
  }
2305
2869
 
2306
2870
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2309,8 +2873,8 @@ table {
2309
2873
  flex: none;
2310
2874
  width: 0.5em;
2311
2875
  height: 0.5em;
2312
- border-inline-end: 2px solid var(--color-fg-muted);
2313
- border-block-end: 2px solid var(--color-fg-muted);
2876
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2877
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2314
2878
  transform: rotate(45deg);
2315
2879
  transition: transform var(--duration-normal) var(--ease-default);
2316
2880
  }
@@ -2329,7 +2893,7 @@ table {
2329
2893
 
2330
2894
  /* ── Bordered variant ── */
2331
2895
  [data-ui="collapsible"][data-variant="bordered"] {
2332
- border: 1px solid var(--color-border);
2896
+ border: var(--border-width) solid var(--color-border);
2333
2897
  }
2334
2898
 
2335
2899
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2462,13 +3026,13 @@ table {
2462
3026
 
2463
3027
  /* === primitives/description-list.css === */
2464
3028
  /* @ui:component description-list */
2465
- /* @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 */
3029
+ /* @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 */
2466
3030
 
2467
3031
  /* ── Base ── */
2468
3032
  [data-ui="description-list"] {
2469
3033
  margin: 0;
2470
3034
  padding: 0;
2471
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3035
+ font-family: var(--doc-font, var(--font-body));
2472
3036
  }
2473
3037
 
2474
3038
  /* ── Term ── */
@@ -2524,7 +3088,7 @@ table {
2524
3088
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2525
3089
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2526
3090
  padding-bottom: var(--space-4);
2527
- border-bottom: 1px solid var(--color-border);
3091
+ border-bottom: var(--border-width) solid var(--color-border);
2528
3092
  }
2529
3093
 
2530
3094
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2536,7 +3100,7 @@ table {
2536
3100
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2537
3101
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2538
3102
  padding-bottom: var(--space-3);
2539
- border-bottom: 1px solid var(--color-border);
3103
+ border-bottom: var(--border-width) solid var(--color-border);
2540
3104
  }
2541
3105
 
2542
3106
  /* ── Size: Small ── */
@@ -2574,7 +3138,7 @@ table {
2574
3138
 
2575
3139
  /* === primitives/empty-state.css === */
2576
3140
  /* @ui:component empty-state */
2577
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3141
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2578
3142
 
2579
3143
  /* ── Base ── */
2580
3144
  [data-ui="empty-state"] {
@@ -2595,6 +3159,7 @@ table {
2595
3159
 
2596
3160
  /* ── Title ── */
2597
3161
  [data-ui="empty-state"] [data-part="title"] {
3162
+ font-family: var(--font-heading);
2598
3163
  font-size: var(--text-lg);
2599
3164
  font-weight: var(--weight-medium);
2600
3165
  color: var(--color-fg);
@@ -2642,7 +3207,7 @@ table {
2642
3207
 
2643
3208
  /* === primitives/field-group.css === */
2644
3209
  /* @ui:component field-group */
2645
- /* @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 */
3210
+ /* @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 */
2646
3211
 
2647
3212
  /* ── Base / spacing ownership ──
2648
3213
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2654,7 +3219,7 @@ table {
2654
3219
  display: flex;
2655
3220
  flex-direction: column;
2656
3221
  gap: var(--space-2);
2657
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3222
+ font-family: var(--doc-font, var(--font-body));
2658
3223
  }
2659
3224
 
2660
3225
  /* ── Label ── */
@@ -2724,7 +3289,7 @@ table {
2724
3289
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2725
3290
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2726
3291
  border-color: var(--field-error-color);
2727
- box-shadow: 0 0 0 1px var(--field-error-color);
3292
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2728
3293
  }
2729
3294
 
2730
3295
  /* ── State: Validating ──
@@ -2734,7 +3299,7 @@ table {
2734
3299
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2735
3300
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2736
3301
  border-color: var(--field-validating-color);
2737
- box-shadow: 0 0 0 1px var(--field-validating-color);
3302
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2738
3303
  }
2739
3304
 
2740
3305
  /* ── State: Disabled ──
@@ -2753,8 +3318,8 @@ table {
2753
3318
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2754
3319
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2755
3320
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2756
- border-color: var(--color-success, oklch(0.62 0.19 145));
2757
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3321
+ border-color: var(--color-success);
3322
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2758
3323
  }
2759
3324
 
2760
3325
  /* ── Variant: Horizontal ── */
@@ -3059,7 +3624,7 @@ table {
3059
3624
 
3060
3625
  /* === primitives/image.css === */
3061
3626
  /* @ui:component image */
3062
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3627
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3063
3628
 
3064
3629
  /* ── Base ── */
3065
3630
  [data-ui="image"] {
@@ -3083,7 +3648,7 @@ table {
3083
3648
  [data-ui="image"] [data-part="caption"] {
3084
3649
  display: block;
3085
3650
  margin-top: var(--space-2);
3086
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3651
+ font-family: var(--doc-font, var(--font-body));
3087
3652
  font-size: var(--image-caption-size);
3088
3653
  color: var(--image-caption-color);
3089
3654
  line-height: 1.4;
@@ -3180,7 +3745,7 @@ table {
3180
3745
 
3181
3746
  /* === primitives/input.css === */
3182
3747
  /* @ui:component input */
3183
- /* @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 */
3748
+ /* @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 */
3184
3749
 
3185
3750
  /* ── Base ── */
3186
3751
  [data-ui="input"] {
@@ -3188,11 +3753,18 @@ table {
3188
3753
  width: 100%;
3189
3754
  height: var(--input-height, 40px);
3190
3755
  padding-inline: var(--space-3);
3191
- border: 1px solid var(--color-border);
3756
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3757
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3758
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3759
+ is drawn. Identical to the shorthand at every other value of the token. */
3760
+ border-style: solid;
3761
+ border-color: var(--color-border);
3762
+ border-width: var(--input-border-width);
3192
3763
  border-radius: var(--input-radius, var(--radius-md));
3193
- background: var(--input-bg, var(--color-bg));
3764
+ corner-shape: var(--corner-shape);
3765
+ background: var(--input-fill);
3194
3766
  color: var(--color-fg);
3195
- font-family: var(--input-font, var(--font-sans));
3767
+ font-family: var(--input-font, var(--font-ui));
3196
3768
  font-size: var(--text-sm);
3197
3769
  line-height: 1;
3198
3770
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3208,8 +3780,11 @@ table {
3208
3780
  }
3209
3781
 
3210
3782
  [data-ui="input"]:focus {
3211
- outline: 2px solid var(--color-ring);
3212
- outline-offset: -1px;
3783
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3784
+ /* The ring replaces the border rather than sitting outside it: inset by
3785
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3786
+ outline-offset: calc(-1 * var(--input-border-width));
3787
+ box-shadow: var(--focus-shadow);
3213
3788
  border-color: transparent;
3214
3789
  }
3215
3790
 
@@ -3237,7 +3812,7 @@ table {
3237
3812
  }
3238
3813
 
3239
3814
  [data-ui="input"]:disabled {
3240
- opacity: 0.5;
3815
+ opacity: var(--disabled-opacity);
3241
3816
  cursor: not-allowed;
3242
3817
  }
3243
3818
 
@@ -3300,7 +3875,7 @@ table {
3300
3875
 
3301
3876
  /* === primitives/kbd.css === */
3302
3877
  /* @ui:component kbd */
3303
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3878
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3304
3879
 
3305
3880
  /* ── Base ── */
3306
3881
  [data-ui="kbd"] {
@@ -3310,8 +3885,8 @@ table {
3310
3885
  height: 20px;
3311
3886
  min-width: 20px;
3312
3887
  padding-inline: var(--space-1h);
3313
- border: 1px solid var(--color-border);
3314
- border-bottom-width: 2px;
3888
+ border: var(--border-width) solid var(--color-border);
3889
+ border-bottom-width: var(--border-width-strong);
3315
3890
  border-radius: var(--radius-sm);
3316
3891
  background: var(--color-bg-subtle);
3317
3892
  color: var(--color-fg);
@@ -3324,7 +3899,7 @@ table {
3324
3899
 
3325
3900
  /* === primitives/key-value.css === */
3326
3901
  /* @ui:component key-value */
3327
- /* @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 */
3902
+ /* @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 */
3328
3903
 
3329
3904
  /* ── Base ── */
3330
3905
  [data-ui="key-value"] {
@@ -3333,7 +3908,7 @@ table {
3333
3908
  gap: var(--kv-pair-gap);
3334
3909
  margin: 0;
3335
3910
  padding: 0;
3336
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3911
+ font-family: var(--doc-font, var(--font-body));
3337
3912
  }
3338
3913
 
3339
3914
  /* ── Label ── */
@@ -3463,12 +4038,12 @@ table {
3463
4038
 
3464
4039
  /* === primitives/label.css === */
3465
4040
  /* @ui:component label */
3466
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4041
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3467
4042
 
3468
4043
  /* ── Base ── */
3469
4044
  [data-ui="label"] {
3470
4045
  display: block;
3471
- font-family: var(--font-sans);
4046
+ font-family: var(--font-ui);
3472
4047
  font-size: var(--text-sm);
3473
4048
  font-weight: var(--weight-medium);
3474
4049
  color: var(--color-fg);
@@ -3501,21 +4076,21 @@ table {
3501
4076
 
3502
4077
  /* ── States ── */
3503
4078
  [data-ui="label"][data-state="disabled"] {
3504
- opacity: 0.5;
4079
+ opacity: var(--disabled-opacity);
3505
4080
  cursor: not-allowed;
3506
4081
  }
3507
4082
 
3508
4083
  /* === primitives/link.css === */
3509
4084
  /* @ui:component link */
3510
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4085
+ /* @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 */
3511
4086
 
3512
4087
  /* ── Base ── */
3513
4088
  [data-ui="link"] {
3514
4089
  color: var(--color-primary);
3515
4090
  font-family: inherit;
3516
- text-decoration: underline;
3517
- text-decoration-thickness: 1px;
3518
- text-underline-offset: 0.2em;
4091
+ text-decoration-line: var(--link-decoration);
4092
+ text-decoration-thickness: var(--link-thickness);
4093
+ text-underline-offset: var(--link-underline-offset);
3519
4094
  border-radius: var(--radius-sm);
3520
4095
  cursor: pointer;
3521
4096
  }
@@ -3529,8 +4104,9 @@ table {
3529
4104
  }
3530
4105
 
3531
4106
  [data-ui="link"]:focus-visible {
3532
- outline: 2px solid var(--color-ring);
3533
- outline-offset: 2px;
4107
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4108
+ outline-offset: var(--focus-ring-offset);
4109
+ box-shadow: var(--focus-shadow);
3534
4110
  }
3535
4111
 
3536
4112
  /* ── Variants ── */
@@ -3554,7 +4130,7 @@ table {
3554
4130
 
3555
4131
  /* === primitives/nav.css === */
3556
4132
  /* @ui:component nav */
3557
- /* @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 */
4133
+ /* @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 */
3558
4134
 
3559
4135
  /* ── Base ── */
3560
4136
  [data-ui="nav"] {
@@ -3604,14 +4180,14 @@ table {
3604
4180
 
3605
4181
  /* ── Underline variant ── */
3606
4182
  [data-ui="nav"][data-variant="underline"] {
3607
- border-bottom: 1px solid var(--color-border);
4183
+ border-bottom: var(--border-width) solid var(--color-border);
3608
4184
  gap: 0;
3609
4185
  }
3610
4186
 
3611
4187
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3612
4188
  border-radius: 0;
3613
4189
  padding: var(--space-2) var(--space-4);
3614
- border-bottom: 2px solid transparent;
4190
+ border-bottom: var(--border-width-strong) solid transparent;
3615
4191
  margin-bottom: -1px;
3616
4192
  }
3617
4193
 
@@ -3667,7 +4243,7 @@ table {
3667
4243
 
3668
4244
  /* === primitives/page-break.css === */
3669
4245
  /* @ui:component page-break */
3670
- /* @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 */
4246
+ /* @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 */
3671
4247
 
3672
4248
  /* ── Base (Screen) ── */
3673
4249
  [data-ui="page-break"] {
@@ -3682,12 +4258,12 @@ table {
3682
4258
  [data-ui="page-break"]::after {
3683
4259
  content: "";
3684
4260
  flex: 1;
3685
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4261
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3686
4262
  }
3687
4263
 
3688
4264
  /* ── Label (Screen) ── */
3689
4265
  [data-ui="page-break"] {
3690
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4266
+ font-family: var(--doc-font, var(--font-body));
3691
4267
  font-size: var(--page-break-screen-label-size);
3692
4268
  color: var(--page-break-screen-label-color);
3693
4269
  letter-spacing: 0.05em;
@@ -3729,7 +4305,7 @@ table {
3729
4305
 
3730
4306
  /* === primitives/progress.css === */
3731
4307
  /* @ui:component progress */
3732
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4308
+ /* @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 */
3733
4309
 
3734
4310
  /* ── Base ── */
3735
4311
  [data-ui="progress"] {
@@ -3804,7 +4380,7 @@ table {
3804
4380
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3805
4381
  @media (forced-colors: active) {
3806
4382
  [data-ui="progress"] [data-part="track"] {
3807
- border: 1px solid ButtonText;
4383
+ border: var(--border-width) solid ButtonText;
3808
4384
  }
3809
4385
 
3810
4386
  [data-ui="progress"] [data-part="fill"],
@@ -3818,7 +4394,7 @@ table {
3818
4394
 
3819
4395
  /* === primitives/radio.css === */
3820
4396
  /* @ui:component radio */
3821
- /* @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 */
4397
+ /* @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 */
3822
4398
 
3823
4399
  /* -- Radio group -- */
3824
4400
  [data-ui="radio-group"] {
@@ -3840,7 +4416,7 @@ table {
3840
4416
 
3841
4417
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3842
4418
  cursor: not-allowed;
3843
- opacity: 0.5;
4419
+ opacity: var(--disabled-opacity);
3844
4420
  }
3845
4421
 
3846
4422
  /* -- Base -- */
@@ -3852,7 +4428,7 @@ table {
3852
4428
  width: var(--radio-size, 18px);
3853
4429
  height: var(--radio-size, 18px);
3854
4430
  flex-shrink: 0;
3855
- border: 1px solid var(--color-border);
4431
+ border: var(--border-width) solid var(--color-border);
3856
4432
  border-radius: var(--radius-full);
3857
4433
  background: var(--color-bg);
3858
4434
  cursor: pointer;
@@ -3866,8 +4442,9 @@ table {
3866
4442
  }
3867
4443
 
3868
4444
  [data-ui="radio"]:focus-visible {
3869
- outline: 2px solid var(--color-ring);
3870
- outline-offset: 2px;
4445
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4446
+ outline-offset: var(--focus-ring-offset);
4447
+ box-shadow: var(--focus-shadow);
3871
4448
  }
3872
4449
 
3873
4450
  /* -- Checked -- */
@@ -3920,7 +4497,7 @@ table {
3920
4497
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3921
4498
  @media (forced-colors: active) {
3922
4499
  [data-ui="radio"] {
3923
- border: 1px solid ButtonText;
4500
+ border: var(--border-width) solid ButtonText;
3924
4501
  }
3925
4502
 
3926
4503
  [data-ui="radio"]:checked {
@@ -3940,7 +4517,7 @@ table {
3940
4517
 
3941
4518
  /* === primitives/select.css === */
3942
4519
  /* @ui:component select */
3943
- /* @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 */
4520
+ /* @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 */
3944
4521
 
3945
4522
  /* -- Base -- */
3946
4523
  [data-ui="select"] {
@@ -3949,11 +4526,17 @@ table {
3949
4526
  height: var(--select-height, 40px);
3950
4527
  padding-inline: var(--space-3);
3951
4528
  padding-inline-end: var(--space-8, 2rem);
3952
- border: 1px solid var(--color-border);
4529
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4530
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4531
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4532
+ is drawn. Identical to the shorthand at every other value of the token. */
4533
+ border-style: solid;
4534
+ border-color: var(--color-border);
4535
+ border-width: var(--input-border-width);
3953
4536
  border-radius: var(--select-radius, var(--radius-md));
3954
- background: var(--select-bg, var(--color-bg));
4537
+ background: var(--select-bg, var(--input-fill));
3955
4538
  color: var(--color-fg);
3956
- font-family: var(--select-font, var(--font-sans));
4539
+ font-family: var(--select-font, var(--font-ui));
3957
4540
  font-size: var(--text-sm);
3958
4541
  line-height: 1;
3959
4542
  cursor: pointer;
@@ -3983,8 +4566,11 @@ table {
3983
4566
  }
3984
4567
 
3985
4568
  [data-ui="select"]:focus {
3986
- outline: 2px solid var(--color-ring);
3987
- outline-offset: -1px;
4569
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4570
+ /* The ring replaces the border rather than sitting outside it: inset by
4571
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4572
+ outline-offset: calc(-1 * var(--input-border-width));
4573
+ box-shadow: var(--focus-shadow);
3988
4574
  border-color: transparent;
3989
4575
  }
3990
4576
 
@@ -4017,7 +4603,7 @@ table {
4017
4603
  }
4018
4604
 
4019
4605
  [data-ui="select"]:disabled {
4020
- opacity: 0.5;
4606
+ opacity: var(--disabled-opacity);
4021
4607
  cursor: not-allowed;
4022
4608
  }
4023
4609
 
@@ -4030,12 +4616,12 @@ table {
4030
4616
 
4031
4617
  /* === primitives/separator.css === */
4032
4618
  /* @ui:component separator */
4033
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4619
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4034
4620
 
4035
4621
  /* ── Base (horizontal) ── */
4036
4622
  [data-ui="separator"] {
4037
4623
  border: none;
4038
- border-top: 1px solid var(--color-border);
4624
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4039
4625
  margin: 0;
4040
4626
  width: 100%;
4041
4627
  }
@@ -4043,7 +4629,7 @@ table {
4043
4629
  /* ── Vertical ── */
4044
4630
  [data-ui="separator"][data-variant="vertical"] {
4045
4631
  border-top: none;
4046
- border-inline-start: 1px solid var(--color-border);
4632
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4047
4633
  width: auto;
4048
4634
  height: 100%;
4049
4635
  align-self: stretch;
@@ -4061,11 +4647,11 @@ div[data-ui="separator"]::before,
4061
4647
  div[data-ui="separator"]::after {
4062
4648
  content: "";
4063
4649
  flex: 1;
4064
- border-top: 1px solid var(--color-border);
4650
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4065
4651
  }
4066
4652
 
4067
4653
  [data-ui="separator"] [data-part="label"] {
4068
- font-family: var(--font-sans);
4654
+ font-family: var(--font-ui);
4069
4655
  font-size: var(--text-xs);
4070
4656
  color: var(--color-fg-muted);
4071
4657
  white-space: nowrap;
@@ -4103,17 +4689,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4103
4689
 
4104
4690
  /* ── Style: Thick ── */
4105
4691
  [data-ui="separator"][data-style="thick"] {
4106
- border-top-width: 2px;
4692
+ border-top-width: var(--border-width-strong);
4107
4693
  }
4108
4694
 
4109
4695
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4110
4696
  border-top-width: 0;
4111
- border-inline-start-width: 2px;
4697
+ border-inline-start-width: var(--border-width-strong);
4112
4698
  }
4113
4699
 
4114
4700
  div[data-ui="separator"][data-style="thick"]::before,
4115
4701
  div[data-ui="separator"][data-style="thick"]::after {
4116
- border-top-width: 2px;
4702
+ border-top-width: var(--border-width-strong);
4117
4703
  }
4118
4704
 
4119
4705
  /* ── Vertical Sizes ── */
@@ -4131,20 +4717,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4131
4717
 
4132
4718
  /* === primitives/signature.css === */
4133
4719
  /* @ui:component signature */
4134
- /* @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 */
4720
+ /* @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 */
4135
4721
 
4136
4722
  /* ── Base ── */
4137
4723
  [data-ui="signature"] {
4138
4724
  display: flex;
4139
4725
  flex-direction: column;
4140
4726
  gap: var(--space-2);
4141
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4727
+ font-family: var(--doc-font, var(--font-body));
4142
4728
  margin-top: var(--doc-signature-gap);
4143
4729
  }
4144
4730
 
4145
4731
  /* ── Line ── */
4146
4732
  [data-ui="signature"] [data-part="line"] {
4147
- border-top: 1px solid var(--doc-signature-line-color);
4733
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4148
4734
  min-height: 1px;
4149
4735
  }
4150
4736
 
@@ -4247,14 +4833,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4247
4833
 
4248
4834
  /* === primitives/spinner.css === */
4249
4835
  /* @ui:component spinner */
4250
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4836
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4251
4837
 
4252
4838
  /* ── Base ── */
4253
4839
  [data-ui="spinner"] {
4254
4840
  display: inline-block;
4255
4841
  width: 24px;
4256
4842
  height: 24px;
4257
- border: 2px solid var(--color-border);
4843
+ border: var(--border-width-strong) solid var(--color-border);
4258
4844
  border-top-color: var(--color-primary);
4259
4845
  border-radius: var(--radius-full);
4260
4846
  animation: faqir-spin 0.75s linear infinite;
@@ -4270,13 +4856,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4270
4856
  [data-ui="spinner"][data-size="lg"] {
4271
4857
  width: 32px;
4272
4858
  height: 32px;
4273
- border-width: 3px;
4859
+ border-width: var(--border-width-lg);
4274
4860
  }
4275
4861
 
4276
4862
  [data-ui="spinner"][data-size="xl"] {
4277
4863
  width: 48px;
4278
4864
  height: 48px;
4279
- border-width: 3px;
4865
+ border-width: var(--border-width-lg);
4280
4866
  }
4281
4867
 
4282
4868
  /* ── Motion ── */
@@ -4858,14 +5444,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4858
5444
 
4859
5445
  /* === primitives/stat.css === */
4860
5446
  /* @ui:component stat */
4861
- /* @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 */
5447
+ /* @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 */
4862
5448
 
4863
5449
  /* ── Base ── */
4864
5450
  [data-ui="stat"] {
4865
5451
  display: flex;
4866
5452
  flex-direction: column;
4867
5453
  gap: var(--space-1);
4868
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5454
+ font-family: var(--doc-font, var(--font-body));
4869
5455
  }
4870
5456
 
4871
5457
  /* ── Label ── */
@@ -4879,6 +5465,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4879
5465
 
4880
5466
  /* ── Value ── */
4881
5467
  [data-ui="stat"] [data-part="value"] {
5468
+ font-family: var(--font-heading);
4882
5469
  font-size: var(--stat-value-size);
4883
5470
  font-weight: var(--stat-value-weight);
4884
5471
  color: var(--color-fg);
@@ -4937,10 +5524,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4937
5524
  /* ── Variant: Card ── */
4938
5525
  [data-ui="stat"][data-variant="card"] {
4939
5526
  padding: var(--space-4);
4940
- border: 1px solid var(--color-border);
5527
+ border: var(--border-width) solid var(--color-border);
4941
5528
  border-radius: var(--radius-md, 0.375rem);
4942
5529
  background: var(--color-bg);
4943
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5530
+ box-shadow: var(--shadow-sm);
4944
5531
  }
4945
5532
 
4946
5533
  /* ── Value + Change Inline ── */
@@ -4952,7 +5539,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4952
5539
  @media print {
4953
5540
  [data-ui="stat"][data-variant="card"] {
4954
5541
  box-shadow: none;
4955
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5542
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
4956
5543
  }
4957
5544
 
4958
5545
  [data-ui="stat"] {
@@ -4962,7 +5549,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4962
5549
 
4963
5550
  /* === primitives/stepper.css === */
4964
5551
  /* @ui:component stepper */
4965
- /* @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 */
5552
+ /* @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 */
4966
5553
 
4967
5554
  /* ── Base ── */
4968
5555
  [data-ui="stepper"] {
@@ -5041,7 +5628,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5041
5628
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5042
5629
  [data-ui="stepper"] [data-part="connector"] {
5043
5630
  flex: 1;
5044
- height: 2px;
5631
+ height: var(--border-width-strong);
5045
5632
  background: var(--color-border);
5046
5633
  margin: 0 var(--space-1);
5047
5634
  min-width: var(--space-2);
@@ -5109,18 +5696,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5109
5696
 
5110
5697
  /* === primitives/surface.css === */
5111
5698
  /* @ui:component surface */
5112
- /* @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 */
5699
+ /* @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 */
5113
5700
 
5114
5701
  /* ── Base ── */
5115
5702
  [data-ui="surface"] {
5116
- background: var(--color-surface-1);
5703
+ background-color: var(--color-surface-1);
5704
+ background-image: var(--texture-surface);
5117
5705
  border-radius: var(--radius-lg);
5118
- border: 1px solid var(--color-surface-1-border);
5706
+ corner-shape: var(--corner-shape);
5707
+ border: var(--border-width) solid var(--color-surface-1-border);
5119
5708
  }
5120
5709
 
5121
5710
  /* ── Elevation Variants ── */
5122
5711
  [data-ui="surface"][data-variant="flat"] {
5123
- background: var(--color-bg);
5712
+ background-color: var(--color-bg);
5124
5713
  border: none;
5125
5714
  box-shadow: none;
5126
5715
  }
@@ -5130,11 +5719,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5130
5719
  }
5131
5720
 
5132
5721
  [data-ui="surface"][data-variant="overlay"] {
5133
- background: var(--color-surface-2);
5722
+ background-color: var(--color-surface-2);
5134
5723
  box-shadow: var(--shadow-lg);
5135
5724
  border-color: var(--color-surface-2-border);
5136
5725
  }
5137
5726
 
5727
+ /* An overlay is the one surface variant that floats over other content, so it
5728
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5729
+ its own: a browser without backdrop-filter renders the solid surface above
5730
+ and never sees this rule. */
5731
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5732
+ [data-ui="surface"][data-variant="overlay"] {
5733
+ -webkit-backdrop-filter: var(--surface-backdrop);
5734
+ backdrop-filter: var(--surface-backdrop);
5735
+ }
5736
+ }
5737
+
5138
5738
  /* ── Padding Sizes ── */
5139
5739
  [data-ui="surface"][data-size="sm"] {
5140
5740
  padding: var(--space-3);
@@ -5190,7 +5790,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5190
5790
 
5191
5791
  /* === primitives/switch.css === */
5192
5792
  /* @ui:component switch */
5193
- /* @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 */
5793
+ /* @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 */
5194
5794
 
5195
5795
  /* -- Label wrapper -- */
5196
5796
  [data-ui="switch-label"] {
@@ -5202,7 +5802,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5202
5802
 
5203
5803
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5204
5804
  cursor: not-allowed;
5205
- opacity: 0.5;
5805
+ opacity: var(--disabled-opacity);
5206
5806
  }
5207
5807
 
5208
5808
  /* -- Base (track) -- */
@@ -5230,8 +5830,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5230
5830
  width: var(--switch-width, 44px);
5231
5831
  height: var(--switch-height, 24px);
5232
5832
  padding: var(--space-0h, 2px);
5233
- border: 1px solid var(--color-border);
5234
- border-radius: var(--radius-full);
5833
+ border: var(--border-width) solid var(--color-border);
5834
+ border-radius: var(--switch-radius);
5235
5835
  background: var(--switch-bg, var(--color-bg-muted));
5236
5836
  cursor: pointer;
5237
5837
  position: relative;
@@ -5241,8 +5841,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5241
5841
  }
5242
5842
 
5243
5843
  [data-ui="switch"]:focus-visible {
5244
- outline: 2px solid var(--color-ring);
5245
- outline-offset: 2px;
5844
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5845
+ outline-offset: var(--focus-ring-offset);
5846
+ box-shadow: var(--focus-shadow);
5246
5847
  }
5247
5848
 
5248
5849
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5251,7 +5852,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5251
5852
  display: block;
5252
5853
  width: var(--switch-thumb, 18px);
5253
5854
  height: var(--switch-thumb, 18px);
5254
- border-radius: var(--radius-full);
5855
+ border-radius: var(--switch-radius);
5255
5856
  background: var(--color-primary-fg);
5256
5857
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5257
5858
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5263,7 +5864,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5263
5864
  display: block;
5264
5865
  width: var(--switch-thumb, 18px);
5265
5866
  height: var(--switch-thumb, 18px);
5266
- border-radius: var(--radius-full);
5867
+ border-radius: var(--switch-radius);
5267
5868
  background: var(--color-primary-fg);
5268
5869
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5269
5870
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5345,7 +5946,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5345
5946
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5346
5947
  @media (forced-colors: active) {
5347
5948
  [data-ui="switch"] {
5348
- border: 1px solid ButtonText;
5949
+ border: var(--border-width) solid ButtonText;
5349
5950
  background: ButtonFace;
5350
5951
  }
5351
5952
 
@@ -5502,25 +6103,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5502
6103
 
5503
6104
  /* === primitives/text.css === */
5504
6105
  /* @ui:component text */
5505
- /* @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 */
6106
+ /* @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 */
5506
6107
 
5507
6108
  /* ── Heading ── */
5508
6109
  [data-ui="heading"] {
5509
- font-family: var(--font-sans);
5510
- font-weight: var(--weight-bold);
6110
+ font-family: var(--font-heading);
6111
+ font-weight: var(--heading-weight);
5511
6112
  color: var(--color-fg);
5512
- line-height: var(--leading-tight);
5513
- letter-spacing: -0.01em;
6113
+ line-height: var(--heading-leading);
6114
+ text-transform: var(--heading-transform);
6115
+ font-variant-caps: var(--heading-caps);
6116
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6117
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6118
+ headings sets --heading-tracking once and every size follows, instead of
6119
+ each size having to re-derive its own number. */
6120
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5514
6121
  }
5515
6122
 
5516
6123
  [data-ui="heading"][data-size="1"] {
5517
6124
  font-size: var(--text-4xl);
5518
- letter-spacing: -0.02em;
6125
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5519
6126
  }
5520
6127
 
5521
6128
  [data-ui="heading"][data-size="2"] {
5522
6129
  font-size: var(--text-3xl);
5523
- letter-spacing: -0.02em;
6130
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5524
6131
  }
5525
6132
 
5526
6133
  [data-ui="heading"][data-size="3"] {
@@ -5544,7 +6151,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5544
6151
 
5545
6152
  /* ── Text ── */
5546
6153
  [data-ui="text"] {
5547
- font-family: var(--font-sans);
6154
+ font-family: var(--font-body);
5548
6155
  color: var(--color-fg);
5549
6156
  }
5550
6157
 
@@ -5622,7 +6229,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5622
6229
 
5623
6230
  /* === primitives/textarea.css === */
5624
6231
  /* @ui:component textarea */
5625
- /* @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 */
6232
+ /* @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 */
5626
6233
 
5627
6234
  /* -- Base -- */
5628
6235
  [data-ui="textarea"] {
@@ -5630,11 +6237,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5630
6237
  width: 100%;
5631
6238
  min-height: var(--textarea-min-height, 80px);
5632
6239
  padding: var(--space-2) var(--space-3);
5633
- border: 1px solid var(--color-border);
6240
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6241
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6242
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6243
+ is drawn. Identical to the shorthand at every other value of the token. */
6244
+ border-style: solid;
6245
+ border-color: var(--color-border);
6246
+ border-width: var(--input-border-width);
5634
6247
  border-radius: var(--textarea-radius, var(--radius-md));
5635
- background: var(--textarea-bg, var(--color-bg));
6248
+ background: var(--textarea-bg, var(--input-fill));
5636
6249
  color: var(--color-fg);
5637
- font-family: var(--textarea-font, var(--font-sans));
6250
+ font-family: var(--textarea-font, var(--font-ui));
5638
6251
  font-size: var(--text-sm);
5639
6252
  line-height: 1.5;
5640
6253
  resize: vertical;
@@ -5651,8 +6264,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5651
6264
  }
5652
6265
 
5653
6266
  [data-ui="textarea"]:focus {
5654
- outline: 2px solid var(--color-ring);
5655
- outline-offset: -1px;
6267
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6268
+ /* The ring replaces the border rather than sitting outside it: inset by
6269
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6270
+ outline-offset: calc(-1 * var(--input-border-width));
6271
+ box-shadow: var(--focus-shadow);
5656
6272
  border-color: transparent;
5657
6273
  }
5658
6274
 
@@ -5680,7 +6296,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5680
6296
  }
5681
6297
 
5682
6298
  [data-ui="textarea"]:disabled {
5683
- opacity: 0.5;
6299
+ opacity: var(--disabled-opacity);
5684
6300
  cursor: not-allowed;
5685
6301
  resize: none;
5686
6302
  }
@@ -5694,7 +6310,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5694
6310
 
5695
6311
  /* === primitives/toggle.css === */
5696
6312
  /* @ui:component toggle */
5697
- /* @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 */
6313
+ /* @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 */
5698
6314
 
5699
6315
  /* ── Base (off / unpressed) ── */
5700
6316
  [data-ui="toggle"] {
@@ -5703,11 +6319,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5703
6319
  justify-content: center;
5704
6320
  gap: var(--space-1h);
5705
6321
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5706
- border: 1px solid var(--color-border);
6322
+ border: var(--border-width) solid var(--color-border);
5707
6323
  border-radius: var(--toggle-radius, var(--radius-md));
5708
6324
  background: var(--color-bg);
5709
6325
  color: var(--color-fg-muted);
5710
- font-family: var(--toggle-font, var(--font-sans));
6326
+ font-family: var(--toggle-font, var(--font-ui));
5711
6327
  font-size: var(--text-sm);
5712
6328
  font-weight: var(--weight-medium);
5713
6329
  line-height: 1;
@@ -5724,8 +6340,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5724
6340
  }
5725
6341
 
5726
6342
  [data-ui="toggle"]:focus-visible {
5727
- outline: 2px solid var(--color-ring);
5728
- outline-offset: 2px;
6343
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6344
+ outline-offset: var(--focus-ring-offset);
6345
+ box-shadow: var(--focus-shadow);
5729
6346
  }
5730
6347
 
5731
6348
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5742,7 +6359,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5742
6359
 
5743
6360
  /* ── Disabled ── */
5744
6361
  [data-ui="toggle"]:disabled {
5745
- opacity: 0.5;
6362
+ opacity: var(--disabled-opacity);
5746
6363
  cursor: not-allowed;
5747
6364
  }
5748
6365
 
@@ -5766,7 +6383,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5766
6383
 
5767
6384
  /* === primitives/watermark.css === */
5768
6385
  /* @ui:component watermark */
5769
- /* @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 */
6386
+ /* @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 */
5770
6387
 
5771
6388
  [data-ui="watermark"] {
5772
6389
  position: fixed;
@@ -5785,7 +6402,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5785
6402
 
5786
6403
  [data-ui="watermark"] > [data-part="mark"] {
5787
6404
  color: var(--color-fg-muted);
5788
- font-family: var(--doc-font, var(--font-sans));
6405
+ font-family: var(--doc-font, var(--font-body));
5789
6406
  font-size: var(--text-4xl);
5790
6407
  font-weight: var(--weight-bold);
5791
6408
  line-height: var(--leading-tight);
@@ -5843,7 +6460,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5843
6460
 
5844
6461
  /* === recipes/accordion.css === */
5845
6462
  /* @ui:component accordion */
5846
- /* @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 */
6463
+ /* @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 */
5847
6464
 
5848
6465
  /* ── Root ── */
5849
6466
  [data-ui="accordion"] {
@@ -5852,7 +6469,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5852
6469
 
5853
6470
  /* ── Item ── */
5854
6471
  [data-ui="accordion"] [data-part="item"] {
5855
- border-bottom: 1px solid var(--color-border);
6472
+ border-bottom: var(--border-width) solid var(--color-border);
5856
6473
  }
5857
6474
 
5858
6475
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5869,7 +6486,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5869
6486
  border: none;
5870
6487
  background: transparent;
5871
6488
  color: var(--color-fg);
5872
- font-family: var(--font-sans, system-ui, sans-serif);
6489
+ font-family: var(--font-ui);
5873
6490
  font-size: var(--text-base);
5874
6491
  font-weight: var(--weight-medium);
5875
6492
  text-align: start;
@@ -5883,8 +6500,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5883
6500
  }
5884
6501
 
5885
6502
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5886
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5887
- outline-offset: -2px;
6503
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6504
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5888
6505
  border-radius: var(--radius-sm, 0.25rem);
5889
6506
  }
5890
6507
 
@@ -5916,13 +6533,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5916
6533
 
5917
6534
  /* ── Bordered Variant ── */
5918
6535
  [data-ui="accordion"][data-bordered="true"] {
5919
- border: 1px solid var(--color-border);
6536
+ border: var(--border-width) solid var(--color-border);
5920
6537
  border-radius: var(--radius-lg);
5921
6538
  overflow: hidden;
5922
6539
  }
5923
6540
 
5924
6541
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5925
- border-bottom: 1px solid var(--color-border);
6542
+ border-bottom: var(--border-width) solid var(--color-border);
5926
6543
  }
5927
6544
 
5928
6545
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5939,7 +6556,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5939
6556
 
5940
6557
  /* === recipes/alert-dialog.css === */
5941
6558
  /* @ui:component alert-dialog */
5942
- /* @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 */
6559
+ /* @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 */
5943
6560
 
5944
6561
  /* ── Root ── */
5945
6562
  [data-ui="alert-dialog"] {
@@ -5975,7 +6592,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5975
6592
  max-height: 85vh;
5976
6593
  overflow-y: auto;
5977
6594
  background: var(--color-bg);
5978
- border: 1px solid var(--color-border);
6595
+ border: var(--border-width) solid var(--color-border);
5979
6596
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
5980
6597
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
5981
6598
  opacity: 0;
@@ -6021,6 +6638,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6021
6638
  /* ── Title ── */
6022
6639
  [data-ui="alert-dialog"] [data-part="title"] {
6023
6640
  margin: 0;
6641
+ font-family: var(--font-heading);
6024
6642
  font-size: var(--text-lg, 1.125rem);
6025
6643
  font-weight: var(--weight-semibold, 600);
6026
6644
  color: var(--color-fg);
@@ -6060,7 +6678,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6060
6678
 
6061
6679
  /* === recipes/barcode.css === */
6062
6680
  /* @ui:component barcode */
6063
- /* @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 */
6681
+ /* @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 */
6064
6682
 
6065
6683
  [data-ui="barcode"] {
6066
6684
  display: inline-flex;
@@ -6087,7 +6705,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6087
6705
 
6088
6706
  [data-ui="barcode"] > [data-part="caption"] {
6089
6707
  color: var(--doc-legal-color, var(--color-fg-muted));
6090
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6708
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6091
6709
  font-size: var(--doc-legal-size);
6092
6710
  line-height: var(--leading-normal);
6093
6711
  text-align: center;
@@ -6107,7 +6725,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6107
6725
 
6108
6726
  /* === recipes/calendar.css === */
6109
6727
  /* @ui:component calendar */
6110
- /* @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 */
6728
+ /* @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 */
6111
6729
 
6112
6730
  /* ── Root ── */
6113
6731
  [data-ui="calendar"] {
@@ -6140,7 +6758,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6140
6758
  width: 28px;
6141
6759
  height: 28px;
6142
6760
  padding: 0;
6143
- border: 1px solid var(--color-border);
6761
+ border: var(--border-width) solid var(--color-border);
6144
6762
  border-radius: var(--radius-md);
6145
6763
  background: var(--color-bg);
6146
6764
  color: var(--color-fg);
@@ -6156,13 +6774,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6156
6774
 
6157
6775
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6158
6776
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6159
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6160
- outline-offset: 2px;
6777
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6778
+ outline-offset: var(--focus-ring-offset);
6161
6779
  }
6162
6780
 
6163
6781
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6164
6782
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6165
- opacity: 0.4;
6783
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6784
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6785
+ opacity: calc(var(--disabled-opacity) * 0.8);
6166
6786
  cursor: not-allowed;
6167
6787
  }
6168
6788
 
@@ -6197,11 +6817,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6197
6817
  width: 36px;
6198
6818
  height: 36px;
6199
6819
  padding: 0;
6200
- border: 1px solid transparent;
6820
+ border: var(--border-width) solid transparent;
6201
6821
  border-radius: var(--radius-full);
6202
6822
  background: transparent;
6203
6823
  color: var(--color-fg);
6204
- font-family: var(--font-sans, system-ui, sans-serif);
6824
+ font-family: var(--font-ui);
6205
6825
  font-size: var(--text-sm);
6206
6826
  cursor: pointer;
6207
6827
  transition: background var(--duration-fast) var(--ease-default),
@@ -6214,8 +6834,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6214
6834
  }
6215
6835
 
6216
6836
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6217
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6218
- outline-offset: 2px;
6837
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6838
+ outline-offset: var(--focus-ring-offset);
6219
6839
  }
6220
6840
 
6221
6841
  /* ── Today ── */
@@ -6250,7 +6870,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6250
6870
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6251
6871
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6252
6872
  [data-ui="calendar"] [data-part="day"]:disabled {
6253
- opacity: 0.5;
6873
+ opacity: var(--disabled-opacity);
6254
6874
  cursor: not-allowed;
6255
6875
  text-decoration: line-through;
6256
6876
  }
@@ -6314,7 +6934,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6314
6934
 
6315
6935
  /* === recipes/carousel.css === */
6316
6936
  /* @ui:component carousel */
6317
- /* @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 */
6937
+ /* @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 */
6318
6938
 
6319
6939
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6320
6940
  every slide is a snap target. Everything below works with no controller
@@ -6328,7 +6948,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6328
6948
  inline-size: 100%;
6329
6949
  min-inline-size: 0;
6330
6950
  max-inline-size: 100%;
6331
- font-family: var(--carousel-font, var(--font-sans));
6951
+ font-family: var(--carousel-font, var(--font-ui));
6332
6952
  }
6333
6953
 
6334
6954
  /* ── Viewport: the scroll-snap strip ── */
@@ -6354,8 +6974,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6354
6974
  }
6355
6975
 
6356
6976
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6357
- outline: 2px solid var(--color-ring);
6358
- outline-offset: 2px;
6977
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6978
+ outline-offset: var(--focus-ring-offset);
6359
6979
  }
6360
6980
 
6361
6981
  /* ── Slide: one full-width snap target ── */
@@ -6363,7 +6983,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6363
6983
  flex: 0 0 var(--carousel-slide-size, 100%);
6364
6984
  min-inline-size: 0;
6365
6985
  padding: var(--space-4);
6366
- border: 1px solid var(--color-border);
6986
+ border: var(--border-width) solid var(--color-border);
6367
6987
  border-radius: var(--radius-lg);
6368
6988
  background: var(--color-bg);
6369
6989
  color: var(--color-fg);
@@ -6392,7 +7012,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6392
7012
  min-inline-size: 2rem;
6393
7013
  min-block-size: 2rem;
6394
7014
  padding: var(--space-1) var(--space-2);
6395
- border: 1px solid var(--color-border);
7015
+ border: var(--border-width) solid var(--color-border);
6396
7016
  border-radius: var(--radius-md);
6397
7017
  background: var(--color-bg);
6398
7018
  color: var(--color-fg);
@@ -6411,14 +7031,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6411
7031
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6412
7032
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6413
7033
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6414
- outline: 2px solid var(--color-ring);
6415
- outline-offset: 2px;
7034
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7035
+ outline-offset: var(--focus-ring-offset);
6416
7036
  }
6417
7037
 
6418
7038
  /* Boundary contract "stop" — the controller disables the end button. */
6419
7039
  [data-ui="carousel"] [data-part="prev"]:disabled,
6420
7040
  [data-ui="carousel"] [data-part="next"]:disabled {
6421
- opacity: 0.4;
7041
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7042
+ opacity: calc(var(--disabled-opacity) * 0.8);
6422
7043
  cursor: not-allowed;
6423
7044
  }
6424
7045
 
@@ -6427,7 +7048,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6427
7048
  inline-size: 0.625rem;
6428
7049
  block-size: 0.625rem;
6429
7050
  padding: 0;
6430
- border: 1px solid var(--color-border);
7051
+ border: var(--border-width) solid var(--color-border);
6431
7052
  border-radius: 50%;
6432
7053
  background: var(--color-bg-muted);
6433
7054
  cursor: pointer;
@@ -6463,7 +7084,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6463
7084
 
6464
7085
  /* === recipes/combobox.css === */
6465
7086
  /* @ui:component combobox */
6466
- /* @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 */
7087
+ /* @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 */
6467
7088
 
6468
7089
  /* ── Root ── */
6469
7090
  [data-ui="combobox"] {
@@ -6477,11 +7098,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6477
7098
  display: block;
6478
7099
  width: 100%;
6479
7100
  padding: var(--space-2) var(--space-3);
6480
- border: 1px solid var(--color-border);
7101
+ border: var(--border-width) solid var(--color-border);
6481
7102
  border-radius: var(--radius-md);
6482
7103
  background: var(--color-bg);
6483
7104
  color: var(--color-fg);
6484
- font-family: var(--font-sans, system-ui, sans-serif);
7105
+ font-family: var(--font-ui);
6485
7106
  font-size: var(--text-sm);
6486
7107
  line-height: 1.5;
6487
7108
  outline: none;
@@ -6494,8 +7115,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6494
7115
  }
6495
7116
 
6496
7117
  [data-ui="combobox"] [data-part="input"]:focus {
6497
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6498
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7118
+ border-color: var(--focus-ring-color);
7119
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6499
7120
  }
6500
7121
 
6501
7122
  /* ── Listbox ── */
@@ -6507,7 +7128,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6507
7128
  z-index: var(--z-dropdown);
6508
7129
  margin-top: var(--space-1);
6509
7130
  padding: var(--space-1);
6510
- border: 1px solid var(--color-border);
7131
+ border: var(--border-width) solid var(--color-border);
6511
7132
  border-radius: var(--radius-lg);
6512
7133
  background: var(--color-bg);
6513
7134
  box-shadow: var(--shadow-md);
@@ -6592,7 +7213,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6592
7213
 
6593
7214
  /* === recipes/command-palette.css === */
6594
7215
  /* @ui:component command-palette */
6595
- /* @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 */
7216
+ /* @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 */
6596
7217
 
6597
7218
  /* ── Root ── */
6598
7219
  [data-ui="command-palette"] {
@@ -6625,7 +7246,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6625
7246
  display: flex;
6626
7247
  flex-direction: column;
6627
7248
  background: var(--color-bg);
6628
- border: 1px solid var(--color-border);
7249
+ border: var(--border-width) solid var(--color-border);
6629
7250
  border-radius: var(--radius-xl);
6630
7251
  box-shadow: var(--shadow-xl);
6631
7252
  overflow: hidden;
@@ -6657,7 +7278,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6657
7278
  display: flex;
6658
7279
  align-items: center;
6659
7280
  padding: var(--space-3) var(--space-4);
6660
- border-bottom: 1px solid var(--color-border);
7281
+ border-bottom: var(--border-width) solid var(--color-border);
6661
7282
  }
6662
7283
 
6663
7284
  /* ── Search Input ── */
@@ -6667,7 +7288,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6667
7288
  border: none;
6668
7289
  background: transparent;
6669
7290
  color: var(--color-fg);
6670
- font-family: var(--font-sans, system-ui, sans-serif);
7291
+ font-family: var(--font-ui);
6671
7292
  font-size: var(--text-base);
6672
7293
  outline: none;
6673
7294
  }
@@ -6751,7 +7372,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6751
7372
  align-items: center;
6752
7373
  gap: var(--space-1, 0.25rem);
6753
7374
  padding: var(--space-1, 0.25rem) var(--space-2);
6754
- border: 1px solid var(--color-border);
7375
+ border: var(--border-width) solid var(--color-border);
6755
7376
  border-radius: var(--radius-sm, 0.25rem);
6756
7377
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6757
7378
  color: var(--color-fg-muted);
@@ -6780,7 +7401,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6780
7401
 
6781
7402
  /* === recipes/context-menu.css === */
6782
7403
  /* @ui:component context-menu */
6783
- /* @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 */
7404
+ /* @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 */
6784
7405
 
6785
7406
  [data-ui="context-menu"] {
6786
7407
  position: relative;
@@ -6793,12 +7414,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6793
7414
  border-radius: var(--radius-lg);
6794
7415
  background: var(--color-bg-muted);
6795
7416
  color: var(--color-fg);
6796
- font-family: var(--font-sans, system-ui, sans-serif);
7417
+ font-family: var(--font-ui);
6797
7418
  }
6798
7419
 
6799
7420
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6800
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6801
- outline-offset: var(--space-1);
7421
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7422
+ outline-offset: var(--focus-ring-offset);
6802
7423
  }
6803
7424
 
6804
7425
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6830,7 +7451,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6830
7451
  border-radius: var(--radius-md);
6831
7452
  background: transparent;
6832
7453
  color: var(--color-fg);
6833
- font-family: var(--font-sans, system-ui, sans-serif);
7454
+ font-family: var(--font-ui);
6834
7455
  font-size: var(--text-sm);
6835
7456
  font-weight: var(--weight-medium);
6836
7457
  text-align: start;
@@ -6854,15 +7475,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6854
7475
  focus additionally draws the ring, inset so it does not overlap the item
6855
7476
  above. [W3-3] */
6856
7477
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6857
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6858
- outline-offset: calc(var(--space-px) * -2);
7478
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7479
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6859
7480
  }
6860
7481
 
6861
7482
  [data-ui="context-menu"] [data-part="item"]:disabled,
6862
7483
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6863
7484
  color: var(--color-fg-muted);
6864
7485
  cursor: not-allowed;
6865
- opacity: 0.5;
7486
+ opacity: var(--disabled-opacity);
6866
7487
  }
6867
7488
 
6868
7489
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6881,7 +7502,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6881
7502
 
6882
7503
  /* === recipes/date-picker.css === */
6883
7504
  /* @ui:component date-picker */
6884
- /* @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 */
7505
+ /* @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 */
6885
7506
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6886
7507
 
6887
7508
  /* ── Root ── */
@@ -6902,11 +7523,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6902
7523
  width: 100%;
6903
7524
  padding: var(--space-2, 0.5rem) var(--space-3);
6904
7525
  padding-inline-end: var(--space-8, 2.5rem);
6905
- border: 1px solid var(--color-border);
7526
+ border: var(--border-width) solid var(--color-border);
6906
7527
  border-radius: var(--radius-md);
6907
7528
  background: var(--color-bg);
6908
7529
  color: var(--color-fg);
6909
- font-family: var(--font-sans, system-ui, sans-serif);
7530
+ font-family: var(--font-ui);
6910
7531
  font-size: var(--text-sm);
6911
7532
  line-height: 1.5;
6912
7533
  cursor: pointer;
@@ -6918,8 +7539,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6918
7539
  }
6919
7540
 
6920
7541
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6921
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6922
- outline-offset: 2px;
7542
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7543
+ outline-offset: var(--focus-ring-offset);
6923
7544
  border-color: var(--color-primary);
6924
7545
  }
6925
7546
 
@@ -6942,7 +7563,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6942
7563
  z-index: var(--z-dropdown);
6943
7564
  margin-top: var(--space-1);
6944
7565
  padding: var(--space-3);
6945
- border: 1px solid var(--color-border);
7566
+ border: var(--border-width) solid var(--color-border);
6946
7567
  border-radius: var(--radius-lg);
6947
7568
  background: var(--color-bg);
6948
7569
  box-shadow: var(--shadow-lg);
@@ -6981,7 +7602,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6981
7602
 
6982
7603
  /* === recipes/dialog.css === */
6983
7604
  /* @ui:component dialog */
6984
- /* @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 */
7605
+ /* @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 */
6985
7606
 
6986
7607
  /* ── Root ── */
6987
7608
  [data-ui="dialog"] {
@@ -7016,15 +7637,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7016
7637
  width: 90%;
7017
7638
  max-height: 85vh;
7018
7639
  overflow-y: auto;
7019
- background: var(--color-bg);
7020
- border: 1px solid var(--color-border);
7640
+ background: var(--panel-bg);
7641
+ border: var(--border-width) solid var(--color-border);
7021
7642
  border-radius: var(--dialog-radius, var(--radius-xl));
7643
+ corner-shape: var(--corner-shape);
7022
7644
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7023
7645
  opacity: 0;
7024
7646
  transition: opacity var(--duration-normal) var(--ease-out),
7025
7647
  transform var(--duration-normal) var(--ease-out);
7026
7648
  }
7027
7649
 
7650
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7651
+ [data-ui="dialog"] [data-part="panel"] {
7652
+ -webkit-backdrop-filter: var(--surface-backdrop);
7653
+ backdrop-filter: var(--surface-backdrop);
7654
+ }
7655
+ }
7656
+
7028
7657
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7029
7658
  opacity: 1;
7030
7659
  transform: translate(-50%, -50%) scale(1);
@@ -7073,6 +7702,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7073
7702
  /* ── Title ── */
7074
7703
  [data-ui="dialog"] [data-part="title"] {
7075
7704
  margin: 0;
7705
+ font-family: var(--font-heading);
7076
7706
  font-size: var(--text-lg, 1.125rem);
7077
7707
  font-weight: var(--weight-semibold, 600);
7078
7708
  color: var(--color-fg);
@@ -7107,8 +7737,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7107
7737
  }
7108
7738
 
7109
7739
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7110
- outline: 2px solid var(--color-ring);
7111
- outline-offset: 2px;
7740
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7741
+ outline-offset: var(--focus-ring-offset);
7112
7742
  }
7113
7743
 
7114
7744
  /* ── Description ── */
@@ -7144,7 +7774,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7144
7774
 
7145
7775
  /* === recipes/drawer.css === */
7146
7776
  /* @ui:component drawer */
7147
- /* @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 */
7777
+ /* @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 */
7148
7778
 
7149
7779
  /* ── Root ── */
7150
7780
  [data-ui="drawer"] {
@@ -7179,17 +7809,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7179
7809
  flex-direction: column;
7180
7810
  width: var(--drawer-width, 400px);
7181
7811
  max-width: 100vw;
7182
- background: var(--color-bg);
7812
+ background: var(--panel-bg);
7183
7813
  border: none;
7184
7814
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7185
7815
  transition: transform var(--duration-slow) var(--ease-out);
7186
7816
  }
7187
7817
 
7818
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7819
+ [data-ui="drawer"] [data-part="panel"] {
7820
+ -webkit-backdrop-filter: var(--surface-backdrop);
7821
+ backdrop-filter: var(--surface-backdrop);
7822
+ }
7823
+ }
7824
+
7188
7825
  /* ── Side Variants ── */
7189
7826
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7190
7827
  inset-inline-start: 0;
7191
7828
  inset-inline-end: auto;
7192
- border-inline-end: 1px solid var(--color-border);
7829
+ border-inline-end: var(--border-width) solid var(--color-border);
7193
7830
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7194
7831
  transform: translateX(-100%);
7195
7832
  }
@@ -7197,7 +7834,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7197
7834
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7198
7835
  inset-inline-end: 0;
7199
7836
  inset-inline-start: auto;
7200
- border-inline-start: 1px solid var(--color-border);
7837
+ border-inline-start: var(--border-width) solid var(--color-border);
7201
7838
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7202
7839
  transform: translateX(100%);
7203
7840
  }
@@ -7251,6 +7888,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7251
7888
  /* ── Title ── */
7252
7889
  [data-ui="drawer"] [data-part="title"] {
7253
7890
  margin: 0;
7891
+ font-family: var(--font-heading);
7254
7892
  font-size: var(--text-lg, 1.125rem);
7255
7893
  font-weight: var(--weight-semibold, 600);
7256
7894
  color: var(--color-fg);
@@ -7285,8 +7923,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7285
7923
  }
7286
7924
 
7287
7925
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7288
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7289
- outline-offset: 2px;
7926
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7927
+ outline-offset: var(--focus-ring-offset);
7290
7928
  }
7291
7929
 
7292
7930
  /* ── Body ── */
@@ -7305,7 +7943,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7305
7943
  gap: var(--space-3, 0.75rem);
7306
7944
  padding: var(--space-6);
7307
7945
  padding-top: var(--space-4);
7308
- border-top: 1px solid var(--color-border);
7946
+ border-top: var(--border-width) solid var(--color-border);
7309
7947
  flex-shrink: 0;
7310
7948
  }
7311
7949
 
@@ -7319,7 +7957,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7319
7957
 
7320
7958
  /* === recipes/dropdown.css === */
7321
7959
  /* @ui:component dropdown */
7322
- /* @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 */
7960
+ /* @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 */
7323
7961
 
7324
7962
  /* ── Root ── */
7325
7963
  [data-ui="dropdown"] {
@@ -7333,11 +7971,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7333
7971
  align-items: center;
7334
7972
  gap: var(--space-2);
7335
7973
  padding: var(--space-2) var(--space-3);
7336
- border: 1px solid var(--color-border);
7974
+ border: var(--border-width) solid var(--color-border);
7337
7975
  border-radius: var(--radius-md);
7338
7976
  background: var(--color-bg);
7339
7977
  color: var(--color-fg);
7340
- font-family: var(--font-sans, system-ui, sans-serif);
7978
+ font-family: var(--font-ui);
7341
7979
  font-size: var(--text-sm);
7342
7980
  font-weight: var(--weight-medium);
7343
7981
  cursor: pointer;
@@ -7351,8 +7989,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7351
7989
  }
7352
7990
 
7353
7991
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7354
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7355
- outline-offset: 2px;
7992
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7993
+ outline-offset: var(--focus-ring-offset);
7356
7994
  }
7357
7995
 
7358
7996
  /* ── Menu ── */
@@ -7364,9 +8002,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7364
8002
  min-width: 180px;
7365
8003
  margin-top: var(--space-1);
7366
8004
  padding: var(--space-1);
7367
- border: 1px solid var(--color-border);
8005
+ border: var(--border-width) solid var(--color-border);
7368
8006
  border-radius: var(--radius-lg);
7369
- background: var(--color-bg);
8007
+ background: var(--panel-bg);
7370
8008
  box-shadow: var(--shadow-md);
7371
8009
  opacity: 0;
7372
8010
  transform: translateY(-4px);
@@ -7374,6 +8012,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7374
8012
  transform var(--duration-fast) var(--ease-out);
7375
8013
  }
7376
8014
 
8015
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8016
+ [data-ui="dropdown"] [data-part="menu"] {
8017
+ -webkit-backdrop-filter: var(--surface-backdrop);
8018
+ backdrop-filter: var(--surface-backdrop);
8019
+ }
8020
+ }
8021
+
7377
8022
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7378
8023
  opacity: 1;
7379
8024
  transform: translateY(0);
@@ -7396,7 +8041,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7396
8041
  border-radius: var(--radius-md);
7397
8042
  background: transparent;
7398
8043
  color: var(--color-fg);
7399
- font-family: var(--font-sans, system-ui, sans-serif);
8044
+ font-family: var(--font-ui);
7400
8045
  font-size: var(--text-sm);
7401
8046
  text-align: start;
7402
8047
  cursor: pointer;
@@ -7418,12 +8063,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7418
8063
  focus additionally draws the ring, inset so it does not overlap the item
7419
8064
  above. [W3-3] */
7420
8065
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7421
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7422
- outline-offset: -2px;
8066
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8067
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7423
8068
  }
7424
8069
 
7425
8070
  [data-ui="dropdown"] [data-part="item"]:disabled {
7426
- opacity: 0.5;
8071
+ opacity: var(--disabled-opacity);
7427
8072
  cursor: not-allowed;
7428
8073
  pointer-events: none;
7429
8074
  }
@@ -7476,14 +8121,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7476
8121
 
7477
8122
  /* === recipes/file-upload.css === */
7478
8123
  /* @ui:component file-upload */
7479
- /* @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 */
8124
+ /* @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 */
7480
8125
 
7481
8126
  [data-ui="file-upload"] {
7482
8127
  display: grid;
7483
8128
  gap: var(--space-4);
7484
8129
  inline-size: 100%;
7485
8130
  color: var(--color-fg);
7486
- font-family: var(--font-sans);
8131
+ font-family: var(--font-ui);
7487
8132
  }
7488
8133
 
7489
8134
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7518,14 +8163,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7518
8163
  }
7519
8164
 
7520
8165
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7521
- outline: var(--space-px) solid var(--color-ring);
7522
- outline-offset: var(--space-1);
8166
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8167
+ outline-offset: var(--focus-ring-offset);
7523
8168
  }
7524
8169
 
7525
8170
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7526
8171
  border-color: var(--color-primary);
7527
8172
  background: var(--color-primary-subtle);
7528
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8173
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7529
8174
  }
7530
8175
 
7531
8176
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7599,8 +8244,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7599
8244
  }
7600
8245
 
7601
8246
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7602
- outline: var(--space-px) solid var(--color-ring);
7603
- outline-offset: var(--space-1);
8247
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8248
+ outline-offset: var(--focus-ring-offset);
7604
8249
  }
7605
8250
 
7606
8251
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7622,7 +8267,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7622
8267
  }
7623
8268
 
7624
8269
  [data-ui="file-upload"][data-disabled] {
7625
- opacity: 0.5;
8270
+ opacity: var(--disabled-opacity);
7626
8271
  }
7627
8272
 
7628
8273
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7638,7 +8283,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7638
8283
 
7639
8284
  /* === recipes/input-otp.css === */
7640
8285
  /* @ui:component input-otp */
7641
- /* @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 */
8286
+ /* @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 */
7642
8287
 
7643
8288
  /* ── Root ── */
7644
8289
  [data-ui="input-otp"] {
@@ -7653,7 +8298,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7653
8298
  gutter. The transparent input is `inset: 0`, so it follows the box the
7654
8299
  segments settle into however many rows that takes. */
7655
8300
  max-inline-size: 100%;
7656
- font-family: var(--font-sans, system-ui, sans-serif);
8301
+ font-family: var(--font-ui);
7657
8302
  }
7658
8303
 
7659
8304
  /* ── Real input ──
@@ -7698,14 +8343,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7698
8343
  justify-content: center;
7699
8344
  inline-size: var(--input-otp-segment-size);
7700
8345
  block-size: var(--input-otp-segment-size);
7701
- border: 1px solid var(--color-border);
8346
+ border: var(--border-width) solid var(--color-border);
7702
8347
  border-radius: var(--radius-md);
7703
8348
  background: var(--color-bg);
7704
8349
  color: var(--color-fg);
7705
8350
  font-size: var(--text-lg, 1.125rem);
7706
8351
  font-variant-numeric: tabular-nums;
7707
8352
  line-height: 1;
7708
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8353
+ transition: border-color var(--duration-fast) var(--ease-default),
7709
8354
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7710
8355
  }
7711
8356
 
@@ -7717,7 +8362,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7717
8362
  /* Active (caret / selected) segment while focused */
7718
8363
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7719
8364
  border-color: var(--color-ring);
7720
- box-shadow: 0 0 0 1px var(--color-ring);
8365
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7721
8366
  }
7722
8367
 
7723
8368
  /* Blinking caret in the next-to-fill empty slot */
@@ -7765,7 +8410,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7765
8410
 
7766
8411
  /* ── Disabled ── */
7767
8412
  [data-ui="input-otp"][data-disabled] {
7768
- opacity: 0.5;
8413
+ opacity: var(--disabled-opacity);
7769
8414
  cursor: not-allowed;
7770
8415
  }
7771
8416
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7789,7 +8434,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7789
8434
 
7790
8435
  /* === recipes/menubar.css === */
7791
8436
  /* @ui:component menubar */
7792
- /* @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 */
8437
+ /* @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 */
7793
8438
 
7794
8439
  [data-ui="menubar"] {
7795
8440
  position: relative;
@@ -7807,7 +8452,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7807
8452
  border-radius: var(--radius-lg);
7808
8453
  background: var(--color-bg);
7809
8454
  color: var(--color-fg);
7810
- font-family: var(--font-sans);
8455
+ font-family: var(--font-ui);
7811
8456
  }
7812
8457
 
7813
8458
  [data-ui="menubar"] [data-part="group"] {
@@ -7849,7 +8494,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7849
8494
 
7850
8495
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7851
8496
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7852
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8497
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7853
8498
  }
7854
8499
 
7855
8500
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7884,7 +8529,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7884
8529
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7885
8530
  color: var(--color-fg-muted);
7886
8531
  cursor: not-allowed;
7887
- opacity: 0.6;
8532
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8533
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8534
+ it (1.1A-27). */
8535
+ opacity: calc(var(--disabled-opacity) * 1.2);
7888
8536
  }
7889
8537
 
7890
8538
  [data-ui="menubar"] [data-part="separator"] {
@@ -7916,7 +8564,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7916
8564
 
7917
8565
  /* === recipes/pagination.css === */
7918
8566
  /* @ui:component pagination */
7919
- /* @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 */
8567
+ /* @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 */
7920
8568
 
7921
8569
  /* ── Root ── */
7922
8570
  [data-ui="pagination"] {
@@ -7952,11 +8600,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7952
8600
  min-width: 36px;
7953
8601
  height: 36px;
7954
8602
  padding: 0 var(--space-2);
7955
- border: 1px solid var(--color-border);
8603
+ border: var(--border-width) solid var(--color-border);
7956
8604
  border-radius: var(--radius-md);
7957
8605
  background: var(--color-bg);
7958
8606
  color: var(--color-fg);
7959
- font-family: var(--font-sans, system-ui, sans-serif);
8607
+ font-family: var(--font-ui);
7960
8608
  font-size: var(--text-sm);
7961
8609
  font-weight: var(--weight-medium);
7962
8610
  cursor: pointer;
@@ -7977,8 +8625,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7977
8625
  [data-ui="pagination"] [data-part="page"]:focus-visible,
7978
8626
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
7979
8627
  [data-ui="pagination"] [data-part="next"]:focus-visible {
7980
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7981
- outline-offset: 2px;
8628
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8629
+ outline-offset: var(--focus-ring-offset);
7982
8630
  }
7983
8631
 
7984
8632
  /* ── Active page ── */
@@ -8002,7 +8650,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8002
8650
  /* ── Disabled ── */
8003
8651
  [data-ui="pagination"] [data-part="prev"]:disabled,
8004
8652
  [data-ui="pagination"] [data-part="next"]:disabled {
8005
- opacity: 0.5;
8653
+ opacity: var(--disabled-opacity);
8006
8654
  cursor: not-allowed;
8007
8655
  pointer-events: none;
8008
8656
  }
@@ -8072,7 +8720,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8072
8720
 
8073
8721
  /* === recipes/popover.css === */
8074
8722
  /* @ui:component popover */
8075
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8723
+ /* @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 */
8076
8724
 
8077
8725
  /* ── Root ── */
8078
8726
  [data-ui="popover"] {
@@ -8086,11 +8734,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8086
8734
  align-items: center;
8087
8735
  gap: var(--space-2, 0.5rem);
8088
8736
  padding: var(--space-2, 0.5rem) var(--space-3);
8089
- border: 1px solid var(--color-border);
8737
+ border: var(--border-width) solid var(--color-border);
8090
8738
  border-radius: var(--radius-md, 0.375rem);
8091
8739
  background: var(--color-bg);
8092
8740
  color: var(--color-fg);
8093
- font-family: var(--font-sans, system-ui, sans-serif);
8741
+ font-family: var(--font-ui);
8094
8742
  font-size: var(--text-sm, 0.875rem);
8095
8743
  font-weight: var(--weight-medium, 500);
8096
8744
  cursor: pointer;
@@ -8104,8 +8752,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8104
8752
  }
8105
8753
 
8106
8754
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8107
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8108
- outline-offset: 2px;
8755
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8756
+ outline-offset: var(--focus-ring-offset);
8109
8757
  }
8110
8758
 
8111
8759
  /* ── Content ── */
@@ -8114,9 +8762,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8114
8762
  z-index: var(--z-dropdown);
8115
8763
  min-width: 200px;
8116
8764
  padding: var(--space-4);
8117
- border: 1px solid var(--color-border);
8765
+ border: var(--border-width) solid var(--color-border);
8118
8766
  border-radius: var(--radius-lg);
8119
- background: var(--color-bg);
8767
+ background: var(--panel-bg);
8120
8768
  color: var(--color-fg);
8121
8769
  box-shadow: var(--shadow-md);
8122
8770
  opacity: 0;
@@ -8125,6 +8773,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8125
8773
  transform var(--duration-fast) var(--ease-default);
8126
8774
  }
8127
8775
 
8776
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8777
+ [data-ui="popover"] [data-part="content"] {
8778
+ -webkit-backdrop-filter: var(--surface-backdrop);
8779
+ backdrop-filter: var(--surface-backdrop);
8780
+ }
8781
+ }
8782
+
8128
8783
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8129
8784
  opacity: 1;
8130
8785
  transform: scale(1);
@@ -8212,8 +8867,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8212
8867
  position: absolute;
8213
8868
  width: 8px;
8214
8869
  height: 8px;
8215
- background: var(--color-bg);
8216
- border: 1px solid var(--color-border);
8870
+ background: var(--panel-bg);
8871
+ border: var(--border-width) solid var(--color-border);
8217
8872
  transform: rotate(45deg);
8218
8873
  }
8219
8874
 
@@ -8314,8 +8969,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8314
8969
  }
8315
8970
 
8316
8971
  [data-ui="popover"] [data-part="close"]:focus-visible {
8317
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8318
- outline-offset: 2px;
8972
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8973
+ outline-offset: var(--focus-ring-offset);
8319
8974
  }
8320
8975
 
8321
8976
  /* ── Motion ── */
@@ -8328,7 +8983,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8328
8983
 
8329
8984
  /* === recipes/qr-code.css === */
8330
8985
  /* @ui:component qr-code */
8331
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8986
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8332
8987
 
8333
8988
  /* ── Base ── */
8334
8989
  [data-ui="qr-code"] {
@@ -8346,7 +9001,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8346
9001
 
8347
9002
  /* ── Caption ── */
8348
9003
  [data-ui="qr-code"] [data-part="caption"] {
8349
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
9004
+ font-family: var(--doc-font, var(--font-body));
8350
9005
  font-size: var(--doc-legal-size, var(--text-xs));
8351
9006
  color: var(--doc-legal-color, var(--color-fg-muted));
8352
9007
  text-align: center;
@@ -8387,7 +9042,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8387
9042
 
8388
9043
  /* === recipes/select-custom.css === */
8389
9044
  /* @ui:component select-custom */
8390
- /* @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 */
9045
+ /* @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 */
8391
9046
 
8392
9047
  /* ── Root ── */
8393
9048
  [data-ui="select-custom"] {
@@ -8404,11 +9059,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8404
9059
  width: 100%;
8405
9060
  min-width: 180px;
8406
9061
  padding: var(--space-2) var(--space-3);
8407
- border: 1px solid var(--color-border);
9062
+ border: var(--border-width) solid var(--color-border);
8408
9063
  border-radius: var(--radius-md);
8409
9064
  background: var(--color-bg);
8410
9065
  color: var(--color-fg);
8411
- font-family: var(--font-sans, system-ui, sans-serif);
9066
+ font-family: var(--font-ui);
8412
9067
  font-size: var(--text-sm);
8413
9068
  cursor: pointer;
8414
9069
  white-space: nowrap;
@@ -8421,8 +9076,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8421
9076
  }
8422
9077
 
8423
9078
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8424
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8425
- outline-offset: 2px;
9079
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9080
+ outline-offset: var(--focus-ring-offset);
8426
9081
  }
8427
9082
 
8428
9083
  /* ── Value ── */
@@ -8458,7 +9113,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8458
9113
  z-index: var(--z-dropdown);
8459
9114
  margin-top: var(--space-1);
8460
9115
  padding: var(--space-1);
8461
- border: 1px solid var(--color-border);
9116
+ border: var(--border-width) solid var(--color-border);
8462
9117
  border-radius: var(--radius-lg);
8463
9118
  background: var(--color-bg);
8464
9119
  box-shadow: var(--shadow-md);
@@ -8482,11 +9137,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8482
9137
  padding: var(--space-2) var(--space-3);
8483
9138
  margin-bottom: var(--space-1);
8484
9139
  border: none;
8485
- border-bottom: 1px solid var(--color-border);
9140
+ border-bottom: var(--border-width) solid var(--color-border);
8486
9141
  border-radius: 0;
8487
9142
  background: transparent;
8488
9143
  color: var(--color-fg);
8489
- font-family: var(--font-sans, system-ui, sans-serif);
9144
+ font-family: var(--font-ui);
8490
9145
  font-size: var(--text-sm);
8491
9146
  outline: none;
8492
9147
  }
@@ -8580,7 +9235,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8580
9235
 
8581
9236
  /* === recipes/sheet.css === */
8582
9237
  /* @ui:component sheet */
8583
- /* @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 */
9238
+ /* @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 */
8584
9239
 
8585
9240
  /* ── Root ── */
8586
9241
  [data-ui="sheet"] {
@@ -8611,11 +9266,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8611
9266
  z-index: var(--z-modal);
8612
9267
  display: flex;
8613
9268
  flex-direction: column;
8614
- background: var(--color-bg);
9269
+ background: var(--panel-bg);
8615
9270
  box-shadow: var(--shadow-xl);
8616
9271
  transition: transform var(--duration-slow) var(--ease-out);
8617
9272
  }
8618
9273
 
9274
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9275
+ [data-ui="sheet"] [data-part="panel"] {
9276
+ -webkit-backdrop-filter: var(--surface-backdrop);
9277
+ backdrop-filter: var(--surface-backdrop);
9278
+ }
9279
+ }
9280
+
8619
9281
  /* ── Side: Bottom ── */
8620
9282
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8621
9283
  bottom: 0;
@@ -8643,7 +9305,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8643
9305
  bottom: 0;
8644
9306
  max-width: 100vw;
8645
9307
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8646
- border-inline-end: 1px solid var(--color-border);
9308
+ border-inline-end: var(--border-width) solid var(--color-border);
8647
9309
  transform: translateX(-100%);
8648
9310
  }
8649
9311
 
@@ -8654,7 +9316,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8654
9316
  bottom: 0;
8655
9317
  max-width: 100vw;
8656
9318
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8657
- border-inline-start: 1px solid var(--color-border);
9319
+ border-inline-start: var(--border-width) solid var(--color-border);
8658
9320
  transform: translateX(100%);
8659
9321
  }
8660
9322
 
@@ -8731,6 +9393,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8731
9393
  /* ── Title ── */
8732
9394
  [data-ui="sheet"] [data-part="title"] {
8733
9395
  margin: 0;
9396
+ font-family: var(--font-heading);
8734
9397
  font-size: var(--text-lg, 1.125rem);
8735
9398
  font-weight: var(--weight-semibold, 600);
8736
9399
  color: var(--color-fg);
@@ -8765,8 +9428,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8765
9428
  }
8766
9429
 
8767
9430
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8768
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8769
- outline-offset: 2px;
9431
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9432
+ outline-offset: var(--focus-ring-offset);
8770
9433
  }
8771
9434
 
8772
9435
  /* ── Body ── */
@@ -8787,7 +9450,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8787
9450
 
8788
9451
  /* === recipes/sidebar.css === */
8789
9452
  /* @ui:component sidebar */
8790
- /* @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 */
9453
+ /* @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 */
8791
9454
 
8792
9455
  /* ── Root ──
8793
9456
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8831,7 +9494,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8831
9494
  flex-direction: column;
8832
9495
  gap: var(--space-2);
8833
9496
  background: var(--sidebar-bg);
8834
- border-inline-end: 1px solid var(--color-border);
9497
+ border-inline-end: var(--border-width) solid var(--color-border);
8835
9498
  border-start-end-radius: var(--radius-lg, 0.5rem);
8836
9499
  border-end-end-radius: var(--radius-lg, 0.5rem);
8837
9500
  box-shadow: var(--shadow-xl);
@@ -8912,8 +9575,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8912
9575
  }
8913
9576
 
8914
9577
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8915
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8916
- outline-offset: 2px;
9578
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9579
+ outline-offset: var(--focus-ring-offset);
8917
9580
  }
8918
9581
 
8919
9582
  /* ── Navigation ── */
@@ -8949,8 +9612,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8949
9612
  }
8950
9613
 
8951
9614
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
8952
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8953
- outline-offset: -2px;
9615
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9616
+ outline-offset: calc(-1 * var(--focus-ring-offset));
8954
9617
  }
8955
9618
 
8956
9619
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -8977,7 +9640,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8977
9640
  [data-ui="sidebar"] [data-part="footer"] {
8978
9641
  flex-shrink: 0;
8979
9642
  padding: var(--space-3) var(--space-4);
8980
- border-block-start: 1px solid var(--color-border);
9643
+ border-block-start: var(--border-width) solid var(--color-border);
8981
9644
  }
8982
9645
 
8983
9646
  /* ── Rail (icons only) ── */
@@ -9070,7 +9733,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9070
9733
 
9071
9734
  /* === recipes/slider.css === */
9072
9735
  /* @ui:component slider */
9073
- /* @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 */
9736
+ /* @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 */
9074
9737
 
9075
9738
  /* ── Root ── */
9076
9739
  [data-ui="slider"] {
@@ -9120,28 +9783,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9120
9783
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9121
9784
  transform: translate(-50%, -50%);
9122
9785
  background: var(--color-bg, white);
9123
- border: 2px solid var(--color-primary);
9786
+ border: var(--border-width-strong) solid var(--color-primary);
9124
9787
  border-radius: var(--radius-full, 9999px);
9125
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9788
+ box-shadow: var(--shadow-sm);
9126
9789
  cursor: grab;
9127
9790
  touch-action: none;
9128
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9791
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9129
9792
  }
9130
9793
 
9131
9794
  [data-ui="slider"] [data-part="thumb"]:hover {
9132
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9133
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9795
+ box-shadow: var(--shadow-sm),
9796
+ 0 0 0 4px var(--color-primary-subtle);
9134
9797
  }
9135
9798
 
9136
9799
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9137
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9138
- outline-offset: 2px;
9800
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9801
+ outline-offset: var(--focus-ring-offset);
9139
9802
  }
9140
9803
 
9141
9804
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9142
9805
  cursor: grabbing;
9143
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9144
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9806
+ box-shadow: var(--shadow-sm),
9807
+ 0 0 0 5px var(--color-primary-subtle);
9145
9808
  }
9146
9809
 
9147
9810
  /* ── Value output ── */
@@ -9149,7 +9812,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9149
9812
  flex: 0 0 auto;
9150
9813
  min-inline-size: 3ch;
9151
9814
  color: var(--color-fg-muted);
9152
- font-family: var(--font-sans, system-ui, sans-serif);
9815
+ font-family: var(--font-ui);
9153
9816
  font-size: var(--text-sm);
9154
9817
  font-variant-numeric: tabular-nums;
9155
9818
  text-align: end;
@@ -9168,7 +9831,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9168
9831
 
9169
9832
  /* ── Disabled ── */
9170
9833
  [data-ui="slider"][data-disabled] {
9171
- opacity: 0.5;
9834
+ opacity: var(--disabled-opacity);
9172
9835
  cursor: not-allowed;
9173
9836
  pointer-events: none;
9174
9837
  }
@@ -9186,7 +9849,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9186
9849
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9187
9850
  @media (forced-colors: active) {
9188
9851
  [data-ui="slider"] [data-part="track"] {
9189
- border: 1px solid ButtonText;
9852
+ border: var(--border-width) solid ButtonText;
9190
9853
  }
9191
9854
 
9192
9855
  [data-ui="slider"] [data-part="range"] {
@@ -9197,7 +9860,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9197
9860
  [data-ui="slider"] [data-part="thumb"] {
9198
9861
  forced-color-adjust: none;
9199
9862
  background: ButtonText;
9200
- border: 1px solid ButtonFace;
9863
+ border: var(--border-width) solid ButtonFace;
9201
9864
  }
9202
9865
 
9203
9866
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9207,7 +9870,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9207
9870
 
9208
9871
  /* === recipes/table.css === */
9209
9872
  /* @ui:component table */
9210
- /* @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 */
9873
+ /* @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 */
9211
9874
 
9212
9875
  /* ── Root ── */
9213
9876
  [data-ui="table"] {
@@ -9233,7 +9896,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9233
9896
  width: 100%;
9234
9897
  border-collapse: separate;
9235
9898
  border-spacing: 0;
9236
- font-family: var(--font-sans, system-ui, sans-serif);
9899
+ font-family: var(--font-body);
9237
9900
  }
9238
9901
 
9239
9902
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9255,7 +9918,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9255
9918
  font-weight: var(--weight-semibold);
9256
9919
  color: var(--color-fg-muted);
9257
9920
  background: var(--color-bg);
9258
- border-bottom: 2px solid var(--color-border);
9921
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9259
9922
  white-space: nowrap;
9260
9923
  user-select: none;
9261
9924
  }
@@ -9313,8 +9976,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9313
9976
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9314
9977
  [data-ui="table"] [data-part="th"]:focus-visible,
9315
9978
  [data-ui="table"] [data-part="td"]:focus-visible {
9316
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9317
- outline-offset: -2px;
9979
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9980
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9318
9981
  }
9319
9982
 
9320
9983
  /* ── Data Cell ── */
@@ -9322,7 +9985,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9322
9985
  padding: var(--space-3) var(--space-4);
9323
9986
  font-size: var(--text-sm);
9324
9987
  color: var(--color-fg);
9325
- border-bottom: 1px solid var(--color-border);
9988
+ border-bottom: var(--border-width) solid var(--color-border);
9326
9989
  background: var(--color-bg);
9327
9990
  transition: background var(--duration-fast) var(--ease-default);
9328
9991
  }
@@ -9351,31 +10014,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9351
10014
  Static fallback via nth-child; once the controller stamps data-stripe on the
9352
10015
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9353
10016
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9354
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10017
+ background: var(--stripe-bg);
9355
10018
  }
9356
10019
 
9357
10020
  [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"] {
9358
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10021
+ background: var(--stripe-bg);
9359
10022
  }
9360
10023
 
9361
10024
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9362
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10025
+ background: var(--stripe-bg);
9363
10026
  }
9364
10027
 
9365
10028
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9366
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10029
+ background: var(--stripe-bg);
9367
10030
  }
9368
10031
 
9369
10032
  /* ── Bordered Variant ── */
9370
10033
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9371
- border: 1px solid var(--color-border);
10034
+ border: var(--border-width) solid var(--color-border);
9372
10035
  border-radius: var(--radius-md, 0.375rem);
9373
10036
  overflow: hidden;
9374
10037
  }
9375
10038
 
9376
10039
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9377
10040
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9378
- border: 1px solid var(--color-border);
10041
+ border: var(--border-width) solid var(--color-border);
9379
10042
  }
9380
10043
 
9381
10044
  /* ── Size: Small ── */
@@ -9403,7 +10066,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9403
10066
  /* ── Footer ── */
9404
10067
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9405
10068
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9406
- border-top: 2px solid var(--color-border);
10069
+ border-top: var(--border-width-strong) solid var(--color-border);
9407
10070
  border-bottom: none;
9408
10071
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9409
10072
  }
@@ -9529,7 +10192,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9529
10192
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9530
10193
  padding: var(--space-1) var(--space-2);
9531
10194
  background: var(--color-bg);
9532
- border-bottom: 1px solid var(--color-border);
10195
+ border-bottom: var(--border-width) solid var(--color-border);
9533
10196
  }
9534
10197
 
9535
10198
  [data-ui="table"] [data-part="filter-input"],
@@ -9541,14 +10204,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9541
10204
  font-size: var(--text-xs);
9542
10205
  color: var(--color-fg);
9543
10206
  background: var(--color-bg);
9544
- border: 1px solid var(--color-border);
10207
+ border: var(--border-width) solid var(--color-border);
9545
10208
  border-radius: var(--radius-sm);
9546
10209
  }
9547
10210
 
9548
10211
  [data-ui="table"] [data-part="filter-input"]:focus,
9549
10212
  [data-ui="table"] [data-part="filter"]:focus {
9550
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9551
- outline-offset: -1px;
10213
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10214
+ outline-offset: calc(-1 * var(--border-width));
9552
10215
  border-color: var(--color-primary);
9553
10216
  }
9554
10217
 
@@ -9569,7 +10232,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9569
10232
  text-align: inherit;
9570
10233
  color: var(--color-fg);
9571
10234
  background: var(--color-bg);
9572
- border: 1px solid var(--color-primary);
10235
+ border: var(--border-width) solid var(--color-primary);
9573
10236
  border-radius: var(--radius-sm);
9574
10237
  outline: none;
9575
10238
  }
@@ -9622,11 +10285,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9622
10285
  }
9623
10286
 
9624
10287
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9625
- border-block-start: 2px solid var(--color-primary);
10288
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9626
10289
  }
9627
10290
 
9628
10291
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9629
- border-block-end: 2px solid var(--color-primary);
10292
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9630
10293
  }
9631
10294
 
9632
10295
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9634,11 +10297,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9634
10297
  }
9635
10298
 
9636
10299
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9637
- border-inline-start: 2px solid var(--color-primary);
10300
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9638
10301
  }
9639
10302
 
9640
10303
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9641
- border-inline-end: 2px solid var(--color-primary);
10304
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9642
10305
  }
9643
10306
 
9644
10307
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9711,11 +10374,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9711
10374
  }
9712
10375
 
9713
10376
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9714
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10377
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9715
10378
  }
9716
10379
 
9717
10380
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9718
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10381
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9719
10382
  }
9720
10383
 
9721
10384
  /* ── Column Visibility ── */
@@ -9787,7 +10450,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9787
10450
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9788
10451
  display: block;
9789
10452
  margin-block-end: var(--space-3);
9790
- border: 1px solid var(--color-border);
10453
+ border: var(--border-width) solid var(--color-border);
9791
10454
  border-radius: var(--radius-md);
9792
10455
  background: var(--color-bg);
9793
10456
  overflow: hidden;
@@ -9801,7 +10464,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9801
10464
  gap: var(--space-4);
9802
10465
  text-align: end;
9803
10466
  border-bottom: none;
9804
- border-block-end: 1px solid var(--color-border);
10467
+ border-block-end: var(--border-width) solid var(--color-border);
9805
10468
  }
9806
10469
 
9807
10470
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9898,7 +10561,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9898
10561
 
9899
10562
  /* === recipes/tabs.css === */
9900
10563
  /* @ui:component tabs */
9901
- /* @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 */
10564
+ /* @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 */
9902
10565
 
9903
10566
  /* ── Root ── */
9904
10567
  [data-ui="tabs"] {
@@ -9927,7 +10590,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9927
10590
  border: none;
9928
10591
  background: transparent;
9929
10592
  color: var(--color-fg-muted);
9930
- font-family: var(--font-sans, system-ui, sans-serif);
10593
+ font-family: var(--font-ui);
9931
10594
  font-size: var(--text-sm);
9932
10595
  font-weight: var(--weight-medium);
9933
10596
  cursor: pointer;
@@ -9942,8 +10605,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9942
10605
  }
9943
10606
 
9944
10607
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9945
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9946
- outline-offset: -2px;
10608
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10609
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9947
10610
  border-radius: var(--radius-md);
9948
10611
  }
9949
10612
 
@@ -9953,12 +10616,12 @@ div[data-ui="separator"][data-style="thick"]::after {
9953
10616
 
9954
10617
  /* ── Underline Variant ── */
9955
10618
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
9956
- border-bottom: 1px solid var(--color-border);
10619
+ border-bottom: var(--border-width) solid var(--color-border);
9957
10620
  gap: 0;
9958
10621
  }
9959
10622
 
9960
10623
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
9961
- border-bottom: 2px solid transparent;
10624
+ border-bottom: var(--border-width-strong) solid transparent;
9962
10625
  margin-bottom: -1px;
9963
10626
  border-radius: 0;
9964
10627
  }
@@ -9990,17 +10653,17 @@ div[data-ui="separator"][data-style="thick"]::after {
9990
10653
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
9991
10654
  background: var(--color-bg);
9992
10655
  color: var(--color-fg);
9993
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10656
+ box-shadow: var(--shadow-xs);
9994
10657
  }
9995
10658
 
9996
10659
  /* ── Enclosed Variant ── */
9997
10660
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
9998
- border-bottom: 1px solid var(--color-border);
10661
+ border-bottom: var(--border-width) solid var(--color-border);
9999
10662
  gap: 0;
10000
10663
  }
10001
10664
 
10002
10665
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10003
- border: 1px solid transparent;
10666
+ border: var(--border-width) solid transparent;
10004
10667
  border-bottom: none;
10005
10668
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10006
10669
  margin-bottom: -1px;
@@ -10045,8 +10708,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10045
10708
  @media (forced-colors: active) {
10046
10709
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10047
10710
  /* An outline the OS preserves, on every variant. */
10048
- outline: 2px solid Highlight;
10049
- outline-offset: -2px;
10711
+ outline: var(--border-width-strong) solid Highlight;
10712
+ outline-offset: calc(-1 * var(--border-width-strong));
10050
10713
  }
10051
10714
 
10052
10715
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10061,7 +10724,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10061
10724
 
10062
10725
  /* === recipes/tag-input.css === */
10063
10726
  /* @ui:component tag-input */
10064
- /* @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 */
10727
+ /* @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 */
10065
10728
 
10066
10729
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10067
10730
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10082,7 +10745,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10082
10745
  gap: var(--space-1h);
10083
10746
  width: 100%;
10084
10747
  padding: var(--space-1h) var(--space-2);
10085
- border: 1px solid var(--color-border);
10748
+ border: var(--border-width) solid var(--color-border);
10086
10749
  border-radius: var(--radius-md);
10087
10750
  background: var(--color-bg);
10088
10751
  list-style: none;
@@ -10091,8 +10754,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10091
10754
  }
10092
10755
 
10093
10756
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10094
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10095
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10757
+ border-color: var(--focus-ring-color);
10758
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10096
10759
  }
10097
10760
 
10098
10761
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10103,7 +10766,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10103
10766
  border: none;
10104
10767
  background: transparent;
10105
10768
  color: var(--color-fg);
10106
- font-family: var(--font-sans, system-ui, sans-serif);
10769
+ font-family: var(--font-ui);
10107
10770
  font-size: var(--text-sm);
10108
10771
  line-height: 1.5;
10109
10772
  outline: none;
@@ -10122,7 +10785,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10122
10785
  z-index: var(--z-dropdown);
10123
10786
  margin-top: var(--space-1);
10124
10787
  padding: var(--space-1);
10125
- border: 1px solid var(--color-border);
10788
+ border: var(--border-width) solid var(--color-border);
10126
10789
  border-radius: var(--radius-lg);
10127
10790
  background: var(--color-bg);
10128
10791
  box-shadow: var(--shadow-md);
@@ -10169,7 +10832,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10169
10832
 
10170
10833
  /* === recipes/toast.css === */
10171
10834
  /* @ui:component toast */
10172
- /* @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 */
10835
+ /* @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 */
10173
10836
 
10174
10837
  /* ── Container ── */
10175
10838
  [data-ui="toast"][data-part="container"] {
@@ -10218,8 +10881,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10218
10881
  max-width: 380px;
10219
10882
  width: max-content;
10220
10883
  padding: var(--space-3) var(--space-4);
10221
- background: var(--color-bg);
10222
- border: 1px solid var(--color-border);
10884
+ background: var(--panel-bg);
10885
+ border: var(--border-width) solid var(--color-border);
10223
10886
  border-radius: var(--radius-lg);
10224
10887
  box-shadow: var(--shadow-lg);
10225
10888
  pointer-events: auto;
@@ -10229,6 +10892,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10229
10892
  transform var(--duration-normal) var(--ease-out);
10230
10893
  }
10231
10894
 
10895
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10896
+ [data-ui="toast"] [data-part="toast"] {
10897
+ -webkit-backdrop-filter: var(--surface-backdrop);
10898
+ backdrop-filter: var(--surface-backdrop);
10899
+ }
10900
+ }
10901
+
10232
10902
  /* ── State: Entering ── */
10233
10903
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10234
10904
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10268,7 +10938,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10268
10938
 
10269
10939
  /* ── Tone Variants ── */
10270
10940
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10271
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10941
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10272
10942
  }
10273
10943
 
10274
10944
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10276,7 +10946,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10276
10946
  }
10277
10947
 
10278
10948
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10279
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10949
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10280
10950
  }
10281
10951
 
10282
10952
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10284,7 +10954,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10284
10954
  }
10285
10955
 
10286
10956
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10287
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10957
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10288
10958
  }
10289
10959
 
10290
10960
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10306,7 +10976,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10306
10976
  /* ── Message ── */
10307
10977
  [data-ui="toast"] [data-part="message"] {
10308
10978
  flex: 1;
10309
- font-family: var(--font-sans, system-ui, sans-serif);
10979
+ font-family: var(--font-ui);
10310
10980
  font-size: var(--text-sm);
10311
10981
  font-weight: var(--weight-medium);
10312
10982
  color: var(--color-fg);
@@ -10317,11 +10987,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10317
10987
  [data-ui="toast"] [data-part="action"] {
10318
10988
  flex-shrink: 0;
10319
10989
  padding: var(--space-1, 0.25rem) var(--space-2);
10320
- border: 1px solid var(--color-border);
10990
+ border: var(--border-width) solid var(--color-border);
10321
10991
  border-radius: var(--radius-md, 0.375rem);
10322
10992
  background: transparent;
10323
10993
  color: var(--color-fg);
10324
- font-family: var(--font-sans, system-ui, sans-serif);
10994
+ font-family: var(--font-ui);
10325
10995
  font-size: var(--text-xs, 0.75rem);
10326
10996
  font-weight: var(--weight-medium);
10327
10997
  cursor: pointer;
@@ -10334,8 +11004,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10334
11004
  }
10335
11005
 
10336
11006
  [data-ui="toast"] [data-part="action"]:focus-visible {
10337
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10338
- outline-offset: 2px;
11007
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11008
+ outline-offset: var(--focus-ring-offset);
10339
11009
  }
10340
11010
 
10341
11011
  /* ── Close Button ── */
@@ -10361,8 +11031,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10361
11031
  }
10362
11032
 
10363
11033
  [data-ui="toast"] [data-part="close"]:focus-visible {
10364
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10365
- outline-offset: 2px;
11034
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11035
+ outline-offset: var(--focus-ring-offset);
10366
11036
  }
10367
11037
 
10368
11038
  /* ── Motion ── */
@@ -10375,14 +11045,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10375
11045
 
10376
11046
  /* === recipes/toggle-group.css === */
10377
11047
  /* @ui:component toggle-group */
10378
- /* @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 */
11048
+ /* @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 */
10379
11049
 
10380
11050
  /* ── Root: a segmented row of toggle buttons ── */
10381
11051
  [data-ui="toggle-group"] {
10382
11052
  display: inline-flex;
10383
11053
  gap: var(--space-1);
10384
11054
  padding: var(--space-1);
10385
- border: 1px solid var(--color-border);
11055
+ border: var(--border-width) solid var(--color-border);
10386
11056
  border-radius: var(--radius-md);
10387
11057
  background: var(--color-bg);
10388
11058
  }
@@ -10397,7 +11067,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10397
11067
  border-radius: var(--radius-md);
10398
11068
  background: transparent;
10399
11069
  color: var(--color-fg-muted);
10400
- font-family: var(--toggle-group-font, var(--font-sans));
11070
+ font-family: var(--toggle-group-font, var(--font-ui));
10401
11071
  font-size: var(--text-sm);
10402
11072
  font-weight: var(--weight-medium);
10403
11073
  line-height: 1;
@@ -10438,13 +11108,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10438
11108
 
10439
11109
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10440
11110
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10441
- outline: 2px solid var(--color-ring);
10442
- outline-offset: 2px;
11111
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11112
+ outline-offset: var(--focus-ring-offset);
10443
11113
  }
10444
11114
 
10445
11115
  /* ── Disabled control ── */
10446
11116
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10447
- opacity: 0.5;
11117
+ opacity: var(--disabled-opacity);
10448
11118
  cursor: not-allowed;
10449
11119
  }
10450
11120
 
@@ -10457,7 +11127,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10457
11127
 
10458
11128
  /* === recipes/tooltip.css === */
10459
11129
  /* @ui:component tooltip */
10460
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11130
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10461
11131
 
10462
11132
  /* ── Root ── */
10463
11133
  [data-ui="tooltip"] {
@@ -10478,7 +11148,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10478
11148
  color: var(--color-bg);
10479
11149
  border-radius: var(--radius-md);
10480
11150
  padding: var(--space-1h, 0.375rem) var(--space-2);
10481
- font-family: var(--font-sans, system-ui, sans-serif);
11151
+ font-family: var(--font-ui);
10482
11152
  font-size: var(--text-xs, 0.75rem);
10483
11153
  line-height: 1.4;
10484
11154
  white-space: nowrap;
@@ -10489,6 +11159,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10489
11159
  transform var(--duration-fast) var(--ease-default);
10490
11160
  }
10491
11161
 
11162
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11163
+ [data-ui="tooltip"] [data-part="content"] {
11164
+ -webkit-backdrop-filter: var(--surface-backdrop);
11165
+ backdrop-filter: var(--surface-backdrop);
11166
+ }
11167
+ }
11168
+
10492
11169
  /* Default position (top) when no variant is specified */
10493
11170
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10494
11171
  bottom: 100%;
@@ -10604,7 +11281,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10604
11281
 
10605
11282
  /* === recipes/tree-view.css === */
10606
11283
  /* @ui:component tree-view */
10607
- /* @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 */
11284
+ /* @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 */
10608
11285
 
10609
11286
  [data-ui="tree-view"],
10610
11287
  [data-ui="tree-view"] [data-part="group"] {
@@ -10617,7 +11294,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10617
11294
  inline-size: 100%;
10618
11295
  padding: var(--space-1);
10619
11296
  color: var(--color-fg);
10620
- font-family: var(--font-sans);
11297
+ font-family: var(--font-ui);
10621
11298
  font-size: var(--text-sm);
10622
11299
  }
10623
11300
 
@@ -10645,8 +11322,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10645
11322
  }
10646
11323
 
10647
11324
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10648
- outline: var(--space-px) solid var(--color-ring);
10649
- outline-offset: var(--space-px);
11325
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11326
+ outline-offset: var(--focus-ring-offset);
10650
11327
  }
10651
11328
 
10652
11329
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10685,7 +11362,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10685
11362
 
10686
11363
  /* === patterns/auth-form.css === */
10687
11364
  /* @ui:component auth-form */
10688
- /* @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 */
11365
+ /* @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 */
10689
11366
 
10690
11367
  /* ── Root Container ── */
10691
11368
  [data-ui="auth-form"] {
@@ -10693,7 +11370,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10693
11370
  align-items: center;
10694
11371
  justify-content: center;
10695
11372
  width: 100%;
10696
- font-family: var(--font-sans);
11373
+ font-family: var(--font-body);
10697
11374
  }
10698
11375
 
10699
11376
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10725,9 +11402,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10725
11402
 
10726
11403
  [data-ui="auth-form"] [data-part="title"] {
10727
11404
  margin: 0;
11405
+ font-family: var(--font-heading);
10728
11406
  font-size: var(--text-xl);
10729
- font-weight: var(--weight-bold);
10730
- line-height: var(--leading-tight);
11407
+ font-weight: var(--heading-weight);
11408
+ letter-spacing: var(--heading-tracking);
11409
+ text-transform: var(--heading-transform);
11410
+ font-variant-caps: var(--heading-caps);
11411
+ line-height: var(--heading-leading);
10731
11412
  color: var(--color-fg);
10732
11413
  }
10733
11414
 
@@ -10744,7 +11425,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10744
11425
  margin: var(--space-4) var(--space-6) 0;
10745
11426
  padding: var(--space-3);
10746
11427
  background: var(--color-destructive-subtle);
10747
- border: 1px solid var(--color-destructive);
11428
+ border: var(--border-width) solid var(--color-destructive);
10748
11429
  border-radius: var(--radius-lg);
10749
11430
  color: var(--color-destructive);
10750
11431
  font-size: var(--text-sm);
@@ -10822,13 +11503,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10822
11503
  }
10823
11504
 
10824
11505
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10825
- text-decoration: underline;
11506
+ text-decoration-line: var(--link-decoration);
10826
11507
  color: var(--color-primary-hover);
10827
11508
  }
10828
11509
 
10829
11510
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10830
- outline: 2px solid var(--color-ring);
10831
- outline-offset: 2px;
11511
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11512
+ outline-offset: var(--focus-ring-offset);
10832
11513
  border-radius: var(--radius-sm, 0.25rem);
10833
11514
  }
10834
11515
 
@@ -10956,8 +11637,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10956
11637
  max-width: var(--auth-form-max-width, 400px);
10957
11638
  border-radius: var(--card-radius, var(--radius-lg));
10958
11639
  box-shadow: var(--card-shadow, var(--shadow-sm));
10959
- border-inline-start: 1px solid var(--card-border, var(--color-border));
10960
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11640
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11641
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
10961
11642
  }
10962
11643
  }
10963
11644
 
@@ -10972,7 +11653,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10972
11653
 
10973
11654
  /* === patterns/crud-table.css === */
10974
11655
  /* @ui:component crud-table */
10975
- /* @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 */
11656
+ /* @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 */
10976
11657
 
10977
11658
  /* ── Root ── */
10978
11659
  [data-ui="crud-table"] {
@@ -10980,7 +11661,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10980
11661
  flex-direction: column;
10981
11662
  gap: var(--space-4);
10982
11663
  width: 100%;
10983
- font-family: var(--font-sans, system-ui, sans-serif);
11664
+ font-family: var(--font-body);
10984
11665
  }
10985
11666
 
10986
11667
  /* ── Toolbar ── */
@@ -11038,7 +11719,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11038
11719
  gap: var(--space-3);
11039
11720
  padding: var(--space-3) var(--space-4);
11040
11721
  background: var(--color-bg-subtle);
11041
- border: 1px solid var(--color-border);
11722
+ border: var(--border-width) solid var(--color-border);
11042
11723
  border-radius: var(--radius-md);
11043
11724
  }
11044
11725
 
@@ -11053,7 +11734,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11053
11734
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11054
11735
  width: 100%;
11055
11736
  overflow-x: auto;
11056
- border: 1px solid var(--color-border);
11737
+ border: var(--border-width) solid var(--color-border);
11057
11738
  border-radius: var(--radius-lg);
11058
11739
  background: var(--color-bg);
11059
11740
  }
@@ -11083,7 +11764,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11083
11764
  padding: var(--space-8) var(--space-4);
11084
11765
  text-align: center;
11085
11766
  min-height: 240px;
11086
- border: 1px dashed var(--color-border);
11767
+ border: var(--border-width) dashed var(--color-border);
11087
11768
  border-radius: var(--radius-lg);
11088
11769
  background: var(--color-bg);
11089
11770
  }
@@ -11196,7 +11877,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11196
11877
 
11197
11878
  /* === patterns/dashboard-shell.css === */
11198
11879
  /* @ui:component dashboard-shell */
11199
- /* @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 */
11880
+ /* @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 */
11200
11881
 
11201
11882
  /* ── Shell Grid Layout ──
11202
11883
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11221,7 +11902,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11221
11902
  "footer";
11222
11903
  min-height: 100vh;
11223
11904
  background: var(--color-bg);
11224
- font-family: var(--font-sans);
11905
+ font-family: var(--font-body);
11225
11906
  color: var(--color-fg);
11226
11907
  }
11227
11908
 
@@ -11245,7 +11926,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11245
11926
  gap: var(--space-2);
11246
11927
  padding: var(--space-4);
11247
11928
  background: var(--color-bg-subtle);
11248
- border-inline-end: 1px solid var(--color-border);
11929
+ border-inline-end: var(--border-width) solid var(--color-border);
11249
11930
  overflow-y: auto;
11250
11931
  position: fixed;
11251
11932
  top: 0;
@@ -11265,7 +11946,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11265
11946
 
11266
11947
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11267
11948
  border-inline-end: none;
11268
- border-inline-start: 1px solid var(--color-border);
11949
+ border-inline-start: var(--border-width) solid var(--color-border);
11269
11950
  inset-inline-start: auto;
11270
11951
  inset-inline-end: 0;
11271
11952
  transform: translateX(100%);
@@ -11340,7 +12021,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11340
12021
  gap: var(--space-3);
11341
12022
  padding: var(--space-2) var(--space-3);
11342
12023
  border-radius: var(--radius-md);
11343
- font-family: var(--font-sans);
12024
+ font-family: var(--font-ui);
11344
12025
  font-size: var(--text-sm);
11345
12026
  font-weight: var(--weight-medium);
11346
12027
  line-height: var(--leading-normal);
@@ -11359,8 +12040,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11359
12040
  }
11360
12041
 
11361
12042
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11362
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11363
- outline-offset: -2px;
12043
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12044
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11364
12045
  }
11365
12046
 
11366
12047
  /* ── Nav Item Active ── */
@@ -11407,7 +12088,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11407
12088
  gap: var(--space-2);
11408
12089
  padding: 0 var(--space-3);
11409
12090
  background: var(--color-bg);
11410
- border-bottom: 1px solid var(--color-border);
12091
+ border-bottom: var(--border-width) solid var(--color-border);
11411
12092
  position: sticky;
11412
12093
  top: 0;
11413
12094
  z-index: var(--z-sticky);
@@ -11488,7 +12169,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11488
12169
  align-items: center;
11489
12170
  gap: var(--space-3);
11490
12171
  padding: var(--space-4) var(--space-6);
11491
- border-top: 1px solid var(--color-border);
12172
+ border-top: var(--border-width) solid var(--color-border);
11492
12173
  font-size: var(--text-xs);
11493
12174
  color: var(--color-fg-muted);
11494
12175
  }
@@ -11571,7 +12252,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11571
12252
 
11572
12253
  /* === patterns/document.css === */
11573
12254
  /* @ui:component document */
11574
- /* @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 */
12255
+ /* @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 */
11575
12256
 
11576
12257
  /* ── Page Rules ── */
11577
12258
  @page {
@@ -11611,14 +12292,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11611
12292
  max-width: var(--doc-max-width);
11612
12293
  margin: var(--space-4) auto;
11613
12294
  padding: var(--space-6) var(--space-4);
11614
- background: var(--color-bg, #fff);
12295
+ background-color: var(--color-bg, #fff);
12296
+ background-image: var(--texture-page);
11615
12297
  color: var(--color-fg);
11616
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12298
+ font-family: var(--doc-font, var(--font-body));
11617
12299
  font-size: var(--doc-font-size);
11618
12300
  line-height: var(--doc-line-height);
11619
- box-shadow: var(--shadow-lg,
11620
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11621
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12301
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12302
+ colour no theme could reach. --shadow-lg is always defined by the token
12303
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12304
+ than re-tokenised. */
12305
+ box-shadow: var(--shadow-lg);
11622
12306
  border-radius: 0;
11623
12307
  position: relative;
11624
12308
  }
@@ -11634,7 +12318,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11634
12318
  [data-ui="document"] > [data-part="header"] {
11635
12319
  margin-block-end: var(--doc-section-gap);
11636
12320
  padding-block-end: var(--doc-component-gap);
11637
- border-block-end: 1px solid var(--color-border);
12321
+ border-block-end: var(--border-width) solid var(--color-border);
11638
12322
  }
11639
12323
 
11640
12324
  /* ── Body ── */
@@ -11644,13 +12328,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11644
12328
  gap: var(--doc-section-gap);
11645
12329
  }
11646
12330
 
12331
+ /* ── Headings ──
12332
+ The document's own heading face and weight (1.1A-21): a print theme sets
12333
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12334
+ from the body copy (document-serif's Times titles over Georgia text). Both
12335
+ default to the page's heading role in tokens/document.css, and each falls
12336
+ back to what a heading rendered before the tokens had a reader. A heading
12337
+ that carries its own data-weight keeps it — that is the author asking. */
12338
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12339
+ font-family: var(--doc-heading-font, var(--font-body));
12340
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12341
+ }
12342
+
11647
12343
  /* ── Running footer ──
11648
12344
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11649
12345
  [data-ui="document"] > [data-part="doc-footer"],
11650
12346
  [data-ui="document"] > [data-part="footer"] {
11651
12347
  margin-block-start: var(--doc-section-gap);
11652
12348
  padding-block-start: var(--doc-component-gap);
11653
- border-block-start: 1px solid var(--color-border);
12349
+ border-block-start: var(--border-width) solid var(--color-border);
11654
12350
  font-size: var(--doc-legal-size);
11655
12351
  color: var(--doc-legal-color);
11656
12352
  }
@@ -11688,7 +12384,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11688
12384
 
11689
12385
  /* ── Variant: Report ── */
11690
12386
  [data-ui="document"][data-variant="report"] {
11691
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12387
+ /* A report is serif-set by definition. It re-points the document's own font
12388
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12389
+ (key-value, callout, signature — all of which read --doc-font) follows the
12390
+ report into serif instead of staying sans inside a serif page. `report` is
12391
+ the author asking for serif; a theme that wants its own document face
12392
+ declares --doc-font at :root, which this variant deliberately outranks. */
12393
+ --doc-font: Georgia, 'Times New Roman', serif;
11692
12394
  line-height: 1.6;
11693
12395
  }
11694
12396
 
@@ -11783,7 +12485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11783
12485
  z-index: var(--z-raised);
11784
12486
  margin-block-end: 0;
11785
12487
  padding-block-end: var(--doc-running-gap);
11786
- border-block-end: 1px solid var(--doc-print-border-color);
12488
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11787
12489
  background: var(--doc-bg);
11788
12490
  transform: translateZ(0);
11789
12491
  }
@@ -11799,7 +12501,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11799
12501
  z-index: var(--z-raised);
11800
12502
  margin-block-start: 0;
11801
12503
  padding-block-start: var(--doc-running-gap);
11802
- border-block-start: 1px solid var(--doc-print-border-color);
12504
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11803
12505
  background: var(--doc-bg);
11804
12506
  transform: translateZ(0);
11805
12507
  }
@@ -11828,7 +12530,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11828
12530
 
11829
12531
  /* === patterns/empty-state.css === */
11830
12532
  /* @ui:component empty-state */
11831
- /* @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 */
12533
+ /* @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 */
11832
12534
 
11833
12535
  /* ── Root ── */
11834
12536
  [data-ui="empty-state"] {
@@ -11839,7 +12541,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11839
12541
  text-align: center;
11840
12542
  padding: var(--space-8) var(--space-6);
11841
12543
  gap: var(--space-3);
11842
- font-family: var(--font-sans, system-ui, sans-serif);
12544
+ font-family: var(--font-body);
11843
12545
  }
11844
12546
 
11845
12547
  /* ── Icon ── */
@@ -11862,10 +12564,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11862
12564
 
11863
12565
  /* ── Title ── */
11864
12566
  [data-ui="empty-state"] [data-part="title"] {
11865
- font-family: var(--font-sans, system-ui, sans-serif);
12567
+ font-family: var(--font-heading);
11866
12568
  font-size: var(--text-lg);
11867
12569
  font-weight: var(--weight-semibold);
11868
- line-height: var(--leading-tight);
12570
+ letter-spacing: var(--heading-tracking);
12571
+ text-transform: var(--heading-transform);
12572
+ font-variant-caps: var(--heading-caps);
12573
+ line-height: var(--heading-leading);
11869
12574
  color: var(--color-fg);
11870
12575
  margin: 0;
11871
12576
  }
@@ -11963,7 +12668,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11963
12668
 
11964
12669
  /* === patterns/feature-grid.css === */
11965
12670
  /* @ui:component feature-grid */
11966
- /* @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 */
12671
+ /* @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 */
11967
12672
 
11968
12673
  /* ── Root ──
11969
12674
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -11973,7 +12678,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11973
12678
  gap: var(--space-4);
11974
12679
  padding-block: var(--space-12);
11975
12680
  padding-inline: var(--space-4);
11976
- font-family: var(--font-sans, system-ui, sans-serif);
12681
+ font-family: var(--font-body);
11977
12682
  color: var(--color-fg);
11978
12683
  background: var(--color-bg);
11979
12684
  }
@@ -12115,7 +12820,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12115
12820
  max-inline-size: var(--measure-narrow);
12116
12821
  margin-inline: auto;
12117
12822
  padding-block: var(--space-8);
12118
- font-family: var(--font-sans);
12823
+ font-family: var(--font-body);
12119
12824
  }
12120
12825
 
12121
12826
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12135,7 +12840,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12135
12840
 
12136
12841
  /* === patterns/hero.css === */
12137
12842
  /* @ui:component hero */
12138
- /* @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 */
12843
+ /* @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 */
12139
12844
 
12140
12845
  /* ── Root ──
12141
12846
  A one-column grid by default; the layout variants only change how that grid
@@ -12149,9 +12854,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12149
12854
  gap: var(--space-4);
12150
12855
  padding-block: var(--space-12);
12151
12856
  padding-inline: var(--space-4);
12152
- font-family: var(--font-sans, system-ui, sans-serif);
12857
+ font-family: var(--font-body);
12153
12858
  color: var(--color-fg);
12154
- background: var(--color-bg);
12859
+ background-color: var(--color-bg);
12860
+ background-image: var(--texture-surface);
12155
12861
  }
12156
12862
 
12157
12863
  /* ── Eyebrow ── */
@@ -12163,9 +12869,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12163
12869
  /* ── Headline ── */
12164
12870
  [data-ui="hero"] [data-part="headline"] {
12165
12871
  margin: 0;
12872
+ font-family: var(--font-heading);
12166
12873
  font-size: var(--text-3xl);
12167
- font-weight: var(--weight-bold);
12168
- line-height: var(--leading-tight);
12874
+ font-weight: var(--heading-weight);
12875
+ letter-spacing: var(--heading-tracking);
12876
+ text-transform: var(--heading-transform);
12877
+ font-variant-caps: var(--heading-caps);
12878
+ line-height: var(--heading-leading);
12169
12879
  color: var(--color-fg);
12170
12880
  text-wrap: balance;
12171
12881
  }
@@ -12284,7 +12994,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12284
12994
 
12285
12995
  /* === patterns/inbox.css === */
12286
12996
  /* @ui:component inbox */
12287
- /* @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 */
12997
+ /* @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 */
12288
12998
 
12289
12999
  /* ── Root ──
12290
13000
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12304,7 +13014,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12304
13014
  overflow: hidden;
12305
13015
  border: var(--space-px, 1px) solid var(--color-border);
12306
13016
  border-radius: var(--radius-lg);
12307
- font-family: var(--font-sans, system-ui, sans-serif);
13017
+ font-family: var(--font-body);
12308
13018
  color: var(--color-fg);
12309
13019
  background: var(--color-bg);
12310
13020
  }
@@ -12396,8 +13106,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12396
13106
  }
12397
13107
 
12398
13108
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12399
- outline: 2px solid var(--color-ring);
12400
- outline-offset: 2px;
13109
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13110
+ outline-offset: var(--focus-ring-offset);
12401
13111
  }
12402
13112
 
12403
13113
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12556,7 +13266,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12556
13266
 
12557
13267
  /* === patterns/pricing.css === */
12558
13268
  /* @ui:component pricing */
12559
- /* @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 */
13269
+ /* @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 */
12560
13270
 
12561
13271
  /* ── Root ──
12562
13272
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12566,7 +13276,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12566
13276
  gap: var(--space-4);
12567
13277
  padding-block: var(--space-12);
12568
13278
  padding-inline: var(--space-4);
12569
- font-family: var(--font-sans, system-ui, sans-serif);
13279
+ font-family: var(--font-body);
12570
13280
  color: var(--color-fg);
12571
13281
  background: var(--color-bg);
12572
13282
  }
@@ -12616,9 +13326,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12616
13326
 
12617
13327
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12618
13328
  margin: 0;
13329
+ font-family: var(--font-heading);
12619
13330
  font-size: var(--text-lg);
12620
13331
  font-weight: var(--weight-semibold);
12621
- line-height: var(--leading-tight);
13332
+ letter-spacing: var(--heading-tracking);
13333
+ text-transform: var(--heading-transform);
13334
+ font-variant-caps: var(--heading-caps);
13335
+ line-height: var(--heading-leading);
12622
13336
  }
12623
13337
 
12624
13338
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12679,7 +13393,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12679
13393
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12680
13394
  border-color: var(--color-primary);
12681
13395
  box-shadow: var(--shadow-md);
12682
- outline: var(--space-px, 1px) solid var(--color-primary);
13396
+ outline: var(--border-width-strong) solid var(--color-primary);
12683
13397
  }
12684
13398
 
12685
13399
  /* ── Footnote ── */
@@ -12724,14 +13438,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12724
13438
 
12725
13439
  /* === patterns/search-results.css === */
12726
13440
  /* @ui:component search-results */
12727
- /* @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 */
13441
+ /* @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 */
12728
13442
 
12729
13443
  /* ── Root ── */
12730
13444
  [data-ui="search-results"] {
12731
13445
  display: flex;
12732
13446
  flex-direction: column;
12733
13447
  gap: var(--space-4);
12734
- font-family: var(--font-sans, system-ui, sans-serif);
13448
+ font-family: var(--font-body);
12735
13449
  }
12736
13450
 
12737
13451
  /* ── Search Input ── */
@@ -12759,7 +13473,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12759
13473
  justify-content: space-between;
12760
13474
  gap: var(--space-4);
12761
13475
  padding-bottom: var(--space-2);
12762
- border-bottom: 1px solid var(--color-border);
13476
+ border-bottom: var(--border-width) solid var(--color-border);
12763
13477
  }
12764
13478
 
12765
13479
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12794,7 +13508,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12794
13508
  flex-direction: column;
12795
13509
  gap: var(--space-2);
12796
13510
  padding: var(--space-4);
12797
- border: 1px solid var(--color-border);
13511
+ border: var(--border-width) solid var(--color-border);
12798
13512
  border-radius: var(--radius-md);
12799
13513
  background: var(--color-bg);
12800
13514
  transition: background var(--duration-fast) var(--ease-default),
@@ -12853,7 +13567,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12853
13567
  display: flex;
12854
13568
  justify-content: center;
12855
13569
  padding-top: var(--space-4);
12856
- border-top: 1px solid var(--color-border);
13570
+ border-top: var(--border-width) solid var(--color-border);
12857
13571
  }
12858
13572
 
12859
13573
  /* ── Loading ── */
@@ -12893,7 +13607,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12893
13607
 
12894
13608
  /* ── Error State ── */
12895
13609
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12896
- border: 1px solid var(--color-border);
13610
+ border: var(--border-width) solid var(--color-border);
12897
13611
  border-radius: var(--radius-md);
12898
13612
  padding: var(--space-6);
12899
13613
  text-align: center;
@@ -12902,8 +13616,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12902
13616
 
12903
13617
  /* ── Focus management ── */
12904
13618
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12905
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12906
- outline-offset: 2px;
13619
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13620
+ outline-offset: var(--focus-ring-offset);
12907
13621
  }
12908
13622
 
12909
13623
  /* ── Motion ── */
@@ -12919,7 +13633,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12919
13633
 
12920
13634
  /* === patterns/settings-page.css === */
12921
13635
  /* @ui:component settings-page */
12922
- /* @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 */
13636
+ /* @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 */
12923
13637
 
12924
13638
  /* ── Root ── */
12925
13639
  [data-ui="settings-page"] {
@@ -12929,7 +13643,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12929
13643
  width: 100%;
12930
13644
  max-width: 768px;
12931
13645
  margin-inline: auto;
12932
- font-family: var(--font-sans, system-ui, sans-serif);
13646
+ font-family: var(--font-body);
12933
13647
  color: var(--color-fg);
12934
13648
  }
12935
13649
 
@@ -12943,9 +13657,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12943
13657
  /* ── Title ── */
12944
13658
  [data-ui="settings-page"] [data-part="title"] {
12945
13659
  margin: 0;
13660
+ font-family: var(--font-heading);
12946
13661
  font-size: var(--text-xl, 1.25rem);
12947
13662
  font-weight: var(--weight-semibold, 600);
12948
- line-height: var(--leading-tight);
13663
+ letter-spacing: var(--heading-tracking);
13664
+ text-transform: var(--heading-transform);
13665
+ font-variant-caps: var(--heading-caps);
13666
+ line-height: var(--heading-leading);
12949
13667
  color: var(--color-fg);
12950
13668
  }
12951
13669
 
@@ -13009,7 +13727,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13009
13727
  gap: var(--space-3, 0.75rem);
13010
13728
  padding: var(--space-4);
13011
13729
  background: var(--color-bg);
13012
- border-top: 1px solid var(--color-border);
13730
+ border-top: var(--border-width) solid var(--color-border);
13013
13731
  border-radius: var(--radius-lg);
13014
13732
  box-shadow: var(--shadow-md);
13015
13733
  position: sticky;
@@ -13073,7 +13791,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13073
13791
  flex-direction: row;
13074
13792
  flex-wrap: wrap;
13075
13793
  border-inline-end: none;
13076
- border-bottom: 1px solid var(--color-border);
13794
+ border-bottom: var(--border-width) solid var(--color-border);
13077
13795
  padding-inline-end: 0;
13078
13796
  position: static;
13079
13797
  }
@@ -13092,7 +13810,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13092
13810
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13093
13811
  flex-direction: column;
13094
13812
  border-bottom: none;
13095
- border-inline-end: 1px solid var(--color-border);
13813
+ border-inline-end: var(--border-width) solid var(--color-border);
13096
13814
  padding-inline-end: var(--space-4);
13097
13815
  position: sticky;
13098
13816
  top: var(--space-4);
@@ -13110,7 +13828,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13110
13828
  justify-content: flex-start;
13111
13829
  text-align: start;
13112
13830
  border-bottom: none;
13113
- border-inline-start: 2px solid transparent;
13831
+ border-inline-start: var(--border-width-strong) solid transparent;
13114
13832
  margin-bottom: 0;
13115
13833
  margin-inline-end: -1px;
13116
13834
  padding: var(--space-2) var(--space-3);
@@ -13144,7 +13862,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13144
13862
 
13145
13863
  /* === patterns/site-footer.css === */
13146
13864
  /* @ui:component site-footer */
13147
- /* @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 */
13865
+ /* @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 */
13148
13866
 
13149
13867
  /* ── Root ──
13150
13868
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13154,11 +13872,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13154
13872
  gap: var(--space-8);
13155
13873
  padding-block: var(--space-10);
13156
13874
  padding-inline: var(--space-4);
13157
- font-family: var(--font-sans, system-ui, sans-serif);
13875
+ font-family: var(--font-body);
13158
13876
  font-size: var(--text-sm);
13159
13877
  color: var(--color-fg-muted);
13160
13878
  background: var(--color-bg-subtle);
13161
- border-block-start: 1px solid var(--color-border);
13879
+ border-block-start: var(--border-width) solid var(--color-border);
13162
13880
  }
13163
13881
 
13164
13882
  /* ── Brand ── */
@@ -13290,7 +14008,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13290
14008
 
13291
14009
  /* === patterns/stats-dashboard.css === */
13292
14010
  /* @ui:component stats-dashboard */
13293
- /* @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 */
14011
+ /* @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 */
13294
14012
 
13295
14013
  /* ── Root ──
13296
14014
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13303,7 +14021,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13303
14021
  gap: var(--space-3);
13304
14022
  padding-block: var(--space-8);
13305
14023
  padding-inline: var(--space-4);
13306
- font-family: var(--font-sans, system-ui, sans-serif);
14024
+ font-family: var(--font-body);
13307
14025
  color: var(--color-fg);
13308
14026
  background: var(--color-bg);
13309
14027
  }
@@ -13377,9 +14095,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13377
14095
 
13378
14096
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13379
14097
  margin: 0;
14098
+ font-family: var(--font-heading);
13380
14099
  font-size: var(--text-lg);
13381
14100
  font-weight: var(--weight-semibold);
13382
- line-height: var(--leading-tight);
14101
+ letter-spacing: var(--heading-tracking);
14102
+ text-transform: var(--heading-transform);
14103
+ font-variant-caps: var(--heading-caps);
14104
+ line-height: var(--heading-leading);
13383
14105
  }
13384
14106
 
13385
14107
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13470,7 +14192,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13470
14192
  gap: var(--space-6);
13471
14193
  max-inline-size: var(--measure-narrow);
13472
14194
  margin-inline: auto;
13473
- font-family: var(--font-sans);
14195
+ font-family: var(--font-body);
13474
14196
  }
13475
14197
 
13476
14198
  [data-ui="wizard"] [data-part="heading"] {