@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/glass.css === */
645
1033
  /* @ui:theme glass — frosted translucent surfaces over cool neutrals; indigo accent, layered and airy */
646
1034
 
@@ -651,10 +1039,15 @@
651
1039
  its own. This is what a browser without backdrop-filter renders.
652
1040
  2. The `@supports ((-webkit-backdrop-filter: …) or (backdrop-filter: …))`
653
1041
  block at the end is the only place translucency exists: it re-points the
654
- elevated-surface tokens at `color-mix(… , transparent)` values and frosts
655
- the floating panels with `backdrop-filter`. No color-mix or
656
- backdrop-filter appears outside that block, so degradation is the solid
657
- theme above, not a half-transparent one.
1042
+ elevated-surface tokens at `color-mix(… , transparent)` values and names
1043
+ the frost in `--surface-backdrop`. No color-mix or backdrop-filter value
1044
+ appears outside that block, so degradation is the solid theme above, not a
1045
+ half-transparent one.
1046
+
1047
+ Since 1.1A-14 that block declares TOKENS and nothing else: the components
1048
+ carry the `backdrop-filter: var(--surface-backdrop)` declaration (1.1A-04)
1049
+ and the panel fill is `--panel-bg`, so the theme no longer reaches into five
1050
+ components by selector to say one thing about surfaces.
658
1051
 
659
1052
  Contrast is gated twice (tests/themes/glass.test.ts): the solid fallbacks
660
1053
  through the standard `contrast-tokens` maths, and the translucent surfaces
@@ -709,6 +1102,16 @@
709
1102
  --color-border-strong: oklch(0.79 0.016 250);
710
1103
  --color-ring: oklch(0.50 0.20 275);
711
1104
 
1105
+ /* ── Radii (generous — a pane of glass has no sharp corner) ──
1106
+ The silhouette this theme always had in the design and never in tokens:
1107
+ every radius steps up one notch from the base ladder, which is what makes
1108
+ `shape.radius` derive `round` rather than the registry's `soft`. */
1109
+ --radius-sm: 0.375rem; /* 6px */
1110
+ --radius-md: 0.625rem; /* 10px */
1111
+ --radius-lg: 0.875rem; /* 14px */
1112
+ --radius-xl: 1.125rem; /* 18px */
1113
+ --radius-2xl: 1.5rem; /* 24px */
1114
+
712
1115
  /* ── Shadows (large, soft — surfaces float) ── */
713
1116
  --shadow-xs: 0 1px 3px oklch(0.30 0.04 260 / 0.08);
714
1117
  --shadow-sm: 0 2px 8px oklch(0.30 0.04 260 / 0.10);
@@ -717,6 +1120,18 @@
717
1120
  --shadow-xl: 0 24px 56px oklch(0.30 0.04 260 / 0.18), 0 8px 16px oklch(0.30 0.04 260 / 0.08);
718
1121
  }
719
1122
 
1123
+ :root,
1124
+ [data-theme] {
1125
+ /* ── Controls: filled wells ──
1126
+ A text field on a frosted page is a recess, not an outlined box on the same
1127
+ white as the page behind it. `--input-fill` (1.1A-05) is the one declaration
1128
+ that fills `input`, `textarea` and `select` together.
1129
+ On `:root, [data-theme]`: the token layer re-resolves these aliases on
1130
+ every scheme island (tokens/aliases.css), so a `:root`-only override
1131
+ would fall back to the default inside a nested `data-theme` region. */
1132
+ --input-fill: var(--input-bg-filled);
1133
+ }
1134
+
720
1135
  /* ── Dark Mode ── */
721
1136
  /* Deep blue-gray glass, luminous periwinkle primary */
