@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/paper.css === */
645
1033
  /* @ui:theme paper — warm, natural, print-inspired theme with cream tones and earthy accents */
646
1034
 
@@ -690,12 +1078,29 @@
690
1078
  --color-border-strong: oklch(0.78 0.03 65); /* stronger warm border */
691
1079
  --color-ring: oklch(0.52 0.14 45);
692
1080
 
693
- /* ── Shadows (warm, soft) ── */
694
- --shadow-xs: 0 1px 2px oklch(0.30 0.04 50 / 0.06);
695
- --shadow-sm: 0 1px 4px oklch(0.30 0.04 50 / 0.08);
696
- --shadow-md: 0 4px 8px oklch(0.30 0.04 50 / 0.07), 0 1px 3px oklch(0.30 0.04 50 / 0.05);
697
- --shadow-lg: 0 8px 16px oklch(0.30 0.04 50 / 0.08), 0 3px 6px oklch(0.30 0.04 50 / 0.05);
698
- --shadow-xl: 0 16px 32px oklch(0.30 0.04 50 / 0.10), 0 6px 12px oklch(0.30 0.04 50 / 0.05);
1081
+ /* ── Shadows: none. Paper does not float. ──
1082
+ The theme is named for a printed page, and a printed page has no elevation:
1083
+ a card is a ruled box, not a card lying on a desk. Depth therefore derives
1084
+ `flat`, which is also what separates this theme from every other warm-light
1085
+ one in the registry. The ruling that replaces the shadow is already there —
1086
+ `--color-border` is a warm tan and every edge reads it. */
1087
+ --shadow-xs: none;
1088
+ --shadow-sm: none;
1089
+ --shadow-md: none;
1090
+ --shadow-lg: none;
1091
+ --shadow-xl: none;
1092
+
1093
+ /* ── Type: an editorial serif, said in roles ──
1094
+ Georgia for what is READ (headings and body); the UI face stays sans, so
1095
+ controls keep their platform voice while the page reads like print. This is
1096
+ the pairing `--doc-font` has expressed for documents since 0.6 — the role
1097
+ tokens let the whole theme say it, not just its invoices. */
1098
+ --font-heading: 'Georgia', var(--font-serif);
1099
+ --font-body: 'Georgia', var(--font-serif);
1100
+ --heading-weight: var(--weight-semibold); /* a serif headline does not need bold to carry */
1101
+
1102
+ /* ── Material: the paper itself ── */
1103
+ --texture-page: var(--texture-paper);
699
1104
  }
700
1105
 
701
1106
  /* ── Dark Mode ── */
@@ -744,12 +1149,12 @@
744
1149
  --color-border-strong: oklch(0.36 0.04 55);
745
1150
  --color-ring: oklch(0.68 0.12 50);
746
1151
 
747
- /* ── Shadows (warm, diffuse) ── */
1152
+ /* ── Shadows: none in dark either — see the light block ── */
748
1153
  --shadow-xs: none;
749
- --shadow-sm: 0 1px 4px oklch(0.10 0.03 50 / 0.3);
750
- --shadow-md: 0 4px 8px oklch(0.10 0.03 50 / 0.3), 0 1px 3px oklch(0.10 0.03 50 / 0.2);
751
- --shadow-lg: 0 8px 20px oklch(0.10 0.03 50 / 0.35), 0 3px 8px oklch(0.10 0.03 50 / 0.2);
752
- --shadow-xl: 0 16px 40px oklch(0.10 0.03 50 / 0.4), 0 6px 12px oklch(0.10 0.03 50 / 0.25);
1154
+ --shadow-sm: none;
1155
+ --shadow-md: none;
1156
+ --shadow-lg: none;
1157
+ --shadow-xl: none;
753
1158
  }
754
1159
 
755
1160
  /* ── Auto Dark Mode (system preference) ── */
@@ -798,12 +1203,12 @@
798
1203
  --color-border-strong: oklch(0.36 0.04 55);
799
1204
  --color-ring: oklch(0.68 0.12 50);
800
1205
 
801
- /* ── Shadows (warm, diffuse) ── */
1206
+ /* ── Shadows: none in dark either — see the light block ── */
802
1207
  --shadow-xs: none;
803
- --shadow-sm: 0 1px 4px oklch(0.10 0.03 50 / 0.3);
804
- --shadow-md: 0 4px 8px oklch(0.10 0.03 50 / 0.3), 0 1px 3px oklch(0.10 0.03 50 / 0.2);
805
- --shadow-lg: 0 8px 20px oklch(0.10 0.03 50 / 0.35), 0 3px 8px oklch(0.10 0.03 50 / 0.2);
806
- --shadow-xl: 0 16px 40px oklch(0.10 0.03 50 / 0.4), 0 6px 12px oklch(0.10 0.03 50 / 0.25);
1208
+ --shadow-sm: none;
1209
+ --shadow-md: none;
1210
+ --shadow-lg: none;
1211
+ --shadow-xl: none;
807
1212
  }
808
1213
  }
809
1214
 
@@ -812,13 +1217,12 @@
812
1217
  these override the structural document tokens for a warmer feel. */
813
1218
 
814
1219
  :root {
815
- --doc-font: 'Georgia', var(--font-serif); /* serif body text for warmth */
816
- --doc-heading-font: var(--font-sans); /* sans headings on serif body */
1220
+ --doc-font: var(--font-body); /* the theme's own reading face */
1221
+ --doc-heading-font: var(--font-heading); /* …and its headline face */
817
1222
  --doc-font-size: var(--text-sm); /* 14px */
818
1223
  --doc-heading-size: var(--text-xl);
819
1224
  --doc-subheading-size: var(--text-lg);
820
1225
  --doc-legal-size: var(--text-xs);
821
- --doc-legal-color: var(--color-fg-muted); /* follows the active paper scheme */
822
1226
  --doc-section-gap: var(--space-8);
823
1227
  --doc-component-gap: var(--space-4);
824
1228
  --doc-table-header-bg: var(--color-bg-muted); /* warm parchment headers */
@@ -828,6 +1232,14 @@
828
1232
  --doc-signature-line-color: var(--color-border-strong); /* warm gray signing line */
829
1233
  }
830
1234
 
1235
+ :root,
1236
+ [data-theme] {
1237
+ /* The token layer re-resolves this alias on every scheme island
1238
+ (tokens/document.css), so a `:root`-only override would fall back to the
1239
+ default inside a nested `data-theme` region. */
1240
+ --doc-legal-color: var(--color-fg-muted); /* follows the active paper scheme */
1241
+ }
1242
+
831
1243
  /* === base/reset.css === */
832
1244
  /* @ui:base reset — modern CSS reset for Faqir projects */
833
1245
 
@@ -842,11 +1254,38 @@
842
1254
  padding: 0;
843
1255
  }
844
1256
 
1257
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1258
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1259
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1260
+ these three rules; declaring them here (rather than in each theme) is what
1261
+ makes the two authoring forms interchangeable. Nothing else in the registry
1262
+ declares `color-scheme`, so this is purely additive.
1263
+
1264
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1265
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1266
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1267
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1268
+ dark island inside a light page has always worked here. */
1269
+ :root {
1270
+ color-scheme: light;
1271
+ }
1272
+
1273
+ [data-theme="dark"] {
1274
+ color-scheme: dark;
1275
+ }
1276
+
1277
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1278
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1279
+ does for a theme authored in the three-block form. */
1280
+ [data-theme="auto"] {
1281
+ color-scheme: light dark;
1282
+ }
1283
+
845
1284
  html {
846
1285
  -webkit-text-size-adjust: 100%;
847
1286
  -moz-tab-size: 4;
848
1287
  tab-size: 4;
849
- font-family: var(--font-sans);
1288
+ font-family: var(--font-body);
850
1289
  font-size: var(--text-base);
851
1290
  line-height: var(--leading-normal);
852
1291
  color: var(--color-fg);
@@ -857,6 +1296,11 @@ html {
857
1296
 
858
1297
  body {
859
1298
  min-height: 100dvh;
1299
+ /* The page's material. `none` by default (the initial value), so this is a
1300
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1301
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1302
+ covers the viewport, so the two compose instead of overwriting. */
1303
+ background-image: var(--texture-page);
860
1304
  }
861
1305
 
862
1306
  img,
@@ -926,10 +1370,32 @@ table {
926
1370
  }
927
1371
  }
928
1372
 
929
- /* Focus visible — default ring */
1373
+ /* Text selection — the decoration axis reaching the one surface no component
1374
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1375
+ of a themed page that never matched the theme. Both values are tokens
1376
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1377
+ ::selection {
1378
+ background-color: var(--selection-bg);
1379
+ color: var(--selection-fg);
1380
+ }
1381
+
1382
+ /* Focus visible — the default ring, and the only place it is spelled out.
1383
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1384
+ focus once and every element that has not drawn its own ring follows. */
930
1385
  :focus-visible {
931
- outline: 2px solid var(--color-ring);
932
- outline-offset: 2px;
1386
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1387
+ outline-offset: var(--focus-ring-offset);
1388
+ }
1389
+
1390
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1391
+ is not a property focus owns: an element's resting shadow — a card's depth,
1392
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1393
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1394
+ sets a shadow outranks this one, so it lands only on an element nothing else
1395
+ shadows, and it never takes a shadow away. The controls that draw their own
1396
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1397
+ :where(:focus-visible) {
1398
+ box-shadow: var(--focus-shadow);
933
1399
  }
934
1400
 
935
1401
  /* Hidden but accessible */
@@ -958,7 +1424,7 @@ table {
958
1424
  /* @ui:base prose — typography defaults for long-form content */
959
1425
 
960
1426
  [data-ui="prose"] {
961
- font-family: var(--font-sans);
1427
+ font-family: var(--font-body);
962
1428
  font-size: var(--text-base);
963
1429
  line-height: var(--leading-relaxed);
964
1430
  color: var(--color-fg);
@@ -966,29 +1432,45 @@ table {
966
1432
  }
967
1433
 
968
1434
  [data-ui="prose"] h1 {
1435
+ font-family: var(--font-heading);
969
1436
  font-size: var(--text-4xl);
970
- font-weight: var(--weight-bold);
971
- line-height: var(--leading-tight);
1437
+ font-weight: var(--heading-weight);
1438
+ letter-spacing: var(--heading-tracking);
1439
+ text-transform: var(--heading-transform);
1440
+ font-variant-caps: var(--heading-caps);
1441
+ line-height: var(--heading-leading);
972
1442
  margin-block: var(--space-8) var(--space-4);
973
1443
  }
974
1444
 
975
1445
  [data-ui="prose"] h2 {
1446
+ font-family: var(--font-heading);
976
1447
  font-size: var(--text-3xl);
977
1448
  font-weight: var(--weight-semibold);
978
- line-height: var(--leading-tight);
1449
+ letter-spacing: var(--heading-tracking);
1450
+ text-transform: var(--heading-transform);
1451
+ font-variant-caps: var(--heading-caps);
1452
+ line-height: var(--heading-leading);
979
1453
  margin-block: var(--space-8) var(--space-3);
980
1454
  }
981
1455
 
982
1456
  [data-ui="prose"] h3 {
1457
+ font-family: var(--font-heading);
983
1458
  font-size: var(--text-2xl);
984
1459
  font-weight: var(--weight-semibold);
1460
+ letter-spacing: var(--heading-tracking);
1461
+ text-transform: var(--heading-transform);
1462
+ font-variant-caps: var(--heading-caps);
985
1463
  line-height: var(--leading-snug);
986
1464
  margin-block: var(--space-6) var(--space-3);
987
1465
  }
988
1466
 
989
1467
  [data-ui="prose"] h4 {
1468
+ font-family: var(--font-heading);
990
1469
  font-size: var(--text-xl);
991
1470
  font-weight: var(--weight-semibold);
1471
+ letter-spacing: var(--heading-tracking);
1472
+ text-transform: var(--heading-transform);
1473
+ font-variant-caps: var(--heading-caps);
992
1474
  line-height: var(--leading-snug);
993
1475
  margin-block: var(--space-6) var(--space-2);
994
1476
  }
@@ -999,8 +1481,8 @@ table {
999
1481
 
1000
1482
  [data-ui="prose"] a {
1001
1483
  color: var(--color-primary);
1002
- text-decoration: underline;
1003
- text-underline-offset: 2px;
1484
+ text-decoration-line: var(--link-decoration);
1485
+ text-underline-offset: var(--link-underline-offset);
1004
1486
  }
1005
1487
 
1006
1488
  [data-ui="prose"] a:hover {
@@ -1037,7 +1519,7 @@ table {
1037
1519
  }
1038
1520
 
1039
1521
  [data-ui="prose"] blockquote {
1040
- border-inline-start: 3px solid var(--color-border-strong);
1522
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1041
1523
  padding-inline-start: var(--space-4);
1042
1524
  color: var(--color-fg-muted);
1043
1525
  margin-block: var(--space-4);
@@ -1059,9 +1541,15 @@ table {
1059
1541
  margin-block: var(--space-1);
1060
1542
  }
1061
1543
 
1544
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1545
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1546
+ [data-ui="prose"] li::marker {
1547
+ color: var(--marker-color);
1548
+ }
1549
+
1062
1550
  [data-ui="prose"] hr {
1063
1551
  border: none;
1064
- border-block-start: 1px solid var(--color-border);
1552
+ border-block-start: var(--border-width) solid var(--color-border);
1065
1553
  margin-block: var(--space-8);
1066
1554
  }
1067
1555
 
@@ -1080,12 +1568,12 @@ table {
1080
1568
  font-weight: var(--weight-semibold);
1081
1569
  text-align: start;
1082
1570
  padding: var(--space-2) var(--space-3);
1083
- border-block-end: 2px solid var(--color-border-strong);
1571
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1084
1572
  }
1085
1573
 
1086
1574
  [data-ui="prose"] td {
1087
1575
  padding: var(--space-2) var(--space-3);
1088
- border-block-end: 1px solid var(--color-border);
1576
+ border-block-end: var(--border-width) solid var(--color-border);
1089
1577
  }
1090
1578
 
1091
1579
  /* First child no top margin, last child no bottom margin */
@@ -1270,7 +1758,7 @@ table {
1270
1758
 
1271
1759
  /* === primitives/avatar.css === */
1272
1760
  /* @ui:component avatar */
1273
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1761
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1274
1762
 
1275
1763
  /* ── Base ── */
1276
1764
  [data-ui="avatar"] {
@@ -1300,7 +1788,7 @@ table {
1300
1788
  height: 100%;
1301
1789
  background: var(--color-bg-muted);
1302
1790
  color: var(--color-fg-muted);
1303
- font-family: var(--font-sans);
1791
+ font-family: var(--font-ui);
1304
1792
  font-size: var(--text-sm);
1305
1793
  font-weight: var(--weight-medium);
1306
1794
  text-transform: uppercase;
@@ -1325,7 +1813,7 @@ table {
1325
1813
 
1326
1814
  /* === primitives/badge.css === */
1327
1815
  /* @ui:component badge */
1328
- /* @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 */
1816
+ /* @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 */
1329
1817
 
1330
1818
  /* ── Base ── */
1331
1819
  [data-ui="badge"] {
@@ -1335,9 +1823,10 @@ table {
1335
1823
  gap: var(--space-1);
1336
1824
  padding: 0.125rem var(--space-2);
1337
1825
  border-radius: var(--badge-radius, var(--radius-full));
1826
+ corner-shape: var(--corner-shape);
1338
1827
  background: var(--color-bg-muted);
1339
1828
  color: var(--color-fg);
1340
- font-family: var(--badge-font, var(--font-sans));
1829
+ font-family: var(--badge-font, var(--font-ui));
1341
1830
  font-size: var(--text-xs);
1342
1831
  font-weight: var(--weight-medium);
1343
1832
  line-height: 1.5;
@@ -1383,11 +1872,11 @@ table {
1383
1872
 
1384
1873
  /* === primitives/breadcrumb.css === */
1385
1874
  /* @ui:component breadcrumb */
1386
- /* @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 */
1875
+ /* @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 */
1387
1876
 
1388
1877
  /* ── Root ── */
1389
1878
  [data-ui="breadcrumb"] {
1390
- font-family: var(--breadcrumb-font, var(--font-sans));
1879
+ font-family: var(--breadcrumb-font, var(--font-ui));
1391
1880
  font-size: var(--breadcrumb-size, var(--text-sm));
1392
1881
  color: var(--color-fg-muted);
1393
1882
  }
@@ -1413,12 +1902,13 @@ table {
1413
1902
 
1414
1903
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1415
1904
  color: var(--color-primary-hover);
1416
- text-decoration: underline;
1905
+ text-decoration-line: var(--link-decoration);
1417
1906
  }
1418
1907
 
1419
1908
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1420
- outline: 2px solid var(--color-ring);
1421
- outline-offset: 2px;
1909
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1910
+ outline-offset: var(--focus-ring-offset);
1911
+ box-shadow: var(--focus-shadow);
1422
1912
  }
1423
1913
 
1424
1914
  /* ── Separator (presentational) ── */
@@ -1458,7 +1948,7 @@ table {
1458
1948
 
1459
1949
  /* === primitives/button.css === */
1460
1950
  /* @ui:component button */
1461
- /* @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 */
1951
+ /* @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 */
1462
1952
 
1463
1953
  /* ── Base ── */
1464
1954
  [data-ui="button"] {
@@ -1468,18 +1958,21 @@ table {
1468
1958
  gap: var(--space-2);
1469
1959
  height: var(--button-height-md, 40px);
1470
1960
  padding-inline: var(--space-4);
1471
- border: 1px solid var(--color-border);
1961
+ border: var(--border-width) solid var(--color-border);
1472
1962
  border-radius: var(--button-radius, var(--radius-md));
1963
+ corner-shape: var(--corner-shape);
1473
1964
  background: var(--color-bg);
1474
1965
  color: var(--color-fg);
1475
- font-family: var(--font-sans);
1966
+ font-family: var(--font-ui);
1476
1967
  font-size: var(--text-sm);
1477
1968
  font-weight: var(--weight-medium);
1969
+ text-transform: var(--button-text-transform);
1478
1970
  line-height: 1;
1479
1971
  cursor: pointer;
1480
1972
  transition: background var(--duration-fast) var(--ease-default),
1481
1973
  border-color var(--duration-fast) var(--ease-default),
1482
1974
  color var(--duration-fast) var(--ease-default),
1975
+ translate var(--duration-fast) var(--ease-default),
1483
1976
  box-shadow var(--duration-fast) var(--ease-default);
1484
1977
  user-select: none;
1485
1978
  white-space: nowrap;
@@ -1488,11 +1981,16 @@ table {
1488
1981
 
1489
1982
  [data-ui="button"]:hover {
1490
1983
  background: var(--color-bg-muted);
1984
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1985
+ this rule computes what the button computed before the token existed; a
1986
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1987
+ translate: var(--motion-hover-lift);
1491
1988
  }
1492
1989
 
1493
1990
  [data-ui="button"]:focus-visible {
1494
- outline: 2px solid var(--color-ring);
1495
- outline-offset: 2px;
1991
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1992
+ outline-offset: var(--focus-ring-offset);
1993
+ box-shadow: var(--focus-shadow);
1496
1994
  }
1497
1995
 
1498
1996
  /* ── Variants ── */
@@ -1548,7 +2046,7 @@ table {
1548
2046
  padding: 0;
1549
2047
  }
1550
2048
  [data-ui="button"][data-variant="link"]:hover {
1551
- text-decoration: underline;
2049
+ text-decoration-line: var(--link-decoration);
1552
2050
  }
1553
2051
 
1554
2052
  /* ── Sizes ── */
@@ -1567,7 +2065,7 @@ table {
1567
2065
  /* ── States ── */
1568
2066
  [data-ui="button"]:disabled,
1569
2067
  [data-ui="button"][data-state="disabled"] {
1570
- opacity: 0.5;
2068
+ opacity: var(--disabled-opacity);
1571
2069
  cursor: not-allowed;
1572
2070
  pointer-events: none;
1573
2071
  }
@@ -1582,7 +2080,7 @@ table {
1582
2080
  position: absolute;
1583
2081
  width: 1em;
1584
2082
  height: 1em;
1585
- border: 2px solid currentColor;
2083
+ border: var(--border-width-strong) solid currentColor;
1586
2084
  border-inline-end-color: transparent;
1587
2085
  border-radius: var(--radius-full);
1588
2086
  animation: faqir-spin 0.6s linear infinite;
@@ -1629,7 +2127,7 @@ table {
1629
2127
 
1630
2128
  /* === primitives/callout.css === */
1631
2129
  /* @ui:component callout */
1632
- /* @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 */
2130
+ /* @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 */
1633
2131
 
1634
2132
  /* ── Base ── */
1635
2133
  [data-ui="callout"] {
@@ -1638,7 +2136,7 @@ table {
1638
2136
  padding: var(--callout-padding-y) var(--callout-padding-x);
1639
2137
  border-radius: var(--callout-radius);
1640
2138
  border-inline-start: var(--callout-border-left-width) solid;
1641
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2139
+ font-family: var(--doc-font, var(--font-body));
1642
2140
  font-size: var(--callout-font-size);
1643
2141
  line-height: var(--doc-line-height, 1.5);
1644
2142
  }
@@ -1669,6 +2167,7 @@ table {
1669
2167
  /* ── Title ── */
1670
2168
  [data-ui="callout"] [data-part="title"] {
1671
2169
  display: block;
2170
+ font-family: var(--font-heading);
1672
2171
  font-weight: var(--weight-semibold);
1673
2172
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1674
2173
  }
@@ -1695,8 +2194,9 @@ table {
1695
2194
  }
1696
2195
 
1697
2196
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1698
- outline: 2px solid var(--color-ring, var(--color-info));
1699
- outline-offset: 2px;
2197
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2198
+ outline-offset: var(--focus-ring-offset);
2199
+ box-shadow: var(--focus-shadow);
1700
2200
  opacity: 1;
1701
2201
  }
1702
2202
 
@@ -1782,17 +2282,36 @@ table {
1782
2282
 
1783
2283
  /* === primitives/card.css === */
1784
2284
  /* @ui:component card */
1785
- /* @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 */
2285
+ /* @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 */
1786
2286
 
1787
2287
  /* ── Base ── */
1788
2288
  [data-ui="card"] {
1789
2289
  display: flex;
1790
2290
  flex-direction: column;
1791
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2291
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1792
2292
  border-radius: var(--card-radius, var(--radius-lg));
1793
- background: var(--card-bg, var(--color-surface-1));
2293
+ corner-shape: var(--corner-shape);
2294
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2295
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2296
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2297
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1794
2298
  box-shadow: var(--card-shadow, var(--shadow-sm));
1795
2299
  overflow: hidden;
2300
+ transition: translate var(--duration-fast) var(--ease-default);
2301
+ }
2302
+
2303
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2304
+ value of `translate`), so a card sits exactly where it always sat until a
2305
+ theme says surfaces rise under the pointer. */
2306
+ [data-ui="card"]:hover {
2307
+ translate: var(--motion-hover-lift);
2308
+ }
2309
+
2310
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2311
+ [data-ui="card"] {
2312
+ -webkit-backdrop-filter: var(--surface-backdrop);
2313
+ backdrop-filter: var(--surface-backdrop);
2314
+ }
1796
2315
  }
1797
2316
 
1798
2317
  /* ── Variants ── */
@@ -1801,7 +2320,7 @@ table {
1801
2320
  }
1802
2321
 
1803
2322
  [data-ui="card"][data-variant="filled"] {
1804
- background: var(--color-surface-2);
2323
+ background: var(--texture-surface), var(--color-surface-2);
1805
2324
  border-color: var(--color-surface-2-border);
1806
2325
  box-shadow: none;
1807
2326
  }
@@ -1816,7 +2335,7 @@ table {
1816
2335
  }
1817
2336
 
1818
2337
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1819
- font-family: var(--font-sans);
2338
+ font-family: var(--font-heading);
1820
2339
  font-size: var(--text-lg);
1821
2340
  font-weight: var(--weight-semibold);
1822
2341
  line-height: var(--leading-tight);
@@ -1857,9 +2376,19 @@ table {
1857
2376
  padding-top: 0;
1858
2377
  }
1859
2378
 
2379
+ /* ── Motion ── */
2380
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2381
+ theme states one — but the house rule is that a stylesheet which transitions
2382
+ carries its own opt-out, so a reader never has to check the token first. */
2383
+ @media (prefers-reduced-motion: reduce) {
2384
+ [data-ui="card"] {
2385
+ transition: none;
2386
+ }
2387
+ }
2388
+
1860
2389
  /* === primitives/checkbox.css === */
1861
2390
  /* @ui:component checkbox */
1862
- /* @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 */
2391
+ /* @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 */
1863
2392
 
1864
2393
  /* -- Label wrapper -- */
1865
2394
  [data-ui="checkbox-label"] {
@@ -1871,7 +2400,7 @@ table {
1871
2400
 
1872
2401
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1873
2402
  cursor: not-allowed;
1874
- opacity: 0.5;
2403
+ opacity: var(--disabled-opacity);
1875
2404
  }
1876
2405
 
1877
2406
  /* -- Base -- */
@@ -1883,8 +2412,8 @@ table {
1883
2412
  width: var(--checkbox-size, 18px);
1884
2413
  height: var(--checkbox-size, 18px);
1885
2414
  flex-shrink: 0;
1886
- border: 1px solid var(--color-border);
1887
- border-radius: var(--checkbox-radius, var(--radius-sm));
2415
+ border: var(--border-width) solid var(--color-border);
2416
+ border-radius: var(--checkbox-radius);
1888
2417
  background: var(--color-bg);
1889
2418
  cursor: pointer;
1890
2419
  transition: background var(--duration-fast) var(--ease-default),
@@ -1897,8 +2426,9 @@ table {
1897
2426
  }
1898
2427
 
1899
2428
  [data-ui="checkbox"]:focus-visible {
1900
- outline: 2px solid var(--color-ring);
1901
- outline-offset: 2px;
2429
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2430
+ outline-offset: var(--focus-ring-offset);
2431
+ box-shadow: var(--focus-shadow);
1902
2432
  }
1903
2433
 
1904
2434
  /* -- Checked -- */
@@ -1989,7 +2519,7 @@ table {
1989
2519
  The mask has to opt out of the substitution to stay readable. [W3-3] */
1990
2520
  @media (forced-colors: active) {
1991
2521
  [data-ui="checkbox"] {
1992
- border: 1px solid ButtonText;
2522
+ border: var(--border-width) solid ButtonText;
1993
2523
  }
1994
2524
 
1995
2525
  [data-ui="checkbox"]:checked,
@@ -2013,7 +2543,7 @@ table {
2013
2543
 
2014
2544
  /* === primitives/chip.css === */
2015
2545
  /* @ui:component chip */
2016
- /* @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 */
2546
+ /* @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 */
2017
2547
 
2018
2548
  /* ── Base ── */
2019
2549
  [data-ui="chip"] {
@@ -2021,11 +2551,11 @@ table {
2021
2551
  align-items: center;
2022
2552
  gap: var(--space-1);
2023
2553
  padding: var(--space-1) var(--space-2);
2024
- border: 1px solid transparent;
2554
+ border: var(--border-width) solid transparent;
2025
2555
  border-radius: var(--chip-radius, var(--radius-full));
2026
2556
  background: var(--color-bg-muted);
2027
2557
  color: var(--color-fg);
2028
- font-family: var(--chip-font, var(--font-sans));
2558
+ font-family: var(--chip-font, var(--font-ui));
2029
2559
  font-size: var(--text-sm);
2030
2560
  font-weight: var(--weight-medium);
2031
2561
  line-height: 1.2;
@@ -2061,8 +2591,11 @@ table {
2061
2591
  }
2062
2592
 
2063
2593
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2064
- outline: 2px solid var(--color-ring);
2065
- outline-offset: 1px;
2594
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2595
+ /* Half the default gap — the dismiss target is small, and the full ring
2596
+ would collide with the chip's own edge. */
2597
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2598
+ box-shadow: var(--focus-shadow);
2066
2599
  }
2067
2600
 
2068
2601
  /* ── Variants ── */
@@ -2285,12 +2818,12 @@ table {
2285
2818
 
2286
2819
  /* === primitives/collapsible.css === */
2287
2820
  /* @ui:component collapsible */
2288
- /* @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 */
2821
+ /* @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 */
2289
2822
 
2290
2823
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2291
2824
  [data-ui="collapsible"] {
2292
2825
  border-radius: var(--collapsible-radius, var(--radius-md));
2293
- font-family: var(--collapsible-font, var(--font-sans));
2826
+ font-family: var(--collapsible-font, var(--font-ui));
2294
2827
  color: var(--color-fg);
2295
2828
  }
2296
2829
 
@@ -2320,8 +2853,9 @@ table {
2320
2853
  }
2321
2854
 
2322
2855
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2323
- outline: 2px solid var(--color-ring);
2324
- outline-offset: 2px;
2856
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2857
+ outline-offset: var(--focus-ring-offset);
2858
+ box-shadow: var(--focus-shadow);
2325
2859
  }
2326
2860
 
2327
2861
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2330,8 +2864,8 @@ table {
2330
2864
  flex: none;
2331
2865
  width: 0.5em;
2332
2866
  height: 0.5em;
2333
- border-inline-end: 2px solid var(--color-fg-muted);
2334
- border-block-end: 2px solid var(--color-fg-muted);
2867
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2868
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2335
2869
  transform: rotate(45deg);
2336
2870
  transition: transform var(--duration-normal) var(--ease-default);
2337
2871
  }
@@ -2350,7 +2884,7 @@ table {
2350
2884
 
2351
2885
  /* ── Bordered variant ── */
2352
2886
  [data-ui="collapsible"][data-variant="bordered"] {
2353
- border: 1px solid var(--color-border);
2887
+ border: var(--border-width) solid var(--color-border);
2354
2888
  }
2355
2889
 
2356
2890
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2483,13 +3017,13 @@ table {
2483
3017
 
2484
3018
  /* === primitives/description-list.css === */
2485
3019
  /* @ui:component description-list */
2486
- /* @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 */
3020
+ /* @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 */
2487
3021
 
2488
3022
  /* ── Base ── */
2489
3023
  [data-ui="description-list"] {
2490
3024
  margin: 0;
2491
3025
  padding: 0;
2492
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3026
+ font-family: var(--doc-font, var(--font-body));
2493
3027
  }
2494
3028
 
2495
3029
  /* ── Term ── */
@@ -2545,7 +3079,7 @@ table {
2545
3079
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2546
3080
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2547
3081
  padding-bottom: var(--space-4);
2548
- border-bottom: 1px solid var(--color-border);
3082
+ border-bottom: var(--border-width) solid var(--color-border);
2549
3083
  }
2550
3084
 
2551
3085
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2557,7 +3091,7 @@ table {
2557
3091
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2558
3092
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2559
3093
  padding-bottom: var(--space-3);
2560
- border-bottom: 1px solid var(--color-border);
3094
+ border-bottom: var(--border-width) solid var(--color-border);
2561
3095
  }
2562
3096
 
2563
3097
  /* ── Size: Small ── */
@@ -2595,7 +3129,7 @@ table {
2595
3129
 
2596
3130
  /* === primitives/empty-state.css === */
2597
3131
  /* @ui:component empty-state */
2598
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3132
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2599
3133
 
2600
3134
  /* ── Base ── */
2601
3135
  [data-ui="empty-state"] {
@@ -2616,6 +3150,7 @@ table {
2616
3150
 
2617
3151
  /* ── Title ── */
2618
3152
  [data-ui="empty-state"] [data-part="title"] {
3153
+ font-family: var(--font-heading);
2619
3154
  font-size: var(--text-lg);
2620
3155
  font-weight: var(--weight-medium);
2621
3156
  color: var(--color-fg);
@@ -2663,7 +3198,7 @@ table {
2663
3198
 
2664
3199
  /* === primitives/field-group.css === */
2665
3200
  /* @ui:component field-group */
2666
- /* @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 */
3201
+ /* @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 */
2667
3202
 
2668
3203
  /* ── Base / spacing ownership ──
2669
3204
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2675,7 +3210,7 @@ table {
2675
3210
  display: flex;
2676
3211
  flex-direction: column;
2677
3212
  gap: var(--space-2);
2678
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3213
+ font-family: var(--doc-font, var(--font-body));
2679
3214
  }
2680
3215
 
2681
3216
  /* ── Label ── */
@@ -2745,7 +3280,7 @@ table {
2745
3280
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2746
3281
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2747
3282
  border-color: var(--field-error-color);
2748
- box-shadow: 0 0 0 1px var(--field-error-color);
3283
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2749
3284
  }
2750
3285
 
2751
3286
  /* ── State: Validating ──
@@ -2755,7 +3290,7 @@ table {
2755
3290
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2756
3291
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2757
3292
  border-color: var(--field-validating-color);
2758
- box-shadow: 0 0 0 1px var(--field-validating-color);
3293
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2759
3294
  }
2760
3295
 
2761
3296
  /* ── State: Disabled ──
@@ -2774,8 +3309,8 @@ table {
2774
3309
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2775
3310
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2776
3311
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2777
- border-color: var(--color-success, oklch(0.62 0.19 145));
2778
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3312
+ border-color: var(--color-success);
3313
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2779
3314
  }
2780
3315
 
2781
3316
  /* ── Variant: Horizontal ── */
@@ -3080,7 +3615,7 @@ table {
3080
3615
 
3081
3616
  /* === primitives/image.css === */
3082
3617
  /* @ui:component image */
3083
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3618
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3084
3619
 
3085
3620
  /* ── Base ── */
3086
3621
  [data-ui="image"] {
@@ -3104,7 +3639,7 @@ table {
3104
3639
  [data-ui="image"] [data-part="caption"] {
3105
3640
  display: block;
3106
3641
  margin-top: var(--space-2);
3107
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3642
+ font-family: var(--doc-font, var(--font-body));
3108
3643
  font-size: var(--image-caption-size);
3109
3644
  color: var(--image-caption-color);
3110
3645
  line-height: 1.4;
@@ -3201,7 +3736,7 @@ table {
3201
3736
 
3202
3737
  /* === primitives/input.css === */
3203
3738
  /* @ui:component input */
3204
- /* @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 */
3739
+ /* @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 */
3205
3740
 
3206
3741
  /* ── Base ── */
3207
3742
  [data-ui="input"] {
@@ -3209,11 +3744,18 @@ table {
3209
3744
  width: 100%;
3210
3745
  height: var(--input-height, 40px);
3211
3746
  padding-inline: var(--space-3);
3212
- border: 1px solid var(--color-border);
3747
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3748
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3749
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3750
+ is drawn. Identical to the shorthand at every other value of the token. */
3751
+ border-style: solid;
3752
+ border-color: var(--color-border);
3753
+ border-width: var(--input-border-width);
3213
3754
  border-radius: var(--input-radius, var(--radius-md));
3214
- background: var(--input-bg, var(--color-bg));
3755
+ corner-shape: var(--corner-shape);
3756
+ background: var(--input-fill);
3215
3757
  color: var(--color-fg);
3216
- font-family: var(--input-font, var(--font-sans));
3758
+ font-family: var(--input-font, var(--font-ui));
3217
3759
  font-size: var(--text-sm);
3218
3760
  line-height: 1;
3219
3761
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3229,8 +3771,11 @@ table {
3229
3771
  }
3230
3772
 
3231
3773
  [data-ui="input"]:focus {
3232
- outline: 2px solid var(--color-ring);
3233
- outline-offset: -1px;
3774
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3775
+ /* The ring replaces the border rather than sitting outside it: inset by
3776
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3777
+ outline-offset: calc(-1 * var(--input-border-width));
3778
+ box-shadow: var(--focus-shadow);
3234
3779
  border-color: transparent;
3235
3780
  }
3236
3781
 
@@ -3258,7 +3803,7 @@ table {
3258
3803
  }
3259
3804
 
3260
3805
  [data-ui="input"]:disabled {
3261
- opacity: 0.5;
3806
+ opacity: var(--disabled-opacity);
3262
3807
  cursor: not-allowed;
3263
3808
  }
3264
3809
 
@@ -3321,7 +3866,7 @@ table {
3321
3866
 
3322
3867
  /* === primitives/kbd.css === */
3323
3868
  /* @ui:component kbd */
3324
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3869
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3325
3870
 
3326
3871
  /* ── Base ── */
3327
3872
  [data-ui="kbd"] {
@@ -3331,8 +3876,8 @@ table {
3331
3876
  height: 20px;
3332
3877
  min-width: 20px;
3333
3878
  padding-inline: var(--space-1h);
3334
- border: 1px solid var(--color-border);
3335
- border-bottom-width: 2px;
3879
+ border: var(--border-width) solid var(--color-border);
3880
+ border-bottom-width: var(--border-width-strong);
3336
3881
  border-radius: var(--radius-sm);
3337
3882
  background: var(--color-bg-subtle);
3338
3883
  color: var(--color-fg);
@@ -3345,7 +3890,7 @@ table {
3345
3890
 
3346
3891
  /* === primitives/key-value.css === */
3347
3892
  /* @ui:component key-value */
3348
- /* @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 */
3893
+ /* @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 */
3349
3894
 
3350
3895
  /* ── Base ── */
3351
3896
  [data-ui="key-value"] {
@@ -3354,7 +3899,7 @@ table {
3354
3899
  gap: var(--kv-pair-gap);
3355
3900
  margin: 0;
3356
3901
  padding: 0;
3357
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3902
+ font-family: var(--doc-font, var(--font-body));
3358
3903
  }
3359
3904
 
3360
3905
  /* ── Label ── */
@@ -3484,12 +4029,12 @@ table {
3484
4029
 
3485
4030
  /* === primitives/label.css === */
3486
4031
  /* @ui:component label */
3487
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4032
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3488
4033
 
3489
4034
  /* ── Base ── */
3490
4035
  [data-ui="label"] {
3491
4036
  display: block;
3492
- font-family: var(--font-sans);
4037
+ font-family: var(--font-ui);
3493
4038
  font-size: var(--text-sm);
3494
4039
  font-weight: var(--weight-medium);
3495
4040
  color: var(--color-fg);
@@ -3522,21 +4067,21 @@ table {
3522
4067
 
3523
4068
  /* ── States ── */
3524
4069
  [data-ui="label"][data-state="disabled"] {
3525
- opacity: 0.5;
4070
+ opacity: var(--disabled-opacity);
3526
4071
  cursor: not-allowed;
3527
4072
  }
3528
4073
 
3529
4074
  /* === primitives/link.css === */
3530
4075
  /* @ui:component link */
3531
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4076
+ /* @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 */
3532
4077
 
3533
4078
  /* ── Base ── */
3534
4079
  [data-ui="link"] {
3535
4080
  color: var(--color-primary);
3536
4081
  font-family: inherit;
3537
- text-decoration: underline;
3538
- text-decoration-thickness: 1px;
3539
- text-underline-offset: 0.2em;
4082
+ text-decoration-line: var(--link-decoration);
4083
+ text-decoration-thickness: var(--link-thickness);
4084
+ text-underline-offset: var(--link-underline-offset);
3540
4085
  border-radius: var(--radius-sm);
3541
4086
  cursor: pointer;
3542
4087
  }
@@ -3550,8 +4095,9 @@ table {
3550
4095
  }
3551
4096
 
3552
4097
  [data-ui="link"]:focus-visible {
3553
- outline: 2px solid var(--color-ring);
3554
- outline-offset: 2px;
4098
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4099
+ outline-offset: var(--focus-ring-offset);
4100
+ box-shadow: var(--focus-shadow);
3555
4101
  }
3556
4102
 
3557
4103
  /* ── Variants ── */
@@ -3575,7 +4121,7 @@ table {
3575
4121
 
3576
4122
  /* === primitives/nav.css === */
3577
4123
  /* @ui:component nav */
3578
- /* @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 */
4124
+ /* @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 */
3579
4125
 
3580
4126
  /* ── Base ── */
3581
4127
  [data-ui="nav"] {
@@ -3625,14 +4171,14 @@ table {
3625
4171
 
3626
4172
  /* ── Underline variant ── */
3627
4173
  [data-ui="nav"][data-variant="underline"] {
3628
- border-bottom: 1px solid var(--color-border);
4174
+ border-bottom: var(--border-width) solid var(--color-border);
3629
4175
  gap: 0;
3630
4176
  }
3631
4177
 
3632
4178
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3633
4179
  border-radius: 0;
3634
4180
  padding: var(--space-2) var(--space-4);
3635
- border-bottom: 2px solid transparent;
4181
+ border-bottom: var(--border-width-strong) solid transparent;
3636
4182
  margin-bottom: -1px;
3637
4183
  }
3638
4184
 
@@ -3688,7 +4234,7 @@ table {
3688
4234
 
3689
4235
  /* === primitives/page-break.css === */
3690
4236
  /* @ui:component page-break */
3691
- /* @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 */
4237
+ /* @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 */
3692
4238
 
3693
4239
  /* ── Base (Screen) ── */
3694
4240
  [data-ui="page-break"] {
@@ -3703,12 +4249,12 @@ table {
3703
4249
  [data-ui="page-break"]::after {
3704
4250
  content: "";
3705
4251
  flex: 1;
3706
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4252
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3707
4253
  }
3708
4254
 
3709
4255
  /* ── Label (Screen) ── */
3710
4256
  [data-ui="page-break"] {
3711
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4257
+ font-family: var(--doc-font, var(--font-body));
3712
4258
  font-size: var(--page-break-screen-label-size);
3713
4259
  color: var(--page-break-screen-label-color);
3714
4260
  letter-spacing: 0.05em;
@@ -3750,7 +4296,7 @@ table {
3750
4296
 
3751
4297
  /* === primitives/progress.css === */
3752
4298
  /* @ui:component progress */
3753
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4299
+ /* @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 */
3754
4300
 
3755
4301
  /* ── Base ── */
3756
4302
  [data-ui="progress"] {
@@ -3825,7 +4371,7 @@ table {
3825
4371
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3826
4372
  @media (forced-colors: active) {
3827
4373
  [data-ui="progress"] [data-part="track"] {
3828
- border: 1px solid ButtonText;
4374
+ border: var(--border-width) solid ButtonText;
3829
4375
  }
3830
4376
 
3831
4377
  [data-ui="progress"] [data-part="fill"],
@@ -3839,7 +4385,7 @@ table {
3839
4385
 
3840
4386
  /* === primitives/radio.css === */
3841
4387
  /* @ui:component radio */
3842
- /* @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 */
4388
+ /* @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 */
3843
4389
 
3844
4390
  /* -- Radio group -- */
3845
4391
  [data-ui="radio-group"] {
@@ -3861,7 +4407,7 @@ table {
3861
4407
 
3862
4408
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3863
4409
  cursor: not-allowed;
3864
- opacity: 0.5;
4410
+ opacity: var(--disabled-opacity);
3865
4411
  }
3866
4412
 
3867
4413
  /* -- Base -- */
@@ -3873,7 +4419,7 @@ table {
3873
4419
  width: var(--radio-size, 18px);
3874
4420
  height: var(--radio-size, 18px);
3875
4421
  flex-shrink: 0;
3876
- border: 1px solid var(--color-border);
4422
+ border: var(--border-width) solid var(--color-border);
3877
4423
  border-radius: var(--radius-full);
3878
4424
  background: var(--color-bg);
3879
4425
  cursor: pointer;
@@ -3887,8 +4433,9 @@ table {
3887
4433
  }
3888
4434
 
3889
4435
  [data-ui="radio"]:focus-visible {
3890
- outline: 2px solid var(--color-ring);
3891
- outline-offset: 2px;
4436
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4437
+ outline-offset: var(--focus-ring-offset);
4438
+ box-shadow: var(--focus-shadow);
3892
4439
  }
3893
4440
 
3894
4441
  /* -- Checked -- */
@@ -3941,7 +4488,7 @@ table {
3941
4488
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3942
4489
  @media (forced-colors: active) {
3943
4490
  [data-ui="radio"] {
3944
- border: 1px solid ButtonText;
4491
+ border: var(--border-width) solid ButtonText;
3945
4492
  }
3946
4493
 
3947
4494
  [data-ui="radio"]:checked {
@@ -3961,7 +4508,7 @@ table {
3961
4508
 
3962
4509
  /* === primitives/select.css === */
3963
4510
  /* @ui:component select */
3964
- /* @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 */
4511
+ /* @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 */
3965
4512
 
3966
4513
  /* -- Base -- */
3967
4514
  [data-ui="select"] {
@@ -3970,11 +4517,17 @@ table {
3970
4517
  height: var(--select-height, 40px);
3971
4518
  padding-inline: var(--space-3);
3972
4519
  padding-inline-end: var(--space-8, 2rem);
3973
- border: 1px solid var(--color-border);
4520
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4521
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4522
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4523
+ is drawn. Identical to the shorthand at every other value of the token. */
4524
+ border-style: solid;
4525
+ border-color: var(--color-border);
4526
+ border-width: var(--input-border-width);
3974
4527
  border-radius: var(--select-radius, var(--radius-md));
3975
- background: var(--select-bg, var(--color-bg));
4528
+ background: var(--select-bg, var(--input-fill));
3976
4529
  color: var(--color-fg);
3977
- font-family: var(--select-font, var(--font-sans));
4530
+ font-family: var(--select-font, var(--font-ui));
3978
4531
  font-size: var(--text-sm);
3979
4532
  line-height: 1;
3980
4533
  cursor: pointer;
@@ -4004,8 +4557,11 @@ table {
4004
4557
  }
4005
4558
 
4006
4559
  [data-ui="select"]:focus {
4007
- outline: 2px solid var(--color-ring);
4008
- outline-offset: -1px;
4560
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4561
+ /* The ring replaces the border rather than sitting outside it: inset by
4562
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4563
+ outline-offset: calc(-1 * var(--input-border-width));
4564
+ box-shadow: var(--focus-shadow);
4009
4565
  border-color: transparent;
4010
4566
  }
4011
4567
 
@@ -4038,7 +4594,7 @@ table {
4038
4594
  }
4039
4595
 
4040
4596
  [data-ui="select"]:disabled {
4041
- opacity: 0.5;
4597
+ opacity: var(--disabled-opacity);
4042
4598
  cursor: not-allowed;
4043
4599
  }
4044
4600
 
@@ -4051,12 +4607,12 @@ table {
4051
4607
 
4052
4608
  /* === primitives/separator.css === */
4053
4609
  /* @ui:component separator */
4054
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4610
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4055
4611
 
4056
4612
  /* ── Base (horizontal) ── */
4057
4613
  [data-ui="separator"] {
4058
4614
  border: none;
4059
- border-top: 1px solid var(--color-border);
4615
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4060
4616
  margin: 0;
4061
4617
  width: 100%;
4062
4618
  }
@@ -4064,7 +4620,7 @@ table {
4064
4620
  /* ── Vertical ── */
4065
4621
  [data-ui="separator"][data-variant="vertical"] {
4066
4622
  border-top: none;
4067
- border-inline-start: 1px solid var(--color-border);
4623
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4068
4624
  width: auto;
4069
4625
  height: 100%;
4070
4626
  align-self: stretch;
@@ -4082,11 +4638,11 @@ div[data-ui="separator"]::before,
4082
4638
  div[data-ui="separator"]::after {
4083
4639
  content: "";
4084
4640
  flex: 1;
4085
- border-top: 1px solid var(--color-border);
4641
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4086
4642
  }
4087
4643
 
4088
4644
  [data-ui="separator"] [data-part="label"] {
4089
- font-family: var(--font-sans);
4645
+ font-family: var(--font-ui);
4090
4646
  font-size: var(--text-xs);
4091
4647
  color: var(--color-fg-muted);
4092
4648
  white-space: nowrap;
@@ -4124,17 +4680,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4124
4680
 
4125
4681
  /* ── Style: Thick ── */
4126
4682
  [data-ui="separator"][data-style="thick"] {
4127
- border-top-width: 2px;
4683
+ border-top-width: var(--border-width-strong);
4128
4684
  }
4129
4685
 
4130
4686
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4131
4687
  border-top-width: 0;
4132
- border-inline-start-width: 2px;
4688
+ border-inline-start-width: var(--border-width-strong);
4133
4689
  }
4134
4690
 
4135
4691
  div[data-ui="separator"][data-style="thick"]::before,
4136
4692
  div[data-ui="separator"][data-style="thick"]::after {
4137
- border-top-width: 2px;
4693
+ border-top-width: var(--border-width-strong);
4138
4694
  }
4139
4695
 
4140
4696
  /* ── Vertical Sizes ── */
@@ -4152,20 +4708,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4152
4708
 
4153
4709
  /* === primitives/signature.css === */
4154
4710
  /* @ui:component signature */
4155
- /* @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 */
4711
+ /* @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 */
4156
4712
 
4157
4713
  /* ── Base ── */
4158
4714
  [data-ui="signature"] {
4159
4715
  display: flex;
4160
4716
  flex-direction: column;
4161
4717
  gap: var(--space-2);
4162
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4718
+ font-family: var(--doc-font, var(--font-body));
4163
4719
  margin-top: var(--doc-signature-gap);
4164
4720
  }
4165
4721
 
4166
4722
  /* ── Line ── */
4167
4723
  [data-ui="signature"] [data-part="line"] {
4168
- border-top: 1px solid var(--doc-signature-line-color);
4724
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4169
4725
  min-height: 1px;
4170
4726
  }
4171
4727
 
@@ -4268,14 +4824,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4268
4824
 
4269
4825
  /* === primitives/spinner.css === */
4270
4826
  /* @ui:component spinner */
4271
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4827
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4272
4828
 
4273
4829
  /* ── Base ── */
4274
4830
  [data-ui="spinner"] {
4275
4831
  display: inline-block;
4276
4832
  width: 24px;
4277
4833
  height: 24px;
4278
- border: 2px solid var(--color-border);
4834
+ border: var(--border-width-strong) solid var(--color-border);
4279
4835
  border-top-color: var(--color-primary);
4280
4836
  border-radius: var(--radius-full);
4281
4837
  animation: faqir-spin 0.75s linear infinite;
@@ -4291,13 +4847,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4291
4847
  [data-ui="spinner"][data-size="lg"] {
4292
4848
  width: 32px;
4293
4849
  height: 32px;
4294
- border-width: 3px;
4850
+ border-width: var(--border-width-lg);
4295
4851
  }
4296
4852
 
4297
4853
  [data-ui="spinner"][data-size="xl"] {
4298
4854
  width: 48px;
4299
4855
  height: 48px;
4300
- border-width: 3px;
4856
+ border-width: var(--border-width-lg);
4301
4857
  }
4302
4858
 
4303
4859
  /* ── Motion ── */
@@ -4879,14 +5435,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4879
5435
 
4880
5436
  /* === primitives/stat.css === */
4881
5437
  /* @ui:component stat */
4882
- /* @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 */
5438
+ /* @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 */
4883
5439
 
4884
5440
  /* ── Base ── */
4885
5441
  [data-ui="stat"] {
4886
5442
  display: flex;
4887
5443
  flex-direction: column;
4888
5444
  gap: var(--space-1);
4889
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5445
+ font-family: var(--doc-font, var(--font-body));
4890
5446
  }
4891
5447
 
4892
5448
  /* ── Label ── */
@@ -4900,6 +5456,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4900
5456
 
4901
5457
  /* ── Value ── */
4902
5458
  [data-ui="stat"] [data-part="value"] {
5459
+ font-family: var(--font-heading);
4903
5460
  font-size: var(--stat-value-size);
4904
5461
  font-weight: var(--stat-value-weight);
4905
5462
  color: var(--color-fg);
@@ -4958,10 +5515,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4958
5515
  /* ── Variant: Card ── */
4959
5516
  [data-ui="stat"][data-variant="card"] {
4960
5517
  padding: var(--space-4);
4961
- border: 1px solid var(--color-border);
5518
+ border: var(--border-width) solid var(--color-border);
4962
5519
  border-radius: var(--radius-md, 0.375rem);
4963
5520
  background: var(--color-bg);
4964
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5521
+ box-shadow: var(--shadow-sm);
4965
5522
  }
4966
5523
 
4967
5524
  /* ── Value + Change Inline ── */
@@ -4973,7 +5530,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4973
5530
  @media print {
4974
5531
  [data-ui="stat"][data-variant="card"] {
4975
5532
  box-shadow: none;
4976
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5533
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
4977
5534
  }
4978
5535
 
4979
5536
  [data-ui="stat"] {
@@ -4983,7 +5540,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4983
5540
 
4984
5541
  /* === primitives/stepper.css === */
4985
5542
  /* @ui:component stepper */
4986
- /* @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 */
5543
+ /* @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 */
4987
5544
 
4988
5545
  /* ── Base ── */
4989
5546
  [data-ui="stepper"] {
@@ -5062,7 +5619,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5062
5619
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5063
5620
  [data-ui="stepper"] [data-part="connector"] {
5064
5621
  flex: 1;
5065
- height: 2px;
5622
+ height: var(--border-width-strong);
5066
5623
  background: var(--color-border);
5067
5624
  margin: 0 var(--space-1);
5068
5625
  min-width: var(--space-2);
@@ -5130,18 +5687,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5130
5687
 
5131
5688
  /* === primitives/surface.css === */
5132
5689
  /* @ui:component surface */
5133
- /* @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 */
5690
+ /* @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 */
5134
5691
 
5135
5692
  /* ── Base ── */
5136
5693
  [data-ui="surface"] {
5137
- background: var(--color-surface-1);
5694
+ background-color: var(--color-surface-1);
5695
+ background-image: var(--texture-surface);
5138
5696
  border-radius: var(--radius-lg);
5139
- border: 1px solid var(--color-surface-1-border);
5697
+ corner-shape: var(--corner-shape);
5698
+ border: var(--border-width) solid var(--color-surface-1-border);
5140
5699
  }
5141
5700
 
5142
5701
  /* ── Elevation Variants ── */
5143
5702
  [data-ui="surface"][data-variant="flat"] {
5144
- background: var(--color-bg);
5703
+ background-color: var(--color-bg);
5145
5704
  border: none;
5146
5705
  box-shadow: none;
5147
5706
  }
@@ -5151,11 +5710,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5151
5710
  }
5152
5711
 
5153
5712
  [data-ui="surface"][data-variant="overlay"] {
5154
- background: var(--color-surface-2);
5713
+ background-color: var(--color-surface-2);
5155
5714
  box-shadow: var(--shadow-lg);
5156
5715
  border-color: var(--color-surface-2-border);
5157
5716
  }
5158
5717
 
5718
+ /* An overlay is the one surface variant that floats over other content, so it
5719
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5720
+ its own: a browser without backdrop-filter renders the solid surface above
5721
+ and never sees this rule. */
5722
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5723
+ [data-ui="surface"][data-variant="overlay"] {
5724
+ -webkit-backdrop-filter: var(--surface-backdrop);
5725
+ backdrop-filter: var(--surface-backdrop);
5726
+ }
5727
+ }
5728
+
5159
5729
  /* ── Padding Sizes ── */
5160
5730
  [data-ui="surface"][data-size="sm"] {
5161
5731
  padding: var(--space-3);
@@ -5211,7 +5781,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5211
5781
 
5212
5782
  /* === primitives/switch.css === */
5213
5783
  /* @ui:component switch */
5214
- /* @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 */
5784
+ /* @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 */
5215
5785
 
5216
5786
  /* -- Label wrapper -- */
5217
5787
  [data-ui="switch-label"] {
@@ -5223,7 +5793,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5223
5793
 
5224
5794
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5225
5795
  cursor: not-allowed;
5226
- opacity: 0.5;
5796
+ opacity: var(--disabled-opacity);
5227
5797
  }
5228
5798
 
5229
5799
  /* -- Base (track) -- */
@@ -5251,8 +5821,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5251
5821
  width: var(--switch-width, 44px);
5252
5822
  height: var(--switch-height, 24px);
5253
5823
  padding: var(--space-0h, 2px);
5254
- border: 1px solid var(--color-border);
5255
- border-radius: var(--radius-full);
5824
+ border: var(--border-width) solid var(--color-border);
5825
+ border-radius: var(--switch-radius);
5256
5826
  background: var(--switch-bg, var(--color-bg-muted));
5257
5827
  cursor: pointer;
5258
5828
  position: relative;
@@ -5262,8 +5832,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5262
5832
  }
5263
5833
 
5264
5834
  [data-ui="switch"]:focus-visible {
5265
- outline: 2px solid var(--color-ring);
5266
- outline-offset: 2px;
5835
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5836
+ outline-offset: var(--focus-ring-offset);
5837
+ box-shadow: var(--focus-shadow);
5267
5838
  }
5268
5839
 
5269
5840
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5272,7 +5843,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5272
5843
  display: block;
5273
5844
  width: var(--switch-thumb, 18px);
5274
5845
  height: var(--switch-thumb, 18px);
5275
- border-radius: var(--radius-full);
5846
+ border-radius: var(--switch-radius);
5276
5847
  background: var(--color-primary-fg);
5277
5848
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5278
5849
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5284,7 +5855,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5284
5855
  display: block;
5285
5856
  width: var(--switch-thumb, 18px);
5286
5857
  height: var(--switch-thumb, 18px);
5287
- border-radius: var(--radius-full);
5858
+ border-radius: var(--switch-radius);
5288
5859
  background: var(--color-primary-fg);
5289
5860
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5290
5861
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5366,7 +5937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5366
5937
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5367
5938
  @media (forced-colors: active) {
5368
5939
  [data-ui="switch"] {
5369
- border: 1px solid ButtonText;
5940
+ border: var(--border-width) solid ButtonText;
5370
5941
  background: ButtonFace;
5371
5942
  }
5372
5943
 
@@ -5523,25 +6094,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5523
6094
 
5524
6095
  /* === primitives/text.css === */
5525
6096
  /* @ui:component text */
5526
- /* @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 */
6097
+ /* @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 */
5527
6098
 
5528
6099
  /* ── Heading ── */
5529
6100
  [data-ui="heading"] {
5530
- font-family: var(--font-sans);
5531
- font-weight: var(--weight-bold);
6101
+ font-family: var(--font-heading);
6102
+ font-weight: var(--heading-weight);
5532
6103
  color: var(--color-fg);
5533
- line-height: var(--leading-tight);
5534
- letter-spacing: -0.01em;
6104
+ line-height: var(--heading-leading);
6105
+ text-transform: var(--heading-transform);
6106
+ font-variant-caps: var(--heading-caps);
6107
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6108
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6109
+ headings sets --heading-tracking once and every size follows, instead of
6110
+ each size having to re-derive its own number. */
6111
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5535
6112
  }
5536
6113
 
5537
6114
  [data-ui="heading"][data-size="1"] {
5538
6115
  font-size: var(--text-4xl);
5539
- letter-spacing: -0.02em;
6116
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5540
6117
  }
5541
6118
 
5542
6119
  [data-ui="heading"][data-size="2"] {
5543
6120
  font-size: var(--text-3xl);
5544
- letter-spacing: -0.02em;
6121
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5545
6122
  }
5546
6123
 
5547
6124
  [data-ui="heading"][data-size="3"] {
@@ -5565,7 +6142,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5565
6142
 
5566
6143
  /* ── Text ── */
5567
6144
  [data-ui="text"] {
5568
- font-family: var(--font-sans);
6145
+ font-family: var(--font-body);
5569
6146
  color: var(--color-fg);
5570
6147
  }
5571
6148
 
@@ -5643,7 +6220,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5643
6220
 
5644
6221
  /* === primitives/textarea.css === */
5645
6222
  /* @ui:component textarea */
5646
- /* @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 */
6223
+ /* @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 */
5647
6224
 
5648
6225
  /* -- Base -- */
5649
6226
  [data-ui="textarea"] {
@@ -5651,11 +6228,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5651
6228
  width: 100%;
5652
6229
  min-height: var(--textarea-min-height, 80px);
5653
6230
  padding: var(--space-2) var(--space-3);
5654
- border: 1px solid var(--color-border);
6231
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6232
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6233
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6234
+ is drawn. Identical to the shorthand at every other value of the token. */
6235
+ border-style: solid;
6236
+ border-color: var(--color-border);
6237
+ border-width: var(--input-border-width);
5655
6238
  border-radius: var(--textarea-radius, var(--radius-md));
5656
- background: var(--textarea-bg, var(--color-bg));
6239
+ background: var(--textarea-bg, var(--input-fill));
5657
6240
  color: var(--color-fg);
5658
- font-family: var(--textarea-font, var(--font-sans));
6241
+ font-family: var(--textarea-font, var(--font-ui));
5659
6242
  font-size: var(--text-sm);
5660
6243
  line-height: 1.5;
5661
6244
  resize: vertical;
@@ -5672,8 +6255,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5672
6255
  }
5673
6256
 
5674
6257
  [data-ui="textarea"]:focus {
5675
- outline: 2px solid var(--color-ring);
5676
- outline-offset: -1px;
6258
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6259
+ /* The ring replaces the border rather than sitting outside it: inset by
6260
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6261
+ outline-offset: calc(-1 * var(--input-border-width));
6262
+ box-shadow: var(--focus-shadow);
5677
6263
  border-color: transparent;
5678
6264
  }
5679
6265
 
@@ -5701,7 +6287,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5701
6287
  }
5702
6288
 
5703
6289
  [data-ui="textarea"]:disabled {
5704
- opacity: 0.5;
6290
+ opacity: var(--disabled-opacity);
5705
6291
  cursor: not-allowed;
5706
6292
  resize: none;
5707
6293
  }
@@ -5715,7 +6301,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5715
6301
 
5716
6302
  /* === primitives/toggle.css === */
5717
6303
  /* @ui:component toggle */
5718
- /* @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 */
6304
+ /* @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 */
5719
6305
 
5720
6306
  /* ── Base (off / unpressed) ── */
5721
6307
  [data-ui="toggle"] {
@@ -5724,11 +6310,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5724
6310
  justify-content: center;
5725
6311
  gap: var(--space-1h);
5726
6312
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5727
- border: 1px solid var(--color-border);
6313
+ border: var(--border-width) solid var(--color-border);
5728
6314
  border-radius: var(--toggle-radius, var(--radius-md));
5729
6315
  background: var(--color-bg);
5730
6316
  color: var(--color-fg-muted);
5731
- font-family: var(--toggle-font, var(--font-sans));
6317
+ font-family: var(--toggle-font, var(--font-ui));
5732
6318
  font-size: var(--text-sm);
5733
6319
  font-weight: var(--weight-medium);
5734
6320
  line-height: 1;
@@ -5745,8 +6331,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5745
6331
  }
5746
6332
 
5747
6333
  [data-ui="toggle"]:focus-visible {
5748
- outline: 2px solid var(--color-ring);
5749
- outline-offset: 2px;
6334
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6335
+ outline-offset: var(--focus-ring-offset);
6336
+ box-shadow: var(--focus-shadow);
5750
6337
  }
5751
6338
 
5752
6339
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5763,7 +6350,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5763
6350
 
5764
6351
  /* ── Disabled ── */
5765
6352
  [data-ui="toggle"]:disabled {
5766
- opacity: 0.5;
6353
+ opacity: var(--disabled-opacity);
5767
6354
  cursor: not-allowed;
5768
6355
  }
5769
6356
 
@@ -5787,7 +6374,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5787
6374
 
5788
6375
  /* === primitives/watermark.css === */
5789
6376
  /* @ui:component watermark */
5790
- /* @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 */
6377
+ /* @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 */
5791
6378
 
5792
6379
  [data-ui="watermark"] {
5793
6380
  position: fixed;
@@ -5806,7 +6393,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5806
6393
 
5807
6394
  [data-ui="watermark"] > [data-part="mark"] {
5808
6395
  color: var(--color-fg-muted);
5809
- font-family: var(--doc-font, var(--font-sans));
6396
+ font-family: var(--doc-font, var(--font-body));
5810
6397
  font-size: var(--text-4xl);
5811
6398
  font-weight: var(--weight-bold);
5812
6399
  line-height: var(--leading-tight);
@@ -5864,7 +6451,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5864
6451
 
5865
6452
  /* === recipes/accordion.css === */
5866
6453
  /* @ui:component accordion */
5867
- /* @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 */
6454
+ /* @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 */
5868
6455
 
5869
6456
  /* ── Root ── */
5870
6457
  [data-ui="accordion"] {
@@ -5873,7 +6460,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5873
6460
 
5874
6461
  /* ── Item ── */
5875
6462
  [data-ui="accordion"] [data-part="item"] {
5876
- border-bottom: 1px solid var(--color-border);
6463
+ border-bottom: var(--border-width) solid var(--color-border);
5877
6464
  }
5878
6465
 
5879
6466
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5890,7 +6477,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5890
6477
  border: none;
5891
6478
  background: transparent;
5892
6479
  color: var(--color-fg);
5893
- font-family: var(--font-sans, system-ui, sans-serif);
6480
+ font-family: var(--font-ui);
5894
6481
  font-size: var(--text-base);
5895
6482
  font-weight: var(--weight-medium);
5896
6483
  text-align: start;
@@ -5904,8 +6491,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5904
6491
  }
5905
6492
 
5906
6493
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5907
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5908
- outline-offset: -2px;
6494
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6495
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5909
6496
  border-radius: var(--radius-sm, 0.25rem);
5910
6497
  }
5911
6498
 
@@ -5937,13 +6524,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5937
6524
 
5938
6525
  /* ── Bordered Variant ── */
5939
6526
  [data-ui="accordion"][data-bordered="true"] {
5940
- border: 1px solid var(--color-border);
6527
+ border: var(--border-width) solid var(--color-border);
5941
6528
  border-radius: var(--radius-lg);
5942
6529
  overflow: hidden;
5943
6530
  }
5944
6531
 
5945
6532
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5946
- border-bottom: 1px solid var(--color-border);
6533
+ border-bottom: var(--border-width) solid var(--color-border);
5947
6534
  }
5948
6535
 
5949
6536
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5960,7 +6547,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5960
6547
 
5961
6548
  /* === recipes/alert-dialog.css === */
5962
6549
  /* @ui:component alert-dialog */
5963
- /* @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 */
6550
+ /* @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 */
5964
6551
 
5965
6552
  /* ── Root ── */
5966
6553
  [data-ui="alert-dialog"] {
@@ -5996,7 +6583,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5996
6583
  max-height: 85vh;
5997
6584
  overflow-y: auto;
5998
6585
  background: var(--color-bg);
5999
- border: 1px solid var(--color-border);
6586
+ border: var(--border-width) solid var(--color-border);
6000
6587
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
6001
6588
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
6002
6589
  opacity: 0;
@@ -6042,6 +6629,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6042
6629
  /* ── Title ── */
6043
6630
  [data-ui="alert-dialog"] [data-part="title"] {
6044
6631
  margin: 0;
6632
+ font-family: var(--font-heading);
6045
6633
  font-size: var(--text-lg, 1.125rem);
6046
6634
  font-weight: var(--weight-semibold, 600);
6047
6635
  color: var(--color-fg);
@@ -6081,7 +6669,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6081
6669
 
6082
6670
  /* === recipes/barcode.css === */
6083
6671
  /* @ui:component barcode */
6084
- /* @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 */
6672
+ /* @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 */
6085
6673
 
6086
6674
  [data-ui="barcode"] {
6087
6675
  display: inline-flex;
@@ -6108,7 +6696,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6108
6696
 
6109
6697
  [data-ui="barcode"] > [data-part="caption"] {
6110
6698
  color: var(--doc-legal-color, var(--color-fg-muted));
6111
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6699
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6112
6700
  font-size: var(--doc-legal-size);
6113
6701
  line-height: var(--leading-normal);
6114
6702
  text-align: center;
@@ -6128,7 +6716,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6128
6716
 
6129
6717
  /* === recipes/calendar.css === */
6130
6718
  /* @ui:component calendar */
6131
- /* @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 */
6719
+ /* @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 */
6132
6720
 
6133
6721
  /* ── Root ── */
6134
6722
  [data-ui="calendar"] {
@@ -6161,7 +6749,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6161
6749
  width: 28px;
6162
6750
  height: 28px;
6163
6751
  padding: 0;
6164
- border: 1px solid var(--color-border);
6752
+ border: var(--border-width) solid var(--color-border);
6165
6753
  border-radius: var(--radius-md);
6166
6754
  background: var(--color-bg);
6167
6755
  color: var(--color-fg);
@@ -6177,13 +6765,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6177
6765
 
6178
6766
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6179
6767
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6180
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6181
- outline-offset: 2px;
6768
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6769
+ outline-offset: var(--focus-ring-offset);
6182
6770
  }
6183
6771
 
6184
6772
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6185
6773
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6186
- opacity: 0.4;
6774
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6775
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6776
+ opacity: calc(var(--disabled-opacity) * 0.8);
6187
6777
  cursor: not-allowed;
6188
6778
  }
6189
6779
 
@@ -6218,11 +6808,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6218
6808
  width: 36px;
6219
6809
  height: 36px;
6220
6810
  padding: 0;
6221
- border: 1px solid transparent;
6811
+ border: var(--border-width) solid transparent;
6222
6812
  border-radius: var(--radius-full);
6223
6813
  background: transparent;
6224
6814
  color: var(--color-fg);
6225
- font-family: var(--font-sans, system-ui, sans-serif);
6815
+ font-family: var(--font-ui);
6226
6816
  font-size: var(--text-sm);
6227
6817
  cursor: pointer;
6228
6818
  transition: background var(--duration-fast) var(--ease-default),
@@ -6235,8 +6825,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6235
6825
  }
6236
6826
 
6237
6827
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6238
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6239
- outline-offset: 2px;
6828
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6829
+ outline-offset: var(--focus-ring-offset);
6240
6830
  }
6241
6831
 
6242
6832
  /* ── Today ── */
@@ -6271,7 +6861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6271
6861
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6272
6862
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6273
6863
  [data-ui="calendar"] [data-part="day"]:disabled {
6274
- opacity: 0.5;
6864
+ opacity: var(--disabled-opacity);
6275
6865
  cursor: not-allowed;
6276
6866
  text-decoration: line-through;
6277
6867
  }
@@ -6335,7 +6925,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6335
6925
 
6336
6926
  /* === recipes/carousel.css === */
6337
6927
  /* @ui:component carousel */
6338
- /* @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 */
6928
+ /* @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 */
6339
6929
 
6340
6930
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6341
6931
  every slide is a snap target. Everything below works with no controller
@@ -6349,7 +6939,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6349
6939
  inline-size: 100%;
6350
6940
  min-inline-size: 0;
6351
6941
  max-inline-size: 100%;
6352
- font-family: var(--carousel-font, var(--font-sans));
6942
+ font-family: var(--carousel-font, var(--font-ui));
6353
6943
  }
6354
6944
 
6355
6945
  /* ── Viewport: the scroll-snap strip ── */
@@ -6375,8 +6965,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6375
6965
  }
6376
6966
 
6377
6967
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6378
- outline: 2px solid var(--color-ring);
6379
- outline-offset: 2px;
6968
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6969
+ outline-offset: var(--focus-ring-offset);
6380
6970
  }
6381
6971
 
6382
6972
  /* ── Slide: one full-width snap target ── */
@@ -6384,7 +6974,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6384
6974
  flex: 0 0 var(--carousel-slide-size, 100%);
6385
6975
  min-inline-size: 0;
6386
6976
  padding: var(--space-4);
6387
- border: 1px solid var(--color-border);
6977
+ border: var(--border-width) solid var(--color-border);
6388
6978
  border-radius: var(--radius-lg);
6389
6979
  background: var(--color-bg);
6390
6980
  color: var(--color-fg);
@@ -6413,7 +7003,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6413
7003
  min-inline-size: 2rem;
6414
7004
  min-block-size: 2rem;
6415
7005
  padding: var(--space-1) var(--space-2);
6416
- border: 1px solid var(--color-border);
7006
+ border: var(--border-width) solid var(--color-border);
6417
7007
  border-radius: var(--radius-md);
6418
7008
  background: var(--color-bg);
6419
7009
  color: var(--color-fg);
@@ -6432,14 +7022,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6432
7022
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6433
7023
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6434
7024
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6435
- outline: 2px solid var(--color-ring);
6436
- outline-offset: 2px;
7025
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7026
+ outline-offset: var(--focus-ring-offset);
6437
7027
  }
6438
7028
 
6439
7029
  /* Boundary contract "stop" — the controller disables the end button. */
6440
7030
  [data-ui="carousel"] [data-part="prev"]:disabled,
6441
7031
  [data-ui="carousel"] [data-part="next"]:disabled {
6442
- opacity: 0.4;
7032
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7033
+ opacity: calc(var(--disabled-opacity) * 0.8);
6443
7034
  cursor: not-allowed;
6444
7035
  }
6445
7036
 
@@ -6448,7 +7039,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6448
7039
  inline-size: 0.625rem;
6449
7040
  block-size: 0.625rem;
6450
7041
  padding: 0;
6451
- border: 1px solid var(--color-border);
7042
+ border: var(--border-width) solid var(--color-border);
6452
7043
  border-radius: 50%;
6453
7044
  background: var(--color-bg-muted);
6454
7045
  cursor: pointer;
@@ -6484,7 +7075,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6484
7075
 
6485
7076
  /* === recipes/combobox.css === */
6486
7077
  /* @ui:component combobox */
6487
- /* @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 */
7078
+ /* @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 */
6488
7079
 
6489
7080
  /* ── Root ── */
6490
7081
  [data-ui="combobox"] {
@@ -6498,11 +7089,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6498
7089
  display: block;
6499
7090
  width: 100%;
6500
7091
  padding: var(--space-2) var(--space-3);
6501
- border: 1px solid var(--color-border);
7092
+ border: var(--border-width) solid var(--color-border);
6502
7093
  border-radius: var(--radius-md);
6503
7094
  background: var(--color-bg);
6504
7095
  color: var(--color-fg);
6505
- font-family: var(--font-sans, system-ui, sans-serif);
7096
+ font-family: var(--font-ui);
6506
7097
  font-size: var(--text-sm);
6507
7098
  line-height: 1.5;
6508
7099
  outline: none;
@@ -6515,8 +7106,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6515
7106
  }
6516
7107
 
6517
7108
  [data-ui="combobox"] [data-part="input"]:focus {
6518
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6519
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7109
+ border-color: var(--focus-ring-color);
7110
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6520
7111
  }
6521
7112
 
6522
7113
  /* ── Listbox ── */
@@ -6528,7 +7119,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6528
7119
  z-index: var(--z-dropdown);
6529
7120
  margin-top: var(--space-1);
6530
7121
  padding: var(--space-1);
6531
- border: 1px solid var(--color-border);
7122
+ border: var(--border-width) solid var(--color-border);
6532
7123
  border-radius: var(--radius-lg);
6533
7124
  background: var(--color-bg);
6534
7125
  box-shadow: var(--shadow-md);
@@ -6613,7 +7204,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6613
7204
 
6614
7205
  /* === recipes/command-palette.css === */
6615
7206
  /* @ui:component command-palette */
6616
- /* @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 */
7207
+ /* @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 */
6617
7208
 
6618
7209
  /* ── Root ── */
6619
7210
  [data-ui="command-palette"] {
@@ -6646,7 +7237,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6646
7237
  display: flex;
6647
7238
  flex-direction: column;
6648
7239
  background: var(--color-bg);
6649
- border: 1px solid var(--color-border);
7240
+ border: var(--border-width) solid var(--color-border);
6650
7241
  border-radius: var(--radius-xl);
6651
7242
  box-shadow: var(--shadow-xl);
6652
7243
  overflow: hidden;
@@ -6678,7 +7269,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6678
7269
  display: flex;
6679
7270
  align-items: center;
6680
7271
  padding: var(--space-3) var(--space-4);
6681
- border-bottom: 1px solid var(--color-border);
7272
+ border-bottom: var(--border-width) solid var(--color-border);
6682
7273
  }
6683
7274
 
6684
7275
  /* ── Search Input ── */
@@ -6688,7 +7279,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6688
7279
  border: none;
6689
7280
  background: transparent;
6690
7281
  color: var(--color-fg);
6691
- font-family: var(--font-sans, system-ui, sans-serif);
7282
+ font-family: var(--font-ui);
6692
7283
  font-size: var(--text-base);
6693
7284
  outline: none;
6694
7285
  }
@@ -6772,7 +7363,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6772
7363
  align-items: center;
6773
7364
  gap: var(--space-1, 0.25rem);
6774
7365
  padding: var(--space-1, 0.25rem) var(--space-2);
6775
- border: 1px solid var(--color-border);
7366
+ border: var(--border-width) solid var(--color-border);
6776
7367
  border-radius: var(--radius-sm, 0.25rem);
6777
7368
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6778
7369
  color: var(--color-fg-muted);
@@ -6801,7 +7392,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6801
7392
 
6802
7393
  /* === recipes/context-menu.css === */
6803
7394
  /* @ui:component context-menu */
6804
- /* @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 */
7395
+ /* @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 */
6805
7396
 
6806
7397
  [data-ui="context-menu"] {
6807
7398
  position: relative;
@@ -6814,12 +7405,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6814
7405
  border-radius: var(--radius-lg);
6815
7406
  background: var(--color-bg-muted);
6816
7407
  color: var(--color-fg);
6817
- font-family: var(--font-sans, system-ui, sans-serif);
7408
+ font-family: var(--font-ui);
6818
7409
  }
6819
7410
 
6820
7411
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6821
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6822
- outline-offset: var(--space-1);
7412
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7413
+ outline-offset: var(--focus-ring-offset);
6823
7414
  }
6824
7415
 
6825
7416
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6851,7 +7442,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6851
7442
  border-radius: var(--radius-md);
6852
7443
  background: transparent;
6853
7444
  color: var(--color-fg);
6854
- font-family: var(--font-sans, system-ui, sans-serif);
7445
+ font-family: var(--font-ui);
6855
7446
  font-size: var(--text-sm);
6856
7447
  font-weight: var(--weight-medium);
6857
7448
  text-align: start;
@@ -6875,15 +7466,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6875
7466
  focus additionally draws the ring, inset so it does not overlap the item
6876
7467
  above. [W3-3] */
6877
7468
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6878
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6879
- outline-offset: calc(var(--space-px) * -2);
7469
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7470
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6880
7471
  }
6881
7472
 
6882
7473
  [data-ui="context-menu"] [data-part="item"]:disabled,
6883
7474
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6884
7475
  color: var(--color-fg-muted);
6885
7476
  cursor: not-allowed;
6886
- opacity: 0.5;
7477
+ opacity: var(--disabled-opacity);
6887
7478
  }
6888
7479
 
6889
7480
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6902,7 +7493,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6902
7493
 
6903
7494
  /* === recipes/date-picker.css === */
6904
7495
  /* @ui:component date-picker */
6905
- /* @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 */
7496
+ /* @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 */
6906
7497
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6907
7498
 
6908
7499
  /* ── Root ── */
@@ -6923,11 +7514,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6923
7514
  width: 100%;
6924
7515
  padding: var(--space-2, 0.5rem) var(--space-3);
6925
7516
  padding-inline-end: var(--space-8, 2.5rem);
6926
- border: 1px solid var(--color-border);
7517
+ border: var(--border-width) solid var(--color-border);
6927
7518
  border-radius: var(--radius-md);
6928
7519
  background: var(--color-bg);
6929
7520
  color: var(--color-fg);
6930
- font-family: var(--font-sans, system-ui, sans-serif);
7521
+ font-family: var(--font-ui);
6931
7522
  font-size: var(--text-sm);
6932
7523
  line-height: 1.5;
6933
7524
  cursor: pointer;
@@ -6939,8 +7530,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6939
7530
  }
6940
7531
 
6941
7532
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6942
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6943
- outline-offset: 2px;
7533
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7534
+ outline-offset: var(--focus-ring-offset);
6944
7535
  border-color: var(--color-primary);
6945
7536
  }
6946
7537
 
@@ -6963,7 +7554,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6963
7554
  z-index: var(--z-dropdown);
6964
7555
  margin-top: var(--space-1);
6965
7556
  padding: var(--space-3);
6966
- border: 1px solid var(--color-border);
7557
+ border: var(--border-width) solid var(--color-border);
6967
7558
  border-radius: var(--radius-lg);
6968
7559
  background: var(--color-bg);
6969
7560
  box-shadow: var(--shadow-lg);
@@ -7002,7 +7593,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7002
7593
 
7003
7594
  /* === recipes/dialog.css === */
7004
7595
  /* @ui:component dialog */
7005
- /* @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 */
7596
+ /* @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 */
7006
7597
 
7007
7598
  /* ── Root ── */
7008
7599
  [data-ui="dialog"] {
@@ -7037,15 +7628,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7037
7628
  width: 90%;
7038
7629
  max-height: 85vh;
7039
7630
  overflow-y: auto;
7040
- background: var(--color-bg);
7041
- border: 1px solid var(--color-border);
7631
+ background: var(--panel-bg);
7632
+ border: var(--border-width) solid var(--color-border);
7042
7633
  border-radius: var(--dialog-radius, var(--radius-xl));
7634
+ corner-shape: var(--corner-shape);
7043
7635
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7044
7636
  opacity: 0;
7045
7637
  transition: opacity var(--duration-normal) var(--ease-out),
7046
7638
  transform var(--duration-normal) var(--ease-out);
7047
7639
  }
7048
7640
 
7641
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7642
+ [data-ui="dialog"] [data-part="panel"] {
7643
+ -webkit-backdrop-filter: var(--surface-backdrop);
7644
+ backdrop-filter: var(--surface-backdrop);
7645
+ }
7646
+ }
7647
+
7049
7648
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7050
7649
  opacity: 1;
7051
7650
  transform: translate(-50%, -50%) scale(1);
@@ -7094,6 +7693,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7094
7693
  /* ── Title ── */
7095
7694
  [data-ui="dialog"] [data-part="title"] {
7096
7695
  margin: 0;
7696
+ font-family: var(--font-heading);
7097
7697
  font-size: var(--text-lg, 1.125rem);
7098
7698
  font-weight: var(--weight-semibold, 600);
7099
7699
  color: var(--color-fg);
@@ -7128,8 +7728,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7128
7728
  }
7129
7729
 
7130
7730
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7131
- outline: 2px solid var(--color-ring);
7132
- outline-offset: 2px;
7731
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7732
+ outline-offset: var(--focus-ring-offset);
7133
7733
  }
7134
7734
 
7135
7735
  /* ── Description ── */
@@ -7165,7 +7765,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7165
7765
 
7166
7766
  /* === recipes/drawer.css === */
7167
7767
  /* @ui:component drawer */
7168
- /* @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 */
7768
+ /* @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 */
7169
7769
 
7170
7770
  /* ── Root ── */
7171
7771
  [data-ui="drawer"] {
@@ -7200,17 +7800,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7200
7800
  flex-direction: column;
7201
7801
  width: var(--drawer-width, 400px);
7202
7802
  max-width: 100vw;
7203
- background: var(--color-bg);
7803
+ background: var(--panel-bg);
7204
7804
  border: none;
7205
7805
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7206
7806
  transition: transform var(--duration-slow) var(--ease-out);
7207
7807
  }
7208
7808
 
7809
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7810
+ [data-ui="drawer"] [data-part="panel"] {
7811
+ -webkit-backdrop-filter: var(--surface-backdrop);
7812
+ backdrop-filter: var(--surface-backdrop);
7813
+ }
7814
+ }
7815
+
7209
7816
  /* ── Side Variants ── */
7210
7817
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7211
7818
  inset-inline-start: 0;
7212
7819
  inset-inline-end: auto;
7213
- border-inline-end: 1px solid var(--color-border);
7820
+ border-inline-end: var(--border-width) solid var(--color-border);
7214
7821
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7215
7822
  transform: translateX(-100%);
7216
7823
  }
@@ -7218,7 +7825,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7218
7825
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7219
7826
  inset-inline-end: 0;
7220
7827
  inset-inline-start: auto;
7221
- border-inline-start: 1px solid var(--color-border);
7828
+ border-inline-start: var(--border-width) solid var(--color-border);
7222
7829
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7223
7830
  transform: translateX(100%);
7224
7831
  }
@@ -7272,6 +7879,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7272
7879
  /* ── Title ── */
7273
7880
  [data-ui="drawer"] [data-part="title"] {
7274
7881
  margin: 0;
7882
+ font-family: var(--font-heading);
7275
7883
  font-size: var(--text-lg, 1.125rem);
7276
7884
  font-weight: var(--weight-semibold, 600);
7277
7885
  color: var(--color-fg);
@@ -7306,8 +7914,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7306
7914
  }
7307
7915
 
7308
7916
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7309
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7310
- outline-offset: 2px;
7917
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7918
+ outline-offset: var(--focus-ring-offset);
7311
7919
  }
7312
7920
 
7313
7921
  /* ── Body ── */
@@ -7326,7 +7934,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7326
7934
  gap: var(--space-3, 0.75rem);
7327
7935
  padding: var(--space-6);
7328
7936
  padding-top: var(--space-4);
7329
- border-top: 1px solid var(--color-border);
7937
+ border-top: var(--border-width) solid var(--color-border);
7330
7938
  flex-shrink: 0;
7331
7939
  }
7332
7940
 
@@ -7340,7 +7948,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7340
7948
 
7341
7949
  /* === recipes/dropdown.css === */
7342
7950
  /* @ui:component dropdown */
7343
- /* @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 */
7951
+ /* @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 */
7344
7952
 
7345
7953
  /* ── Root ── */
7346
7954
  [data-ui="dropdown"] {
@@ -7354,11 +7962,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7354
7962
  align-items: center;
7355
7963
  gap: var(--space-2);
7356
7964
  padding: var(--space-2) var(--space-3);
7357
- border: 1px solid var(--color-border);
7965
+ border: var(--border-width) solid var(--color-border);
7358
7966
  border-radius: var(--radius-md);
7359
7967
  background: var(--color-bg);
7360
7968
  color: var(--color-fg);
7361
- font-family: var(--font-sans, system-ui, sans-serif);
7969
+ font-family: var(--font-ui);
7362
7970
  font-size: var(--text-sm);
7363
7971
  font-weight: var(--weight-medium);
7364
7972
  cursor: pointer;
@@ -7372,8 +7980,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7372
7980
  }
7373
7981
 
7374
7982
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7375
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7376
- outline-offset: 2px;
7983
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7984
+ outline-offset: var(--focus-ring-offset);
7377
7985
  }
7378
7986
 
7379
7987
  /* ── Menu ── */
@@ -7385,9 +7993,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7385
7993
  min-width: 180px;
7386
7994
  margin-top: var(--space-1);
7387
7995
  padding: var(--space-1);
7388
- border: 1px solid var(--color-border);
7996
+ border: var(--border-width) solid var(--color-border);
7389
7997
  border-radius: var(--radius-lg);
7390
- background: var(--color-bg);
7998
+ background: var(--panel-bg);
7391
7999
  box-shadow: var(--shadow-md);
7392
8000
  opacity: 0;
7393
8001
  transform: translateY(-4px);
@@ -7395,6 +8003,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7395
8003
  transform var(--duration-fast) var(--ease-out);
7396
8004
  }
7397
8005
 
8006
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8007
+ [data-ui="dropdown"] [data-part="menu"] {
8008
+ -webkit-backdrop-filter: var(--surface-backdrop);
8009
+ backdrop-filter: var(--surface-backdrop);
8010
+ }
8011
+ }
8012
+
7398
8013
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7399
8014
  opacity: 1;
7400
8015
  transform: translateY(0);
@@ -7417,7 +8032,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7417
8032
  border-radius: var(--radius-md);
7418
8033
  background: transparent;
7419
8034
  color: var(--color-fg);
7420
- font-family: var(--font-sans, system-ui, sans-serif);
8035
+ font-family: var(--font-ui);
7421
8036
  font-size: var(--text-sm);
7422
8037
  text-align: start;
7423
8038
  cursor: pointer;
@@ -7439,12 +8054,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7439
8054
  focus additionally draws the ring, inset so it does not overlap the item
7440
8055
  above. [W3-3] */
7441
8056
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7442
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7443
- outline-offset: -2px;
8057
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8058
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7444
8059
  }
7445
8060
 
7446
8061
  [data-ui="dropdown"] [data-part="item"]:disabled {
7447
- opacity: 0.5;
8062
+ opacity: var(--disabled-opacity);
7448
8063
  cursor: not-allowed;
7449
8064
  pointer-events: none;
7450
8065
  }
@@ -7497,14 +8112,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7497
8112
 
7498
8113
  /* === recipes/file-upload.css === */
7499
8114
  /* @ui:component file-upload */
7500
- /* @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 */
8115
+ /* @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 */
7501
8116
 
7502
8117
  [data-ui="file-upload"] {
7503
8118
  display: grid;
7504
8119
  gap: var(--space-4);
7505
8120
  inline-size: 100%;
7506
8121
  color: var(--color-fg);
7507
- font-family: var(--font-sans);
8122
+ font-family: var(--font-ui);
7508
8123
  }
7509
8124
 
7510
8125
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7539,14 +8154,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7539
8154
  }
7540
8155
 
7541
8156
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7542
- outline: var(--space-px) solid var(--color-ring);
7543
- outline-offset: var(--space-1);
8157
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8158
+ outline-offset: var(--focus-ring-offset);
7544
8159
  }
7545
8160
 
7546
8161
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7547
8162
  border-color: var(--color-primary);
7548
8163
  background: var(--color-primary-subtle);
7549
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8164
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7550
8165
  }
7551
8166
 
7552
8167
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7620,8 +8235,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7620
8235
  }
7621
8236
 
7622
8237
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7623
- outline: var(--space-px) solid var(--color-ring);
7624
- outline-offset: var(--space-1);
8238
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8239
+ outline-offset: var(--focus-ring-offset);
7625
8240
  }
7626
8241
 
7627
8242
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7643,7 +8258,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7643
8258
  }
7644
8259
 
7645
8260
  [data-ui="file-upload"][data-disabled] {
7646
- opacity: 0.5;
8261
+ opacity: var(--disabled-opacity);
7647
8262
  }
7648
8263
 
7649
8264
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7659,7 +8274,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7659
8274
 
7660
8275
  /* === recipes/input-otp.css === */
7661
8276
  /* @ui:component input-otp */
7662
- /* @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 */
8277
+ /* @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 */
7663
8278
 
7664
8279
  /* ── Root ── */
7665
8280
  [data-ui="input-otp"] {
@@ -7674,7 +8289,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7674
8289
  gutter. The transparent input is `inset: 0`, so it follows the box the
7675
8290
  segments settle into however many rows that takes. */
7676
8291
  max-inline-size: 100%;
7677
- font-family: var(--font-sans, system-ui, sans-serif);
8292
+ font-family: var(--font-ui);
7678
8293
  }
7679
8294
 
7680
8295
  /* ── Real input ──
@@ -7719,14 +8334,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7719
8334
  justify-content: center;
7720
8335
  inline-size: var(--input-otp-segment-size);
7721
8336
  block-size: var(--input-otp-segment-size);
7722
- border: 1px solid var(--color-border);
8337
+ border: var(--border-width) solid var(--color-border);
7723
8338
  border-radius: var(--radius-md);
7724
8339
  background: var(--color-bg);
7725
8340
  color: var(--color-fg);
7726
8341
  font-size: var(--text-lg, 1.125rem);
7727
8342
  font-variant-numeric: tabular-nums;
7728
8343
  line-height: 1;
7729
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8344
+ transition: border-color var(--duration-fast) var(--ease-default),
7730
8345
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7731
8346
  }
7732
8347
 
@@ -7738,7 +8353,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7738
8353
  /* Active (caret / selected) segment while focused */
7739
8354
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7740
8355
  border-color: var(--color-ring);
7741
- box-shadow: 0 0 0 1px var(--color-ring);
8356
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7742
8357
  }
7743
8358
 
7744
8359
  /* Blinking caret in the next-to-fill empty slot */
@@ -7786,7 +8401,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7786
8401
 
7787
8402
  /* ── Disabled ── */
7788
8403
  [data-ui="input-otp"][data-disabled] {
7789
- opacity: 0.5;
8404
+ opacity: var(--disabled-opacity);
7790
8405
  cursor: not-allowed;
7791
8406
  }
7792
8407
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7810,7 +8425,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7810
8425
 
7811
8426
  /* === recipes/menubar.css === */
7812
8427
  /* @ui:component menubar */
7813
- /* @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 */
8428
+ /* @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 */
7814
8429
 
7815
8430
  [data-ui="menubar"] {
7816
8431
  position: relative;
@@ -7828,7 +8443,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7828
8443
  border-radius: var(--radius-lg);
7829
8444
  background: var(--color-bg);
7830
8445
  color: var(--color-fg);
7831
- font-family: var(--font-sans);
8446
+ font-family: var(--font-ui);
7832
8447
  }
7833
8448
 
7834
8449
  [data-ui="menubar"] [data-part="group"] {
@@ -7870,7 +8485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7870
8485
 
7871
8486
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7872
8487
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7873
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8488
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7874
8489
  }
7875
8490
 
7876
8491
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7905,7 +8520,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7905
8520
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7906
8521
  color: var(--color-fg-muted);
7907
8522
  cursor: not-allowed;
7908
- opacity: 0.6;
8523
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8524
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8525
+ it (1.1A-27). */
8526
+ opacity: calc(var(--disabled-opacity) * 1.2);
7909
8527
  }
7910
8528
 
7911
8529
  [data-ui="menubar"] [data-part="separator"] {
@@ -7937,7 +8555,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7937
8555
 
7938
8556
  /* === recipes/pagination.css === */
7939
8557
  /* @ui:component pagination */
7940
- /* @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 */
8558
+ /* @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 */
7941
8559
 
7942
8560
  /* ── Root ── */
7943
8561
  [data-ui="pagination"] {
@@ -7973,11 +8591,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7973
8591
  min-width: 36px;
7974
8592
  height: 36px;
7975
8593
  padding: 0 var(--space-2);
7976
- border: 1px solid var(--color-border);
8594
+ border: var(--border-width) solid var(--color-border);
7977
8595
  border-radius: var(--radius-md);
7978
8596
  background: var(--color-bg);
7979
8597
  color: var(--color-fg);
7980
- font-family: var(--font-sans, system-ui, sans-serif);
8598
+ font-family: var(--font-ui);
7981
8599
  font-size: var(--text-sm);
7982
8600
  font-weight: var(--weight-medium);
7983
8601
  cursor: pointer;
@@ -7998,8 +8616,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7998
8616
  [data-ui="pagination"] [data-part="page"]:focus-visible,
7999
8617
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
8000
8618
  [data-ui="pagination"] [data-part="next"]:focus-visible {
8001
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8002
- outline-offset: 2px;
8619
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8620
+ outline-offset: var(--focus-ring-offset);
8003
8621
  }
8004
8622
 
8005
8623
  /* ── Active page ── */
@@ -8023,7 +8641,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8023
8641
  /* ── Disabled ── */
8024
8642
  [data-ui="pagination"] [data-part="prev"]:disabled,
8025
8643
  [data-ui="pagination"] [data-part="next"]:disabled {
8026
- opacity: 0.5;
8644
+ opacity: var(--disabled-opacity);
8027
8645
  cursor: not-allowed;
8028
8646
  pointer-events: none;
8029
8647
  }
@@ -8093,7 +8711,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8093
8711
 
8094
8712
  /* === recipes/popover.css === */
8095
8713
  /* @ui:component popover */
8096
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8714
+ /* @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 */
8097
8715
 
8098
8716
  /* ── Root ── */
8099
8717
  [data-ui="popover"] {
@@ -8107,11 +8725,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8107
8725
  align-items: center;
8108
8726
  gap: var(--space-2, 0.5rem);
8109
8727
  padding: var(--space-2, 0.5rem) var(--space-3);
8110
- border: 1px solid var(--color-border);
8728
+ border: var(--border-width) solid var(--color-border);
8111
8729
  border-radius: var(--radius-md, 0.375rem);
8112
8730
  background: var(--color-bg);
8113
8731
  color: var(--color-fg);
8114
- font-family: var(--font-sans, system-ui, sans-serif);
8732
+ font-family: var(--font-ui);
8115
8733
  font-size: var(--text-sm, 0.875rem);
8116
8734
  font-weight: var(--weight-medium, 500);
8117
8735
  cursor: pointer;
@@ -8125,8 +8743,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8125
8743
  }
8126
8744
 
8127
8745
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8128
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8129
- outline-offset: 2px;
8746
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8747
+ outline-offset: var(--focus-ring-offset);
8130
8748
  }
8131
8749
 
8132
8750
  /* ── Content ── */
@@ -8135,9 +8753,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8135
8753
  z-index: var(--z-dropdown);
8136
8754
  min-width: 200px;
8137
8755
  padding: var(--space-4);
8138
- border: 1px solid var(--color-border);
8756
+ border: var(--border-width) solid var(--color-border);
8139
8757
  border-radius: var(--radius-lg);
8140
- background: var(--color-bg);
8758
+ background: var(--panel-bg);
8141
8759
  color: var(--color-fg);
8142
8760
  box-shadow: var(--shadow-md);
8143
8761
  opacity: 0;
@@ -8146,6 +8764,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8146
8764
  transform var(--duration-fast) var(--ease-default);
8147
8765
  }
8148
8766
 
8767
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8768
+ [data-ui="popover"] [data-part="content"] {
8769
+ -webkit-backdrop-filter: var(--surface-backdrop);
8770
+ backdrop-filter: var(--surface-backdrop);
8771
+ }
8772
+ }
8773
+
8149
8774
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8150
8775
  opacity: 1;
8151
8776
  transform: scale(1);
@@ -8233,8 +8858,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8233
8858
  position: absolute;
8234
8859
  width: 8px;
8235
8860
  height: 8px;
8236
- background: var(--color-bg);
8237
- border: 1px solid var(--color-border);
8861
+ background: var(--panel-bg);
8862
+ border: var(--border-width) solid var(--color-border);
8238
8863
  transform: rotate(45deg);
8239
8864
  }
8240
8865
 
@@ -8335,8 +8960,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8335
8960
  }
8336
8961
 
8337
8962
  [data-ui="popover"] [data-part="close"]:focus-visible {
8338
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8339
- outline-offset: 2px;
8963
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8964
+ outline-offset: var(--focus-ring-offset);
8340
8965
  }
8341
8966
 
8342
8967
  /* ── Motion ── */
@@ -8349,7 +8974,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8349
8974
 
8350
8975
  /* === recipes/qr-code.css === */
8351
8976
  /* @ui:component qr-code */
8352
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8977
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8353
8978
 
8354
8979
  /* ── Base ── */
8355
8980
  [data-ui="qr-code"] {
@@ -8367,7 +8992,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8367
8992
 
8368
8993
  /* ── Caption ── */
8369
8994
  [data-ui="qr-code"] [data-part="caption"] {
8370
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
8995
+ font-family: var(--doc-font, var(--font-body));
8371
8996
  font-size: var(--doc-legal-size, var(--text-xs));
8372
8997
  color: var(--doc-legal-color, var(--color-fg-muted));
8373
8998
  text-align: center;
@@ -8408,7 +9033,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8408
9033
 
8409
9034
  /* === recipes/select-custom.css === */
8410
9035
  /* @ui:component select-custom */
8411
- /* @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 */
9036
+ /* @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 */
8412
9037
 
8413
9038
  /* ── Root ── */
8414
9039
  [data-ui="select-custom"] {
@@ -8425,11 +9050,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8425
9050
  width: 100%;
8426
9051
  min-width: 180px;
8427
9052
  padding: var(--space-2) var(--space-3);
8428
- border: 1px solid var(--color-border);
9053
+ border: var(--border-width) solid var(--color-border);
8429
9054
  border-radius: var(--radius-md);
8430
9055
  background: var(--color-bg);
8431
9056
  color: var(--color-fg);
8432
- font-family: var(--font-sans, system-ui, sans-serif);
9057
+ font-family: var(--font-ui);
8433
9058
  font-size: var(--text-sm);
8434
9059
  cursor: pointer;
8435
9060
  white-space: nowrap;
@@ -8442,8 +9067,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8442
9067
  }
8443
9068
 
8444
9069
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8445
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8446
- outline-offset: 2px;
9070
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9071
+ outline-offset: var(--focus-ring-offset);
8447
9072
  }
8448
9073
 
8449
9074
  /* ── Value ── */
@@ -8479,7 +9104,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8479
9104
  z-index: var(--z-dropdown);
8480
9105
  margin-top: var(--space-1);
8481
9106
  padding: var(--space-1);
8482
- border: 1px solid var(--color-border);
9107
+ border: var(--border-width) solid var(--color-border);
8483
9108
  border-radius: var(--radius-lg);
8484
9109
  background: var(--color-bg);
8485
9110
  box-shadow: var(--shadow-md);
@@ -8503,11 +9128,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8503
9128
  padding: var(--space-2) var(--space-3);
8504
9129
  margin-bottom: var(--space-1);
8505
9130
  border: none;
8506
- border-bottom: 1px solid var(--color-border);
9131
+ border-bottom: var(--border-width) solid var(--color-border);
8507
9132
  border-radius: 0;
8508
9133
  background: transparent;
8509
9134
  color: var(--color-fg);
8510
- font-family: var(--font-sans, system-ui, sans-serif);
9135
+ font-family: var(--font-ui);
8511
9136
  font-size: var(--text-sm);
8512
9137
  outline: none;
8513
9138
  }
@@ -8601,7 +9226,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8601
9226
 
8602
9227
  /* === recipes/sheet.css === */
8603
9228
  /* @ui:component sheet */
8604
- /* @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 */
9229
+ /* @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 */
8605
9230
 
8606
9231
  /* ── Root ── */
8607
9232
  [data-ui="sheet"] {
@@ -8632,11 +9257,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8632
9257
  z-index: var(--z-modal);
8633
9258
  display: flex;
8634
9259
  flex-direction: column;
8635
- background: var(--color-bg);
9260
+ background: var(--panel-bg);
8636
9261
  box-shadow: var(--shadow-xl);
8637
9262
  transition: transform var(--duration-slow) var(--ease-out);
8638
9263
  }
8639
9264
 
9265
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9266
+ [data-ui="sheet"] [data-part="panel"] {
9267
+ -webkit-backdrop-filter: var(--surface-backdrop);
9268
+ backdrop-filter: var(--surface-backdrop);
9269
+ }
9270
+ }
9271
+
8640
9272
  /* ── Side: Bottom ── */
8641
9273
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8642
9274
  bottom: 0;
@@ -8664,7 +9296,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8664
9296
  bottom: 0;
8665
9297
  max-width: 100vw;
8666
9298
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8667
- border-inline-end: 1px solid var(--color-border);
9299
+ border-inline-end: var(--border-width) solid var(--color-border);
8668
9300
  transform: translateX(-100%);
8669
9301
  }
8670
9302
 
@@ -8675,7 +9307,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8675
9307
  bottom: 0;
8676
9308
  max-width: 100vw;
8677
9309
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8678
- border-inline-start: 1px solid var(--color-border);
9310
+ border-inline-start: var(--border-width) solid var(--color-border);
8679
9311
  transform: translateX(100%);
8680
9312
  }
8681
9313
 
@@ -8752,6 +9384,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8752
9384
  /* ── Title ── */
8753
9385
  [data-ui="sheet"] [data-part="title"] {
8754
9386
  margin: 0;
9387
+ font-family: var(--font-heading);
8755
9388
  font-size: var(--text-lg, 1.125rem);
8756
9389
  font-weight: var(--weight-semibold, 600);
8757
9390
  color: var(--color-fg);
@@ -8786,8 +9419,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8786
9419
  }
8787
9420
 
8788
9421
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8789
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8790
- outline-offset: 2px;
9422
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9423
+ outline-offset: var(--focus-ring-offset);
8791
9424
  }
8792
9425
 
8793
9426
  /* ── Body ── */
@@ -8808,7 +9441,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8808
9441
 
8809
9442
  /* === recipes/sidebar.css === */
8810
9443
  /* @ui:component sidebar */
8811
- /* @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 */
9444
+ /* @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 */
8812
9445
 
8813
9446
  /* ── Root ──
8814
9447
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8852,7 +9485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8852
9485
  flex-direction: column;
8853
9486
  gap: var(--space-2);
8854
9487
  background: var(--sidebar-bg);
8855
- border-inline-end: 1px solid var(--color-border);
9488
+ border-inline-end: var(--border-width) solid var(--color-border);
8856
9489
  border-start-end-radius: var(--radius-lg, 0.5rem);
8857
9490
  border-end-end-radius: var(--radius-lg, 0.5rem);
8858
9491
  box-shadow: var(--shadow-xl);
@@ -8933,8 +9566,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8933
9566
  }
8934
9567
 
8935
9568
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8936
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8937
- outline-offset: 2px;
9569
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9570
+ outline-offset: var(--focus-ring-offset);
8938
9571
  }
8939
9572
 
8940
9573
  /* ── Navigation ── */
@@ -8970,8 +9603,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8970
9603
  }
8971
9604
 
8972
9605
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
8973
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8974
- outline-offset: -2px;
9606
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9607
+ outline-offset: calc(-1 * var(--focus-ring-offset));
8975
9608
  }
8976
9609
 
8977
9610
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -8998,7 +9631,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8998
9631
  [data-ui="sidebar"] [data-part="footer"] {
8999
9632
  flex-shrink: 0;
9000
9633
  padding: var(--space-3) var(--space-4);
9001
- border-block-start: 1px solid var(--color-border);
9634
+ border-block-start: var(--border-width) solid var(--color-border);
9002
9635
  }
9003
9636
 
9004
9637
  /* ── Rail (icons only) ── */
@@ -9091,7 +9724,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9091
9724
 
9092
9725
  /* === recipes/slider.css === */
9093
9726
  /* @ui:component slider */
9094
- /* @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 */
9727
+ /* @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 */
9095
9728
 
9096
9729
  /* ── Root ── */
9097
9730
  [data-ui="slider"] {
@@ -9141,28 +9774,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9141
9774
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9142
9775
  transform: translate(-50%, -50%);
9143
9776
  background: var(--color-bg, white);
9144
- border: 2px solid var(--color-primary);
9777
+ border: var(--border-width-strong) solid var(--color-primary);
9145
9778
  border-radius: var(--radius-full, 9999px);
9146
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9779
+ box-shadow: var(--shadow-sm);
9147
9780
  cursor: grab;
9148
9781
  touch-action: none;
9149
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9782
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9150
9783
  }
9151
9784
 
9152
9785
  [data-ui="slider"] [data-part="thumb"]:hover {
9153
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9154
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9786
+ box-shadow: var(--shadow-sm),
9787
+ 0 0 0 4px var(--color-primary-subtle);
9155
9788
  }
9156
9789
 
9157
9790
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9158
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9159
- outline-offset: 2px;
9791
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9792
+ outline-offset: var(--focus-ring-offset);
9160
9793
  }
9161
9794
 
9162
9795
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9163
9796
  cursor: grabbing;
9164
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9165
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9797
+ box-shadow: var(--shadow-sm),
9798
+ 0 0 0 5px var(--color-primary-subtle);
9166
9799
  }
9167
9800
 
9168
9801
  /* ── Value output ── */
@@ -9170,7 +9803,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9170
9803
  flex: 0 0 auto;
9171
9804
  min-inline-size: 3ch;
9172
9805
  color: var(--color-fg-muted);
9173
- font-family: var(--font-sans, system-ui, sans-serif);
9806
+ font-family: var(--font-ui);
9174
9807
  font-size: var(--text-sm);
9175
9808
  font-variant-numeric: tabular-nums;
9176
9809
  text-align: end;
@@ -9189,7 +9822,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9189
9822
 
9190
9823
  /* ── Disabled ── */
9191
9824
  [data-ui="slider"][data-disabled] {
9192
- opacity: 0.5;
9825
+ opacity: var(--disabled-opacity);
9193
9826
  cursor: not-allowed;
9194
9827
  pointer-events: none;
9195
9828
  }
@@ -9207,7 +9840,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9207
9840
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9208
9841
  @media (forced-colors: active) {
9209
9842
  [data-ui="slider"] [data-part="track"] {
9210
- border: 1px solid ButtonText;
9843
+ border: var(--border-width) solid ButtonText;
9211
9844
  }
9212
9845
 
9213
9846
  [data-ui="slider"] [data-part="range"] {
@@ -9218,7 +9851,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9218
9851
  [data-ui="slider"] [data-part="thumb"] {
9219
9852
  forced-color-adjust: none;
9220
9853
  background: ButtonText;
9221
- border: 1px solid ButtonFace;
9854
+ border: var(--border-width) solid ButtonFace;
9222
9855
  }
9223
9856
 
9224
9857
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9228,7 +9861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9228
9861
 
9229
9862
  /* === recipes/table.css === */
9230
9863
  /* @ui:component table */
9231
- /* @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 */
9864
+ /* @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 */
9232
9865
 
9233
9866
  /* ── Root ── */
9234
9867
  [data-ui="table"] {
@@ -9254,7 +9887,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9254
9887
  width: 100%;
9255
9888
  border-collapse: separate;
9256
9889
  border-spacing: 0;
9257
- font-family: var(--font-sans, system-ui, sans-serif);
9890
+ font-family: var(--font-body);
9258
9891
  }
9259
9892
 
9260
9893
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9276,7 +9909,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9276
9909
  font-weight: var(--weight-semibold);
9277
9910
  color: var(--color-fg-muted);
9278
9911
  background: var(--color-bg);
9279
- border-bottom: 2px solid var(--color-border);
9912
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9280
9913
  white-space: nowrap;
9281
9914
  user-select: none;
9282
9915
  }
@@ -9334,8 +9967,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9334
9967
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9335
9968
  [data-ui="table"] [data-part="th"]:focus-visible,
9336
9969
  [data-ui="table"] [data-part="td"]:focus-visible {
9337
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9338
- outline-offset: -2px;
9970
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9971
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9339
9972
  }
9340
9973
 
9341
9974
  /* ── Data Cell ── */
@@ -9343,7 +9976,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9343
9976
  padding: var(--space-3) var(--space-4);
9344
9977
  font-size: var(--text-sm);
9345
9978
  color: var(--color-fg);
9346
- border-bottom: 1px solid var(--color-border);
9979
+ border-bottom: var(--border-width) solid var(--color-border);
9347
9980
  background: var(--color-bg);
9348
9981
  transition: background var(--duration-fast) var(--ease-default);
9349
9982
  }
@@ -9372,31 +10005,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9372
10005
  Static fallback via nth-child; once the controller stamps data-stripe on the
9373
10006
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9374
10007
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9375
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10008
+ background: var(--stripe-bg);
9376
10009
  }
9377
10010
 
9378
10011
  [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"] {
9379
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10012
+ background: var(--stripe-bg);
9380
10013
  }
9381
10014
 
9382
10015
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9383
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10016
+ background: var(--stripe-bg);
9384
10017
  }
9385
10018
 
9386
10019
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9387
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10020
+ background: var(--stripe-bg);
9388
10021
  }
9389
10022
 
9390
10023
  /* ── Bordered Variant ── */
9391
10024
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9392
- border: 1px solid var(--color-border);
10025
+ border: var(--border-width) solid var(--color-border);
9393
10026
  border-radius: var(--radius-md, 0.375rem);
9394
10027
  overflow: hidden;
9395
10028
  }
9396
10029
 
9397
10030
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9398
10031
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9399
- border: 1px solid var(--color-border);
10032
+ border: var(--border-width) solid var(--color-border);
9400
10033
  }
9401
10034
 
9402
10035
  /* ── Size: Small ── */
@@ -9424,7 +10057,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9424
10057
  /* ── Footer ── */
9425
10058
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9426
10059
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9427
- border-top: 2px solid var(--color-border);
10060
+ border-top: var(--border-width-strong) solid var(--color-border);
9428
10061
  border-bottom: none;
9429
10062
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9430
10063
  }
@@ -9550,7 +10183,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9550
10183
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9551
10184
  padding: var(--space-1) var(--space-2);
9552
10185
  background: var(--color-bg);
9553
- border-bottom: 1px solid var(--color-border);
10186
+ border-bottom: var(--border-width) solid var(--color-border);
9554
10187
  }
9555
10188
 
9556
10189
  [data-ui="table"] [data-part="filter-input"],
@@ -9562,14 +10195,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9562
10195
  font-size: var(--text-xs);
9563
10196
  color: var(--color-fg);
9564
10197
  background: var(--color-bg);
9565
- border: 1px solid var(--color-border);
10198
+ border: var(--border-width) solid var(--color-border);
9566
10199
  border-radius: var(--radius-sm);
9567
10200
  }
9568
10201
 
9569
10202
  [data-ui="table"] [data-part="filter-input"]:focus,
9570
10203
  [data-ui="table"] [data-part="filter"]:focus {
9571
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9572
- outline-offset: -1px;
10204
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10205
+ outline-offset: calc(-1 * var(--border-width));
9573
10206
  border-color: var(--color-primary);
9574
10207
  }
9575
10208
 
@@ -9590,7 +10223,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9590
10223
  text-align: inherit;
9591
10224
  color: var(--color-fg);
9592
10225
  background: var(--color-bg);
9593
- border: 1px solid var(--color-primary);
10226
+ border: var(--border-width) solid var(--color-primary);
9594
10227
  border-radius: var(--radius-sm);
9595
10228
  outline: none;
9596
10229
  }
@@ -9643,11 +10276,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9643
10276
  }
9644
10277
 
9645
10278
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9646
- border-block-start: 2px solid var(--color-primary);
10279
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9647
10280
  }
9648
10281
 
9649
10282
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9650
- border-block-end: 2px solid var(--color-primary);
10283
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9651
10284
  }
9652
10285
 
9653
10286
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9655,11 +10288,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9655
10288
  }
9656
10289
 
9657
10290
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9658
- border-inline-start: 2px solid var(--color-primary);
10291
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9659
10292
  }
9660
10293
 
9661
10294
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9662
- border-inline-end: 2px solid var(--color-primary);
10295
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9663
10296
  }
9664
10297
 
9665
10298
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9732,11 +10365,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9732
10365
  }
9733
10366
 
9734
10367
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9735
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10368
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9736
10369
  }
9737
10370
 
9738
10371
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9739
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10372
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9740
10373
  }
9741
10374
 
9742
10375
  /* ── Column Visibility ── */
@@ -9808,7 +10441,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9808
10441
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9809
10442
  display: block;
9810
10443
  margin-block-end: var(--space-3);
9811
- border: 1px solid var(--color-border);
10444
+ border: var(--border-width) solid var(--color-border);
9812
10445
  border-radius: var(--radius-md);
9813
10446
  background: var(--color-bg);
9814
10447
  overflow: hidden;
@@ -9822,7 +10455,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9822
10455
  gap: var(--space-4);
9823
10456
  text-align: end;
9824
10457
  border-bottom: none;
9825
- border-block-end: 1px solid var(--color-border);
10458
+ border-block-end: var(--border-width) solid var(--color-border);
9826
10459
  }
9827
10460
 
9828
10461
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9919,7 +10552,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9919
10552
 
9920
10553
  /* === recipes/tabs.css === */
9921
10554
  /* @ui:component tabs */
9922
- /* @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 */
10555
+ /* @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 */
9923
10556
 
9924
10557
  /* ── Root ── */
9925
10558
  [data-ui="tabs"] {
@@ -9948,7 +10581,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9948
10581
  border: none;
9949
10582
  background: transparent;
9950
10583
  color: var(--color-fg-muted);
9951
- font-family: var(--font-sans, system-ui, sans-serif);
10584
+ font-family: var(--font-ui);
9952
10585
  font-size: var(--text-sm);
9953
10586
  font-weight: var(--weight-medium);
9954
10587
  cursor: pointer;
@@ -9963,8 +10596,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9963
10596
  }
9964
10597
 
9965
10598
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9966
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9967
- outline-offset: -2px;
10599
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10600
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9968
10601
  border-radius: var(--radius-md);
9969
10602
  }
9970
10603
 
@@ -9974,12 +10607,12 @@ div[data-ui="separator"][data-style="thick"]::after {
9974
10607
 
9975
10608
  /* ── Underline Variant ── */
9976
10609
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
9977
- border-bottom: 1px solid var(--color-border);
10610
+ border-bottom: var(--border-width) solid var(--color-border);
9978
10611
  gap: 0;
9979
10612
  }
9980
10613
 
9981
10614
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
9982
- border-bottom: 2px solid transparent;
10615
+ border-bottom: var(--border-width-strong) solid transparent;
9983
10616
  margin-bottom: -1px;
9984
10617
  border-radius: 0;
9985
10618
  }
@@ -10011,17 +10644,17 @@ div[data-ui="separator"][data-style="thick"]::after {
10011
10644
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
10012
10645
  background: var(--color-bg);
10013
10646
  color: var(--color-fg);
10014
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10647
+ box-shadow: var(--shadow-xs);
10015
10648
  }
10016
10649
 
10017
10650
  /* ── Enclosed Variant ── */
10018
10651
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
10019
- border-bottom: 1px solid var(--color-border);
10652
+ border-bottom: var(--border-width) solid var(--color-border);
10020
10653
  gap: 0;
10021
10654
  }
10022
10655
 
10023
10656
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10024
- border: 1px solid transparent;
10657
+ border: var(--border-width) solid transparent;
10025
10658
  border-bottom: none;
10026
10659
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10027
10660
  margin-bottom: -1px;
@@ -10066,8 +10699,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10066
10699
  @media (forced-colors: active) {
10067
10700
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10068
10701
  /* An outline the OS preserves, on every variant. */
10069
- outline: 2px solid Highlight;
10070
- outline-offset: -2px;
10702
+ outline: var(--border-width-strong) solid Highlight;
10703
+ outline-offset: calc(-1 * var(--border-width-strong));
10071
10704
  }
10072
10705
 
10073
10706
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10082,7 +10715,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10082
10715
 
10083
10716
  /* === recipes/tag-input.css === */
10084
10717
  /* @ui:component tag-input */
10085
- /* @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 */
10718
+ /* @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 */
10086
10719
 
10087
10720
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10088
10721
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10103,7 +10736,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10103
10736
  gap: var(--space-1h);
10104
10737
  width: 100%;
10105
10738
  padding: var(--space-1h) var(--space-2);
10106
- border: 1px solid var(--color-border);
10739
+ border: var(--border-width) solid var(--color-border);
10107
10740
  border-radius: var(--radius-md);
10108
10741
  background: var(--color-bg);
10109
10742
  list-style: none;
@@ -10112,8 +10745,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10112
10745
  }
10113
10746
 
10114
10747
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10115
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10116
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10748
+ border-color: var(--focus-ring-color);
10749
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10117
10750
  }
10118
10751
 
10119
10752
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10124,7 +10757,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10124
10757
  border: none;
10125
10758
  background: transparent;
10126
10759
  color: var(--color-fg);
10127
- font-family: var(--font-sans, system-ui, sans-serif);
10760
+ font-family: var(--font-ui);
10128
10761
  font-size: var(--text-sm);
10129
10762
  line-height: 1.5;
10130
10763
  outline: none;
@@ -10143,7 +10776,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10143
10776
  z-index: var(--z-dropdown);
10144
10777
  margin-top: var(--space-1);
10145
10778
  padding: var(--space-1);
10146
- border: 1px solid var(--color-border);
10779
+ border: var(--border-width) solid var(--color-border);
10147
10780
  border-radius: var(--radius-lg);
10148
10781
  background: var(--color-bg);
10149
10782
  box-shadow: var(--shadow-md);
@@ -10190,7 +10823,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10190
10823
 
10191
10824
  /* === recipes/toast.css === */
10192
10825
  /* @ui:component toast */
10193
- /* @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 */
10826
+ /* @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 */
10194
10827
 
10195
10828
  /* ── Container ── */
10196
10829
  [data-ui="toast"][data-part="container"] {
@@ -10239,8 +10872,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10239
10872
  max-width: 380px;
10240
10873
  width: max-content;
10241
10874
  padding: var(--space-3) var(--space-4);
10242
- background: var(--color-bg);
10243
- border: 1px solid var(--color-border);
10875
+ background: var(--panel-bg);
10876
+ border: var(--border-width) solid var(--color-border);
10244
10877
  border-radius: var(--radius-lg);
10245
10878
  box-shadow: var(--shadow-lg);
10246
10879
  pointer-events: auto;
@@ -10250,6 +10883,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10250
10883
  transform var(--duration-normal) var(--ease-out);
10251
10884
  }
10252
10885
 
10886
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10887
+ [data-ui="toast"] [data-part="toast"] {
10888
+ -webkit-backdrop-filter: var(--surface-backdrop);
10889
+ backdrop-filter: var(--surface-backdrop);
10890
+ }
10891
+ }
10892
+
10253
10893
  /* ── State: Entering ── */
10254
10894
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10255
10895
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10289,7 +10929,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10289
10929
 
10290
10930
  /* ── Tone Variants ── */
10291
10931
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10292
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10932
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10293
10933
  }
10294
10934
 
10295
10935
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10297,7 +10937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10297
10937
  }
10298
10938
 
10299
10939
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10300
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10940
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10301
10941
  }
10302
10942
 
10303
10943
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10305,7 +10945,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10305
10945
  }
10306
10946
 
10307
10947
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10308
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10948
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10309
10949
  }
10310
10950
 
10311
10951
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10327,7 +10967,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10327
10967
  /* ── Message ── */
10328
10968
  [data-ui="toast"] [data-part="message"] {
10329
10969
  flex: 1;
10330
- font-family: var(--font-sans, system-ui, sans-serif);
10970
+ font-family: var(--font-ui);
10331
10971
  font-size: var(--text-sm);
10332
10972
  font-weight: var(--weight-medium);
10333
10973
  color: var(--color-fg);
@@ -10338,11 +10978,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10338
10978
  [data-ui="toast"] [data-part="action"] {
10339
10979
  flex-shrink: 0;
10340
10980
  padding: var(--space-1, 0.25rem) var(--space-2);
10341
- border: 1px solid var(--color-border);
10981
+ border: var(--border-width) solid var(--color-border);
10342
10982
  border-radius: var(--radius-md, 0.375rem);
10343
10983
  background: transparent;
10344
10984
  color: var(--color-fg);
10345
- font-family: var(--font-sans, system-ui, sans-serif);
10985
+ font-family: var(--font-ui);
10346
10986
  font-size: var(--text-xs, 0.75rem);
10347
10987
  font-weight: var(--weight-medium);
10348
10988
  cursor: pointer;
@@ -10355,8 +10995,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10355
10995
  }
10356
10996
 
10357
10997
  [data-ui="toast"] [data-part="action"]:focus-visible {
10358
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10359
- outline-offset: 2px;
10998
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10999
+ outline-offset: var(--focus-ring-offset);
10360
11000
  }
10361
11001
 
10362
11002
  /* ── Close Button ── */
@@ -10382,8 +11022,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10382
11022
  }
10383
11023
 
10384
11024
  [data-ui="toast"] [data-part="close"]:focus-visible {
10385
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10386
- outline-offset: 2px;
11025
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11026
+ outline-offset: var(--focus-ring-offset);
10387
11027
  }
10388
11028
 
10389
11029
  /* ── Motion ── */
@@ -10396,14 +11036,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10396
11036
 
10397
11037
  /* === recipes/toggle-group.css === */
10398
11038
  /* @ui:component toggle-group */
10399
- /* @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 */
11039
+ /* @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 */
10400
11040
 
10401
11041
  /* ── Root: a segmented row of toggle buttons ── */
10402
11042
  [data-ui="toggle-group"] {
10403
11043
  display: inline-flex;
10404
11044
  gap: var(--space-1);
10405
11045
  padding: var(--space-1);
10406
- border: 1px solid var(--color-border);
11046
+ border: var(--border-width) solid var(--color-border);
10407
11047
  border-radius: var(--radius-md);
10408
11048
  background: var(--color-bg);
10409
11049
  }
@@ -10418,7 +11058,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10418
11058
  border-radius: var(--radius-md);
10419
11059
  background: transparent;
10420
11060
  color: var(--color-fg-muted);
10421
- font-family: var(--toggle-group-font, var(--font-sans));
11061
+ font-family: var(--toggle-group-font, var(--font-ui));
10422
11062
  font-size: var(--text-sm);
10423
11063
  font-weight: var(--weight-medium);
10424
11064
  line-height: 1;
@@ -10459,13 +11099,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10459
11099
 
10460
11100
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10461
11101
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10462
- outline: 2px solid var(--color-ring);
10463
- outline-offset: 2px;
11102
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11103
+ outline-offset: var(--focus-ring-offset);
10464
11104
  }
10465
11105
 
10466
11106
  /* ── Disabled control ── */
10467
11107
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10468
- opacity: 0.5;
11108
+ opacity: var(--disabled-opacity);
10469
11109
  cursor: not-allowed;
10470
11110
  }
10471
11111
 
@@ -10478,7 +11118,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10478
11118
 
10479
11119
  /* === recipes/tooltip.css === */
10480
11120
  /* @ui:component tooltip */
10481
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11121
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10482
11122
 
10483
11123
  /* ── Root ── */
10484
11124
  [data-ui="tooltip"] {
@@ -10499,7 +11139,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10499
11139
  color: var(--color-bg);
10500
11140
  border-radius: var(--radius-md);
10501
11141
  padding: var(--space-1h, 0.375rem) var(--space-2);
10502
- font-family: var(--font-sans, system-ui, sans-serif);
11142
+ font-family: var(--font-ui);
10503
11143
  font-size: var(--text-xs, 0.75rem);
10504
11144
  line-height: 1.4;
10505
11145
  white-space: nowrap;
@@ -10510,6 +11150,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10510
11150
  transform var(--duration-fast) var(--ease-default);
10511
11151
  }
10512
11152
 
11153
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11154
+ [data-ui="tooltip"] [data-part="content"] {
11155
+ -webkit-backdrop-filter: var(--surface-backdrop);
11156
+ backdrop-filter: var(--surface-backdrop);
11157
+ }
11158
+ }
11159
+
10513
11160
  /* Default position (top) when no variant is specified */
10514
11161
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10515
11162
  bottom: 100%;
@@ -10625,7 +11272,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10625
11272
 
10626
11273
  /* === recipes/tree-view.css === */
10627
11274
  /* @ui:component tree-view */
10628
- /* @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 */
11275
+ /* @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 */
10629
11276
 
10630
11277
  [data-ui="tree-view"],
10631
11278
  [data-ui="tree-view"] [data-part="group"] {
@@ -10638,7 +11285,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10638
11285
  inline-size: 100%;
10639
11286
  padding: var(--space-1);
10640
11287
  color: var(--color-fg);
10641
- font-family: var(--font-sans);
11288
+ font-family: var(--font-ui);
10642
11289
  font-size: var(--text-sm);
10643
11290
  }
10644
11291
 
@@ -10666,8 +11313,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10666
11313
  }
10667
11314
 
10668
11315
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10669
- outline: var(--space-px) solid var(--color-ring);
10670
- outline-offset: var(--space-px);
11316
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11317
+ outline-offset: var(--focus-ring-offset);
10671
11318
  }
10672
11319
 
10673
11320
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10706,7 +11353,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10706
11353
 
10707
11354
  /* === patterns/auth-form.css === */
10708
11355
  /* @ui:component auth-form */
10709
- /* @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 */
11356
+ /* @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 */
10710
11357
 
10711
11358
  /* ── Root Container ── */
10712
11359
  [data-ui="auth-form"] {
@@ -10714,7 +11361,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10714
11361
  align-items: center;
10715
11362
  justify-content: center;
10716
11363
  width: 100%;
10717
- font-family: var(--font-sans);
11364
+ font-family: var(--font-body);
10718
11365
  }
10719
11366
 
10720
11367
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10746,9 +11393,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10746
11393
 
10747
11394
  [data-ui="auth-form"] [data-part="title"] {
10748
11395
  margin: 0;
11396
+ font-family: var(--font-heading);
10749
11397
  font-size: var(--text-xl);
10750
- font-weight: var(--weight-bold);
10751
- line-height: var(--leading-tight);
11398
+ font-weight: var(--heading-weight);
11399
+ letter-spacing: var(--heading-tracking);
11400
+ text-transform: var(--heading-transform);
11401
+ font-variant-caps: var(--heading-caps);
11402
+ line-height: var(--heading-leading);
10752
11403
  color: var(--color-fg);
10753
11404
  }
10754
11405
 
@@ -10765,7 +11416,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10765
11416
  margin: var(--space-4) var(--space-6) 0;
10766
11417
  padding: var(--space-3);
10767
11418
  background: var(--color-destructive-subtle);
10768
- border: 1px solid var(--color-destructive);
11419
+ border: var(--border-width) solid var(--color-destructive);
10769
11420
  border-radius: var(--radius-lg);
10770
11421
  color: var(--color-destructive);
10771
11422
  font-size: var(--text-sm);
@@ -10843,13 +11494,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10843
11494
  }
10844
11495
 
10845
11496
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10846
- text-decoration: underline;
11497
+ text-decoration-line: var(--link-decoration);
10847
11498
  color: var(--color-primary-hover);
10848
11499
  }