722
1137
  [data-theme="dark"] {
@@ -834,34 +1249,36 @@
834
1249
  transparent)` premultiplies to C at alpha p/100, and the tokens mix from
835
1250
  `var(--color-bg…)`, so one declaration follows both schemes.
836
1251
 
837
- Frosted targets: the card surface (via its `--card-bg` alias) and the four
838
- floating panels that hardcode `background: var(--color-bg)` in their recipe
839
- CSS — dialog/sheet panels, popover content, toast. Those need an element
840
- rule to go translucent; the `:root` prefix lifts specificity above the
841
- recipe's own `[data-ui] [data-part]` rule regardless of load order (same
842
- trick as the contrast theme's focus rings). ── */
1252
+ Three declarations now say what fourteen lines of component selectors said:
1253
+
1254
+ --surface-backdrop the frost itself. Every surface that can float — card,
1255
+ surface[data-variant="overlay"] and the seven floating
1256
+ recipes — already declares
1257
+ `backdrop-filter: var(--surface-backdrop)` inside this
1258
+ same feature query, so the theme states the value and
1259
+ the components decide where it lands.
1260
+ --card-bg the card's own translucent fill (a 1.0 alias).
1261
+ --panel-bg the fill of everything that floats WITHOUT a surface of
1262
+ its own — dialog and sheet panels, drawer, popover
1263
+ content and its arrow, dropdown menu, toast. A frost
1264
+ behind an opaque fill renders nothing, which is why the
1265
+ fill has to be a token too (1.1A-14).
1266
+
1267
+ `--glass-blur` stays: it is this theme's own knob, and naming it keeps the
1268
+ radius of the frost readable in one place. ── */
843
1269
  @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
844
1270
  :root {
845
- --glass-blur: 16px;
846
- /* Elevated surfaces: solid → frosted (scheme-aware via var()). */
847
- --card-bg: color-mix(in oklch, var(--color-surface-1) 82%, transparent);
848
- --glass-panel: color-mix(in oklch, var(--color-bg) 78%, transparent);
1271
+ --glass-blur: 16px;
1272
+ --surface-backdrop: blur(var(--glass-blur)) saturate(140%);
849
1273
  }
850
1274
 
851
- :root [data-ui="card"],
852
- :root [data-ui="dialog"] [data-part="panel"],
853
- :root [data-ui="sheet"] [data-part="panel"],
854
- :root [data-ui="popover"] [data-part="content"],
855
- :root [data-ui="toast"] [data-part="toast"] {
856
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
857
- backdrop-filter: blur(var(--glass-blur)) saturate(140%);
858
- }
859
-
860
- :root [data-ui="dialog"] [data-part="panel"],
861
- :root [data-ui="sheet"] [data-part="panel"],
862
- :root [data-ui="popover"] [data-part="content"],
863
- :root [data-ui="toast"] [data-part="toast"] {
864
- background: var(--glass-panel);
1275
+ /* Elevated surfaces: solid → frosted (scheme-aware via var()). On every
1276
+ `[data-theme]` island too: the token layer re-resolves both aliases there,
1277
+ so a `:root`-only frost would turn opaque inside a nested scheme region. */
1278
+ :root,
1279
+ [data-theme] {
1280
+ --card-bg: color-mix(in oklch, var(--color-surface-1) 82%, transparent);
1281
+ --panel-bg: color-mix(in oklch, var(--color-bg) 78%, transparent);
865
1282
  }
866
1283
  }
867
1284
 
@@ -879,11 +1296,38 @@
879
1296
  padding: 0;
880
1297
  }
881
1298
 
1299
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1300
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1301
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1302
+ these three rules; declaring them here (rather than in each theme) is what
1303
+ makes the two authoring forms interchangeable. Nothing else in the registry
1304
+ declares `color-scheme`, so this is purely additive.
1305
+
1306
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1307
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1308
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1309
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1310
+ dark island inside a light page has always worked here. */
1311
+ :root {
1312
+ color-scheme: light;
1313
+ }
1314
+
1315
+ [data-theme="dark"] {
1316
+ color-scheme: dark;
1317
+ }
1318
+
1319
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1320
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1321
+ does for a theme authored in the three-block form. */
1322
+ [data-theme="auto"] {
1323
+ color-scheme: light dark;
1324
+ }
1325
+
882
1326
  html {
883
1327
  -webkit-text-size-adjust: 100%;
884
1328
  -moz-tab-size: 4;
885
1329
  tab-size: 4;
886
- font-family: var(--font-sans);
1330
+ font-family: var(--font-body);
887
1331
  font-size: var(--text-base);
888
1332
  line-height: var(--leading-normal);
889
1333
  color: var(--color-fg);
@@ -894,6 +1338,11 @@ html {
894
1338
 
895
1339
  body {
896
1340
  min-height: 100dvh;
1341
+ /* The page's material. `none` by default (the initial value), so this is a
1342
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1343
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1344
+ covers the viewport, so the two compose instead of overwriting. */
1345
+ background-image: var(--texture-page);
897
1346
  }
898
1347
 
899
1348
  img,
@@ -963,10 +1412,32 @@ table {
963
1412
  }
964
1413
  }
965
1414
 
966
- /* Focus visible — default ring */
1415
+ /* Text selection — the decoration axis reaching the one surface no component
1416
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1417
+ of a themed page that never matched the theme. Both values are tokens
1418
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1419
+ ::selection {
1420
+ background-color: var(--selection-bg);
1421
+ color: var(--selection-fg);
1422
+ }
1423
+
1424
+ /* Focus visible — the default ring, and the only place it is spelled out.
1425
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1426
+ focus once and every element that has not drawn its own ring follows. */
967
1427
  :focus-visible {
968
- outline: 2px solid var(--color-ring);
969
- outline-offset: 2px;
1428
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1429
+ outline-offset: var(--focus-ring-offset);
1430
+ }
1431
+
1432
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1433
+ is not a property focus owns: an element's resting shadow — a card's depth,
1434
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1435
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1436
+ sets a shadow outranks this one, so it lands only on an element nothing else
1437
+ shadows, and it never takes a shadow away. The controls that draw their own
1438
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1439
+ :where(:focus-visible) {
1440
+ box-shadow: var(--focus-shadow);
970
1441
  }
971
1442
 
972
1443
  /* Hidden but accessible */
@@ -995,7 +1466,7 @@ table {
995
1466
  /* @ui:base prose — typography defaults for long-form content */
996
1467
 
997
1468
  [data-ui="prose"] {
998
- font-family: var(--font-sans);
1469
+ font-family: var(--font-body);
999
1470
  font-size: var(--text-base);
1000
1471
  line-height: var(--leading-relaxed);
1001
1472
  color: var(--color-fg);
@@ -1003,29 +1474,45 @@ table {
1003
1474
  }
1004
1475
 
1005
1476
  [data-ui="prose"] h1 {
1477
+ font-family: var(--font-heading);
1006
1478
  font-size: var(--text-4xl);
1007
- font-weight: var(--weight-bold);
1008
- line-height: var(--leading-tight);
1479
+ font-weight: var(--heading-weight);
1480
+ letter-spacing: var(--heading-tracking);
1481
+ text-transform: var(--heading-transform);
1482
+ font-variant-caps: var(--heading-caps);
1483
+ line-height: var(--heading-leading);
1009
1484
  margin-block: var(--space-8) var(--space-4);
1010
1485
  }
1011
1486
 
1012
1487
  [data-ui="prose"] h2 {
1488
+ font-family: var(--font-heading);
1013
1489
  font-size: var(--text-3xl);
1014
1490
  font-weight: var(--weight-semibold);
1015
- line-height: var(--leading-tight);
1491
+ letter-spacing: var(--heading-tracking);
1492
+ text-transform: var(--heading-transform);
1493
+ font-variant-caps: var(--heading-caps);
1494
+ line-height: var(--heading-leading);
1016
1495
  margin-block: var(--space-8) var(--space-3);
1017
1496
  }
1018
1497
 
1019
1498
  [data-ui="prose"] h3 {
1499
+ font-family: var(--font-heading);
1020
1500
  font-size: var(--text-2xl);
1021
1501
  font-weight: var(--weight-semibold);
1502
+ letter-spacing: var(--heading-tracking);
1503
+ text-transform: var(--heading-transform);
1504
+ font-variant-caps: var(--heading-caps);
1022
1505
  line-height: var(--leading-snug);
1023
1506
  margin-block: var(--space-6) var(--space-3);
1024
1507
  }
1025
1508
 
1026
1509
  [data-ui="prose"] h4 {
1510
+ font-family: var(--font-heading);
1027
1511
  font-size: var(--text-xl);
1028
1512
  font-weight: var(--weight-semibold);
1513
+ letter-spacing: var(--heading-tracking);
1514
+ text-transform: var(--heading-transform);
1515
+ font-variant-caps: var(--heading-caps);
1029
1516
  line-height: var(--leading-snug);
1030
1517
  margin-block: var(--space-6) var(--space-2);
1031
1518
  }
@@ -1036,8 +1523,8 @@ table {
1036
1523
 
1037
1524
  [data-ui="prose"] a {
1038
1525
  color: var(--color-primary);
1039
- text-decoration: underline;
1040
- text-underline-offset: 2px;
1526
+ text-decoration-line: var(--link-decoration);
1527
+ text-underline-offset: var(--link-underline-offset);
1041
1528
  }
1042
1529
 
1043
1530
  [data-ui="prose"] a:hover {
@@ -1074,7 +1561,7 @@ table {
1074
1561
  }
1075
1562
 
1076
1563
  [data-ui="prose"] blockquote {
1077
- border-inline-start: 3px solid var(--color-border-strong);
1564
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1078
1565
  padding-inline-start: var(--space-4);
1079
1566
  color: var(--color-fg-muted);
1080
1567
  margin-block: var(--space-4);
@@ -1096,9 +1583,15 @@ table {
1096
1583
  margin-block: var(--space-1);
1097
1584
  }
1098
1585
 
1586
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1587
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1588
+ [data-ui="prose"] li::marker {
1589
+ color: var(--marker-color);
1590
+ }
1591
+
1099
1592
  [data-ui="prose"] hr {
1100
1593
  border: none;
1101
- border-block-start: 1px solid var(--color-border);
1594
+ border-block-start: var(--border-width) solid var(--color-border);
1102
1595
  margin-block: var(--space-8);
1103
1596
  }
1104
1597
 
@@ -1117,12 +1610,12 @@ table {
1117
1610
  font-weight: var(--weight-semibold);
1118
1611
  text-align: start;
1119
1612
  padding: var(--space-2) var(--space-3);
1120
- border-block-end: 2px solid var(--color-border-strong);
1613
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1121
1614
  }
1122
1615
 
1123
1616
  [data-ui="prose"] td {
1124
1617
  padding: var(--space-2) var(--space-3);
1125
- border-block-end: 1px solid var(--color-border);
1618
+ border-block-end: var(--border-width) solid var(--color-border);
1126
1619
  }
1127
1620
 
1128
1621
  /* First child no top margin, last child no bottom margin */
@@ -1307,7 +1800,7 @@ table {
1307
1800
 
1308
1801
  /* === primitives/avatar.css === */
1309
1802
  /* @ui:component avatar */
1310
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1803
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1311
1804
 
1312
1805
  /* ── Base ── */
1313
1806
  [data-ui="avatar"] {
@@ -1337,7 +1830,7 @@ table {
1337
1830
  height: 100%;
1338
1831
  background: var(--color-bg-muted);
1339
1832
  color: var(--color-fg-muted);
1340
- font-family: var(--font-sans);
1833
+ font-family: var(--font-ui);
1341
1834
  font-size: var(--text-sm);
1342
1835
  font-weight: var(--weight-medium);
1343
1836
  text-transform: uppercase;
@@ -1362,7 +1855,7 @@ table {
1362
1855
 
1363
1856
  /* === primitives/badge.css === */
1364
1857
  /* @ui:component badge */
1365
- /* @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 */
1858
+ /* @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 */
1366
1859
 
1367
1860
  /* ── Base ── */
1368
1861
  [data-ui="badge"] {
@@ -1372,9 +1865,10 @@ table {
1372
1865
  gap: var(--space-1);
1373
1866
  padding: 0.125rem var(--space-2);
1374
1867
  border-radius: var(--badge-radius, var(--radius-full));
1868
+ corner-shape: var(--corner-shape);
1375
1869
  background: var(--color-bg-muted);
1376
1870
  color: var(--color-fg);
1377
- font-family: var(--badge-font, var(--font-sans));
1871
+ font-family: var(--badge-font, var(--font-ui));
1378
1872
  font-size: var(--text-xs);
1379
1873
  font-weight: var(--weight-medium);
1380
1874
  line-height: 1.5;
@@ -1420,11 +1914,11 @@ table {
1420
1914
 
1421
1915
  /* === primitives/breadcrumb.css === */
1422
1916
  /* @ui:component breadcrumb */
1423
- /* @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 */
1917
+ /* @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 */
1424
1918
 
1425
1919
  /* ── Root ── */
1426
1920
  [data-ui="breadcrumb"] {
1427
- font-family: var(--breadcrumb-font, var(--font-sans));
1921
+ font-family: var(--breadcrumb-font, var(--font-ui));
1428
1922
  font-size: var(--breadcrumb-size, var(--text-sm));
1429
1923
  color: var(--color-fg-muted);
1430
1924
  }
@@ -1450,12 +1944,13 @@ table {
1450
1944
 
1451
1945
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1452
1946
  color: var(--color-primary-hover);
1453
- text-decoration: underline;
1947
+ text-decoration-line: var(--link-decoration);
1454
1948
  }
1455
1949
 
1456
1950
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1457
- outline: 2px solid var(--color-ring);
1458
- outline-offset: 2px;
1951
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1952
+ outline-offset: var(--focus-ring-offset);
1953
+ box-shadow: var(--focus-shadow);
1459
1954
  }
1460
1955
 
1461
1956
  /* ── Separator (presentational) ── */
@@ -1495,7 +1990,7 @@ table {
1495
1990
 
1496
1991
  /* === primitives/button.css === */
1497
1992
  /* @ui:component button */
1498
- /* @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 */
1993
+ /* @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 */
1499
1994
 
1500
1995
  /* ── Base ── */
1501
1996
  [data-ui="button"] {
@@ -1505,18 +2000,21 @@ table {
1505
2000
  gap: var(--space-2);
1506
2001
  height: var(--button-height-md, 40px);
1507
2002
  padding-inline: var(--space-4);
1508
- border: 1px solid var(--color-border);
2003
+ border: var(--border-width) solid var(--color-border);
1509
2004
  border-radius: var(--button-radius, var(--radius-md));
2005
+ corner-shape: var(--corner-shape);
1510
2006
  background: var(--color-bg);
1511
2007
  color: var(--color-fg);
1512
- font-family: var(--font-sans);
2008
+ font-family: var(--font-ui);
1513
2009
  font-size: var(--text-sm);
1514
2010
  font-weight: var(--weight-medium);
2011
+ text-transform: var(--button-text-transform);
1515
2012
  line-height: 1;
1516
2013
  cursor: pointer;
1517
2014
  transition: background var(--duration-fast) var(--ease-default),
1518
2015
  border-color var(--duration-fast) var(--ease-default),
1519
2016
  color var(--duration-fast) var(--ease-default),
2017
+ translate var(--duration-fast) var(--ease-default),
1520
2018
  box-shadow var(--duration-fast) var(--ease-default);
1521
2019
  user-select: none;
1522
2020
  white-space: nowrap;
@@ -1525,11 +2023,16 @@ table {
1525
2023
 
1526
2024
  [data-ui="button"]:hover {
1527
2025
  background: var(--color-bg-muted);
2026
+ /* The hover lift. `none` by default — the initial value of `translate` — so
2027
+ this rule computes what the button computed before the token existed; a
2028
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
2029
+ translate: var(--motion-hover-lift);
1528
2030
  }
1529
2031
 
1530
2032
  [data-ui="button"]:focus-visible {
1531
- outline: 2px solid var(--color-ring);
1532
- outline-offset: 2px;
2033
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2034
+ outline-offset: var(--focus-ring-offset);
2035
+ box-shadow: var(--focus-shadow);
1533
2036
  }
1534
2037
 
1535
2038
  /* ── Variants ── */
@@ -1585,7 +2088,7 @@ table {
1585
2088
  padding: 0;
1586
2089
  }
1587
2090
  [data-ui="button"][data-variant="link"]:hover {
1588
- text-decoration: underline;
2091
+ text-decoration-line: var(--link-decoration);
1589
2092
  }
1590
2093
 
1591
2094
  /* ── Sizes ── */
@@ -1604,7 +2107,7 @@ table {
1604
2107
  /* ── States ── */
1605
2108
  [data-ui="button"]:disabled,
1606
2109
  [data-ui="button"][data-state="disabled"] {
1607
- opacity: 0.5;
2110
+ opacity: var(--disabled-opacity);
1608
2111
  cursor: not-allowed;
1609
2112
  pointer-events: none;
1610
2113
  }
@@ -1619,7 +2122,7 @@ table {
1619
2122
  position: absolute;
1620
2123
  width: 1em;
1621
2124
  height: 1em;
1622
- border: 2px solid currentColor;
2125
+ border: var(--border-width-strong) solid currentColor;
1623
2126
  border-inline-end-color: transparent;
1624
2127
  border-radius: var(--radius-full);
1625
2128
  animation: faqir-spin 0.6s linear infinite;
@@ -1666,7 +2169,7 @@ table {
1666
2169
 
1667
2170
  /* === primitives/callout.css === */
1668
2171
  /* @ui:component callout */
1669
- /* @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 */
2172
+ /* @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 */
1670
2173
 
1671
2174
  /* ── Base ── */
1672
2175
  [data-ui="callout"] {
@@ -1675,7 +2178,7 @@ table {
1675
2178
  padding: var(--callout-padding-y) var(--callout-padding-x);
1676
2179
  border-radius: var(--callout-radius);
1677
2180
  border-inline-start: var(--callout-border-left-width) solid;
1678
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2181
+ font-family: var(--doc-font, var(--font-body));
1679
2182
  font-size: var(--callout-font-size);
1680
2183
  line-height: var(--doc-line-height, 1.5);
1681
2184
  }
@@ -1706,6 +2209,7 @@ table {
1706
2209
  /* ── Title ── */
1707
2210
  [data-ui="callout"] [data-part="title"] {
1708
2211
  display: block;
2212
+ font-family: var(--font-heading);
1709
2213
  font-weight: var(--weight-semibold);
1710
2214
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1711
2215
  }
@@ -1732,8 +2236,9 @@ table {
1732
2236
  }
1733
2237
 
1734
2238
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1735
- outline: 2px solid var(--color-ring, var(--color-info));
1736
- outline-offset: 2px;
2239
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2240
+ outline-offset: var(--focus-ring-offset);
2241
+ box-shadow: var(--focus-shadow);
1737
2242
  opacity: 1;
1738
2243
  }
1739
2244
 
@@ -1819,17 +2324,36 @@ table {
1819
2324
 
1820
2325
  /* === primitives/card.css === */
1821
2326
  /* @ui:component card */
1822
- /* @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 */
2327
+ /* @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 */
1823
2328
 
1824
2329
  /* ── Base ── */
1825
2330
  [data-ui="card"] {
1826
2331
  display: flex;
1827
2332
  flex-direction: column;
1828
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2333
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1829
2334
  border-radius: var(--card-radius, var(--radius-lg));
1830
- background: var(--card-bg, var(--color-surface-1));
2335
+ corner-shape: var(--corner-shape);
2336
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2337
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2338
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2339
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1831
2340
  box-shadow: var(--card-shadow, var(--shadow-sm));
1832
2341
  overflow: hidden;
2342
+ transition: translate var(--duration-fast) var(--ease-default);
2343
+ }
2344
+
2345
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2346
+ value of `translate`), so a card sits exactly where it always sat until a
2347
+ theme says surfaces rise under the pointer. */
2348
+ [data-ui="card"]:hover {
2349
+ translate: var(--motion-hover-lift);
2350
+ }
2351
+
2352
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2353
+ [data-ui="card"] {
2354
+ -webkit-backdrop-filter: var(--surface-backdrop);
2355
+ backdrop-filter: var(--surface-backdrop);
2356
+ }
1833
2357
  }
1834
2358
 
1835
2359
  /* ── Variants ── */
@@ -1838,7 +2362,7 @@ table {
1838
2362
  }
1839
2363
 
1840
2364
  [data-ui="card"][data-variant="filled"] {
1841
- background: var(--color-surface-2);
2365
+ background: var(--texture-surface), var(--color-surface-2);
1842
2366
  border-color: var(--color-surface-2-border);
1843
2367
  box-shadow: none;
1844
2368
  }
@@ -1853,7 +2377,7 @@ table {
1853
2377
  }
1854
2378
 
1855
2379
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1856
- font-family: var(--font-sans);
2380
+ font-family: var(--font-heading);
1857
2381
  font-size: var(--text-lg);
1858
2382
  font-weight: var(--weight-semibold);
1859
2383
  line-height: var(--leading-tight);
@@ -1894,9 +2418,19 @@ table {
1894
2418
  padding-top: 0;
1895
2419
  }
1896
2420
 
2421
+ /* ── Motion ── */
2422
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2423
+ theme states one — but the house rule is that a stylesheet which transitions
2424
+ carries its own opt-out, so a reader never has to check the token first. */
2425
+ @media (prefers-reduced-motion: reduce) {
2426
+ [data-ui="card"] {
2427
+ transition: none;
2428
+ }
2429
+ }
2430
+
1897
2431
  /* === primitives/checkbox.css === */
1898
2432
  /* @ui:component checkbox */
1899
- /* @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 */
2433
+ /* @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 */
1900
2434
 
1901
2435
  /* -- Label wrapper -- */
1902
2436
  [data-ui="checkbox-label"] {
@@ -1908,7 +2442,7 @@ table {
1908
2442
 
1909
2443
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1910
2444
  cursor: not-allowed;
1911
- opacity: 0.5;
2445
+ opacity: var(--disabled-opacity);
1912
2446
  }
1913
2447
 
1914
2448
  /* -- Base -- */
@@ -1920,8 +2454,8 @@ table {
1920
2454
  width: var(--checkbox-size, 18px);
1921
2455
  height: var(--checkbox-size, 18px);
1922
2456
  flex-shrink: 0;
1923
- border: 1px solid var(--color-border);
1924
- border-radius: var(--checkbox-radius, var(--radius-sm));
2457
+ border: var(--border-width) solid var(--color-border);
2458
+ border-radius: var(--checkbox-radius);
1925
2459
  background: var(--color-bg);
1926
2460
  cursor: pointer;
1927
2461
  transition: background var(--duration-fast) var(--ease-default),
@@ -1934,8 +2468,9 @@ table {
1934
2468
  }
1935
2469
 
1936
2470
  [data-ui="checkbox"]:focus-visible {
1937
- outline: 2px solid var(--color-ring);
1938
- outline-offset: 2px;
2471
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2472
+ outline-offset: var(--focus-ring-offset);
2473
+ box-shadow: var(--focus-shadow);
1939
2474
  }
1940
2475
 
1941
2476
  /* -- Checked -- */
@@ -2026,7 +2561,7 @@ table {
2026
2561
  The mask has to opt out of the substitution to stay readable. [W3-3] */
2027
2562
  @media (forced-colors: active) {
2028
2563
  [data-ui="checkbox"] {
2029
- border: 1px solid ButtonText;
2564
+ border: var(--border-width) solid ButtonText;
2030
2565
  }
2031
2566
 
2032
2567
  [data-ui="checkbox"]:checked,
@@ -2050,7 +2585,7 @@ table {
2050
2585
 
2051
2586
  /* === primitives/chip.css === */
2052
2587
  /* @ui:component chip */
2053
- /* @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 */
2588
+ /* @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 */
2054
2589
 
2055
2590
  /* ── Base ── */
2056
2591
  [data-ui="chip"] {
@@ -2058,11 +2593,11 @@ table {
2058
2593
  align-items: center;
2059
2594
  gap: var(--space-1);
2060
2595
  padding: var(--space-1) var(--space-2);
2061
- border: 1px solid transparent;
2596
+ border: var(--border-width) solid transparent;
2062
2597
  border-radius: var(--chip-radius, var(--radius-full));
2063
2598
  background: var(--color-bg-muted);
2064
2599
  color: var(--color-fg);
2065
- font-family: var(--chip-font, var(--font-sans));
2600
+ font-family: var(--chip-font, var(--font-ui));
2066
2601
  font-size: var(--text-sm);
2067
2602
  font-weight: var(--weight-medium);
2068
2603
  line-height: 1.2;
@@ -2098,8 +2633,11 @@ table {
2098
2633
  }
2099
2634
 
2100
2635
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2101
- outline: 2px solid var(--color-ring);
2102
- outline-offset: 1px;
2636
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2637
+ /* Half the default gap — the dismiss target is small, and the full ring
2638
+ would collide with the chip's own edge. */
2639
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2640
+ box-shadow: var(--focus-shadow);
2103
2641
  }
2104
2642
 
2105
2643
  /* ── Variants ── */
@@ -2322,12 +2860,12 @@ table {
2322
2860
 
2323
2861
  /* === primitives/collapsible.css === */
2324
2862
  /* @ui:component collapsible */
2325
- /* @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 */
2863
+ /* @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 */
2326
2864
 
2327
2865
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2328
2866
  [data-ui="collapsible"] {
2329
2867
  border-radius: var(--collapsible-radius, var(--radius-md));
2330
- font-family: var(--collapsible-font, var(--font-sans));
2868
+ font-family: var(--collapsible-font, var(--font-ui));
2331
2869
  color: var(--color-fg);
2332
2870
  }
2333
2871
 
@@ -2357,8 +2895,9 @@ table {
2357
2895
  }
2358
2896
 
2359
2897
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2360
- outline: 2px solid var(--color-ring);
2361
- outline-offset: 2px;
2898
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2899
+ outline-offset: var(--focus-ring-offset);
2900
+ box-shadow: var(--focus-shadow);
2362
2901
  }
2363
2902
 
2364
2903
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2367,8 +2906,8 @@ table {
2367
2906
  flex: none;
2368
2907
  width: 0.5em;
2369
2908
  height: 0.5em;
2370
- border-inline-end: 2px solid var(--color-fg-muted);
2371
- border-block-end: 2px solid var(--color-fg-muted);
2909
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2910
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2372
2911
  transform: rotate(45deg);
2373
2912
  transition: transform var(--duration-normal) var(--ease-default);
2374
2913
  }
@@ -2387,7 +2926,7 @@ table {
2387
2926
 
2388
2927
  /* ── Bordered variant ── */
2389
2928
  [data-ui="collapsible"][data-variant="bordered"] {
2390
- border: 1px solid var(--color-border);
2929
+ border: var(--border-width) solid var(--color-border);
2391
2930
  }
2392
2931
 
2393
2932
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2520,13 +3059,13 @@ table {
2520
3059
 
2521
3060
  /* === primitives/description-list.css === */
2522
3061
  /* @ui:component description-list */
2523
- /* @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 */
3062
+ /* @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 */
2524
3063
 
2525
3064
  /* ── Base ── */
2526
3065
  [data-ui="description-list"] {
2527
3066
  margin: 0;
2528
3067
  padding: 0;
2529
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3068
+ font-family: var(--doc-font, var(--font-body));
2530
3069
  }
2531
3070
 
2532
3071
  /* ── Term ── */
@@ -2582,7 +3121,7 @@ table {
2582
3121
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2583
3122
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2584
3123
  padding-bottom: var(--space-4);
2585
- border-bottom: 1px solid var(--color-border);
3124
+ border-bottom: var(--border-width) solid var(--color-border);
2586
3125
  }
2587
3126
 
2588
3127
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2594,7 +3133,7 @@ table {
2594
3133
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2595
3134
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2596
3135
  padding-bottom: var(--space-3);
2597
- border-bottom: 1px solid var(--color-border);
3136
+ border-bottom: var(--border-width) solid var(--color-border);
2598
3137
  }
2599
3138
 
2600
3139
  /* ── Size: Small ── */
@@ -2632,7 +3171,7 @@ table {
2632
3171
 
2633
3172
  /* === primitives/empty-state.css === */
2634
3173
  /* @ui:component empty-state */
2635
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3174
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2636
3175
 
2637
3176
  /* ── Base ── */
2638
3177
  [data-ui="empty-state"] {
@@ -2653,6 +3192,7 @@ table {
2653
3192
 
2654
3193
  /* ── Title ── */
2655
3194
  [data-ui="empty-state"] [data-part="title"] {
3195
+ font-family: var(--font-heading);
2656
3196
  font-size: var(--text-lg);
2657
3197
  font-weight: var(--weight-medium);
2658
3198
  color: var(--color-fg);
@@ -2700,7 +3240,7 @@ table {
2700
3240
 
2701
3241
  /* === primitives/field-group.css === */
2702
3242
  /* @ui:component field-group */
2703
- /* @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 */
3243
+ /* @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 */
2704
3244
 
2705
3245
  /* ── Base / spacing ownership ──
2706
3246
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2712,7 +3252,7 @@ table {
2712
3252
  display: flex;
2713
3253
  flex-direction: column;
2714
3254
  gap: var(--space-2);
2715
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3255
+ font-family: var(--doc-font, var(--font-body));
2716
3256
  }
2717
3257
 
2718
3258
  /* ── Label ── */
@@ -2782,7 +3322,7 @@ table {
2782
3322
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2783
3323
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2784
3324
  border-color: var(--field-error-color);
2785
- box-shadow: 0 0 0 1px var(--field-error-color);
3325
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2786
3326
  }
2787
3327
 
2788
3328
  /* ── State: Validating ──
@@ -2792,7 +3332,7 @@ table {
2792
3332
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2793
3333
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2794
3334
  border-color: var(--field-validating-color);
2795
- box-shadow: 0 0 0 1px var(--field-validating-color);
3335
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2796
3336
  }
2797
3337
 
2798
3338
  /* ── State: Disabled ──
@@ -2811,8 +3351,8 @@ table {
2811
3351
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2812
3352
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2813
3353
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2814
- border-color: var(--color-success, oklch(0.62 0.19 145));
2815
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3354
+ border-color: var(--color-success);
3355
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2816
3356
  }
2817
3357
 
2818
3358
  /* ── Variant: Horizontal ── */
@@ -3117,7 +3657,7 @@ table {
3117
3657
 
3118
3658
  /* === primitives/image.css === */
3119
3659
  /* @ui:component image */
3120
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3660
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3121
3661
 
3122
3662
  /* ── Base ── */
3123
3663
  [data-ui="image"] {
@@ -3141,7 +3681,7 @@ table {
3141
3681
  [data-ui="image"] [data-part="caption"] {
3142
3682
  display: block;
3143
3683
  margin-top: var(--space-2);
3144
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3684
+ font-family: var(--doc-font, var(--font-body));
3145
3685
  font-size: var(--image-caption-size);
3146
3686
  color: var(--image-caption-color);
3147
3687
  line-height: 1.4;
@@ -3238,7 +3778,7 @@ table {
3238
3778
 
3239
3779
  /* === primitives/input.css === */
3240
3780
  /* @ui:component input */
3241
- /* @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 */
3781
+ /* @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 */
3242
3782
 
3243
3783
  /* ── Base ── */
3244
3784
  [data-ui="input"] {
@@ -3246,11 +3786,18 @@ table {
3246
3786
  width: 100%;
3247
3787
  height: var(--input-height, 40px);
3248
3788
  padding-inline: var(--space-3);
3249
- border: 1px solid var(--color-border);
3789
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3790
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3791
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3792
+ is drawn. Identical to the shorthand at every other value of the token. */
3793
+ border-style: solid;
3794
+ border-color: var(--color-border);
3795
+ border-width: var(--input-border-width);
3250
3796
  border-radius: var(--input-radius, var(--radius-md));
3251
- background: var(--input-bg, var(--color-bg));
3797
+ corner-shape: var(--corner-shape);
3798
+ background: var(--input-fill);
3252
3799
  color: var(--color-fg);
3253
- font-family: var(--input-font, var(--font-sans));
3800
+ font-family: var(--input-font, var(--font-ui));
3254
3801
  font-size: var(--text-sm);
3255
3802
  line-height: 1;
3256
3803
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3266,8 +3813,11 @@ table {
3266
3813
  }
3267
3814
 
3268
3815
  [data-ui="input"]:focus {
3269
- outline: 2px solid var(--color-ring);
3270
- outline-offset: -1px;
3816
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3817
+ /* The ring replaces the border rather than sitting outside it: inset by
3818
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3819
+ outline-offset: calc(-1 * var(--input-border-width));
3820
+ box-shadow: var(--focus-shadow);
3271
3821
  border-color: transparent;
3272
3822
  }
3273
3823
 
@@ -3295,7 +3845,7 @@ table {
3295
3845
  }
3296
3846
 
3297
3847
  [data-ui="input"]:disabled {
3298
- opacity: 0.5;
3848
+ opacity: var(--disabled-opacity);
3299
3849
  cursor: not-allowed;
3300
3850
  }
3301
3851
 
@@ -3358,7 +3908,7 @@ table {
3358
3908
 
3359
3909
  /* === primitives/kbd.css === */
3360
3910
  /* @ui:component kbd */
3361
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3911
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3362
3912
 
3363
3913
  /* ── Base ── */
3364
3914
  [data-ui="kbd"] {
@@ -3368,8 +3918,8 @@ table {
3368
3918
  height: 20px;
3369
3919
  min-width: 20px;
3370
3920
  padding-inline: var(--space-1h);
3371
- border: 1px solid var(--color-border);
3372
- border-bottom-width: 2px;
3921
+ border: var(--border-width) solid var(--color-border);
3922
+ border-bottom-width: var(--border-width-strong);
3373
3923
  border-radius: var(--radius-sm);
3374
3924
  background: var(--color-bg-subtle);
3375
3925
  color: var(--color-fg);
@@ -3382,7 +3932,7 @@ table {
3382
3932
 
3383
3933
  /* === primitives/key-value.css === */
3384
3934
  /* @ui:component key-value */
3385
- /* @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 */
3935
+ /* @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 */
3386
3936
 
3387
3937
  /* ── Base ── */
3388
3938
  [data-ui="key-value"] {
@@ -3391,7 +3941,7 @@ table {
3391
3941
  gap: var(--kv-pair-gap);
3392
3942
  margin: 0;
3393
3943
  padding: 0;
3394
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3944
+ font-family: var(--doc-font, var(--font-body));
3395
3945
  }
3396
3946
 
3397
3947
  /* ── Label ── */
@@ -3521,12 +4071,12 @@ table {
3521
4071
 
3522
4072
  /* === primitives/label.css === */
3523
4073
  /* @ui:component label */
3524
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4074
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3525
4075
 
3526
4076
  /* ── Base ── */
3527
4077
  [data-ui="label"] {
3528
4078
  display: block;
3529
- font-family: var(--font-sans);
4079
+ font-family: var(--font-ui);
3530
4080
  font-size: var(--text-sm);
3531
4081
  font-weight: var(--weight-medium);
3532
4082
  color: var(--color-fg);
@@ -3559,21 +4109,21 @@ table {
3559
4109
 
3560
4110
  /* ── States ── */
3561
4111
  [data-ui="label"][data-state="disabled"] {
3562
- opacity: 0.5;
4112
+ opacity: var(--disabled-opacity);
3563
4113
  cursor: not-allowed;
3564
4114
  }
3565
4115
 
3566
4116
  /* === primitives/link.css === */
3567
4117
  /* @ui:component link */
3568
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4118
+ /* @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 */
3569
4119
 
3570
4120
  /* ── Base ── */
3571
4121
  [data-ui="link"] {
3572
4122
  color: var(--color-primary);
3573
4123
  font-family: inherit;
3574
- text-decoration: underline;
3575
- text-decoration-thickness: 1px;
3576
- text-underline-offset: 0.2em;
4124
+ text-decoration-line: var(--link-decoration);
4125
+ text-decoration-thickness: var(--link-thickness);
4126
+ text-underline-offset: var(--link-underline-offset);
3577
4127
  border-radius: var(--radius-sm);
3578
4128
  cursor: pointer;
3579
4129
  }
@@ -3587,8 +4137,9 @@ table {
3587
4137
  }
3588
4138
 
3589
4139
  [data-ui="link"]:focus-visible {
3590
- outline: 2px solid var(--color-ring);
3591
- outline-offset: 2px;
4140
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4141
+ outline-offset: var(--focus-ring-offset);
4142
+ box-shadow: var(--focus-shadow);
3592
4143
  }
3593
4144
 
3594
4145
  /* ── Variants ── */
@@ -3612,7 +4163,7 @@ table {
3612
4163
 
3613
4164
  /* === primitives/nav.css === */
3614
4165
  /* @ui:component nav */
3615
- /* @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 */
4166
+ /* @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 */
3616
4167
 
3617
4168
  /* ── Base ── */
3618
4169
  [data-ui="nav"] {
@@ -3662,14 +4213,14 @@ table {
3662
4213
 
3663
4214
  /* ── Underline variant ── */
3664
4215
  [data-ui="nav"][data-variant="underline"] {
3665
- border-bottom: 1px solid var(--color-border);
4216
+ border-bottom: var(--border-width) solid var(--color-border);
3666
4217
  gap: 0;
3667
4218
  }
3668
4219
 
3669
4220
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3670
4221
  border-radius: 0;
3671
4222
  padding: var(--space-2) var(--space-4);
3672
- border-bottom: 2px solid transparent;
4223
+ border-bottom: var(--border-width-strong) solid transparent;
3673
4224
  margin-bottom: -1px;
3674
4225
  }
3675
4226
 
@@ -3725,7 +4276,7 @@ table {
3725
4276
 
3726
4277
  /* === primitives/page-break.css === */
3727
4278
  /* @ui:component page-break */
3728
- /* @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 */
4279
+ /* @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 */
3729
4280
 
3730
4281
  /* ── Base (Screen) ── */
3731
4282
  [data-ui="page-break"] {
@@ -3740,12 +4291,12 @@ table {
3740
4291
  [data-ui="page-break"]::after {
3741
4292
  content: "";
3742
4293
  flex: 1;
3743
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4294
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3744
4295
  }
3745
4296
 
3746
4297
  /* ── Label (Screen) ── */
3747
4298
  [data-ui="page-break"] {
3748
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4299
+ font-family: var(--doc-font, var(--font-body));
3749
4300
  font-size: var(--page-break-screen-label-size);
3750
4301
  color: var(--page-break-screen-label-color);
3751
4302
  letter-spacing: 0.05em;
@@ -3787,7 +4338,7 @@ table {
3787
4338
 
3788
4339
  /* === primitives/progress.css === */
3789
4340
  /* @ui:component progress */
3790
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4341
+ /* @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 */
3791
4342
 
3792
4343
  /* ── Base ── */
3793
4344
  [data-ui="progress"] {
@@ -3862,7 +4413,7 @@ table {
3862
4413
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3863
4414
  @media (forced-colors: active) {
3864
4415
  [data-ui="progress"] [data-part="track"] {
3865
- border: 1px solid ButtonText;
4416
+ border: var(--border-width) solid ButtonText;
3866
4417
  }
3867
4418
 
3868
4419
  [data-ui="progress"] [data-part="fill"],
@@ -3876,7 +4427,7 @@ table {
3876
4427
 
3877
4428
  /* === primitives/radio.css === */
3878
4429
  /* @ui:component radio */
3879
- /* @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 */
4430
+ /* @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 */
3880
4431
 
3881
4432
  /* -- Radio group -- */
3882
4433
  [data-ui="radio-group"] {
@@ -3898,7 +4449,7 @@ table {
3898
4449
 
3899
4450
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3900
4451
  cursor: not-allowed;
3901
- opacity: 0.5;
4452
+ opacity: var(--disabled-opacity);
3902
4453
  }
3903
4454
 
3904
4455
  /* -- Base -- */
@@ -3910,7 +4461,7 @@ table {
3910
4461
  width: var(--radio-size, 18px);
3911
4462
  height: var(--radio-size, 18px);
3912
4463
  flex-shrink: 0;
3913
- border: 1px solid var(--color-border);
4464
+ border: var(--border-width) solid var(--color-border);
3914
4465
  border-radius: var(--radius-full);
3915
4466
  background: var(--color-bg);
3916
4467
  cursor: pointer;
@@ -3924,8 +4475,9 @@ table {
3924
4475
  }
3925
4476
 
3926
4477
  [data-ui="radio"]:focus-visible {
3927
- outline: 2px solid var(--color-ring);
3928
- outline-offset: 2px;
4478
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4479
+ outline-offset: var(--focus-ring-offset);
4480
+ box-shadow: var(--focus-shadow);
3929
4481
  }
3930
4482
 
3931
4483
  /* -- Checked -- */
@@ -3978,7 +4530,7 @@ table {
3978
4530
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3979
4531
  @media (forced-colors: active) {
3980
4532
  [data-ui="radio"] {
3981
- border: 1px solid ButtonText;
4533
+ border: var(--border-width) solid ButtonText;
3982
4534
  }
3983
4535
 
3984
4536
  [data-ui="radio"]:checked {
@@ -3998,7 +4550,7 @@ table {
3998
4550
 
3999
4551
  /* === primitives/select.css === */
4000
4552
  /* @ui:component select */
4001
- /* @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 */
4553
+ /* @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 */
4002
4554
 
4003
4555
  /* -- Base -- */
4004
4556
  [data-ui="select"] {
@@ -4007,11 +4559,17 @@ table {
4007
4559
  height: var(--select-height, 40px);
4008
4560
  padding-inline: var(--space-3);
4009
4561
  padding-inline-end: var(--space-8, 2rem);
4010
- border: 1px solid var(--color-border);
4562
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4563
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4564
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4565
+ is drawn. Identical to the shorthand at every other value of the token. */
4566
+ border-style: solid;
4567
+ border-color: var(--color-border);
4568
+ border-width: var(--input-border-width);
4011
4569
  border-radius: var(--select-radius, var(--radius-md));
4012
- background: var(--select-bg, var(--color-bg));
4570
+ background: var(--select-bg, var(--input-fill));
4013
4571
  color: var(--color-fg);
4014
- font-family: var(--select-font, var(--font-sans));
4572
+ font-family: var(--select-font, var(--font-ui));
4015
4573
  font-size: var(--text-sm);
4016
4574
  line-height: 1;
4017
4575
  cursor: pointer;
@@ -4041,8 +4599,11 @@ table {
4041
4599
  }
4042
4600
 
4043
4601
  [data-ui="select"]:focus {
4044
- outline: 2px solid var(--color-ring);
4045
- outline-offset: -1px;
4602
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4603
+ /* The ring replaces the border rather than sitting outside it: inset by
4604
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4605
+ outline-offset: calc(-1 * var(--input-border-width));
4606
+ box-shadow: var(--focus-shadow);
4046
4607
  border-color: transparent;
4047
4608
  }
4048
4609
 
@@ -4075,7 +4636,7 @@ table {
4075
4636
  }
4076
4637
 
4077
4638
  [data-ui="select"]:disabled {
4078
- opacity: 0.5;
4639
+ opacity: var(--disabled-opacity);
4079
4640
  cursor: not-allowed;
4080
4641
  }
4081
4642
 
@@ -4088,12 +4649,12 @@ table {
4088
4649
 
4089
4650
  /* === primitives/separator.css === */
4090
4651
  /* @ui:component separator */
4091
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4652
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4092
4653
 
4093
4654
  /* ── Base (horizontal) ── */
4094
4655
  [data-ui="separator"] {
4095
4656
  border: none;
4096
- border-top: 1px solid var(--color-border);
4657
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4097
4658
  margin: 0;
4098
4659
  width: 100%;
4099
4660
  }
@@ -4101,7 +4662,7 @@ table {
4101
4662
  /* ── Vertical ── */
4102
4663
  [data-ui="separator"][data-variant="vertical"] {
4103
4664
  border-top: none;
4104
- border-inline-start: 1px solid var(--color-border);
4665
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4105
4666
  width: auto;
4106
4667
  height: 100%;
4107
4668
  align-self: stretch;
@@ -4119,11 +4680,11 @@ div[data-ui="separator"]::before,
4119
4680
  div[data-ui="separator"]::after {
4120
4681
  content: "";
4121
4682
  flex: 1;
4122
- border-top: 1px solid var(--color-border);
4683
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4123
4684
  }
4124
4685
 
4125
4686
  [data-ui="separator"] [data-part="label"] {
4126
- font-family: var(--font-sans);
4687
+ font-family: var(--font-ui);
4127
4688
  font-size: var(--text-xs);
4128
4689
  color: var(--color-fg-muted);
4129
4690
  white-space: nowrap;
@@ -4161,17 +4722,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4161
4722
 
4162
4723
  /* ── Style: Thick ── */
4163
4724
  [data-ui="separator"][data-style="thick"] {
4164
- border-top-width: 2px;
4725
+ border-top-width: var(--border-width-strong);
4165
4726
  }
4166
4727
 
4167
4728
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4168
4729
  border-top-width: 0;
4169
- border-inline-start-width: 2px;
4730
+ border-inline-start-width: var(--border-width-strong);
4170
4731
  }
4171
4732
 
4172
4733
  div[data-ui="separator"][data-style="thick"]::before,
4173
4734
  div[data-ui="separator"][data-style="thick"]::after {
4174
- border-top-width: 2px;
4735
+ border-top-width: var(--border-width-strong);
4175
4736
  }
4176
4737
 
4177
4738
  /* ── Vertical Sizes ── */
@@ -4189,20 +4750,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4189
4750
 
4190
4751
  /* === primitives/signature.css === */
4191
4752
  /* @ui:component signature */
4192
- /* @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 */
4753
+ /* @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 */
4193
4754
 
4194
4755
  /* ── Base ── */
4195
4756
  [data-ui="signature"] {
4196
4757
  display: flex;
4197
4758
  flex-direction: column;
4198
4759
  gap: var(--space-2);
4199
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4760
+ font-family: var(--doc-font, var(--font-body));
4200
4761
  margin-top: var(--doc-signature-gap);
4201
4762
  }
4202
4763
 
4203
4764
  /* ── Line ── */
4204
4765
  [data-ui="signature"] [data-part="line"] {
4205
- border-top: 1px solid var(--doc-signature-line-color);
4766
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4206
4767
  min-height: 1px;
4207
4768
  }
4208
4769
 
@@ -4305,14 +4866,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4305
4866
 
4306
4867
  /* === primitives/spinner.css === */
4307
4868
  /* @ui:component spinner */
4308
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4869
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4309
4870
 
4310
4871
  /* ── Base ── */
4311
4872
  [data-ui="spinner"] {
4312
4873
  display: inline-block;
4313
4874
  width: 24px;
4314
4875
  height: 24px;
4315
- border: 2px solid var(--color-border);
4876
+ border: var(--border-width-strong) solid var(--color-border);
4316
4877
  border-top-color: var(--color-primary);
4317
4878
  border-radius: var(--radius-full);
4318
4879
  animation: faqir-spin 0.75s linear infinite;
@@ -4328,13 +4889,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4328
4889
  [data-ui="spinner"][data-size="lg"] {
4329
4890
  width: 32px;
4330
4891
  height: 32px;
4331
- border-width: 3px;
4892
+ border-width: var(--border-width-lg);
4332
4893
  }
4333
4894
 
4334
4895
  [data-ui="spinner"][data-size="xl"] {
4335
4896
  width: 48px;
4336
4897
  height: 48px;
4337
- border-width: 3px;
4898
+ border-width: var(--border-width-lg);
4338
4899
  }
4339
4900
 
4340
4901
  /* ── Motion ── */
@@ -4916,14 +5477,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4916
5477
 
4917
5478
  /* === primitives/stat.css === */
4918
5479
  /* @ui:component stat */
4919
- /* @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 */
5480
+ /* @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 */
4920
5481
 
4921
5482
  /* ── Base ── */
4922
5483
  [data-ui="stat"] {
4923
5484
  display: flex;
4924
5485
  flex-direction: column;
4925
5486
  gap: var(--space-1);
4926
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5487
+ font-family: var(--doc-font, var(--font-body));
4927
5488
  }
4928
5489
 
4929
5490
  /* ── Label ── */
@@ -4937,6 +5498,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4937
5498
 
4938
5499
  /* ── Value ── */
4939
5500
  [data-ui="stat"] [data-part="value"] {
5501
+ font-family: var(--font-heading);
4940
5502
  font-size: var(--stat-value-size);
4941
5503
  font-weight: var(--stat-value-weight);
4942
5504
  color: var(--color-fg);
@@ -4995,10 +5557,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4995
5557
  /* ── Variant: Card ── */
4996
5558
  [data-ui="stat"][data-variant="card"] {
4997
5559
  padding: var(--space-4);
4998
- border: 1px solid var(--color-border);
5560
+ border: var(--border-width) solid var(--color-border);
4999
5561
  border-radius: var(--radius-md, 0.375rem);
5000
5562
  background: var(--color-bg);
5001
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5563
+ box-shadow: var(--shadow-sm);
5002
5564
  }
5003
5565
 
5004
5566
  /* ── Value + Change Inline ── */
@@ -5010,7 +5572,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5010
5572
  @media print {
5011
5573
  [data-ui="stat"][data-variant="card"] {
5012
5574
  box-shadow: none;
5013
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5575
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
5014
5576
  }
5015
5577
 
5016
5578
  [data-ui="stat"] {
@@ -5020,7 +5582,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5020
5582
 
5021
5583
  /* === primitives/stepper.css === */
5022
5584
  /* @ui:component stepper */
5023
- /* @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 */
5585
+ /* @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 */
5024
5586
 
5025
5587
  /* ── Base ── */
5026
5588
  [data-ui="stepper"] {
@@ -5099,7 +5661,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5099
5661
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5100
5662
  [data-ui="stepper"] [data-part="connector"] {
5101
5663
  flex: 1;
5102
- height: 2px;
5664
+ height: var(--border-width-strong);
5103
5665
  background: var(--color-border);
5104
5666
  margin: 0 var(--space-1);
5105
5667
  min-width: var(--space-2);
@@ -5167,18 +5729,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5167
5729
 
5168
5730
  /* === primitives/surface.css === */
5169
5731
  /* @ui:component surface */
5170
- /* @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 */
5732
+ /* @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 */
5171
5733
 
5172
5734
  /* ── Base ── */
5173
5735
  [data-ui="surface"] {
5174
- background: var(--color-surface-1);
5736
+ background-color: var(--color-surface-1);
5737
+ background-image: var(--texture-surface);
5175
5738
  border-radius: var(--radius-lg);
5176
- border: 1px solid var(--color-surface-1-border);
5739
+ corner-shape: var(--corner-shape);
5740
+ border: var(--border-width) solid var(--color-surface-1-border);
5177
5741
  }
5178
5742
 
5179
5743
  /* ── Elevation Variants ── */
5180
5744
  [data-ui="surface"][data-variant="flat"] {
5181
- background: var(--color-bg);
5745
+ background-color: var(--color-bg);
5182
5746
  border: none;
5183
5747
  box-shadow: none;
5184
5748
  }
@@ -5188,11 +5752,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5188
5752
  }
5189
5753
 
5190
5754
  [data-ui="surface"][data-variant="overlay"] {
5191
- background: var(--color-surface-2);
5755
+ background-color: var(--color-surface-2);
5192
5756
  box-shadow: var(--shadow-lg);
5193
5757
  border-color: var(--color-surface-2-border);
5194
5758
  }
5195
5759
 
5760
+ /* An overlay is the one surface variant that floats over other content, so it
5761
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5762
+ its own: a browser without backdrop-filter renders the solid surface above
5763
+ and never sees this rule. */
5764
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5765
+ [data-ui="surface"][data-variant="overlay"] {
5766
+ -webkit-backdrop-filter: var(--surface-backdrop);
5767
+ backdrop-filter: var(--surface-backdrop);
5768
+ }
5769
+ }
5770
+
5196
5771
  /* ── Padding Sizes ── */
5197
5772
  [data-ui="surface"][data-size="sm"] {
5198
5773
  padding: var(--space-3);
@@ -5248,7 +5823,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5248
5823
 
5249
5824
  /* === primitives/switch.css === */
5250
5825
  /* @ui:component switch */
5251
- /* @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 */
5826
+ /* @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 */
5252
5827
 
5253
5828
  /* -- Label wrapper -- */
5254
5829
  [data-ui="switch-label"] {
@@ -5260,7 +5835,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5260
5835
 
5261
5836
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5262
5837
  cursor: not-allowed;
5263
- opacity: 0.5;
5838
+ opacity: var(--disabled-opacity);
5264
5839
  }
5265
5840
 
5266
5841
  /* -- Base (track) -- */
@@ -5288,8 +5863,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5288
5863
  width: var(--switch-width, 44px);
5289
5864
  height: var(--switch-height, 24px);
5290
5865
  padding: var(--space-0h, 2px);
5291
- border: 1px solid var(--color-border);
5292
- border-radius: var(--radius-full);
5866
+ border: var(--border-width) solid var(--color-border);
5867
+ border-radius: var(--switch-radius);
5293
5868
  background: var(--switch-bg, var(--color-bg-muted));
5294
5869
  cursor: pointer;
5295
5870
  position: relative;
@@ -5299,8 +5874,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5299
5874
  }
5300
5875
 
5301
5876
  [data-ui="switch"]:focus-visible {
5302
- outline: 2px solid var(--color-ring);
5303
- outline-offset: 2px;
5877
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5878
+ outline-offset: var(--focus-ring-offset);
5879
+ box-shadow: var(--focus-shadow);
5304
5880
  }
5305
5881
 
5306
5882
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5309,7 +5885,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5309
5885
  display: block;
5310
5886
  width: var(--switch-thumb, 18px);
5311
5887
  height: var(--switch-thumb, 18px);
5312
- border-radius: var(--radius-full);
5888
+ border-radius: var(--switch-radius);
5313
5889
  background: var(--color-primary-fg);
5314
5890
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5315
5891
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5321,7 +5897,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5321
5897
  display: block;
5322
5898
  width: var(--switch-thumb, 18px);
5323
5899
  height: var(--switch-thumb, 18px);
5324
- border-radius: var(--radius-full);
5900
+ border-radius: var(--switch-radius);
5325
5901
  background: var(--color-primary-fg);
5326
5902
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5327
5903
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5403,7 +5979,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5403
5979
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5404
5980
  @media (forced-colors: active) {
5405
5981
  [data-ui="switch"] {
5406
- border: 1px solid ButtonText;
5982
+ border: var(--border-width) solid ButtonText;
5407
5983
  background: ButtonFace;
5408
5984
  }
5409
5985
 
@@ -5560,25 +6136,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5560
6136
 
5561
6137
  /* === primitives/text.css === */
5562
6138
  /* @ui:component text */
5563
- /* @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 */
6139
+ /* @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 */
5564
6140
 
5565
6141
  /* ── Heading ── */
5566
6142
  [data-ui="heading"] {
5567
- font-family: var(--font-sans);
5568
- font-weight: var(--weight-bold);
6143
+ font-family: var(--font-heading);
6144
+ font-weight: var(--heading-weight);
5569
6145
  color: var(--color-fg);
5570
- line-height: var(--leading-tight);
5571
- letter-spacing: -0.01em;
6146
+ line-height: var(--heading-leading);
6147
+ text-transform: var(--heading-transform);
6148
+ font-variant-caps: var(--heading-caps);
6149
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6150
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6151
+ headings sets --heading-tracking once and every size follows, instead of
6152
+ each size having to re-derive its own number. */
6153
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5572
6154
  }
5573
6155
 
5574
6156
  [data-ui="heading"][data-size="1"] {
5575
6157
  font-size: var(--text-4xl);
5576
- letter-spacing: -0.02em;
6158
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5577
6159
  }
5578
6160
 
5579
6161
  [data-ui="heading"][data-size="2"] {
5580
6162
  font-size: var(--text-3xl);
5581
- letter-spacing: -0.02em;
6163
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5582
6164
  }
5583
6165
 
5584
6166
  [data-ui="heading"][data-size="3"] {
@@ -5602,7 +6184,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5602
6184
 
5603
6185
  /* ── Text ── */
5604
6186
  [data-ui="text"] {
5605
- font-family: var(--font-sans);
6187
+ font-family: var(--font-body);
5606
6188
  color: var(--color-fg);
5607
6189
  }
5608
6190
 
@@ -5680,7 +6262,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5680
6262
 
5681
6263
  /* === primitives/textarea.css === */
5682
6264
  /* @ui:component textarea */
5683
- /* @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 */
6265
+ /* @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 */
5684
6266
 
5685
6267
  /* -- Base -- */
5686
6268
  [data-ui="textarea"] {
@@ -5688,11 +6270,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5688
6270
  width: 100%;
5689
6271
  min-height: var(--textarea-min-height, 80px);
5690
6272
  padding: var(--space-2) var(--space-3);
5691
- border: 1px solid var(--color-border);
6273
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6274
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6275
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6276
+ is drawn. Identical to the shorthand at every other value of the token. */
6277
+ border-style: solid;
6278
+ border-color: var(--color-border);
6279
+ border-width: var(--input-border-width);
5692
6280
  border-radius: var(--textarea-radius, var(--radius-md));
5693
- background: var(--textarea-bg, var(--color-bg));
6281
+ background: var(--textarea-bg, var(--input-fill));
5694
6282
  color: var(--color-fg);
5695
- font-family: var(--textarea-font, var(--font-sans));
6283
+ font-family: var(--textarea-font, var(--font-ui));
5696
6284
  font-size: var(--text-sm);
5697
6285
  line-height: 1.5;
5698
6286
  resize: vertical;
@@ -5709,8 +6297,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5709
6297
  }
5710
6298
 
5711
6299
  [data-ui="textarea"]:focus {
5712
- outline: 2px solid var(--color-ring);
5713
- outline-offset: -1px;
6300
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6301
+ /* The ring replaces the border rather than sitting outside it: inset by
6302
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6303
+ outline-offset: calc(-1 * var(--input-border-width));
6304
+ box-shadow: var(--focus-shadow);
5714
6305
  border-color: transparent;
5715
6306
  }
5716
6307
 
@@ -5738,7 +6329,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5738
6329
  }
5739
6330
 
5740
6331
  [data-ui="textarea"]:disabled {
5741
- opacity: 0.5;
6332
+ opacity: var(--disabled-opacity);
5742
6333
  cursor: not-allowed;
5743
6334
  resize: none;
5744
6335
  }
@@ -5752,7 +6343,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5752
6343
 
5753
6344
  /* === primitives/toggle.css === */
5754
6345
  /* @ui:component toggle */
5755
- /* @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 */
6346
+ /* @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 */
5756
6347
 
5757
6348
  /* ── Base (off / unpressed) ── */
5758
6349
  [data-ui="toggle"] {
@@ -5761,11 +6352,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5761
6352
  justify-content: center;
5762
6353
  gap: var(--space-1h);
5763
6354
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5764
- border: 1px solid var(--color-border);
6355
+ border: var(--border-width) solid var(--color-border);
5765
6356
  border-radius: var(--toggle-radius, var(--radius-md));
5766
6357
  background: var(--color-bg);
5767
6358
  color: var(--color-fg-muted);
5768
- font-family: var(--toggle-font, var(--font-sans));
6359
+ font-family: var(--toggle-font, var(--font-ui));
5769
6360
  font-size: var(--text-sm);
5770
6361
  font-weight: var(--weight-medium);
5771
6362
  line-height: 1;
@@ -5782,8 +6373,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5782
6373
  }
5783
6374
 
5784
6375
  [data-ui="toggle"]:focus-visible {
5785
- outline: 2px solid var(--color-ring);
5786
- outline-offset: 2px;
6376
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6377
+ outline-offset: var(--focus-ring-offset);
6378
+ box-shadow: var(--focus-shadow);
5787
6379
  }
5788
6380
 
5789
6381
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5800,7 +6392,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5800
6392
 
5801
6393
  /* ── Disabled ── */
5802
6394
  [data-ui="toggle"]:disabled {
5803
- opacity: 0.5;
6395
+ opacity: var(--disabled-opacity);
5804
6396
  cursor: not-allowed;
5805
6397
  }
5806
6398
 
@@ -5824,7 +6416,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5824
6416
 
5825
6417
  /* === primitives/watermark.css === */
5826
6418
  /* @ui:component watermark */
5827
- /* @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 */
6419
+ /* @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 */
5828
6420
 
5829
6421
  [data-ui="watermark"] {
5830
6422
  position: fixed;
@@ -5843,7 +6435,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5843
6435
 
5844
6436
  [data-ui="watermark"] > [data-part="mark"] {
5845
6437
  color: var(--color-fg-muted);
5846
- font-family: var(--doc-font, var(--font-sans));
6438
+ font-family: var(--doc-font, var(--font-body));
5847
6439
  font-size: var(--text-4xl);
5848
6440
  font-weight: var(--weight-bold);
5849
6441
  line-height: var(--leading-tight);
@@ -5901,7 +6493,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5901
6493
 
5902
6494
  /* === recipes/accordion.css === */
5903
6495
  /* @ui:component accordion */
5904
- /* @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 */
6496
+ /* @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 */
5905
6497
 
5906
6498
  /* ── Root ── */
5907
6499
  [data-ui="accordion"] {
@@ -5910,7 +6502,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5910
6502
 
5911
6503
  /* ── Item ── */
5912
6504
  [data-ui="accordion"] [data-part="item"] {
5913
- border-bottom: 1px solid var(--color-border);
6505
+ border-bottom: var(--border-width) solid var(--color-border);
5914
6506
  }
5915
6507
 
5916
6508
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5927,7 +6519,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5927
6519
  border: none;
5928
6520
  background: transparent;
5929
6521
  color: var(--color-fg);
5930
- font-family: var(--font-sans, system-ui, sans-serif);
6522
+ font-family: var(--font-ui);
5931
6523
  font-size: var(--text-base);
5932
6524
  font-weight: var(--weight-medium);
5933
6525
  text-align: start;
@@ -5941,8 +6533,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5941
6533
  }
5942
6534
 
5943
6535
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5944
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5945
- outline-offset: -2px;
6536
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6537
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5946
6538
  border-radius: var(--radius-sm, 0.25rem);
5947
6539
  }
5948
6540
 
@@ -5974,13 +6566,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5974
6566
 
5975
6567
  /* ── Bordered Variant ── */
5976
6568
  [data-ui="accordion"][data-bordered="true"] {
5977
- border: 1px solid var(--color-border);
6569
+ border: var(--border-width) solid var(--color-border);
5978
6570
  border-radius: var(--radius-lg);
5979
6571
  overflow: hidden;
5980
6572
  }
5981
6573
 
5982
6574
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5983
- border-bottom: 1px solid var(--color-border);
6575
+ border-bottom: var(--border-width) solid var(--color-border);
5984
6576
  }
5985
6577
 
5986
6578
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5997,7 +6589,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5997
6589
 
5998
6590
  /* === recipes/alert-dialog.css === */
5999
6591
  /* @ui:component alert-dialog */
6000
- /* @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 */
6592
+ /* @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 */
6001
6593
 
6002
6594
  /* ── Root ── */
6003
6595
  [data-ui="alert-dialog"] {
@@ -6033,7 +6625,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6033
6625
  max-height: 85vh;
6034
6626
  overflow-y: auto;
6035
6627
  background: var(--color-bg);
6036
- border: 1px solid var(--color-border);
6628
+ border: var(--border-width) solid var(--color-border);
6037
6629
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
6038
6630
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
6039
6631
  opacity: 0;
@@ -6079,6 +6671,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6079
6671
  /* ── Title ── */
6080
6672
  [data-ui="alert-dialog"] [data-part="title"] {
6081
6673
  margin: 0;
6674
+ font-family: var(--font-heading);
6082
6675
  font-size: var(--text-lg, 1.125rem);
6083
6676
  font-weight: var(--weight-semibold, 600);
6084
6677
  color: var(--color-fg);
@@ -6118,7 +6711,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6118
6711
 
6119
6712
  /* === recipes/barcode.css === */
6120
6713
  /* @ui:component barcode */
6121
- /* @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 */
6714
+ /* @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 */
6122
6715
 
6123
6716
  [data-ui="barcode"] {
6124
6717
  display: inline-flex;
@@ -6145,7 +6738,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6145
6738
 
6146
6739
  [data-ui="barcode"] > [data-part="caption"] {
6147
6740
  color: var(--doc-legal-color, var(--color-fg-muted));
6148
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6741
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6149
6742
  font-size: var(--doc-legal-size);
6150
6743
  line-height: var(--leading-normal);
6151
6744
  text-align: center;
@@ -6165,7 +6758,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6165
6758
 
6166
6759
  /* === recipes/calendar.css === */
6167
6760
  /* @ui:component calendar */
6168
- /* @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 */
6761
+ /* @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 */
6169
6762
 
6170
6763
  /* ── Root ── */
6171
6764
  [data-ui="calendar"] {
@@ -6198,7 +6791,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6198
6791
  width: 28px;
6199
6792
  height: 28px;
6200
6793
  padding: 0;
6201
- border: 1px solid var(--color-border);
6794
+ border: var(--border-width) solid var(--color-border);
6202
6795
  border-radius: var(--radius-md);
6203
6796
  background: var(--color-bg);
6204
6797
  color: var(--color-fg);
@@ -6214,13 +6807,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6214
6807
 
6215
6808
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6216
6809
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6217
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6218
- outline-offset: 2px;
6810
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6811
+ outline-offset: var(--focus-ring-offset);
6219
6812
  }
6220
6813
 
6221
6814
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6222
6815
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6223
- opacity: 0.4;
6816
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6817
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6818
+ opacity: calc(var(--disabled-opacity) * 0.8);
6224
6819
  cursor: not-allowed;
6225
6820
  }
6226
6821
 
@@ -6255,11 +6850,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6255
6850
  width: 36px;
6256
6851
  height: 36px;
6257
6852
  padding: 0;
6258
- border: 1px solid transparent;
6853
+ border: var(--border-width) solid transparent;
6259
6854
  border-radius: var(--radius-full);
6260
6855
  background: transparent;
6261
6856
  color: var(--color-fg);
6262
- font-family: var(--font-sans, system-ui, sans-serif);
6857
+ font-family: var(--font-ui);
6263
6858
  font-size: var(--text-sm);
6264
6859
  cursor: pointer;
6265
6860
  transition: background var(--duration-fast) var(--ease-default),
@@ -6272,8 +6867,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6272
6867
  }
6273
6868
 
6274
6869
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6275
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6276
- outline-offset: 2px;
6870
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6871
+ outline-offset: var(--focus-ring-offset);
6277
6872
  }
6278
6873
 
6279
6874
  /* ── Today ── */
@@ -6308,7 +6903,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6308
6903
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6309
6904
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6310
6905
  [data-ui="calendar"] [data-part="day"]:disabled {
6311
- opacity: 0.5;
6906
+ opacity: var(--disabled-opacity);
6312
6907
  cursor: not-allowed;
6313
6908
  text-decoration: line-through;
6314
6909
  }
@@ -6372,7 +6967,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6372
6967
 
6373
6968
  /* === recipes/carousel.css === */
6374
6969
  /* @ui:component carousel */
6375
- /* @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 */
6970
+ /* @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 */
6376
6971
 
6377
6972
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6378
6973
  every slide is a snap target. Everything below works with no controller
@@ -6386,7 +6981,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6386
6981
  inline-size: 100%;
6387
6982
  min-inline-size: 0;
6388
6983
  max-inline-size: 100%;
6389
- font-family: var(--carousel-font, var(--font-sans));
6984
+ font-family: var(--carousel-font, var(--font-ui));
6390
6985
  }
6391
6986
 
6392
6987
  /* ── Viewport: the scroll-snap strip ── */
@@ -6412,8 +7007,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6412
7007
  }
6413
7008
 
6414
7009
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6415
- outline: 2px solid var(--color-ring);
6416
- outline-offset: 2px;
7010
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7011
+ outline-offset: var(--focus-ring-offset);
6417
7012
  }
6418
7013
 
6419
7014
  /* ── Slide: one full-width snap target ── */
@@ -6421,7 +7016,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6421
7016
  flex: 0 0 var(--carousel-slide-size, 100%);
6422
7017
  min-inline-size: 0;
6423
7018
  padding: var(--space-4);
6424
- border: 1px solid var(--color-border);
7019
+ border: var(--border-width) solid var(--color-border);
6425
7020
  border-radius: var(--radius-lg);
6426
7021
  background: var(--color-bg);
6427
7022
  color: var(--color-fg);
@@ -6450,7 +7045,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6450
7045
  min-inline-size: 2rem;
6451
7046
  min-block-size: 2rem;
6452
7047
  padding: var(--space-1) var(--space-2);
6453
- border: 1px solid var(--color-border);
7048
+ border: var(--border-width) solid var(--color-border);
6454
7049
  border-radius: var(--radius-md);
6455
7050
  background: var(--color-bg);
6456
7051
  color: var(--color-fg);
@@ -6469,14 +7064,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6469
7064
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6470
7065
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6471
7066
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6472
- outline: 2px solid var(--color-ring);
6473
- outline-offset: 2px;
7067
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7068
+ outline-offset: var(--focus-ring-offset);
6474
7069
  }
6475
7070
 
6476
7071
  /* Boundary contract "stop" — the controller disables the end button. */
6477
7072
  [data-ui="carousel"] [data-part="prev"]:disabled,
6478
7073
  [data-ui="carousel"] [data-part="next"]:disabled {
6479
- opacity: 0.4;
7074
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7075
+ opacity: calc(var(--disabled-opacity) * 0.8);
6480
7076
  cursor: not-allowed;
6481
7077
  }
6482
7078
 
@@ -6485,7 +7081,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6485
7081
  inline-size: 0.625rem;
6486
7082
  block-size: 0.625rem;
6487
7083
  padding: 0;
6488
- border: 1px solid var(--color-border);
7084
+ border: var(--border-width) solid var(--color-border);
6489
7085
  border-radius: 50%;
6490
7086
  background: var(--color-bg-muted);
6491
7087
  cursor: pointer;
@@ -6521,7 +7117,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6521
7117
 
6522
7118
  /* === recipes/combobox.css === */
6523
7119
  /* @ui:component combobox */
6524
- /* @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 */
7120
+ /* @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 */
6525
7121
 
6526
7122
  /* ── Root ── */
6527
7123
  [data-ui="combobox"] {
@@ -6535,11 +7131,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6535
7131
  display: block;
6536
7132
  width: 100%;
6537
7133
  padding: var(--space-2) var(--space-3);
6538
- border: 1px solid var(--color-border);
7134
+ border: var(--border-width) solid var(--color-border);
6539
7135
  border-radius: var(--radius-md);
6540
7136
  background: var(--color-bg);
6541
7137
  color: var(--color-fg);
6542
- font-family: var(--font-sans, system-ui, sans-serif);
7138
+ font-family: var(--font-ui);
6543
7139
  font-size: var(--text-sm);
6544
7140
  line-height: 1.5;
6545
7141
  outline: none;
@@ -6552,8 +7148,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6552
7148
  }
6553
7149
 
6554
7150
  [data-ui="combobox"] [data-part="input"]:focus {
6555
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6556
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7151
+ border-color: var(--focus-ring-color);
7152
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6557
7153
  }
6558
7154
 
6559
7155
  /* ── Listbox ── */
@@ -6565,7 +7161,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6565
7161
  z-index: var(--z-dropdown);
6566
7162
  margin-top: var(--space-1);
6567
7163
  padding: var(--space-1);
6568
- border: 1px solid var(--color-border);
7164
+ border: var(--border-width) solid var(--color-border);
6569
7165
  border-radius: var(--radius-lg);
6570
7166
  background: var(--color-bg);
6571
7167
  box-shadow: var(--shadow-md);
@@ -6650,7 +7246,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6650
7246
 
6651
7247
  /* === recipes/command-palette.css === */
6652
7248
  /* @ui:component command-palette */
6653
- /* @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 */
7249
+ /* @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 */
6654
7250
 
6655
7251
  /* ── Root ── */
6656
7252
  [data-ui="command-palette"] {
@@ -6683,7 +7279,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6683
7279
  display: flex;
6684
7280
  flex-direction: column;
6685
7281
  background: var(--color-bg);
6686
- border: 1px solid var(--color-border);
7282
+ border: var(--border-width) solid var(--color-border);
6687
7283
  border-radius: var(--radius-xl);
6688
7284
  box-shadow: var(--shadow-xl);
6689
7285
  overflow: hidden;
@@ -6715,7 +7311,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6715
7311
  display: flex;
6716
7312
  align-items: center;
6717
7313
  padding: var(--space-3) var(--space-4);
6718
- border-bottom: 1px solid var(--color-border);
7314
+ border-bottom: var(--border-width) solid var(--color-border);
6719
7315
  }
6720
7316
 
6721
7317
  /* ── Search Input ── */
@@ -6725,7 +7321,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6725
7321
  border: none;
6726
7322
  background: transparent;
6727
7323
  color: var(--color-fg);
6728
- font-family: var(--font-sans, system-ui, sans-serif);
7324
+ font-family: var(--font-ui);
6729
7325
  font-size: var(--text-base);
6730
7326
  outline: none;
6731
7327
  }
@@ -6809,7 +7405,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6809
7405
  align-items: center;
6810
7406
  gap: var(--space-1, 0.25rem);
6811
7407
  padding: var(--space-1, 0.25rem) var(--space-2);
6812
- border: 1px solid var(--color-border);
7408
+ border: var(--border-width) solid var(--color-border);
6813
7409
  border-radius: var(--radius-sm, 0.25rem);
6814
7410
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6815
7411
  color: var(--color-fg-muted);
@@ -6838,7 +7434,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6838
7434
 
6839
7435
  /* === recipes/context-menu.css === */
6840
7436
  /* @ui:component context-menu */
6841
- /* @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 */
7437
+ /* @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 */
6842
7438
 
6843
7439
  [data-ui="context-menu"] {
6844
7440
  position: relative;
@@ -6851,12 +7447,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6851
7447
  border-radius: var(--radius-lg);
6852
7448
  background: var(--color-bg-muted);
6853
7449
  color: var(--color-fg);
6854
- font-family: var(--font-sans, system-ui, sans-serif);
7450
+ font-family: var(--font-ui);
6855
7451
  }
6856
7452
 
6857
7453
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6858
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6859
- outline-offset: var(--space-1);
7454
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7455
+ outline-offset: var(--focus-ring-offset);
6860
7456
  }
6861
7457
 
6862
7458
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6888,7 +7484,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6888
7484
  border-radius: var(--radius-md);
6889
7485
  background: transparent;
6890
7486
  color: var(--color-fg);
6891
- font-family: var(--font-sans, system-ui, sans-serif);
7487
+ font-family: var(--font-ui);
6892
7488
  font-size: var(--text-sm);
6893
7489
  font-weight: var(--weight-medium);
6894
7490
  text-align: start;
@@ -6912,15 +7508,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6912
7508
  focus additionally draws the ring, inset so it does not overlap the item
6913
7509
  above. [W3-3] */
6914
7510
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6915
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6916
- outline-offset: calc(var(--space-px) * -2);
7511
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7512
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6917
7513
  }
6918
7514
 
6919
7515
  [data-ui="context-menu"] [data-part="item"]:disabled,
6920
7516
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6921
7517
  color: var(--color-fg-muted);
6922
7518
  cursor: not-allowed;
6923
- opacity: 0.5;
7519
+ opacity: var(--disabled-opacity);
6924
7520
  }
6925
7521
 
6926
7522
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6939,7 +7535,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6939
7535
 
6940
7536
  /* === recipes/date-picker.css === */
6941
7537
  /* @ui:component date-picker */
6942
- /* @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 */
7538
+ /* @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 */
6943
7539
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6944
7540
 
6945
7541
  /* ── Root ── */
@@ -6960,11 +7556,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6960
7556
  width: 100%;
6961
7557
  padding: var(--space-2, 0.5rem) var(--space-3);
6962
7558
  padding-inline-end: var(--space-8, 2.5rem);
6963
- border: 1px solid var(--color-border);
7559
+ border: var(--border-width) solid var(--color-border);
6964
7560
  border-radius: var(--radius-md);
6965
7561
  background: var(--color-bg);
6966
7562
  color: var(--color-fg);
6967
- font-family: var(--font-sans, system-ui, sans-serif);
7563
+ font-family: var(--font-ui);
6968
7564
  font-size: var(--text-sm);
6969
7565
  line-height: 1.5;
6970
7566
  cursor: pointer;
@@ -6976,8 +7572,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6976
7572
  }
6977
7573
 
6978
7574
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6979
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6980
- outline-offset: 2px;
7575
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7576
+ outline-offset: var(--focus-ring-offset);
6981
7577
  border-color: var(--color-primary);
6982
7578
  }
6983
7579
 
@@ -7000,7 +7596,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7000
7596
  z-index: var(--z-dropdown);
7001
7597
  margin-top: var(--space-1);
7002
7598
  padding: var(--space-3);
7003
- border: 1px solid var(--color-border);
7599
+ border: var(--border-width) solid var(--color-border);
7004
7600
  border-radius: var(--radius-lg);
7005
7601
  background: var(--color-bg);
7006
7602
  box-shadow: var(--shadow-lg);
@@ -7039,7 +7635,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7039
7635
 
7040
7636
  /* === recipes/dialog.css === */
7041
7637
  /* @ui:component dialog */
7042
- /* @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 */
7638
+ /* @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 */
7043
7639
 
7044
7640
  /* ── Root ── */
7045
7641
  [data-ui="dialog"] {
@@ -7074,15 +7670,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7074
7670
  width: 90%;
7075
7671
  max-height: 85vh;
7076
7672
  overflow-y: auto;
7077
- background: var(--color-bg);
7078
- border: 1px solid var(--color-border);
7673
+ background: var(--panel-bg);
7674
+ border: var(--border-width) solid var(--color-border);
7079
7675
  border-radius: var(--dialog-radius, var(--radius-xl));
7676
+ corner-shape: var(--corner-shape);
7080
7677
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7081
7678
  opacity: 0;
7082
7679
  transition: opacity var(--duration-normal) var(--ease-out),
7083
7680
  transform var(--duration-normal) var(--ease-out);
7084
7681
  }
7085
7682
 
7683
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7684
+ [data-ui="dialog"] [data-part="panel"] {
7685
+ -webkit-backdrop-filter: var(--surface-backdrop);
7686
+ backdrop-filter: var(--surface-backdrop);
7687
+ }
7688
+ }
7689
+
7086
7690
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7087
7691
  opacity: 1;
7088
7692
  transform: translate(-50%, -50%) scale(1);
@@ -7131,6 +7735,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7131
7735
  /* ── Title ── */
7132
7736
  [data-ui="dialog"] [data-part="title"] {
7133
7737
  margin: 0;
7738
+ font-family: var(--font-heading);
7134
7739
  font-size: var(--text-lg, 1.125rem);
7135
7740
  font-weight: var(--weight-semibold, 600);
7136
7741
  color: var(--color-fg);
@@ -7165,8 +7770,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7165
7770
  }
7166
7771
 
7167
7772
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7168
- outline: 2px solid var(--color-ring);
7169
- outline-offset: 2px;
7773
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7774
+ outline-offset: var(--focus-ring-offset);
7170
7775
  }
7171
7776
 
7172
7777
  /* ── Description ── */
@@ -7202,7 +7807,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7202
7807
 
7203
7808
  /* === recipes/drawer.css === */
7204
7809
  /* @ui:component drawer */
7205
- /* @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 */
7810
+ /* @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 */
7206
7811
 
7207
7812
  /* ── Root ── */
7208
7813
  [data-ui="drawer"] {
@@ -7237,17 +7842,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7237
7842
  flex-direction: column;
7238
7843
  width: var(--drawer-width, 400px);
7239
7844
  max-width: 100vw;
7240
- background: var(--color-bg);
7845
+ background: var(--panel-bg);
7241
7846
  border: none;
7242
7847
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7243
7848
  transition: transform var(--duration-slow) var(--ease-out);
7244
7849
  }
7245
7850
 
7851
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7852
+ [data-ui="drawer"] [data-part="panel"] {
7853
+ -webkit-backdrop-filter: var(--surface-backdrop);
7854
+ backdrop-filter: var(--surface-backdrop);
7855
+ }
7856
+ }
7857
+
7246
7858
  /* ── Side Variants ── */
7247
7859
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7248
7860
  inset-inline-start: 0;
7249
7861
  inset-inline-end: auto;
7250
- border-inline-end: 1px solid var(--color-border);
7862
+ border-inline-end: var(--border-width) solid var(--color-border);
7251
7863
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7252
7864
  transform: translateX(-100%);
7253
7865
  }
@@ -7255,7 +7867,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7255
7867
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7256
7868
  inset-inline-end: 0;
7257
7869
  inset-inline-start: auto;
7258
- border-inline-start: 1px solid var(--color-border);
7870
+ border-inline-start: var(--border-width) solid var(--color-border);
7259
7871
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7260
7872
  transform: translateX(100%);
7261
7873
  }
@@ -7309,6 +7921,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7309
7921
  /* ── Title ── */
7310
7922
  [data-ui="drawer"] [data-part="title"] {
7311
7923
  margin: 0;
7924
+ font-family: var(--font-heading);
7312
7925
  font-size: var(--text-lg, 1.125rem);
7313
7926
  font-weight: var(--weight-semibold, 600);
7314
7927
  color: var(--color-fg);
@@ -7343,8 +7956,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7343
7956
  }
7344
7957
 
7345
7958
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7346
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7347
- outline-offset: 2px;
7959
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7960
+ outline-offset: var(--focus-ring-offset);
7348
7961
  }
7349
7962
 
7350
7963
  /* ── Body ── */
@@ -7363,7 +7976,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7363
7976
  gap: var(--space-3, 0.75rem);
7364
7977
  padding: var(--space-6);
7365
7978
  padding-top: var(--space-4);
7366
- border-top: 1px solid var(--color-border);
7979
+ border-top: var(--border-width) solid var(--color-border);
7367
7980
  flex-shrink: 0;
7368
7981
  }
7369
7982
 
@@ -7377,7 +7990,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7377
7990
 
7378
7991
  /* === recipes/dropdown.css === */
7379
7992
  /* @ui:component dropdown */
7380
- /* @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 */
7993
+ /* @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 */
7381
7994
 
7382
7995
  /* ── Root ── */
7383
7996
  [data-ui="dropdown"] {
@@ -7391,11 +8004,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7391
8004
  align-items: center;
7392
8005
  gap: var(--space-2);
7393
8006
  padding: var(--space-2) var(--space-3);
7394
- border: 1px solid var(--color-border);
8007
+ border: var(--border-width) solid var(--color-border);
7395
8008
  border-radius: var(--radius-md);
7396
8009
  background: var(--color-bg);
7397
8010
  color: var(--color-fg);
7398
- font-family: var(--font-sans, system-ui, sans-serif);
8011
+ font-family: var(--font-ui);
7399
8012
  font-size: var(--text-sm);
7400
8013
  font-weight: var(--weight-medium);
7401
8014
  cursor: pointer;
@@ -7409,8 +8022,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7409
8022
  }
7410
8023
 
7411
8024
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7412
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7413
- outline-offset: 2px;
8025
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8026
+ outline-offset: var(--focus-ring-offset);
7414
8027
  }
7415
8028
 
7416
8029
  /* ── Menu ── */
@@ -7422,9 +8035,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7422
8035
  min-width: 180px;
7423
8036
  margin-top: var(--space-1);
7424
8037
  padding: var(--space-1);
7425
- border: 1px solid var(--color-border);
8038
+ border: var(--border-width) solid var(--color-border);
7426
8039
  border-radius: var(--radius-lg);
7427
- background: var(--color-bg);
8040
+ background: var(--panel-bg);
7428
8041
  box-shadow: var(--shadow-md);
7429
8042
  opacity: 0;
7430
8043
  transform: translateY(-4px);
@@ -7432,6 +8045,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7432
8045
  transform var(--duration-fast) var(--ease-out);
7433
8046
  }
7434
8047
 
8048
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8049
+ [data-ui="dropdown"] [data-part="menu"] {
8050
+ -webkit-backdrop-filter: var(--surface-backdrop);
8051
+ backdrop-filter: var(--surface-backdrop);
8052
+ }
8053
+ }
8054
+
7435
8055
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7436
8056
  opacity: 1;
7437
8057
  transform: translateY(0);
@@ -7454,7 +8074,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7454
8074
  border-radius: var(--radius-md);
7455
8075
  background: transparent;
7456
8076
  color: var(--color-fg);
7457
- font-family: var(--font-sans, system-ui, sans-serif);
8077
+ font-family: var(--font-ui);
7458
8078
  font-size: var(--text-sm);
7459
8079
  text-align: start;
7460
8080
  cursor: pointer;
@@ -7476,12 +8096,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7476
8096
  focus additionally draws the ring, inset so it does not overlap the item
7477
8097
  above. [W3-3] */
7478
8098
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7479
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7480
- outline-offset: -2px;
8099
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8100
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7481
8101
  }
7482
8102
 
7483
8103
  [data-ui="dropdown"] [data-part="item"]:disabled {
7484
- opacity: 0.5;
8104
+ opacity: var(--disabled-opacity);
7485
8105
  cursor: not-allowed;
7486
8106
  pointer-events: none;
7487
8107
  }
@@ -7534,14 +8154,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7534
8154
 
7535
8155
  /* === recipes/file-upload.css === */
7536
8156
  /* @ui:component file-upload */
7537
- /* @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 */
8157
+ /* @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 */
7538
8158
 
7539
8159
  [data-ui="file-upload"] {
7540
8160
  display: grid;
7541
8161
  gap: var(--space-4);
7542
8162
  inline-size: 100%;
7543
8163
  color: var(--color-fg);
7544
- font-family: var(--font-sans);
8164
+ font-family: var(--font-ui);
7545
8165
  }
7546
8166
 
7547
8167
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7576,14 +8196,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7576
8196
  }
7577
8197
 
7578
8198
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7579
- outline: var(--space-px) solid var(--color-ring);
7580
- outline-offset: var(--space-1);
8199
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8200
+ outline-offset: var(--focus-ring-offset);
7581
8201
  }
7582
8202
 
7583
8203
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7584
8204
  border-color: var(--color-primary);
7585
8205
  background: var(--color-primary-subtle);
7586
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8206
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7587
8207
  }
7588
8208
 
7589
8209
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7657,8 +8277,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7657
8277
  }
7658
8278
 
7659
8279
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7660
- outline: var(--space-px) solid var(--color-ring);
7661
- outline-offset: var(--space-1);
8280
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8281
+ outline-offset: var(--focus-ring-offset);
7662
8282
  }
7663
8283
 
7664
8284
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7680,7 +8300,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7680
8300
  }
7681
8301
 
7682
8302
  [data-ui="file-upload"][data-disabled] {
7683
- opacity: 0.5;
8303
+ opacity: var(--disabled-opacity);
7684
8304
  }
7685
8305
 
7686
8306
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7696,7 +8316,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7696
8316
 
7697
8317
  /* === recipes/input-otp.css === */
7698
8318
  /* @ui:component input-otp */
7699
- /* @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 */
8319
+ /* @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 */
7700
8320
 
7701
8321
  /* ── Root ── */
7702
8322
  [data-ui="input-otp"] {
@@ -7711,7 +8331,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7711
8331
  gutter. The transparent input is `inset: 0`, so it follows the box the
7712
8332
  segments settle into however many rows that takes. */
7713
8333
  max-inline-size: 100%;
7714
- font-family: var(--font-sans, system-ui, sans-serif);
8334
+ font-family: var(--font-ui);
7715
8335
  }
7716
8336
 
7717
8337
  /* ── Real input ──
@@ -7756,14 +8376,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7756
8376
  justify-content: center;
7757
8377
  inline-size: var(--input-otp-segment-size);
7758
8378
  block-size: var(--input-otp-segment-size);
7759
- border: 1px solid var(--color-border);
8379
+ border: var(--border-width) solid var(--color-border);
7760
8380
  border-radius: var(--radius-md);
7761
8381
  background: var(--color-bg);
7762
8382
  color: var(--color-fg);
7763
8383
  font-size: var(--text-lg, 1.125rem);
7764
8384
  font-variant-numeric: tabular-nums;
7765
8385
  line-height: 1;
7766
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8386
+ transition: border-color var(--duration-fast) var(--ease-default),
7767
8387
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7768
8388
  }
7769
8389
 
@@ -7775,7 +8395,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7775
8395
  /* Active (caret / selected) segment while focused */
7776
8396
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7777
8397
  border-color: var(--color-ring);
7778
- box-shadow: 0 0 0 1px var(--color-ring);
8398
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7779
8399
  }
7780
8400
 
7781
8401
  /* Blinking caret in the next-to-fill empty slot */
@@ -7823,7 +8443,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7823
8443
 
7824
8444
  /* ── Disabled ── */
7825
8445
  [data-ui="input-otp"][data-disabled] {
7826
- opacity: 0.5;
8446
+ opacity: var(--disabled-opacity);
7827
8447
  cursor: not-allowed;
7828
8448
  }
7829
8449
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7847,7 +8467,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7847
8467
 
7848
8468
  /* === recipes/menubar.css === */
7849
8469
  /* @ui:component menubar */
7850
- /* @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 */
8470
+ /* @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 */
7851
8471
 
7852
8472
  [data-ui="menubar"] {
7853
8473
  position: relative;
@@ -7865,7 +8485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7865
8485
  border-radius: var(--radius-lg);
7866
8486
  background: var(--color-bg);
7867
8487
  color: var(--color-fg);
7868
- font-family: var(--font-sans);
8488
+ font-family: var(--font-ui);
7869
8489
  }
7870
8490
 
7871
8491
  [data-ui="menubar"] [data-part="group"] {
@@ -7907,7 +8527,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7907
8527
 
7908
8528
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7909
8529
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7910
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8530
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7911
8531
  }
7912
8532
 
7913
8533
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7942,7 +8562,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7942
8562
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7943
8563
  color: var(--color-fg-muted);
7944
8564
  cursor: not-allowed;
7945
- opacity: 0.6;
8565
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8566
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8567
+ it (1.1A-27). */
8568
+ opacity: calc(var(--disabled-opacity) * 1.2);
7946
8569
  }
7947
8570
 
7948
8571
  [data-ui="menubar"] [data-part="separator"] {
@@ -7974,7 +8597,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7974
8597
 
7975
8598
  /* === recipes/pagination.css === */
7976
8599
  /* @ui:component pagination */
7977
- /* @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 */
8600
+ /* @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 */
7978
8601
 
7979
8602
  /* ── Root ── */
7980
8603
  [data-ui="pagination"] {
@@ -8010,11 +8633,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8010
8633
  min-width: 36px;
8011
8634
  height: 36px;
8012
8635
  padding: 0 var(--space-2);
8013
- border: 1px solid var(--color-border);
8636
+ border: var(--border-width) solid var(--color-border);
8014
8637
  border-radius: var(--radius-md);
8015
8638
  background: var(--color-bg);
8016
8639
  color: var(--color-fg);
8017
- font-family: var(--font-sans, system-ui, sans-serif);
8640
+ font-family: var(--font-ui);
8018
8641
  font-size: var(--text-sm);
8019
8642
  font-weight: var(--weight-medium);
8020
8643
  cursor: pointer;
@@ -8035,8 +8658,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8035
8658
  [data-ui="pagination"] [data-part="page"]:focus-visible,
8036
8659
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
8037
8660
  [data-ui="pagination"] [data-part="next"]:focus-visible {
8038
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8039
- outline-offset: 2px;
8661
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8662
+ outline-offset: var(--focus-ring-offset);
8040
8663
  }
8041
8664
 
8042
8665
  /* ── Active page ── */
@@ -8060,7 +8683,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8060
8683
  /* ── Disabled ── */
8061
8684
  [data-ui="pagination"] [data-part="prev"]:disabled,
8062
8685
  [data-ui="pagination"] [data-part="next"]:disabled {
8063
- opacity: 0.5;
8686
+ opacity: var(--disabled-opacity);
8064
8687
  cursor: not-allowed;
8065
8688
  pointer-events: none;
8066
8689
  }
@@ -8130,7 +8753,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8130
8753
 
8131
8754
  /* === recipes/popover.css === */
8132
8755
  /* @ui:component popover */
8133
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8756
+ /* @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 */
8134
8757
 
8135
8758
  /* ── Root ── */
8136
8759
  [data-ui="popover"] {
@@ -8144,11 +8767,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8144
8767
  align-items: center;
8145
8768
  gap: var(--space-2, 0.5rem);
8146
8769
  padding: var(--space-2, 0.5rem) var(--space-3);
8147
- border: 1px solid var(--color-border);
8770
+ border: var(--border-width) solid var(--color-border);
8148
8771
  border-radius: var(--radius-md, 0.375rem);
8149
8772
  background: var(--color-bg);
8150
8773
  color: var(--color-fg);
8151
- font-family: var(--font-sans, system-ui, sans-serif);
8774
+ font-family: var(--font-ui);
8152
8775
  font-size: var(--text-sm, 0.875rem);
8153
8776
  font-weight: var(--weight-medium, 500);
8154
8777
  cursor: pointer;
@@ -8162,8 +8785,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8162
8785
  }
8163
8786
 
8164
8787
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8165
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8166
- outline-offset: 2px;
8788
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8789
+ outline-offset: var(--focus-ring-offset);
8167
8790
  }
8168
8791
 
8169
8792
  /* ── Content ── */
@@ -8172,9 +8795,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8172
8795
  z-index: var(--z-dropdown);
8173
8796
  min-width: 200px;
8174
8797
  padding: var(--space-4);
8175
- border: 1px solid var(--color-border);
8798
+ border: var(--border-width) solid var(--color-border);
8176
8799
  border-radius: var(--radius-lg);
8177
- background: var(--color-bg);
8800
+ background: var(--panel-bg);
8178
8801
  color: var(--color-fg);
8179
8802
  box-shadow: var(--shadow-md);
8180
8803
  opacity: 0;
@@ -8183,6 +8806,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8183
8806
  transform var(--duration-fast) var(--ease-default);
8184
8807
  }
8185
8808
 
8809
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8810
+ [data-ui="popover"] [data-part="content"] {
8811
+ -webkit-backdrop-filter: var(--surface-backdrop);
8812
+ backdrop-filter: var(--surface-backdrop);
8813
+ }
8814
+ }
8815
+
8186
8816
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8187
8817
  opacity: 1;
8188
8818
  transform: scale(1);
@@ -8270,8 +8900,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8270
8900
  position: absolute;
8271
8901
  width: 8px;
8272
8902
  height: 8px;
8273
- background: var(--color-bg);
8274
- border: 1px solid var(--color-border);
8903
+ background: var(--panel-bg);
8904
+ border: var(--border-width) solid var(--color-border);
8275
8905
  transform: rotate(45deg);
8276
8906
  }
8277
8907
 
@@ -8372,8 +9002,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8372
9002
  }
8373
9003
 
8374
9004
  [data-ui="popover"] [data-part="close"]:focus-visible {
8375
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8376
- outline-offset: 2px;
9005
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9006
+ outline-offset: var(--focus-ring-offset);
8377
9007
  }
8378
9008
 
8379
9009
  /* ── Motion ── */
@@ -8386,7 +9016,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8386
9016
 
8387
9017
  /* === recipes/qr-code.css === */
8388
9018
  /* @ui:component qr-code */
8389
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
9019
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8390
9020
 
8391
9021
  /* ── Base ── */
8392
9022
  [data-ui="qr-code"] {
@@ -8404,7 +9034,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8404
9034
 
8405
9035
  /* ── Caption ── */
8406
9036
  [data-ui="qr-code"] [data-part="caption"] {
8407
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
9037
+ font-family: var(--doc-font, var(--font-body));
8408
9038
  font-size: var(--doc-legal-size, var(--text-xs));
8409
9039
  color: var(--doc-legal-color, var(--color-fg-muted));
8410
9040
  text-align: center;
@@ -8445,7 +9075,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8445
9075
 
8446
9076
  /* === recipes/select-custom.css === */
8447
9077
  /* @ui:component select-custom */
8448
- /* @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 */
9078
+ /* @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 */
8449
9079
 
8450
9080
  /* ── Root ── */
8451
9081
  [data-ui="select-custom"] {
@@ -8462,11 +9092,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8462
9092
  width: 100%;
8463
9093
  min-width: 180px;
8464
9094
  padding: var(--space-2) var(--space-3);
8465
- border: 1px solid var(--color-border);
9095
+ border: var(--border-width) solid var(--color-border);
8466
9096
  border-radius: var(--radius-md);
8467
9097
  background: var(--color-bg);
8468
9098
  color: var(--color-fg);
8469
- font-family: var(--font-sans, system-ui, sans-serif);
9099
+ font-family: var(--font-ui);
8470
9100
  font-size: var(--text-sm);
8471
9101
  cursor: pointer;
8472
9102
  white-space: nowrap;
@@ -8479,8 +9109,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8479
9109
  }
8480
9110
 
8481
9111
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8482
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8483
- outline-offset: 2px;
9112
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9113
+ outline-offset: var(--focus-ring-offset);
8484
9114
  }
8485
9115
 
8486
9116
  /* ── Value ── */
@@ -8516,7 +9146,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8516
9146
  z-index: var(--z-dropdown);
8517
9147
  margin-top: var(--space-1);
8518
9148
  padding: var(--space-1);
8519
- border: 1px solid var(--color-border);
9149
+ border: var(--border-width) solid var(--color-border);
8520
9150
  border-radius: var(--radius-lg);
8521
9151
  background: var(--color-bg);
8522
9152
  box-shadow: var(--shadow-md);
@@ -8540,11 +9170,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8540
9170
  padding: var(--space-2) var(--space-3);
8541
9171
  margin-bottom: var(--space-1);
8542
9172
  border: none;
8543
- border-bottom: 1px solid var(--color-border);
9173
+ border-bottom: var(--border-width) solid var(--color-border);
8544
9174
  border-radius: 0;
8545
9175
  background: transparent;
8546
9176
  color: var(--color-fg);
8547
- font-family: var(--font-sans, system-ui, sans-serif);
9177
+ font-family: var(--font-ui);
8548
9178
  font-size: var(--text-sm);
8549
9179
  outline: none;
8550
9180
  }
@@ -8638,7 +9268,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8638
9268
 
8639
9269
  /* === recipes/sheet.css === */
8640
9270
  /* @ui:component sheet */
8641
- /* @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 */
9271
+ /* @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 */
8642
9272
 
8643
9273
  /* ── Root ── */
8644
9274
  [data-ui="sheet"] {
@@ -8669,11 +9299,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8669
9299
  z-index: var(--z-modal);
8670
9300
  display: flex;
8671
9301
  flex-direction: column;
8672
- background: var(--color-bg);
9302
+ background: var(--panel-bg);
8673
9303
  box-shadow: var(--shadow-xl);
8674
9304
  transition: transform var(--duration-slow) var(--ease-out);
8675
9305
  }
8676
9306
 
9307
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9308
+ [data-ui="sheet"] [data-part="panel"] {
9309
+ -webkit-backdrop-filter: var(--surface-backdrop);
9310
+ backdrop-filter: var(--surface-backdrop);
9311
+ }
9312
+ }
9313
+
8677
9314
  /* ── Side: Bottom ── */
8678
9315
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8679
9316
  bottom: 0;
@@ -8701,7 +9338,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8701
9338
  bottom: 0;
8702
9339
  max-width: 100vw;
8703
9340
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8704
- border-inline-end: 1px solid var(--color-border);
9341
+ border-inline-end: var(--border-width) solid var(--color-border);
8705
9342
  transform: translateX(-100%);
8706
9343
  }
8707
9344
 
@@ -8712,7 +9349,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8712
9349
  bottom: 0;
8713
9350
  max-width: 100vw;
8714
9351
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8715
- border-inline-start: 1px solid var(--color-border);
9352
+ border-inline-start: var(--border-width) solid var(--color-border);
8716
9353
  transform: translateX(100%);
8717
9354
  }
8718
9355
 
@@ -8789,6 +9426,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8789
9426
  /* ── Title ── */
8790
9427
  [data-ui="sheet"] [data-part="title"] {
8791
9428
  margin: 0;
9429
+ font-family: var(--font-heading);
8792
9430
  font-size: var(--text-lg, 1.125rem);
8793
9431
  font-weight: var(--weight-semibold, 600);
8794
9432
  color: var(--color-fg);
@@ -8823,8 +9461,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8823
9461
  }
8824
9462
 
8825
9463
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8826
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8827
- outline-offset: 2px;
9464
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9465
+ outline-offset: var(--focus-ring-offset);
8828
9466
  }
8829
9467
 
8830
9468
  /* ── Body ── */
@@ -8845,7 +9483,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8845
9483
 
8846
9484
  /* === recipes/sidebar.css === */
8847
9485
  /* @ui:component sidebar */
8848
- /* @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 */
9486
+ /* @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 */
8849
9487
 
8850
9488
  /* ── Root ──
8851
9489
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8889,7 +9527,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8889
9527
  flex-direction: column;
8890
9528
  gap: var(--space-2);
8891
9529
  background: var(--sidebar-bg);
8892
- border-inline-end: 1px solid var(--color-border);
9530
+ border-inline-end: var(--border-width) solid var(--color-border);
8893
9531
  border-start-end-radius: var(--radius-lg, 0.5rem);
8894
9532
  border-end-end-radius: var(--radius-lg, 0.5rem);
8895
9533
  box-shadow: var(--shadow-xl);
@@ -8970,8 +9608,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8970
9608
  }
8971
9609
 
8972
9610
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8973
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8974
- outline-offset: 2px;
9611
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9612
+ outline-offset: var(--focus-ring-offset);
8975
9613
  }
8976
9614
 
8977
9615
  /* ── Navigation ── */
@@ -9007,8 +9645,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9007
9645
  }
9008
9646
 
9009
9647
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
9010
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9011
- outline-offset: -2px;
9648
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9649
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9012
9650
  }
9013
9651
 
9014
9652
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -9035,7 +9673,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9035
9673
  [data-ui="sidebar"] [data-part="footer"] {
9036
9674
  flex-shrink: 0;
9037
9675
  padding: var(--space-3) var(--space-4);
9038
- border-block-start: 1px solid var(--color-border);
9676
+ border-block-start: var(--border-width) solid var(--color-border);
9039
9677
  }
9040
9678
 
9041
9679
  /* ── Rail (icons only) ── */
@@ -9128,7 +9766,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9128
9766
 
9129
9767
  /* === recipes/slider.css === */
9130
9768
  /* @ui:component slider */
9131
- /* @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 */
9769
+ /* @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 */
9132
9770
 
9133
9771
  /* ── Root ── */
9134
9772
  [data-ui="slider"] {
@@ -9178,28 +9816,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9178
9816
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9179
9817
  transform: translate(-50%, -50%);
9180
9818
  background: var(--color-bg, white);
9181
- border: 2px solid var(--color-primary);
9819
+ border: var(--border-width-strong) solid var(--color-primary);
9182
9820
  border-radius: var(--radius-full, 9999px);
9183
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9821
+ box-shadow: var(--shadow-sm);
9184
9822
  cursor: grab;
9185
9823
  touch-action: none;
9186
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9824
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9187
9825
  }
9188
9826
 
9189
9827
  [data-ui="slider"] [data-part="thumb"]:hover {
9190
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9191
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9828
+ box-shadow: var(--shadow-sm),
9829
+ 0 0 0 4px var(--color-primary-subtle);
9192
9830
  }
9193
9831
 
9194
9832
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9195
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9196
- outline-offset: 2px;
9833
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9834
+ outline-offset: var(--focus-ring-offset);
9197
9835
  }
9198
9836
 
9199
9837
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9200
9838
  cursor: grabbing;
9201
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9202
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9839
+ box-shadow: var(--shadow-sm),
9840
+ 0 0 0 5px var(--color-primary-subtle);
9203
9841
  }
9204
9842
 
9205
9843
  /* ── Value output ── */
@@ -9207,7 +9845,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9207
9845
  flex: 0 0 auto;
9208
9846
  min-inline-size: 3ch;
9209
9847
  color: var(--color-fg-muted);
9210
- font-family: var(--font-sans, system-ui, sans-serif);
9848
+ font-family: var(--font-ui);
9211
9849
  font-size: var(--text-sm);
9212
9850
  font-variant-numeric: tabular-nums;
9213
9851
  text-align: end;
@@ -9226,7 +9864,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9226
9864
 
9227
9865
  /* ── Disabled ── */
9228
9866
  [data-ui="slider"][data-disabled] {
9229
- opacity: 0.5;
9867
+ opacity: var(--disabled-opacity);
9230
9868
  cursor: not-allowed;
9231
9869
  pointer-events: none;
9232
9870
  }
@@ -9244,7 +9882,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9244
9882
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9245
9883
  @media (forced-colors: active) {
9246
9884
  [data-ui="slider"] [data-part="track"] {
9247
- border: 1px solid ButtonText;
9885
+ border: var(--border-width) solid ButtonText;
9248
9886
  }
9249
9887
 
9250
9888
  [data-ui="slider"] [data-part="range"] {
@@ -9255,7 +9893,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9255
9893
  [data-ui="slider"] [data-part="thumb"] {
9256
9894
  forced-color-adjust: none;
9257
9895
  background: ButtonText;
9258
- border: 1px solid ButtonFace;
9896
+ border: var(--border-width) solid ButtonFace;
9259
9897
  }
9260
9898
 
9261
9899
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9265,7 +9903,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9265
9903
 
9266
9904
  /* === recipes/table.css === */
9267
9905
  /* @ui:component table */
9268
- /* @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 */
9906
+ /* @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 */
9269
9907
 
9270
9908
  /* ── Root ── */
9271
9909
  [data-ui="table"] {
@@ -9291,7 +9929,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9291
9929
  width: 100%;
9292
9930
  border-collapse: separate;
9293
9931
  border-spacing: 0;
9294
- font-family: var(--font-sans, system-ui, sans-serif);
9932
+ font-family: var(--font-body);
9295
9933
  }
9296
9934
 
9297
9935
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9313,7 +9951,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9313
9951
  font-weight: var(--weight-semibold);
9314
9952
  color: var(--color-fg-muted);
9315
9953
  background: var(--color-bg);
9316
- border-bottom: 2px solid var(--color-border);
9954
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9317
9955
  white-space: nowrap;
9318
9956
  user-select: none;
9319
9957
  }
@@ -9371,8 +10009,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9371
10009
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9372
10010
  [data-ui="table"] [data-part="th"]:focus-visible,
9373
10011
  [data-ui="table"] [data-part="td"]:focus-visible {
9374
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9375
- outline-offset: -2px;
10012
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10013
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9376
10014
  }
9377
10015
 
9378
10016
  /* ── Data Cell ── */
@@ -9380,7 +10018,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9380
10018
  padding: var(--space-3) var(--space-4);
9381
10019
  font-size: var(--text-sm);
9382
10020
  color: var(--color-fg);
9383
- border-bottom: 1px solid var(--color-border);
10021
+ border-bottom: var(--border-width) solid var(--color-border);
9384
10022
  background: var(--color-bg);
9385
10023
  transition: background var(--duration-fast) var(--ease-default);
9386
10024
  }
@@ -9409,31 +10047,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9409
10047
  Static fallback via nth-child; once the controller stamps data-stripe on the
9410
10048
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9411
10049
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9412
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10050
+ background: var(--stripe-bg);
9413
10051
  }
9414
10052
 
9415
10053
  [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"] {
9416
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10054
+ background: var(--stripe-bg);
9417
10055
  }
9418
10056
 
9419
10057
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9420
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10058
+ background: var(--stripe-bg);
9421
10059
  }
9422
10060
 
9423
10061
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9424
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10062
+ background: var(--stripe-bg);
9425
10063
  }
9426
10064
 
9427
10065
  /* ── Bordered Variant ── */
9428
10066
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9429
- border: 1px solid var(--color-border);
10067
+ border: var(--border-width) solid var(--color-border);
9430
10068
  border-radius: var(--radius-md, 0.375rem);
9431
10069
  overflow: hidden;
9432
10070
  }
9433
10071
 
9434
10072
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9435
10073
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9436
- border: 1px solid var(--color-border);
10074
+ border: var(--border-width) solid var(--color-border);
9437
10075
  }
9438
10076
 
9439
10077
  /* ── Size: Small ── */
@@ -9461,7 +10099,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9461
10099
  /* ── Footer ── */
9462
10100
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9463
10101
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9464
- border-top: 2px solid var(--color-border);
10102
+ border-top: var(--border-width-strong) solid var(--color-border);
9465
10103
  border-bottom: none;
9466
10104
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9467
10105
  }
@@ -9587,7 +10225,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9587
10225
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9588
10226
  padding: var(--space-1) var(--space-2);
9589
10227
  background: var(--color-bg);
9590
- border-bottom: 1px solid var(--color-border);
10228
+ border-bottom: var(--border-width) solid var(--color-border);
9591
10229
  }
9592
10230
 
9593
10231
  [data-ui="table"] [data-part="filter-input"],
@@ -9599,14 +10237,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9599
10237
  font-size: var(--text-xs);
9600
10238
  color: var(--color-fg);
9601
10239
  background: var(--color-bg);
9602
- border: 1px solid var(--color-border);
10240
+ border: var(--border-width) solid var(--color-border);
9603
10241
  border-radius: var(--radius-sm);
9604
10242
  }
9605
10243
 
9606
10244
  [data-ui="table"] [data-part="filter-input"]:focus,
9607
10245
  [data-ui="table"] [data-part="filter"]:focus {
9608
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9609
- outline-offset: -1px;
10246
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10247
+ outline-offset: calc(-1 * var(--border-width));
9610
10248
  border-color: var(--color-primary);
9611
10249
  }
9612
10250
 
@@ -9627,7 +10265,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9627
10265
  text-align: inherit;
9628
10266
  color: var(--color-fg);
9629
10267
  background: var(--color-bg);
9630
- border: 1px solid var(--color-primary);
10268
+ border: var(--border-width) solid var(--color-primary);
9631
10269
  border-radius: var(--radius-sm);
9632
10270
  outline: none;
9633
10271
  }
@@ -9680,11 +10318,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9680
10318
  }
9681
10319
 
9682
10320
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9683
- border-block-start: 2px solid var(--color-primary);
10321
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9684
10322
  }
9685
10323
 
9686
10324
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9687
- border-block-end: 2px solid var(--color-primary);
10325
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9688
10326
  }
9689
10327
 
9690
10328
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9692,11 +10330,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9692
10330
  }
9693
10331
 
9694
10332
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9695
- border-inline-start: 2px solid var(--color-primary);
10333
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9696
10334
  }
9697
10335
 
9698
10336
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9699
- border-inline-end: 2px solid var(--color-primary);
10337
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9700
10338
  }
9701
10339
 
9702
10340
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9769,11 +10407,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9769
10407
  }
9770
10408
 
9771
10409
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9772
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10410
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9773
10411
  }
9774
10412
 
9775
10413
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9776
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10414
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9777
10415
  }
9778
10416
 
9779
10417
  /* ── Column Visibility ── */
@@ -9845,7 +10483,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9845
10483
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9846
10484
  display: block;
9847
10485
  margin-block-end: var(--space-3);
9848
- border: 1px solid var(--color-border);
10486
+ border: var(--border-width) solid var(--color-border);
9849
10487
  border-radius: var(--radius-md);
9850
10488
  background: var(--color-bg);
9851
10489
  overflow: hidden;
@@ -9859,7 +10497,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9859
10497
  gap: var(--space-4);
9860
10498
  text-align: end;
9861
10499
  border-bottom: none;
9862
- border-block-end: 1px solid var(--color-border);
10500
+ border-block-end: var(--border-width) solid var(--color-border);
9863
10501
  }
9864
10502
 
9865
10503
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9956,7 +10594,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9956
10594
 
9957
10595
  /* === recipes/tabs.css === */
9958
10596
  /* @ui:component tabs */
9959
- /* @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 */
10597
+ /* @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 */
9960
10598
 
9961
10599
  /* ── Root ── */
9962
10600
  [data-ui="tabs"] {
@@ -9985,7 +10623,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9985
10623
  border: none;
9986
10624
  background: transparent;
9987
10625
  color: var(--color-fg-muted);
9988
- font-family: var(--font-sans, system-ui, sans-serif);
10626
+ font-family: var(--font-ui);
9989
10627
  font-size: var(--text-sm);
9990
10628
  font-weight: var(--weight-medium);
9991
10629
  cursor: pointer;
@@ -10000,8 +10638,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10000
10638
  }
10001
10639
 
10002
10640
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
10003
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10004
- outline-offset: -2px;
10641
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10642
+ outline-offset: calc(-1 * var(--focus-ring-offset));
10005
10643
  border-radius: var(--radius-md);
10006
10644
  }
10007
10645
 
@@ -10011,12 +10649,12 @@ div[data-ui="separator"][data-style="thick"]::after {
10011
10649
 
10012
10650
  /* ── Underline Variant ── */
10013
10651
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
10014
- border-bottom: 1px solid var(--color-border);
10652
+ border-bottom: var(--border-width) solid var(--color-border);
10015
10653
  gap: 0;
10016
10654
  }
10017
10655
 
10018
10656
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
10019
- border-bottom: 2px solid transparent;
10657
+ border-bottom: var(--border-width-strong) solid transparent;
10020
10658
  margin-bottom: -1px;
10021
10659
  border-radius: 0;
10022
10660
  }
@@ -10048,17 +10686,17 @@ div[data-ui="separator"][data-style="thick"]::after {
10048
10686
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
10049
10687
  background: var(--color-bg);
10050
10688
  color: var(--color-fg);
10051
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10689
+ box-shadow: var(--shadow-xs);
10052
10690
  }
10053
10691
 
10054
10692
  /* ── Enclosed Variant ── */
10055
10693
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
10056
- border-bottom: 1px solid var(--color-border);
10694
+ border-bottom: var(--border-width) solid var(--color-border);
10057
10695
  gap: 0;
10058
10696
  }
10059
10697
 
10060
10698
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10061
- border: 1px solid transparent;
10699
+ border: var(--border-width) solid transparent;
10062
10700
  border-bottom: none;
10063
10701
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10064
10702
  margin-bottom: -1px;
@@ -10103,8 +10741,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10103
10741
  @media (forced-colors: active) {
10104
10742
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10105
10743
  /* An outline the OS preserves, on every variant. */
10106
- outline: 2px solid Highlight;
10107
- outline-offset: -2px;
10744
+ outline: var(--border-width-strong) solid Highlight;
10745
+ outline-offset: calc(-1 * var(--border-width-strong));
10108
10746
  }
10109
10747
 
10110
10748
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10119,7 +10757,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10119
10757
 
10120
10758
  /* === recipes/tag-input.css === */
10121
10759
  /* @ui:component tag-input */
10122
- /* @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 */
10760
+ /* @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 */
10123
10761
 
10124
10762
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10125
10763
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10140,7 +10778,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10140
10778
  gap: var(--space-1h);
10141
10779
  width: 100%;
10142
10780
  padding: var(--space-1h) var(--space-2);
10143
- border: 1px solid var(--color-border);
10781
+ border: var(--border-width) solid var(--color-border);
10144
10782
  border-radius: var(--radius-md);
10145
10783
  background: var(--color-bg);
10146
10784
  list-style: none;
@@ -10149,8 +10787,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10149
10787
  }
10150
10788
 
10151
10789
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10152
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10153
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10790
+ border-color: var(--focus-ring-color);
10791
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10154
10792
  }
10155
10793
 
10156
10794
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10161,7 +10799,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10161
10799
  border: none;
10162
10800
  background: transparent;
10163
10801
  color: var(--color-fg);
10164
- font-family: var(--font-sans, system-ui, sans-serif);
10802
+ font-family: var(--font-ui);
10165
10803
  font-size: var(--text-sm);
10166
10804
  line-height: 1.5;
10167
10805
  outline: none;
@@ -10180,7 +10818,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10180
10818
  z-index: var(--z-dropdown);
10181
10819
  margin-top: var(--space-1);
10182
10820
  padding: var(--space-1);
10183
- border: 1px solid var(--color-border);
10821
+ border: var(--border-width) solid var(--color-border);
10184
10822
  border-radius: var(--radius-lg);
10185
10823
  background: var(--color-bg);
10186
10824
  box-shadow: var(--shadow-md);
@@ -10227,7 +10865,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10227
10865
 
10228
10866
  /* === recipes/toast.css === */
10229
10867
  /* @ui:component toast */
10230
- /* @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 */
10868
+ /* @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 */
10231
10869
 
10232
10870
  /* ── Container ── */
10233
10871
  [data-ui="toast"][data-part="container"] {
@@ -10276,8 +10914,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10276
10914
  max-width: 380px;
10277
10915
  width: max-content;
10278
10916
  padding: var(--space-3) var(--space-4);
10279
- background: var(--color-bg);
10280
- border: 1px solid var(--color-border);
10917
+ background: var(--panel-bg);
10918
+ border: var(--border-width) solid var(--color-border);
10281
10919
  border-radius: var(--radius-lg);
10282
10920
  box-shadow: var(--shadow-lg);
10283
10921
  pointer-events: auto;
@@ -10287,6 +10925,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10287
10925
  transform var(--duration-normal) var(--ease-out);
10288
10926
  }
10289
10927
 
10928
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10929
+ [data-ui="toast"] [data-part="toast"] {
10930
+ -webkit-backdrop-filter: var(--surface-backdrop);
10931
+ backdrop-filter: var(--surface-backdrop);
10932
+ }
10933
+ }
10934
+
10290
10935
  /* ── State: Entering ── */
10291
10936
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10292
10937
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10326,7 +10971,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10326
10971
 
10327
10972
  /* ── Tone Variants ── */
10328
10973
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10329
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10974
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10330
10975
  }
10331
10976
 
10332
10977
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10334,7 +10979,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10334
10979
  }
10335
10980
 
10336
10981
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10337
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10982
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10338
10983
  }
10339
10984
 
10340
10985
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10342,7 +10987,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10342
10987
  }
10343
10988
 
10344
10989
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10345
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10990
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10346
10991
  }
10347
10992
 
10348
10993
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10364,7 +11009,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10364
11009
  /* ── Message ── */
10365
11010
  [data-ui="toast"] [data-part="message"] {
10366
11011
  flex: 1;
10367
- font-family: var(--font-sans, system-ui, sans-serif);
11012
+ font-family: var(--font-ui);
10368
11013
  font-size: var(--text-sm);
10369
11014
  font-weight: var(--weight-medium);
10370
11015
  color: var(--color-fg);
@@ -10375,11 +11020,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10375
11020
  [data-ui="toast"] [data-part="action"] {
10376
11021
  flex-shrink: 0;
10377
11022
  padding: var(--space-1, 0.25rem) var(--space-2);
10378
- border: 1px solid var(--color-border);
11023
+ border: var(--border-width) solid var(--color-border);
10379
11024
  border-radius: var(--radius-md, 0.375rem);
10380
11025
  background: transparent;
10381
11026
  color: var(--color-fg);
10382
- font-family: var(--font-sans, system-ui, sans-serif);
11027
+ font-family: var(--font-ui);
10383
11028
  font-size: var(--text-xs, 0.75rem);
10384
11029
  font-weight: var(--weight-medium);
10385
11030
  cursor: pointer;
@@ -10392,8 +11037,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10392
11037
  }
10393
11038
 
10394
11039
  [data-ui="toast"] [data-part="action"]:focus-visible {
10395
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10396
- outline-offset: 2px;
11040
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11041
+ outline-offset: var(--focus-ring-offset);
10397
11042
  }
10398
11043
 
10399
11044
  /* ── Close Button ── */
@@ -10419,8 +11064,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10419
11064
  }
10420
11065
 
10421
11066
  [data-ui="toast"] [data-part="close"]:focus-visible {
10422
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10423
- outline-offset: 2px;
11067
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11068
+ outline-offset: var(--focus-ring-offset);
10424
11069
  }
10425
11070
 
10426
11071
  /* ── Motion ── */
@@ -10433,14 +11078,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10433
11078
 
10434
11079
  /* === recipes/toggle-group.css === */
10435
11080
  /* @ui:component toggle-group */
10436
- /* @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 */
11081
+ /* @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 */
10437
11082
 
10438
11083
  /* ── Root: a segmented row of toggle buttons ── */
10439
11084
  [data-ui="toggle-group"] {
10440
11085
  display: inline-flex;
10441
11086
  gap: var(--space-1);
10442
11087
  padding: var(--space-1);
10443
- border: 1px solid var(--color-border);
11088
+ border: var(--border-width) solid var(--color-border);
10444
11089
  border-radius: var(--radius-md);
10445
11090
  background: var(--color-bg);
10446
11091
  }
@@ -10455,7 +11100,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10455
11100
  border-radius: var(--radius-md);
10456
11101
  background: transparent;
10457
11102
  color: var(--color-fg-muted);
10458
- font-family: var(--toggle-group-font, var(--font-sans));
11103
+ font-family: var(--toggle-group-font, var(--font-ui));
10459
11104
  font-size: var(--text-sm);
10460
11105
  font-weight: var(--weight-medium);
10461
11106
  line-height: 1;
@@ -10496,13 +11141,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10496
11141
 
10497
11142
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10498
11143
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10499
- outline: 2px solid var(--color-ring);
10500
- outline-offset: 2px;
11144
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11145
+ outline-offset: var(--focus-ring-offset);
10501
11146
  }
10502
11147
 
10503
11148
  /* ── Disabled control ── */
10504
11149
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10505
- opacity: 0.5;
11150
+ opacity: var(--disabled-opacity);
10506
11151
  cursor: not-allowed;
10507
11152
  }
10508
11153
 
@@ -10515,7 +11160,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10515
11160
 
10516
11161
  /* === recipes/tooltip.css === */
10517
11162
  /* @ui:component tooltip */
10518
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11163
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10519
11164
 
10520
11165
  /* ── Root ── */
10521
11166
  [data-ui="tooltip"] {
@@ -10536,7 +11181,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10536
11181
  color: var(--color-bg);
10537
11182
  border-radius: var(--radius-md);
10538
11183
  padding: var(--space-1h, 0.375rem) var(--space-2);
10539
- font-family: var(--font-sans, system-ui, sans-serif);
11184
+ font-family: var(--font-ui);
10540
11185
  font-size: var(--text-xs, 0.75rem);
10541
11186
  line-height: 1.4;
10542
11187
  white-space: nowrap;
@@ -10547,6 +11192,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10547
11192
  transform var(--duration-fast) var(--ease-default);
10548
11193
  }
10549
11194
 
11195
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11196
+ [data-ui="tooltip"] [data-part="content"] {
11197
+ -webkit-backdrop-filter: var(--surface-backdrop);
11198
+ backdrop-filter: var(--surface-backdrop);
11199
+ }
11200
+ }
11201
+
10550
11202
  /* Default position (top) when no variant is specified */
10551
11203
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10552
11204
  bottom: 100%;
@@ -10662,7 +11314,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10662
11314
 
10663
11315
  /* === recipes/tree-view.css === */
10664
11316
  /* @ui:component tree-view */
10665
- /* @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 */
11317
+ /* @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 */
10666
11318
 
10667
11319
  [data-ui="tree-view"],
10668
11320
  [data-ui="tree-view"] [data-part="group"] {
@@ -10675,7 +11327,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10675
11327
  inline-size: 100%;
10676
11328
  padding: var(--space-1);
10677
11329
  color: var(--color-fg);
10678
- font-family: var(--font-sans);
11330
+ font-family: var(--font-ui);
10679
11331
  font-size: var(--text-sm);
10680
11332
  }
10681
11333
 
@@ -10703,8 +11355,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10703
11355
  }
10704
11356
 
10705
11357
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10706
- outline: var(--space-px) solid var(--color-ring);
10707
- outline-offset: var(--space-px);
11358
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11359
+ outline-offset: var(--focus-ring-offset);
10708
11360
  }
10709
11361
 
10710
11362
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10743,7 +11395,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10743
11395
 
10744
11396
  /* === patterns/auth-form.css === */
10745
11397
  /* @ui:component auth-form */
10746
- /* @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 */
11398
+ /* @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 */
10747
11399
 
10748
11400
  /* ── Root Container ── */
10749
11401
  [data-ui="auth-form"] {
@@ -10751,7 +11403,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10751
11403
  align-items: center;
10752
11404
  justify-content: center;
10753
11405
  width: 100%;
10754
- font-family: var(--font-sans);
11406
+ font-family: var(--font-body);
10755
11407
  }
10756
11408
 
10757
11409
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10783,9 +11435,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10783
11435
 
10784
11436
  [data-ui="auth-form"] [data-part="title"] {
10785
11437
  margin: 0;
11438
+ font-family: var(--font-heading);
10786
11439
  font-size: var(--text-xl);
10787
- font-weight: var(--weight-bold);
10788
- line-height: var(--leading-tight);
11440
+ font-weight: var(--heading-weight);
11441
+ letter-spacing: var(--heading-tracking);
11442
+ text-transform: var(--heading-transform);
11443
+ font-variant-caps: var(--heading-caps);
11444
+ line-height: var(--heading-leading);
10789
11445
  color: var(--color-fg);
10790
11446
  }
10791
11447
 
@@ -10802,7 +11458,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10802
11458
  margin: var(--space-4) var(--space-6) 0;
10803
11459
  padding: var(--space-3);
10804
11460
  background: var(--color-destructive-subtle);
10805
- border: 1px solid var(--color-destructive);
11461
+ border: var(--border-width) solid var(--color-destructive);
10806
11462
  border-radius: var(--radius-lg);
10807
11463
  color: var(--color-destructive);
10808
11464
  font-size: var(--text-sm);
@@ -10880,13 +11536,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10880
11536
  }
10881
11537
 
10882
11538
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10883
- text-decoration: underline;
11539
+ text-decoration-line: var(--link-decoration);
10884
11540
  color: var(--color-primary-hover);
10885
11541
  }
10886
11542
 
10887
11543
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10888
- outline: 2px solid var(--color-ring);
10889
- outline-offset: 2px;
11544
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11545
+ outline-offset: var(--focus-ring-offset);
10890
11546
  border-radius: var(--radius-sm, 0.25rem);
10891
11547
  }
10892
11548
 
@@ -11014,8 +11670,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11014
11670
  max-width: var(--auth-form-max-width, 400px);
11015
11671
  border-radius: var(--card-radius, var(--radius-lg));
11016
11672
  box-shadow: var(--card-shadow, var(--shadow-sm));
11017
- border-inline-start: 1px solid var(--card-border, var(--color-border));
11018
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11673
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11674
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
11019
11675
  }
11020
11676
  }
11021
11677
 
@@ -11030,7 +11686,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11030
11686
 
11031
11687
  /* === patterns/crud-table.css === */
11032
11688
  /* @ui:component crud-table */
11033
- /* @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 */
11689
+ /* @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 */
11034
11690
 
11035
11691
  /* ── Root ── */
11036
11692
  [data-ui="crud-table"] {
@@ -11038,7 +11694,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11038
11694
  flex-direction: column;
11039
11695
  gap: var(--space-4);
11040
11696
  width: 100%;
11041
- font-family: var(--font-sans, system-ui, sans-serif);
11697
+ font-family: var(--font-body);
11042
11698
  }
11043
11699
 
11044
11700
  /* ── Toolbar ── */
@@ -11096,7 +11752,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11096
11752
  gap: var(--space-3);
11097
11753
  padding: var(--space-3) var(--space-4);
11098
11754
  background: var(--color-bg-subtle);
11099
- border: 1px solid var(--color-border);
11755
+ border: var(--border-width) solid var(--color-border);
11100
11756
  border-radius: var(--radius-md);
11101
11757
  }
11102
11758
 
@@ -11111,7 +11767,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11111
11767
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11112
11768
  width: 100%;
11113
11769
  overflow-x: auto;
11114
- border: 1px solid var(--color-border);
11770
+ border: var(--border-width) solid var(--color-border);
11115
11771
  border-radius: var(--radius-lg);
11116
11772
  background: var(--color-bg);
11117
11773
  }
@@ -11141,7 +11797,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11141
11797
  padding: var(--space-8) var(--space-4);
11142
11798
  text-align: center;
11143
11799
  min-height: 240px;
11144
- border: 1px dashed var(--color-border);
11800
+ border: var(--border-width) dashed var(--color-border);
11145
11801
  border-radius: var(--radius-lg);
11146
11802
  background: var(--color-bg);
11147
11803
  }
@@ -11254,7 +11910,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11254
11910
 
11255
11911
  /* === patterns/dashboard-shell.css === */
11256
11912
  /* @ui:component dashboard-shell */
11257
- /* @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 */
11913
+ /* @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 */
11258
11914
 
11259
11915
  /* ── Shell Grid Layout ──
11260
11916
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11279,7 +11935,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11279
11935
  "footer";
11280
11936
  min-height: 100vh;
11281
11937
  background: var(--color-bg);
11282
- font-family: var(--font-sans);
11938
+ font-family: var(--font-body);
11283
11939
  color: var(--color-fg);
11284
11940
  }
11285
11941
 
@@ -11303,7 +11959,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11303
11959
  gap: var(--space-2);
11304
11960
  padding: var(--space-4);
11305
11961
  background: var(--color-bg-subtle);
11306
- border-inline-end: 1px solid var(--color-border);
11962
+ border-inline-end: var(--border-width) solid var(--color-border);
11307
11963
  overflow-y: auto;
11308
11964
  position: fixed;
11309
11965
  top: 0;
@@ -11323,7 +11979,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11323
11979
 
11324
11980
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11325
11981
  border-inline-end: none;
11326
- border-inline-start: 1px solid var(--color-border);
11982
+ border-inline-start: var(--border-width) solid var(--color-border);
11327
11983
  inset-inline-start: auto;
11328
11984
  inset-inline-end: 0;
11329
11985
  transform: translateX(100%);
@@ -11398,7 +12054,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11398
12054
  gap: var(--space-3);
11399
12055
  padding: var(--space-2) var(--space-3);
11400
12056
  border-radius: var(--radius-md);
11401
- font-family: var(--font-sans);
12057
+ font-family: var(--font-ui);
11402
12058
  font-size: var(--text-sm);
11403
12059
  font-weight: var(--weight-medium);
11404
12060
  line-height: var(--leading-normal);
@@ -11417,8 +12073,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11417
12073
  }
11418
12074
 
11419
12075
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11420
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11421
- outline-offset: -2px;
12076
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12077
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11422
12078
  }
11423
12079
 
11424
12080
  /* ── Nav Item Active ── */
@@ -11465,7 +12121,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11465
12121
  gap: var(--space-2);
11466
12122
  padding: 0 var(--space-3);
11467
12123
  background: var(--color-bg);
11468
- border-bottom: 1px solid var(--color-border);
12124
+ border-bottom: var(--border-width) solid var(--color-border);
11469
12125
  position: sticky;
11470
12126
  top: 0;
11471
12127
  z-index: var(--z-sticky);
@@ -11546,7 +12202,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11546
12202
  align-items: center;
11547
12203
  gap: var(--space-3);
11548
12204
  padding: var(--space-4) var(--space-6);
11549
- border-top: 1px solid var(--color-border);
12205
+ border-top: var(--border-width) solid var(--color-border);
11550
12206
  font-size: var(--text-xs);
11551
12207
  color: var(--color-fg-muted);
11552
12208
  }
@@ -11629,7 +12285,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11629
12285
 
11630
12286
  /* === patterns/document.css === */
11631
12287
  /* @ui:component document */
11632
- /* @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 */
12288
+ /* @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 */
11633
12289
 
11634
12290
  /* ── Page Rules ── */
11635
12291
  @page {
@@ -11669,14 +12325,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11669
12325
  max-width: var(--doc-max-width);
11670
12326
  margin: var(--space-4) auto;
11671
12327
  padding: var(--space-6) var(--space-4);
11672
- background: var(--color-bg, #fff);
12328
+ background-color: var(--color-bg, #fff);
12329
+ background-image: var(--texture-page);
11673
12330
  color: var(--color-fg);
11674
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12331
+ font-family: var(--doc-font, var(--font-body));
11675
12332
  font-size: var(--doc-font-size);
11676
12333
  line-height: var(--doc-line-height);
11677
- box-shadow: var(--shadow-lg,
11678
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11679
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12334
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12335
+ colour no theme could reach. --shadow-lg is always defined by the token
12336
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12337
+ than re-tokenised. */
12338
+ box-shadow: var(--shadow-lg);
11680
12339
  border-radius: 0;
11681
12340
  position: relative;
11682
12341
  }
@@ -11692,7 +12351,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11692
12351
  [data-ui="document"] > [data-part="header"] {
11693
12352
  margin-block-end: var(--doc-section-gap);
11694
12353
  padding-block-end: var(--doc-component-gap);
11695
- border-block-end: 1px solid var(--color-border);
12354
+ border-block-end: var(--border-width) solid var(--color-border);
11696
12355
  }
11697
12356
 
11698
12357
  /* ── Body ── */
@@ -11702,13 +12361,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11702
12361
  gap: var(--doc-section-gap);
11703
12362
  }
11704
12363
 
12364
+ /* ── Headings ──
12365
+ The document's own heading face and weight (1.1A-21): a print theme sets
12366
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12367
+ from the body copy (document-serif's Times titles over Georgia text). Both
12368
+ default to the page's heading role in tokens/document.css, and each falls
12369
+ back to what a heading rendered before the tokens had a reader. A heading
12370
+ that carries its own data-weight keeps it — that is the author asking. */
12371
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12372
+ font-family: var(--doc-heading-font, var(--font-body));
12373
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12374
+ }
12375
+
11705
12376
  /* ── Running footer ──
11706
12377
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11707
12378
  [data-ui="document"] > [data-part="doc-footer"],
11708
12379
  [data-ui="document"] > [data-part="footer"] {
11709
12380
  margin-block-start: var(--doc-section-gap);
11710
12381
  padding-block-start: var(--doc-component-gap);
11711
- border-block-start: 1px solid var(--color-border);
12382
+ border-block-start: var(--border-width) solid var(--color-border);
11712
12383
  font-size: var(--doc-legal-size);
11713
12384
  color: var(--doc-legal-color);
11714
12385
  }
@@ -11746,7 +12417,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11746
12417
 
11747
12418
  /* ── Variant: Report ── */
11748
12419
  [data-ui="document"][data-variant="report"] {
11749
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12420
+ /* A report is serif-set by definition. It re-points the document's own font
12421
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12422
+ (key-value, callout, signature — all of which read --doc-font) follows the
12423
+ report into serif instead of staying sans inside a serif page. `report` is
12424
+ the author asking for serif; a theme that wants its own document face
12425
+ declares --doc-font at :root, which this variant deliberately outranks. */
12426
+ --doc-font: Georgia, 'Times New Roman', serif;
11750
12427
  line-height: 1.6;
11751
12428
  }
11752
12429
 
@@ -11841,7 +12518,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11841
12518
  z-index: var(--z-raised);
11842
12519
  margin-block-end: 0;
11843
12520
  padding-block-end: var(--doc-running-gap);
11844
- border-block-end: 1px solid var(--doc-print-border-color);
12521
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11845
12522
  background: var(--doc-bg);
11846
12523
  transform: translateZ(0);
11847
12524
  }
@@ -11857,7 +12534,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11857
12534
  z-index: var(--z-raised);
11858
12535
  margin-block-start: 0;
11859
12536
  padding-block-start: var(--doc-running-gap);
11860
- border-block-start: 1px solid var(--doc-print-border-color);
12537
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11861
12538
  background: var(--doc-bg);
11862
12539
  transform: translateZ(0);
11863
12540
  }
@@ -11886,7 +12563,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11886
12563
 
11887
12564
  /* === patterns/empty-state.css === */
11888
12565
  /* @ui:component empty-state */
11889
- /* @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 */
12566
+ /* @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 */
11890
12567
 
11891
12568
  /* ── Root ── */
11892
12569
  [data-ui="empty-state"] {
@@ -11897,7 +12574,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11897
12574
  text-align: center;
11898
12575
  padding: var(--space-8) var(--space-6);
11899
12576
  gap: var(--space-3);
11900
- font-family: var(--font-sans, system-ui, sans-serif);
12577
+ font-family: var(--font-body);
11901
12578
  }
11902
12579
 
11903
12580
  /* ── Icon ── */
@@ -11920,10 +12597,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11920
12597
 
11921
12598
  /* ── Title ── */
11922
12599
  [data-ui="empty-state"] [data-part="title"] {
11923
- font-family: var(--font-sans, system-ui, sans-serif);
12600
+ font-family: var(--font-heading);
11924
12601
  font-size: var(--text-lg);
11925
12602
  font-weight: var(--weight-semibold);
11926
- line-height: var(--leading-tight);
12603
+ letter-spacing: var(--heading-tracking);
12604
+ text-transform: var(--heading-transform);
12605
+ font-variant-caps: var(--heading-caps);
12606
+ line-height: var(--heading-leading);
11927
12607
  color: var(--color-fg);
11928
12608
  margin: 0;
11929
12609
  }
@@ -12021,7 +12701,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12021
12701
 
12022
12702
  /* === patterns/feature-grid.css === */
12023
12703
  /* @ui:component feature-grid */
12024
- /* @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 */
12704
+ /* @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 */
12025
12705
 
12026
12706
  /* ── Root ──
12027
12707
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12031,7 +12711,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12031
12711
  gap: var(--space-4);
12032
12712
  padding-block: var(--space-12);
12033
12713
  padding-inline: var(--space-4);
12034
- font-family: var(--font-sans, system-ui, sans-serif);
12714
+ font-family: var(--font-body);
12035
12715
  color: var(--color-fg);
12036
12716
  background: var(--color-bg);
12037
12717
  }
@@ -12173,7 +12853,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12173
12853
  max-inline-size: var(--measure-narrow);
12174
12854
  margin-inline: auto;
12175
12855
  padding-block: var(--space-8);
12176
- font-family: var(--font-sans);
12856
+ font-family: var(--font-body);
12177
12857
  }
12178
12858
 
12179
12859
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12193,7 +12873,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12193
12873
 
12194
12874
  /* === patterns/hero.css === */
12195
12875
  /* @ui:component hero */
12196
- /* @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 */
12876
+ /* @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 */
12197
12877
 
12198
12878
  /* ── Root ──
12199
12879
  A one-column grid by default; the layout variants only change how that grid
@@ -12207,9 +12887,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12207
12887
  gap: var(--space-4);
12208
12888
  padding-block: var(--space-12);
12209
12889
  padding-inline: var(--space-4);
12210
- font-family: var(--font-sans, system-ui, sans-serif);
12890
+ font-family: var(--font-body);
12211
12891
  color: var(--color-fg);
12212
- background: var(--color-bg);
12892
+ background-color: var(--color-bg);
12893
+ background-image: var(--texture-surface);
12213
12894
  }
12214
12895
 
12215
12896
  /* ── Eyebrow ── */
@@ -12221,9 +12902,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12221
12902
  /* ── Headline ── */
12222
12903
  [data-ui="hero"] [data-part="headline"] {
12223
12904
  margin: 0;
12905
+ font-family: var(--font-heading);
12224
12906
  font-size: var(--text-3xl);
12225
- font-weight: var(--weight-bold);
12226
- line-height: var(--leading-tight);
12907
+ font-weight: var(--heading-weight);
12908
+ letter-spacing: var(--heading-tracking);
12909
+ text-transform: var(--heading-transform);
12910
+ font-variant-caps: var(--heading-caps);
12911
+ line-height: var(--heading-leading);
12227
12912
  color: var(--color-fg);
12228
12913
  text-wrap: balance;
12229
12914
  }
@@ -12342,7 +13027,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12342
13027
 
12343
13028
  /* === patterns/inbox.css === */
12344
13029
  /* @ui:component inbox */
12345
- /* @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 */
13030
+ /* @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 */
12346
13031
 
12347
13032
  /* ── Root ──
12348
13033
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12362,7 +13047,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12362
13047
  overflow: hidden;
12363
13048
  border: var(--space-px, 1px) solid var(--color-border);
12364
13049
  border-radius: var(--radius-lg);
12365
- font-family: var(--font-sans, system-ui, sans-serif);
13050
+ font-family: var(--font-body);
12366
13051
  color: var(--color-fg);
12367
13052
  background: var(--color-bg);
12368
13053
  }
@@ -12454,8 +13139,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12454
13139
  }
12455
13140
 
12456
13141
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12457
- outline: 2px solid var(--color-ring);
12458
- outline-offset: 2px;
13142
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13143
+ outline-offset: var(--focus-ring-offset);
12459
13144
  }
12460
13145
 
12461
13146
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12614,7 +13299,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12614
13299
 
12615
13300
  /* === patterns/pricing.css === */
12616
13301
  /* @ui:component pricing */
12617
- /* @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 */
13302
+ /* @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 */
12618
13303
 
12619
13304
  /* ── Root ──
12620
13305
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12624,7 +13309,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12624
13309
  gap: var(--space-4);
12625
13310
  padding-block: var(--space-12);
12626
13311
  padding-inline: var(--space-4);
12627
- font-family: var(--font-sans, system-ui, sans-serif);
13312
+ font-family: var(--font-body);
12628
13313
  color: var(--color-fg);
12629
13314
  background: var(--color-bg);
12630
13315
  }
@@ -12674,9 +13359,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12674
13359
 
12675
13360
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12676
13361
  margin: 0;
13362
+ font-family: var(--font-heading);
12677
13363
  font-size: var(--text-lg);
12678
13364
  font-weight: var(--weight-semibold);
12679
- line-height: var(--leading-tight);
13365
+ letter-spacing: var(--heading-tracking);
13366
+ text-transform: var(--heading-transform);
13367
+ font-variant-caps: var(--heading-caps);
13368
+ line-height: var(--heading-leading);
12680
13369
  }
12681
13370
 
12682
13371
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12737,7 +13426,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12737
13426
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12738
13427
  border-color: var(--color-primary);
12739
13428
  box-shadow: var(--shadow-md);
12740
- outline: var(--space-px, 1px) solid var(--color-primary);
13429
+ outline: var(--border-width-strong) solid var(--color-primary);
12741
13430
  }
12742
13431
 
12743
13432
  /* ── Footnote ── */
@@ -12782,14 +13471,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12782
13471
 
12783
13472
  /* === patterns/search-results.css === */
12784
13473
  /* @ui:component search-results */
12785
- /* @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 */
13474
+ /* @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 */
12786
13475
 
12787
13476
  /* ── Root ── */
12788
13477
  [data-ui="search-results"] {
12789
13478
  display: flex;
12790
13479
  flex-direction: column;
12791
13480
  gap: var(--space-4);
12792
- font-family: var(--font-sans, system-ui, sans-serif);
13481
+ font-family: var(--font-body);
12793
13482
  }
12794
13483
 
12795
13484
  /* ── Search Input ── */
@@ -12817,7 +13506,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12817
13506
  justify-content: space-between;
12818
13507
  gap: var(--space-4);
12819
13508
  padding-bottom: var(--space-2);
12820
- border-bottom: 1px solid var(--color-border);
13509
+ border-bottom: var(--border-width) solid var(--color-border);
12821
13510
  }
12822
13511
 
12823
13512
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12852,7 +13541,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12852
13541
  flex-direction: column;
12853
13542
  gap: var(--space-2);
12854
13543
  padding: var(--space-4);
12855
- border: 1px solid var(--color-border);
13544
+ border: var(--border-width) solid var(--color-border);
12856
13545
  border-radius: var(--radius-md);
12857
13546
  background: var(--color-bg);
12858
13547
  transition: background var(--duration-fast) var(--ease-default),
@@ -12911,7 +13600,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12911
13600
  display: flex;
12912
13601
  justify-content: center;
12913
13602
  padding-top: var(--space-4);
12914
- border-top: 1px solid var(--color-border);
13603
+ border-top: var(--border-width) solid var(--color-border);
12915
13604
  }
12916
13605
 
12917
13606
  /* ── Loading ── */
@@ -12951,7 +13640,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12951
13640
 
12952
13641
  /* ── Error State ── */
12953
13642
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12954
- border: 1px solid var(--color-border);
13643
+ border: var(--border-width) solid var(--color-border);
12955
13644
  border-radius: var(--radius-md);
12956
13645
  padding: var(--space-6);
12957
13646
  text-align: center;
@@ -12960,8 +13649,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12960
13649
 
12961
13650
  /* ── Focus management ── */
12962
13651
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12963
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12964
- outline-offset: 2px;
13652
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13653
+ outline-offset: var(--focus-ring-offset);
12965
13654
  }
12966
13655
 
12967
13656
  /* ── Motion ── */
@@ -12977,7 +13666,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12977
13666
 
12978
13667
  /* === patterns/settings-page.css === */
12979
13668
  /* @ui:component settings-page */
12980
- /* @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 */
13669
+ /* @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 */
12981
13670
 
12982
13671
  /* ── Root ── */
12983
13672
  [data-ui="settings-page"] {
@@ -12987,7 +13676,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12987
13676
  width: 100%;
12988
13677
  max-width: 768px;
12989
13678
  margin-inline: auto;
12990
- font-family: var(--font-sans, system-ui, sans-serif);
13679
+ font-family: var(--font-body);
12991
13680
  color: var(--color-fg);
12992
13681
  }
12993
13682
 
@@ -13001,9 +13690,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13001
13690
  /* ── Title ── */
13002
13691
  [data-ui="settings-page"] [data-part="title"] {
13003
13692
  margin: 0;
13693
+ font-family: var(--font-heading);
13004
13694
  font-size: var(--text-xl, 1.25rem);
13005
13695
  font-weight: var(--weight-semibold, 600);
13006
- line-height: var(--leading-tight);
13696
+ letter-spacing: var(--heading-tracking);
13697
+ text-transform: var(--heading-transform);
13698
+ font-variant-caps: var(--heading-caps);
13699
+ line-height: var(--heading-leading);
13007
13700
  color: var(--color-fg);
13008
13701
  }
13009
13702
 
@@ -13067,7 +13760,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13067
13760
  gap: var(--space-3, 0.75rem);
13068
13761
  padding: var(--space-4);
13069
13762
  background: var(--color-bg);
13070
- border-top: 1px solid var(--color-border);
13763
+ border-top: var(--border-width) solid var(--color-border);
13071
13764
  border-radius: var(--radius-lg);
13072
13765
  box-shadow: var(--shadow-md);
13073
13766
  position: sticky;
@@ -13131,7 +13824,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13131
13824
  flex-direction: row;
13132
13825
  flex-wrap: wrap;
13133
13826
  border-inline-end: none;
13134
- border-bottom: 1px solid var(--color-border);
13827
+ border-bottom: var(--border-width) solid var(--color-border);
13135
13828
  padding-inline-end: 0;
13136
13829
  position: static;
13137
13830
  }
@@ -13150,7 +13843,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13150
13843
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13151
13844
  flex-direction: column;
13152
13845
  border-bottom: none;
13153
- border-inline-end: 1px solid var(--color-border);
13846
+ border-inline-end: var(--border-width) solid var(--color-border);
13154
13847
  padding-inline-end: var(--space-4);
13155
13848
  position: sticky;
13156
13849
  top: var(--space-4);
@@ -13168,7 +13861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13168
13861
  justify-content: flex-start;
13169
13862
  text-align: start;
13170
13863
  border-bottom: none;
13171
- border-inline-start: 2px solid transparent;
13864
+ border-inline-start: var(--border-width-strong) solid transparent;
13172
13865
  margin-bottom: 0;
13173
13866
  margin-inline-end: -1px;
13174
13867
  padding: var(--space-2) var(--space-3);
@@ -13202,7 +13895,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13202
13895
 
13203
13896
  /* === patterns/site-footer.css === */
13204
13897
  /* @ui:component site-footer */
13205
- /* @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 */
13898
+ /* @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 */
13206
13899
 
13207
13900
  /* ── Root ──
13208
13901
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13212,11 +13905,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13212
13905
  gap: var(--space-8);
13213
13906
  padding-block: var(--space-10);
13214
13907
  padding-inline: var(--space-4);
13215
- font-family: var(--font-sans, system-ui, sans-serif);
13908
+ font-family: var(--font-body);
13216
13909
  font-size: var(--text-sm);
13217
13910
  color: var(--color-fg-muted);
13218
13911
  background: var(--color-bg-subtle);
13219
- border-block-start: 1px solid var(--color-border);
13912
+ border-block-start: var(--border-width) solid var(--color-border);
13220
13913
  }
13221
13914
 
13222
13915
  /* ── Brand ── */
@@ -13348,7 +14041,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13348
14041
 
13349
14042
  /* === patterns/stats-dashboard.css === */
13350
14043
  /* @ui:component stats-dashboard */
13351
- /* @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 */
14044
+ /* @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 */
13352
14045
 
13353
14046
  /* ── Root ──
13354
14047
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13361,7 +14054,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13361
14054
  gap: var(--space-3);
13362
14055
  padding-block: var(--space-8);
13363
14056
  padding-inline: var(--space-4);
13364
- font-family: var(--font-sans, system-ui, sans-serif);
14057
+ font-family: var(--font-body);
13365
14058
  color: var(--color-fg);
13366
14059
  background: var(--color-bg);
13367
14060
  }
@@ -13435,9 +14128,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13435
14128
 
13436
14129
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13437
14130
  margin: 0;
14131
+ font-family: var(--font-heading);
13438
14132
  font-size: var(--text-lg);
13439
14133
  font-weight: var(--weight-semibold);
13440
- line-height: var(--leading-tight);
14134
+ letter-spacing: var(--heading-tracking);
14135
+ text-transform: var(--heading-transform);
14136
+ font-variant-caps: var(--heading-caps);
14137
+ line-height: var(--heading-leading);
13441
14138
  }
13442
14139
 
13443
14140
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13528,7 +14225,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13528
14225
  gap: var(--space-6);
13529
14226
  max-inline-size: var(--measure-narrow);
13530
14227
  margin-inline: auto;
13531
- font-family: var(--font-sans);
14228
+ font-family: var(--font-body);
13532
14229
  }
13533
14230
 
13534
14231
  [data-ui="wizard"] [data-part="heading"] {