10849
11500
 
10850
11501
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10851
- outline: 2px solid var(--color-ring);
10852
- outline-offset: 2px;
11502
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11503
+ outline-offset: var(--focus-ring-offset);
10853
11504
  border-radius: var(--radius-sm, 0.25rem);
10854
11505
  }
10855
11506
 
@@ -10977,8 +11628,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10977
11628
  max-width: var(--auth-form-max-width, 400px);
10978
11629
  border-radius: var(--card-radius, var(--radius-lg));
10979
11630
  box-shadow: var(--card-shadow, var(--shadow-sm));
10980
- border-inline-start: 1px solid var(--card-border, var(--color-border));
10981
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11631
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11632
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
10982
11633
  }
10983
11634
  }
10984
11635
 
@@ -10993,7 +11644,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10993
11644
 
10994
11645
  /* === patterns/crud-table.css === */
10995
11646
  /* @ui:component crud-table */
10996
- /* @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 */
11647
+ /* @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 */
10997
11648
 
10998
11649
  /* ── Root ── */
10999
11650
  [data-ui="crud-table"] {
@@ -11001,7 +11652,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11001
11652
  flex-direction: column;
11002
11653
  gap: var(--space-4);
11003
11654
  width: 100%;
11004
- font-family: var(--font-sans, system-ui, sans-serif);
11655
+ font-family: var(--font-body);
11005
11656
  }
11006
11657
 
11007
11658
  /* ── Toolbar ── */
@@ -11059,7 +11710,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11059
11710
  gap: var(--space-3);
11060
11711
  padding: var(--space-3) var(--space-4);
11061
11712
  background: var(--color-bg-subtle);
11062
- border: 1px solid var(--color-border);
11713
+ border: var(--border-width) solid var(--color-border);
11063
11714
  border-radius: var(--radius-md);
11064
11715
  }
11065
11716
 
@@ -11074,7 +11725,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11074
11725
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11075
11726
  width: 100%;
11076
11727
  overflow-x: auto;
11077
- border: 1px solid var(--color-border);
11728
+ border: var(--border-width) solid var(--color-border);
11078
11729
  border-radius: var(--radius-lg);
11079
11730
  background: var(--color-bg);
11080
11731
  }
@@ -11104,7 +11755,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11104
11755
  padding: var(--space-8) var(--space-4);
11105
11756
  text-align: center;
11106
11757
  min-height: 240px;
11107
- border: 1px dashed var(--color-border);
11758
+ border: var(--border-width) dashed var(--color-border);
11108
11759
  border-radius: var(--radius-lg);
11109
11760
  background: var(--color-bg);
11110
11761
  }
@@ -11217,7 +11868,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11217
11868
 
11218
11869
  /* === patterns/dashboard-shell.css === */
11219
11870
  /* @ui:component dashboard-shell */
11220
- /* @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 */
11871
+ /* @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 */
11221
11872
 
11222
11873
  /* ── Shell Grid Layout ──
11223
11874
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11242,7 +11893,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11242
11893
  "footer";
11243
11894
  min-height: 100vh;
11244
11895
  background: var(--color-bg);
11245
- font-family: var(--font-sans);
11896
+ font-family: var(--font-body);
11246
11897
  color: var(--color-fg);
11247
11898
  }
11248
11899
 
@@ -11266,7 +11917,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11266
11917
  gap: var(--space-2);
11267
11918
  padding: var(--space-4);
11268
11919
  background: var(--color-bg-subtle);
11269
- border-inline-end: 1px solid var(--color-border);
11920
+ border-inline-end: var(--border-width) solid var(--color-border);
11270
11921
  overflow-y: auto;
11271
11922
  position: fixed;
11272
11923
  top: 0;
@@ -11286,7 +11937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11286
11937
 
11287
11938
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11288
11939
  border-inline-end: none;
11289
- border-inline-start: 1px solid var(--color-border);
11940
+ border-inline-start: var(--border-width) solid var(--color-border);
11290
11941
  inset-inline-start: auto;
11291
11942
  inset-inline-end: 0;
11292
11943
  transform: translateX(100%);
@@ -11361,7 +12012,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11361
12012
  gap: var(--space-3);
11362
12013
  padding: var(--space-2) var(--space-3);
11363
12014
  border-radius: var(--radius-md);
11364
- font-family: var(--font-sans);
12015
+ font-family: var(--font-ui);
11365
12016
  font-size: var(--text-sm);
11366
12017
  font-weight: var(--weight-medium);
11367
12018
  line-height: var(--leading-normal);
@@ -11380,8 +12031,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11380
12031
  }
11381
12032
 
11382
12033
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11383
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11384
- outline-offset: -2px;
12034
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12035
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11385
12036
  }
11386
12037
 
11387
12038
  /* ── Nav Item Active ── */
@@ -11428,7 +12079,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11428
12079
  gap: var(--space-2);
11429
12080
  padding: 0 var(--space-3);
11430
12081
  background: var(--color-bg);
11431
- border-bottom: 1px solid var(--color-border);
12082
+ border-bottom: var(--border-width) solid var(--color-border);
11432
12083
  position: sticky;
11433
12084
  top: 0;
11434
12085
  z-index: var(--z-sticky);
@@ -11509,7 +12160,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11509
12160
  align-items: center;
11510
12161
  gap: var(--space-3);
11511
12162
  padding: var(--space-4) var(--space-6);
11512
- border-top: 1px solid var(--color-border);
12163
+ border-top: var(--border-width) solid var(--color-border);
11513
12164
  font-size: var(--text-xs);
11514
12165
  color: var(--color-fg-muted);
11515
12166
  }
@@ -11592,7 +12243,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11592
12243
 
11593
12244
  /* === patterns/document.css === */
11594
12245
  /* @ui:component document */
11595
- /* @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 */
12246
+ /* @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 */
11596
12247
 
11597
12248
  /* ── Page Rules ── */
11598
12249
  @page {
@@ -11632,14 +12283,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11632
12283
  max-width: var(--doc-max-width);
11633
12284
  margin: var(--space-4) auto;
11634
12285
  padding: var(--space-6) var(--space-4);
11635
- background: var(--color-bg, #fff);
12286
+ background-color: var(--color-bg, #fff);
12287
+ background-image: var(--texture-page);
11636
12288
  color: var(--color-fg);
11637
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12289
+ font-family: var(--doc-font, var(--font-body));
11638
12290
  font-size: var(--doc-font-size);
11639
12291
  line-height: var(--doc-line-height);
11640
- box-shadow: var(--shadow-lg,
11641
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11642
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12292
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12293
+ colour no theme could reach. --shadow-lg is always defined by the token
12294
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12295
+ than re-tokenised. */
12296
+ box-shadow: var(--shadow-lg);
11643
12297
  border-radius: 0;
11644
12298
  position: relative;
11645
12299
  }
@@ -11655,7 +12309,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11655
12309
  [data-ui="document"] > [data-part="header"] {
11656
12310
  margin-block-end: var(--doc-section-gap);
11657
12311
  padding-block-end: var(--doc-component-gap);
11658
- border-block-end: 1px solid var(--color-border);
12312
+ border-block-end: var(--border-width) solid var(--color-border);
11659
12313
  }
11660
12314
 
11661
12315
  /* ── Body ── */
@@ -11665,13 +12319,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11665
12319
  gap: var(--doc-section-gap);
11666
12320
  }
11667
12321
 
12322
+ /* ── Headings ──
12323
+ The document's own heading face and weight (1.1A-21): a print theme sets
12324
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12325
+ from the body copy (document-serif's Times titles over Georgia text). Both
12326
+ default to the page's heading role in tokens/document.css, and each falls
12327
+ back to what a heading rendered before the tokens had a reader. A heading
12328
+ that carries its own data-weight keeps it — that is the author asking. */
12329
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12330
+ font-family: var(--doc-heading-font, var(--font-body));
12331
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12332
+ }
12333
+
11668
12334
  /* ── Running footer ──
11669
12335
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11670
12336
  [data-ui="document"] > [data-part="doc-footer"],
11671
12337
  [data-ui="document"] > [data-part="footer"] {
11672
12338
  margin-block-start: var(--doc-section-gap);
11673
12339
  padding-block-start: var(--doc-component-gap);
11674
- border-block-start: 1px solid var(--color-border);
12340
+ border-block-start: var(--border-width) solid var(--color-border);
11675
12341
  font-size: var(--doc-legal-size);
11676
12342
  color: var(--doc-legal-color);
11677
12343
  }
@@ -11709,7 +12375,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11709
12375
 
11710
12376
  /* ── Variant: Report ── */
11711
12377
  [data-ui="document"][data-variant="report"] {
11712
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12378
+ /* A report is serif-set by definition. It re-points the document's own font
12379
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12380
+ (key-value, callout, signature — all of which read --doc-font) follows the
12381
+ report into serif instead of staying sans inside a serif page. `report` is
12382
+ the author asking for serif; a theme that wants its own document face
12383
+ declares --doc-font at :root, which this variant deliberately outranks. */
12384
+ --doc-font: Georgia, 'Times New Roman', serif;
11713
12385
  line-height: 1.6;
11714
12386
  }
11715
12387
 
@@ -11804,7 +12476,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11804
12476
  z-index: var(--z-raised);
11805
12477
  margin-block-end: 0;
11806
12478
  padding-block-end: var(--doc-running-gap);
11807
- border-block-end: 1px solid var(--doc-print-border-color);
12479
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11808
12480
  background: var(--doc-bg);
11809
12481
  transform: translateZ(0);
11810
12482
  }
@@ -11820,7 +12492,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11820
12492
  z-index: var(--z-raised);
11821
12493
  margin-block-start: 0;
11822
12494
  padding-block-start: var(--doc-running-gap);
11823
- border-block-start: 1px solid var(--doc-print-border-color);
12495
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11824
12496
  background: var(--doc-bg);
11825
12497
  transform: translateZ(0);
11826
12498
  }
@@ -11849,7 +12521,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11849
12521
 
11850
12522
  /* === patterns/empty-state.css === */
11851
12523
  /* @ui:component empty-state */
11852
- /* @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 */
12524
+ /* @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 */
11853
12525
 
11854
12526
  /* ── Root ── */
11855
12527
  [data-ui="empty-state"] {
@@ -11860,7 +12532,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11860
12532
  text-align: center;
11861
12533
  padding: var(--space-8) var(--space-6);
11862
12534
  gap: var(--space-3);
11863
- font-family: var(--font-sans, system-ui, sans-serif);
12535
+ font-family: var(--font-body);
11864
12536
  }
11865
12537
 
11866
12538
  /* ── Icon ── */
@@ -11883,10 +12555,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11883
12555
 
11884
12556
  /* ── Title ── */
11885
12557
  [data-ui="empty-state"] [data-part="title"] {
11886
- font-family: var(--font-sans, system-ui, sans-serif);
12558
+ font-family: var(--font-heading);
11887
12559
  font-size: var(--text-lg);
11888
12560
  font-weight: var(--weight-semibold);
11889
- line-height: var(--leading-tight);
12561
+ letter-spacing: var(--heading-tracking);
12562
+ text-transform: var(--heading-transform);
12563
+ font-variant-caps: var(--heading-caps);
12564
+ line-height: var(--heading-leading);
11890
12565
  color: var(--color-fg);
11891
12566
  margin: 0;
11892
12567
  }
@@ -11984,7 +12659,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11984
12659
 
11985
12660
  /* === patterns/feature-grid.css === */
11986
12661
  /* @ui:component feature-grid */
11987
- /* @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 */
12662
+ /* @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 */
11988
12663
 
11989
12664
  /* ── Root ──
11990
12665
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -11994,7 +12669,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11994
12669
  gap: var(--space-4);
11995
12670
  padding-block: var(--space-12);
11996
12671
  padding-inline: var(--space-4);
11997
- font-family: var(--font-sans, system-ui, sans-serif);
12672
+ font-family: var(--font-body);
11998
12673
  color: var(--color-fg);
11999
12674
  background: var(--color-bg);
12000
12675
  }
@@ -12136,7 +12811,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12136
12811
  max-inline-size: var(--measure-narrow);
12137
12812
  margin-inline: auto;
12138
12813
  padding-block: var(--space-8);
12139
- font-family: var(--font-sans);
12814
+ font-family: var(--font-body);
12140
12815
  }
12141
12816
 
12142
12817
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12156,7 +12831,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12156
12831
 
12157
12832
  /* === patterns/hero.css === */
12158
12833
  /* @ui:component hero */
12159
- /* @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 */
12834
+ /* @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 */
12160
12835
 
12161
12836
  /* ── Root ──
12162
12837
  A one-column grid by default; the layout variants only change how that grid
@@ -12170,9 +12845,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12170
12845
  gap: var(--space-4);
12171
12846
  padding-block: var(--space-12);
12172
12847
  padding-inline: var(--space-4);
12173
- font-family: var(--font-sans, system-ui, sans-serif);
12848
+ font-family: var(--font-body);
12174
12849
  color: var(--color-fg);
12175
- background: var(--color-bg);
12850
+ background-color: var(--color-bg);
12851
+ background-image: var(--texture-surface);
12176
12852
  }
12177
12853
 
12178
12854
  /* ── Eyebrow ── */
@@ -12184,9 +12860,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12184
12860
  /* ── Headline ── */
12185
12861
  [data-ui="hero"] [data-part="headline"] {
12186
12862
  margin: 0;
12863
+ font-family: var(--font-heading);
12187
12864
  font-size: var(--text-3xl);
12188
- font-weight: var(--weight-bold);
12189
- line-height: var(--leading-tight);
12865
+ font-weight: var(--heading-weight);
12866
+ letter-spacing: var(--heading-tracking);
12867
+ text-transform: var(--heading-transform);
12868
+ font-variant-caps: var(--heading-caps);
12869
+ line-height: var(--heading-leading);
12190
12870
  color: var(--color-fg);
12191
12871
  text-wrap: balance;
12192
12872
  }
@@ -12305,7 +12985,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12305
12985
 
12306
12986
  /* === patterns/inbox.css === */
12307
12987
  /* @ui:component inbox */
12308
- /* @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 */
12988
+ /* @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 */
12309
12989
 
12310
12990
  /* ── Root ──
12311
12991
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12325,7 +13005,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12325
13005
  overflow: hidden;
12326
13006
  border: var(--space-px, 1px) solid var(--color-border);
12327
13007
  border-radius: var(--radius-lg);
12328
- font-family: var(--font-sans, system-ui, sans-serif);
13008
+ font-family: var(--font-body);
12329
13009
  color: var(--color-fg);
12330
13010
  background: var(--color-bg);
12331
13011
  }
@@ -12417,8 +13097,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12417
13097
  }
12418
13098
 
12419
13099
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12420
- outline: 2px solid var(--color-ring);
12421
- outline-offset: 2px;
13100
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13101
+ outline-offset: var(--focus-ring-offset);
12422
13102
  }
12423
13103
 
12424
13104
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12577,7 +13257,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12577
13257
 
12578
13258
  /* === patterns/pricing.css === */
12579
13259
  /* @ui:component pricing */
12580
- /* @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 */
13260
+ /* @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 */
12581
13261
 
12582
13262
  /* ── Root ──
12583
13263
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12587,7 +13267,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12587
13267
  gap: var(--space-4);
12588
13268
  padding-block: var(--space-12);
12589
13269
  padding-inline: var(--space-4);
12590
- font-family: var(--font-sans, system-ui, sans-serif);
13270
+ font-family: var(--font-body);
12591
13271
  color: var(--color-fg);
12592
13272
  background: var(--color-bg);
12593
13273
  }
@@ -12637,9 +13317,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12637
13317
 
12638
13318
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12639
13319
  margin: 0;
13320
+ font-family: var(--font-heading);
12640
13321
  font-size: var(--text-lg);
12641
13322
  font-weight: var(--weight-semibold);
12642
- line-height: var(--leading-tight);
13323
+ letter-spacing: var(--heading-tracking);
13324
+ text-transform: var(--heading-transform);
13325
+ font-variant-caps: var(--heading-caps);
13326
+ line-height: var(--heading-leading);
12643
13327
  }
12644
13328
 
12645
13329
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12700,7 +13384,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12700
13384
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12701
13385
  border-color: var(--color-primary);
12702
13386
  box-shadow: var(--shadow-md);
12703
- outline: var(--space-px, 1px) solid var(--color-primary);
13387
+ outline: var(--border-width-strong) solid var(--color-primary);
12704
13388
  }
12705
13389
 
12706
13390
  /* ── Footnote ── */
@@ -12745,14 +13429,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12745
13429
 
12746
13430
  /* === patterns/search-results.css === */
12747
13431
  /* @ui:component search-results */
12748
- /* @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 */
13432
+ /* @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 */
12749
13433
 
12750
13434
  /* ── Root ── */
12751
13435
  [data-ui="search-results"] {
12752
13436
  display: flex;
12753
13437
  flex-direction: column;
12754
13438
  gap: var(--space-4);
12755
- font-family: var(--font-sans, system-ui, sans-serif);
13439
+ font-family: var(--font-body);
12756
13440
  }
12757
13441
 
12758
13442
  /* ── Search Input ── */
@@ -12780,7 +13464,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12780
13464
  justify-content: space-between;
12781
13465
  gap: var(--space-4);
12782
13466
  padding-bottom: var(--space-2);
12783
- border-bottom: 1px solid var(--color-border);
13467
+ border-bottom: var(--border-width) solid var(--color-border);
12784
13468
  }
12785
13469
 
12786
13470
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12815,7 +13499,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12815
13499
  flex-direction: column;
12816
13500
  gap: var(--space-2);
12817
13501
  padding: var(--space-4);
12818
- border: 1px solid var(--color-border);
13502
+ border: var(--border-width) solid var(--color-border);
12819
13503
  border-radius: var(--radius-md);
12820
13504
  background: var(--color-bg);
12821
13505
  transition: background var(--duration-fast) var(--ease-default),
@@ -12874,7 +13558,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12874
13558
  display: flex;
12875
13559
  justify-content: center;
12876
13560
  padding-top: var(--space-4);
12877
- border-top: 1px solid var(--color-border);
13561
+ border-top: var(--border-width) solid var(--color-border);
12878
13562
  }
12879
13563
 
12880
13564
  /* ── Loading ── */
@@ -12914,7 +13598,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12914
13598
 
12915
13599
  /* ── Error State ── */
12916
13600
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12917
- border: 1px solid var(--color-border);
13601
+ border: var(--border-width) solid var(--color-border);
12918
13602
  border-radius: var(--radius-md);
12919
13603
  padding: var(--space-6);
12920
13604
  text-align: center;
@@ -12923,8 +13607,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12923
13607
 
12924
13608
  /* ── Focus management ── */
12925
13609
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12926
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12927
- outline-offset: 2px;
13610
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13611
+ outline-offset: var(--focus-ring-offset);
12928
13612
  }
12929
13613
 
12930
13614
  /* ── Motion ── */
@@ -12940,7 +13624,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12940
13624
 
12941
13625
  /* === patterns/settings-page.css === */
12942
13626
  /* @ui:component settings-page */
12943
- /* @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 */
13627
+ /* @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 */
12944
13628
 
12945
13629
  /* ── Root ── */
12946
13630
  [data-ui="settings-page"] {
@@ -12950,7 +13634,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12950
13634
  width: 100%;
12951
13635
  max-width: 768px;
12952
13636
  margin-inline: auto;
12953
- font-family: var(--font-sans, system-ui, sans-serif);
13637
+ font-family: var(--font-body);
12954
13638
  color: var(--color-fg);
12955
13639
  }
12956
13640
 
@@ -12964,9 +13648,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12964
13648
  /* ── Title ── */
12965
13649
  [data-ui="settings-page"] [data-part="title"] {
12966
13650
  margin: 0;
13651
+ font-family: var(--font-heading);
12967
13652
  font-size: var(--text-xl, 1.25rem);
12968
13653
  font-weight: var(--weight-semibold, 600);
12969
- line-height: var(--leading-tight);
13654
+ letter-spacing: var(--heading-tracking);
13655
+ text-transform: var(--heading-transform);
13656
+ font-variant-caps: var(--heading-caps);
13657
+ line-height: var(--heading-leading);
12970
13658
  color: var(--color-fg);
12971
13659
  }
12972
13660
 
@@ -13030,7 +13718,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13030
13718
  gap: var(--space-3, 0.75rem);
13031
13719
  padding: var(--space-4);
13032
13720
  background: var(--color-bg);
13033
- border-top: 1px solid var(--color-border);
13721
+ border-top: var(--border-width) solid var(--color-border);
13034
13722
  border-radius: var(--radius-lg);
13035
13723
  box-shadow: var(--shadow-md);
13036
13724
  position: sticky;
@@ -13094,7 +13782,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13094
13782
  flex-direction: row;
13095
13783
  flex-wrap: wrap;
13096
13784
  border-inline-end: none;
13097
- border-bottom: 1px solid var(--color-border);
13785
+ border-bottom: var(--border-width) solid var(--color-border);
13098
13786
  padding-inline-end: 0;
13099
13787
  position: static;
13100
13788
  }
@@ -13113,7 +13801,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13113
13801
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13114
13802
  flex-direction: column;
13115
13803
  border-bottom: none;
13116
- border-inline-end: 1px solid var(--color-border);
13804
+ border-inline-end: var(--border-width) solid var(--color-border);
13117
13805
  padding-inline-end: var(--space-4);
13118
13806
  position: sticky;
13119
13807
  top: var(--space-4);
@@ -13131,7 +13819,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13131
13819
  justify-content: flex-start;
13132
13820
  text-align: start;
13133
13821
  border-bottom: none;
13134
- border-inline-start: 2px solid transparent;
13822
+ border-inline-start: var(--border-width-strong) solid transparent;
13135
13823
  margin-bottom: 0;
13136
13824
  margin-inline-end: -1px;
13137
13825
  padding: var(--space-2) var(--space-3);
@@ -13165,7 +13853,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13165
13853
 
13166
13854
  /* === patterns/site-footer.css === */
13167
13855
  /* @ui:component site-footer */
13168
- /* @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 */
13856
+ /* @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 */
13169
13857
 
13170
13858
  /* ── Root ──
13171
13859
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13175,11 +13863,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13175
13863
  gap: var(--space-8);
13176
13864
  padding-block: var(--space-10);
13177
13865
  padding-inline: var(--space-4);
13178
- font-family: var(--font-sans, system-ui, sans-serif);
13866
+ font-family: var(--font-body);
13179
13867
  font-size: var(--text-sm);
13180
13868
  color: var(--color-fg-muted);
13181
13869
  background: var(--color-bg-subtle);
13182
- border-block-start: 1px solid var(--color-border);
13870
+ border-block-start: var(--border-width) solid var(--color-border);
13183
13871
  }
13184
13872
 
13185
13873
  /* ── Brand ── */
@@ -13311,7 +13999,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13311
13999
 
13312
14000
  /* === patterns/stats-dashboard.css === */
13313
14001
  /* @ui:component stats-dashboard */
13314
- /* @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 */
14002
+ /* @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 */
13315
14003
 
13316
14004
  /* ── Root ──
13317
14005
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13324,7 +14012,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13324
14012
  gap: var(--space-3);
13325
14013
  padding-block: var(--space-8);
13326
14014
  padding-inline: var(--space-4);
13327
- font-family: var(--font-sans, system-ui, sans-serif);
14015
+ font-family: var(--font-body);
13328
14016
  color: var(--color-fg);
13329
14017
  background: var(--color-bg);
13330
14018
  }
@@ -13398,9 +14086,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13398
14086
 
13399
14087
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13400
14088
  margin: 0;
14089
+ font-family: var(--font-heading);
13401
14090
  font-size: var(--text-lg);
13402
14091
  font-weight: var(--weight-semibold);
13403
- line-height: var(--leading-tight);
14092
+ letter-spacing: var(--heading-tracking);
14093
+ text-transform: var(--heading-transform);
14094
+ font-variant-caps: var(--heading-caps);
14095
+ line-height: var(--heading-leading);
13404
14096
  }
13405
14097
 
13406
14098
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13491,7 +14183,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13491
14183
  gap: var(--space-6);
13492
14184
  max-inline-size: var(--measure-narrow);
13493
14185
  margin-inline: auto;
13494
- font-family: var(--font-sans);
14186
+ font-family: var(--font-body);
13495
14187
  }
13496
14188
 
13497
14189
  [data-ui="wizard"] [data-part="heading"] {