@faqir-ui/core 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +121 -57
  4. package/dist/faqir-core.min.js +3 -3
  5. package/dist/faqir-core.min.js.map +3 -3
  6. package/dist/faqir-core.mjs +75 -59
  7. package/dist/faqir.aurora.css +1209 -507
  8. package/dist/faqir.brutalist.css +1184 -489
  9. package/dist/faqir.candy.css +14152 -0
  10. package/dist/faqir.clinical.css +14152 -0
  11. package/dist/faqir.contrast.css +1198 -526
  12. package/dist/faqir.default.css +1261 -588
  13. package/dist/faqir.document-serif.css +1211 -491
  14. package/dist/faqir.document.css +1193 -490
  15. package/dist/faqir.editorial-document.css +14116 -0
  16. package/dist/faqir.editorial.css +14152 -0
  17. package/dist/faqir.fintech.css +14152 -0
  18. package/dist/faqir.glass.css +1214 -517
  19. package/dist/faqir.ink-document.css +14116 -0
  20. package/dist/faqir.ink.css +14127 -0
  21. package/dist/faqir.luxe.css +14211 -0
  22. package/dist/faqir.midnight.css +1229 -507
  23. package/dist/faqir.neo.css +14153 -0
  24. package/dist/faqir.neumorph.css +14151 -0
  25. package/dist/faqir.nordic.css +14151 -0
  26. package/dist/faqir.organic.css +14152 -0
  27. package/dist/faqir.paper.css +1200 -508
  28. package/dist/faqir.slate.css +1296 -564
  29. package/dist/faqir.soft.css +1180 -494
  30. package/dist/faqir.sunset.css +14153 -0
  31. package/dist/faqir.swiss-document.css +14116 -0
  32. package/dist/faqir.swiss.css +14153 -0
  33. package/dist/faqir.terminal.css +1187 -491
  34. package/dist/plugins/faqir-collapse.js +1 -1
  35. package/dist/plugins/faqir-intersect.js +2 -0
  36. package/dist/plugins/faqir-mask.js +27 -17
  37. package/dist/plugins/faqir-rules.js +63 -0
  38. package/dist/plugins/faqir-validate.js +471 -58
  39. package/dist/sri.json +36 -20
  40. package/faqir-core.d.ts +119 -6
  41. package/package.json +1 -1
@@ -131,6 +131,18 @@
131
131
  --font-mono: ui-monospace, 'Cascadia Code', 'JetBrains Mono', monospace;
132
132
  --font-serif: 'Georgia', 'Times New Roman', serif;
133
133
 
134
+ /* ── Font Roles (task 1.1A-01) ──
135
+ The three families above are the PALETTE; these three are the ROLES that
136
+ components actually read. A theme re-points a role once and every heading,
137
+ every paragraph and every control follows — "serif headings on a sans body"
138
+ is one declaration rather than sixty-four stylesheet edits. Components never
139
+ read --font-sans / --font-serif directly (gated by
140
+ tests/tokens/role-tokens.test.ts); --font-mono stays readable by name,
141
+ because "this is code" is a semantic choice, not a stylistic one. */
142
+ --font-heading: var(--font-sans); /* h1–h6, hero headline, card/dialog titles, stat values, doc headings */
143
+ --font-body: var(--font-sans); /* prose, text, document body, descriptions */
144
+ --font-ui: var(--font-sans); /* controls: button, input, select, badge, chip, tabs, menus */
145
+
134
146
  /* ── Font Sizes ── */
135
147
  --text-xs: 0.75rem; /* 12px */
136
148
  --text-sm: 0.875rem; /* 14px */
@@ -153,10 +165,29 @@
153
165
  --weight-medium: 500;
154
166
  --weight-semibold: 600;
155
167
  --weight-bold: 700;
168
+
169
+ /* ── Heading Voice (task 1.1A-01) ──
170
+ What makes a heading sound like the theme rather than like the body text one
171
+ size up: how heavy it is, how tightly the letters sit, whether it shouts, and
172
+ how close its own lines run. The defaults reproduce today's primary heading
173
+ exactly, so a project that sets none of them renders unchanged. A heading
174
+ that deliberately steps DOWN from the primary voice (prose h2–h4, a semibold
175
+ step below h1) keeps its own weight and leading and takes family, tracking
176
+ and case from the voice — the step is the design, not a value to re-derive. */
177
+ --heading-weight: var(--weight-bold);
178
+ --heading-tracking: 0em; /* letter-spacing — carries a unit so it
179
+ composes inside calc() where a heading
180
+ already has its own optical tightening */
181
+ --heading-transform: none; /* text-transform */
182
+ --heading-caps: normal; /* font-variant-caps — small caps are a
183
+ variant, not a transform (1.1A-25), so
184
+ they get a knob of their own that sits
185
+ beside --heading-transform */
186
+ --heading-leading: var(--leading-tight);
156
187
  }
157
188
 
158
189
  /* === tokens/effects.css === */
159
- /* @ui:tokens effects — radii, shadows, z-index */
190
+ /* @ui:tokens effects — radii, shape, shadows, focus, z-index */
160
191
 
161
192
  :root {
162
193
  /* ── Radii ── */
@@ -168,12 +199,49 @@
168
199
  --radius-2xl: 1rem; /* 16px */
169
200
  --radius-full: 9999px;
170
201
 
171
- /* ── Shadows ── */
172
- --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.04);
173
- --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
174
- --shadow-md: 0 4px 6px oklch(0 0 0 / 0.05), 0 2px 4px oklch(0 0 0 / 0.04);
175
- --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.06), 0 4px 6px oklch(0 0 0 / 0.04);
176
- --shadow-xl: 0 20px 25px oklch(0 0 0 / 0.08), 0 8px 10px oklch(0 0 0 / 0.04);
202
+ /* ── Shape ── */
203
+ /* The weight of an edge. A component names the ROLE (--border-width, or
204
+ --border-width-strong where the design leans on a thicker rule), never a
205
+ step, so a theme re-points every edge it ships with one declaration. */
206
+ --border-width-sm: 1px;
207
+ --border-width-md: 2px;
208
+ --border-width-lg: 3px;
209
+ --border-width: var(--border-width-sm); /* the default component border */
210
+ --border-width-strong: var(--border-width-md); /* emphasis: keycap, thick rule, active tab */
211
+ /* Progressive: CSS Borders 4. A browser without the property ignores it; a
212
+ value it does not know resolves to `round`, which is today's rendering. */
213
+ --corner-shape: round; /* bevel | scoop | notch where supported */
214
+
215
+ /* ── Depth ── */
216
+ /* The colour every shadow is cast in, as BARE OKLCH channels (L C H, no
217
+ `oklch()` around them) so each step can still set its own alpha:
218
+ `oklch(var(--shadow-color) / 0.06)`. A theme tints its depth warm, or
219
+ removes it entirely, with one declaration instead of rewriting five
220
+ multi-layer values. `0 0 0` is black — today's rendering, exactly. */
221
+ --shadow-color: 0 0 0;
222
+
223
+ --shadow-xs: 0 1px 2px oklch(var(--shadow-color) / 0.04);
224
+ --shadow-sm: 0 1px 3px oklch(var(--shadow-color) / 0.06), 0 1px 2px oklch(var(--shadow-color) / 0.04);
225
+ --shadow-md: 0 4px 6px oklch(var(--shadow-color) / 0.05), 0 2px 4px oklch(var(--shadow-color) / 0.04);
226
+ --shadow-lg: 0 10px 15px oklch(var(--shadow-color) / 0.06), 0 4px 6px oklch(var(--shadow-color) / 0.04);
227
+ --shadow-xl: 0 20px 25px oklch(var(--shadow-color) / 0.08), 0 8px 10px oklch(var(--shadow-color) / 0.04);
228
+
229
+ /* What an elevated surface does to whatever shows through it. Every surface
230
+ that can float — card, surface[data-variant="overlay"] and the seven
231
+ floating recipes — declares `backdrop-filter: var(--surface-backdrop)`
232
+ inside the same `@supports` guard, so a frosted theme is a token rather
233
+ than a stylesheet that reaches into seven components by selector.
234
+ `none` is the initial value of the property: no-op until a theme speaks. */
235
+ --surface-backdrop: none;
236
+
237
+ /* ── Focus ── */
238
+ /* base/reset.css owns the default ring and reads only these. Every control
239
+ that draws its own ring reads them too, so a theme changes focus once. */
240
+ --focus-ring-width: 2px;
241
+ --focus-ring-offset: 2px;
242
+ --focus-ring-style: solid;
243
+ --focus-ring-color: var(--color-ring);
244
+ --focus-shadow: none; /* a glow theme puts a shadow behind the ring */
177
245
 
178
246
  /* ── Z-Index ── */
179
247
  --z-base: 0;
@@ -186,8 +254,74 @@
186
254
  --z-max: 9999;
187
255
  }
188
256
 
257
+ /* ── Scheme islands ── */
258
+ /* The ring colour, restated where a scheme can change below the root: declared
259
+ on `:root` alone it resolves `--color-ring` once, from the page, and a nested
260
+ `data-theme="dark"` region would draw the light ring. See the same block in
261
+ tokens/aliases.css. `--focus-shadow` is deliberately NOT restated — it is a
262
+ depth value a theme owns, and restating it would replace the theme's glow
263
+ with `none` inside every island. */
264
+ [data-theme],
265
+ [data-skin] {
266
+ --focus-ring-color: var(--color-ring);
267
+ }
268
+
269
+ /* === tokens/textures.css === */
270
+ /* @ui:tokens textures — named surface materials (SVG data URIs) */
271
+
272
+ /* ══════════════════════════════════════════════════════════════════════════
273
+ The material palette.
274
+ ══════════════════════════════════════════════════════════════════════════
275
+ Six named textures, each a self-contained `url("data:image/svg+xml,…")` that
276
+ tiles. Nothing here is consumed directly: components read the two ROLE tokens
277
+ in `aliases.css` — `--texture-page` (body, document) and `--texture-surface`
278
+ (surface, card, hero) — both `none` by default, so the registry renders
279
+ exactly as it did before this file existed. A theme opts in with one
280
+ declaration:
281
+
282
+ --texture-page: var(--texture-grain);
283
+
284
+ This file is deliberately OUTSIDE the themeable surface (see
285
+ `NON_SURFACE_TOKEN_FILES` in `src/theme-manifest.ts`): a theme re-points the
286
+ two role tokens, it does not inherit six data URIs into its manifest.
287
+
288
+ On `currentColor`: the tint is written as `currentColor` so the markup states
289
+ its intent and a theme can re-point the whole token, but a data-URI SVG used
290
+ as `background-image` is its own document — `currentColor` there resolves to
291
+ that document's initial colour (black), not to the host element's `color`.
292
+ That IS the intended neutral for grain and paper, which are meant to darken a
293
+ surface slightly; the alpha in each texture, not the hue, is what carries the
294
+ effect. A theme wanting a different tint ships its own URI.
295
+
296
+ Every texture keeps its alpha low enough to survive on both schemes, and each
297
+ `<svg>` carries explicit `width`/`height` so the tile size is the token's,
298
+ not the browser's default 300×150.
299
+ ══════════════════════════════════════════════════════════════════════════ */
300
+
301
+ :root {
302
+ /* Film grain — fractal noise masking a flat currentColor fill. The mask is
303
+ what makes this a tint rather than the turbulence's own rainbow. */
304
+ --texture-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/mask%3E%3Crect width='160' height='160' fill='currentColor' mask='url(%23m)' opacity='0.14'/%3E%3C/svg%3E");
305
+
306
+ /* Paper fibre — lower frequency, more octaves, softer than grain. */
307
+ --texture-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.04 0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='200' height='200' filter='url(%23p)'/%3E%3C/mask%3E%3Crect width='200' height='200' fill='currentColor' mask='url(%23m)' opacity='0.1'/%3E%3C/svg%3E");
308
+
309
+ /* Dot field — one dot per 16px cell. */
310
+ --texture-dots: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='2' cy='2' r='1' fill='currentColor' opacity='0.18'/%3E%3C/svg%3E");
311
+
312
+ /* Graph-paper grid — hairlines on a 24px cell. */
313
+ --texture-grid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M24 0H0v24' fill='none' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
314
+
315
+ /* Diagonal hatching — 45°, 8px pitch. */
316
+ --texture-stripes: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M-2 2 2-2M0 8 8 0M6 10l4-4' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
317
+
318
+ /* Soft gradient mesh — three offset radial blooms, the only non-tiling
319
+ texture here (it is sized to cover, not to repeat). */
320
+ --texture-mesh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3CradialGradient id='a' cx='20%25' cy='20%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.18'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='b' cx='80%25' cy='30%25' r='55%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.14'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='c' cx='50%25' cy='90%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.12'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3Crect width='640' height='640' fill='url(%23a)'/%3E%3Crect width='640' height='640' fill='url(%23b)'/%3E%3Crect width='640' height='640' fill='url(%23c)'/%3E%3C/svg%3E");
321
+ }
322
+
189
323
  /* === tokens/motion.css === */
190
- /* @ui:tokens motion — easings and durations */
324
+ /* @ui:tokens motion — easings, durations and motion personality */
191
325
 
192
326
  :root {
193
327
  /* ── Easings ── */
@@ -216,6 +350,35 @@
216
350
  /* Preset geometry */
217
351
  --motion-slide-distance: 0.5rem; /* slide-up travel */
218
352
  --motion-scale-from: 0.95; /* scale start/end factor */
353
+
354
+ /* ── Personality (1.1A-05 · §5.2 `motion`) ── */
355
+ /* The easing PALETTE gained a spring. Like --ease-bounce it has no consumer
356
+ of its own: a theme that wants everything to overshoot re-points
357
+ --ease-default at it, exactly as a serif theme re-points --font-body.
358
+ The declaration here is the cubic-bezier APPROXIMATION, because a custom
359
+ property stores whatever tokens it is given — a browser without `linear()`
360
+ would accept the spring happily and then drop every `transition` that used
361
+ it, landing on the initial easing rather than on a fallback. The @supports
362
+ block below is what makes the upgrade conditional. The approximation is
363
+ the bounce curve, deliberately: an overshoot-and-settle cubic-bezier is the
364
+ closest a browser without `linear()` can come to a spring. */
365
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
366
+
367
+ /* How far an interactive surface rises under the pointer. A `translate`
368
+ VALUE, not a length: `none` is the initial value of that property, so the
369
+ default registry computes exactly what it computed before this token
370
+ existed, and a theme states the lift as `0 -1px`. `translate` rather than
371
+ `transform` so a component's own transform is never clobbered. */
372
+ --motion-hover-lift: none;
373
+ }
374
+
375
+ /* The real spring, where `linear()` is understood (Chrome 113+, Safari 17.2+,
376
+ Firefox 112+). Declared second so it wins; guarded so it is never declared at
377
+ all where it would be meaningless. */
378
+ @supports (animation-timing-function: linear(0, 1)) {
379
+ :root {
380
+ --ease-spring: linear(0, 0.3 6%, 0.7 13%, 0.95 20%, 1.03 27%, 1 40%, 1);
381
+ }
219
382
  }
220
383
 
221
384
  /* === tokens/semantic.css === */
@@ -307,27 +470,123 @@
307
470
  --section-gap-lg: var(--space-32); /* 8rem — spacious, one idea per screen */
308
471
  --content-gutter: var(--space-6); /* 1.5rem — page padding-inline */
309
472
 
473
+ /* ── Material ── */
474
+ /* The two textures a theme actually points at. Components never name a
475
+ texture from `tokens/textures.css` directly — they read one of these, so a
476
+ theme re-points two tokens rather than every surface in the registry.
477
+ `--texture-page` dresses the page itself (body, document);
478
+ `--texture-surface` dresses the things that sit ON it (surface, card,
479
+ hero). Both `none`: the initial value of `background-image`, so the
480
+ default registry renders exactly as it did before they existed. */
481
+ --texture-page: none;
482
+ --texture-surface: none;
483
+
484
+ /* ── Decoration (1.1A-05 · §5.2 `decoration`) ── */
485
+ /* The marks a theme draws that are not edges, fills or type: how a link is
486
+ underlined, how a divider is dashed, what selected text looks like, what
487
+ colour a list bullet is. Every default is the value the registry already
488
+ rendered, so this section is a set of handles, not a restyle.
489
+ `--marker-color` is `currentColor` — the initial value of `::marker`'s
490
+ colour — rather than the accent, so a list only changes when a theme says
491
+ it should. */
492
+ --link-decoration: underline;
493
+ --link-underline-offset: 0.2em;
494
+ --link-thickness: 1px;
495
+ --divider-style: solid;
496
+ /* The divider's own width, following the edge by default (1.1A-26). A theme
497
+ that asks for a `double` divider raises it to at least 3px: a double rule
498
+ only splits into two lines from 3px, and the family's 1px hairline would
499
+ paint it as one. */
500
+ --divider-width: var(--border-width);
501
+ /* The zebra, so a theme dials the stripe without restating the four selectors
502
+ the table's striped variant needs (stamped and nth-child, each with a hover
503
+ twin). Deliberately NOT `--table-stripe`: `--table-level`,
504
+ `--table-thead-h` and `--table-pin-offset` are stamped and MEASURED per
505
+ element by the table controller, so claiming the `--table-*` namespace for
506
+ a theme token would put runtime state on the themeable surface. */
507
+ --stripe-bg: var(--color-bg-subtle);
508
+ --selection-bg: var(--color-primary-subtle);
509
+ --selection-fg: var(--color-fg);
510
+ --marker-color: currentColor;
511
+ /* How far a disabled control is dimmed. Seventeen rules across the primitives
512
+ and recipes each spelled `opacity: 0.5`, which left a theme with an opinion
513
+ about disabled legibility no way to state it except by out-specifying every
514
+ one of them — which is exactly what `themes/contrast.css` did, with a
515
+ blanket `:root [data-ui]:disabled` rule, until 1.1A-15 turned it into this
516
+ one declaration. `0.5` is the value those seventeen rules already held. */
517
+ --disabled-opacity: 0.5;
518
+
310
519
  /* ── Button ── */
311
520
  --button-radius: var(--radius-md);
312
521
  --button-height-sm: var(--control-height-sm);
313
522
  --button-height-md: var(--control-height-md);
314
523
  --button-height-lg: var(--control-height-lg);
315
- --button-font: var(--font-sans);
524
+ --button-font: var(--font-ui);
316
525
  --button-weight: var(--weight-medium);
526
+ --button-text-transform: none;
317
527
 
318
528
  /* ── Card ── */
319
529
  --card-radius: var(--radius-lg);
320
530
  --card-shadow: var(--shadow-sm);
321
531
  --card-border: var(--color-surface-1-border);
532
+ --card-border-width: var(--border-width);
322
533
  --card-bg: var(--color-surface-1);
323
534
  --card-padding: var(--space-6);
324
535
 
325
536
  /* ── Input ── */
326
- --input-radius: var(--radius-md);
327
- --input-height: var(--control-height-md);
328
- --input-border: var(--color-border);
329
- --input-bg: var(--color-bg);
330
- --input-font: var(--font-sans);
537
+ /* The text-control silhouette. `--input-border-width` (1.1A-02) is the edge;
538
+ `--input-fill` is what the control paints, and `input`, `textarea` and
539
+ `select` all read it, so one declaration fills every text control.
540
+ `--input-fill` defaults to `--input-bg`, so a project that sets `--input-bg`
541
+ on `:root` — the 1.0 way to fill every input — still gets it. Set BELOW the
542
+ root, `--input-bg` no longer reaches the control: `--input-fill` has already
543
+ resolved it on `:root`, which is where a theme flips the fill, and a
544
+ per-element `--input-bg` winning over that would need the component to tell
545
+ "set here" from "inherited", which CSS cannot. To fill one input, or every
546
+ input in a region, set `--input-fill` there instead. `--input-bg-filled` is
547
+ the value a "filled" theme points `--input-fill` at — named here so the
548
+ silhouette is a token a theme flips rather than a colour it has to pick. */
549
+ --input-radius: var(--radius-md);
550
+ --input-height: var(--control-height-md);
551
+ --input-border: var(--color-border);
552
+ --input-border-width: var(--border-width);
553
+ --input-bg: var(--color-bg);
554
+ --input-bg-filled: var(--color-bg-subtle);
555
+ --input-fill: var(--input-bg);
556
+ --input-font: var(--font-ui);
557
+
558
+ /* ── Checkbox / Switch ── */
559
+ /* The two control shapes that do not follow `--radius-md`: a checkbox is a
560
+ small square with a small radius, a switch is a pill. Both were literal
561
+ `var(--radius-*)` reads in the components; named here, a theme squares its
562
+ switches without touching the radius ladder every other surface uses.
563
+
564
+ The geometry beside them is not decoration — it is the rest of the
565
+ namespace. Naming ONE token `--checkbox-radius` makes `--checkbox-*` a
566
+ token family, and the registry audit then (rightly) reads every other
567
+ `--checkbox-…`/`--switch-…` the components carried as a token wearing a
568
+ fallback as a disguise. They were always the default geometry; these are
569
+ the values the fallbacks already held, said once. */
570
+ --checkbox-size: 18px;
571
+ --checkbox-radius: var(--radius-sm);
572
+ --switch-width: 44px;
573
+ --switch-height: 24px;
574
+ --switch-thumb: 18px;
575
+ --switch-travel: 20px;
576
+ --switch-radius: var(--radius-full);
577
+ --switch-bg: var(--color-bg-muted);
578
+ --switch-thumb-shadow: var(--shadow-xs);
579
+
580
+ /* ── Floating panels ── */
581
+ /* What a panel that floats above the page is filled with: the dialog and
582
+ sheet panels, the drawer, the popover content (and its arrow), the dropdown
583
+ menu and the toast. They all painted `var(--color-bg)` directly, which left
584
+ a theme no way to make a floating surface differ from the page — the frost
585
+ half of that pairing is `--surface-backdrop` (1.1A-04), and a blur behind an
586
+ opaque fill renders nothing, so the fill has to be a token too. `card` has
587
+ had `--card-bg` since 1.0; this is the same handle for the things that have
588
+ no surface of their own. [1.1A-14] */
589
+ --panel-bg: var(--color-bg);
331
590
 
332
591
  /* ── Dialog ── */
333
592
  --dialog-radius: var(--radius-xl);
@@ -336,7 +595,7 @@
336
595
 
337
596
  /* ── Badge ── */
338
597
  --badge-radius: var(--radius-full);
339
- --badge-font: var(--font-sans);
598
+ --badge-font: var(--font-ui);
340
599
 
341
600
  /* ── Avatar ── */
342
601
  --avatar-radius: var(--radius-full);
@@ -345,6 +604,39 @@
345
604
  --avatar-size-lg: 56px;
346
605
  }
347
606
 
607
+ /* ── Scheme islands ── */
608
+ /* The colour aliases above, restated wherever a scheme can change below the
609
+ root. A custom property resolves its var() on the element that DECLARES it,
610
+ so `--panel-bg: var(--color-bg)` on `:root` is computed once, from the page's
611
+ colours, and a nested `<div data-theme="dark">` inherits that light value
612
+ even though its own `--color-bg` is dark — a white dialog on a dark island.
613
+ Components that read `var(--color-bg)` directly never had the problem; the
614
+ aliases 1.1 routed them through did. Restating the declaration on
615
+ `[data-theme]` and `[data-skin]` makes it resolve again there.
616
+
617
+ Only colours are restated. Geometry does not change with the scheme, and
618
+ shadows are the depth axis every theme owns on `:root`: restating either here
619
+ would replace a theme's own value with the default inside every island. A
620
+ theme that overrides one of THESE on `:root` and wants it honoured in an
621
+ island says so on the same selectors.
622
+
623
+ The values must match the `:root` declarations above exactly;
624
+ `tests/tokens/scheme-islands.test.ts` fails if they drift. */
625
+ [data-theme],
626
+ [data-skin] {
627
+ --stripe-bg: var(--color-bg-subtle);
628
+ --selection-bg: var(--color-primary-subtle);
629
+ --selection-fg: var(--color-fg);
630
+ --card-border: var(--color-surface-1-border);
631
+ --card-bg: var(--color-surface-1);
632
+ --input-border: var(--color-border);
633
+ --input-bg: var(--color-bg);
634
+ --input-bg-filled: var(--color-bg-subtle);
635
+ --input-fill: var(--input-bg);
636
+ --switch-bg: var(--color-bg-muted);
637
+ --panel-bg: var(--color-bg);
638
+ }
639
+
348
640
  /* === tokens/document.css === */
349
641
  /* @ui:tokens document — structural tokens for document/print rendering */
350
642
  /* These tokens control page geometry, document typography, table density,
@@ -376,10 +668,10 @@
376
668
  Separate from the base typography tokens because documents have
377
669
  different optimal sizes than screen UIs. 14px body + 12px legal
378
670
  is standard for A4 business documents. */
379
- --doc-font: var(--font-sans);
671
+ --doc-font: var(--font-body);
380
672
  --doc-font-size: var(--text-sm); /* 14px — optimal for A4 */
381
673
  --doc-line-height: var(--leading-normal); /* 1.5 */
382
- --doc-heading-font: var(--font-sans);
674
+ --doc-heading-font: var(--font-heading);
383
675
  --doc-heading-weight: var(--weight-bold);
384
676
  --doc-heading-size: var(--text-xl); /* 20px for doc titles */
385
677
  --doc-subheading-size: var(--text-lg); /* 18px for section titles */
@@ -430,6 +722,16 @@
430
722
  --doc-print-border-color: oklch(0.60 0 0); /* medium gray borders in print */
431
723
  }
432
724
 
725
+ /* ── Scheme islands ── */
726
+ /* `--doc-legal-color` is the one document colour screen components read (the
727
+ key-value label and the image caption), so it is restated where a scheme can
728
+ change below the root — see the same block in tokens/aliases.css. The rest
729
+ of this file is print ink, which does not follow the scheme. */
730
+ [data-theme],
731
+ [data-skin] {
732
+ --doc-legal-color: var(--color-fg-muted);
733
+ }
734
+
433
735
  /* === tokens/doc-aliases.css === */
434
736
  /* @ui:tokens doc-aliases — component-level document tokens */
435
737
  /* Maps document-layer tokens to specific primitive/recipe attribute selectors.
@@ -476,7 +778,10 @@
476
778
  --field-error-size: var(--doc-legal-size);
477
779
  --field-error-color: var(--color-destructive);
478
780
  --field-validating-color: var(--color-fg-muted); /* async validation in flight */
479
- --field-disabled-opacity: 0.55; /* honest disabled affordance */
781
+ /* The role `--disabled-opacity` sets for every control, nudged 10% lighter:
782
+ 0.55 at the 0.5 default, which is the value this alias always held, and it
783
+ follows a theme that states the role (1.1A-27). */
784
+ --field-disabled-opacity: calc(var(--disabled-opacity) * 1.1);
480
785
  --field-required-color: var(--color-destructive);
481
786
  --field-required-marker: ' *'; /* appended to required labels */
482
787
 
@@ -496,15 +801,47 @@
496
801
  --stat-change-negative: var(--color-destructive);
497
802
  }
498
803
 
804
+ /* ── Scheme islands ── */
805
+ /* The colour aliases above, restated where a scheme can change below the root —
806
+ a custom property resolves its var() on the element that declares it, so a
807
+ `:root`-only alias would carry the page's light value into a nested
808
+ `data-theme="dark"` region. See the same block in tokens/aliases.css; the
809
+ values must match the `:root` declarations above exactly. */
810
+ [data-theme],
811
+ [data-skin] {
812
+ --kv-label-color: var(--doc-legal-color);
813
+ --kv-value-color: var(--color-fg);
814
+ --callout-bg: var(--color-bg-subtle);
815
+ --callout-fg: var(--color-fg);
816
+ --image-border: var(--color-border);
817
+ --image-caption-color: var(--doc-legal-color);
818
+ --field-label-color: var(--color-fg);
819
+ --field-description-color: var(--color-fg-muted);
820
+ --field-error-color: var(--color-destructive);
821
+ --field-validating-color: var(--color-fg-muted);
822
+ --field-required-color: var(--color-destructive);
823
+ --page-break-screen-color: var(--color-border);
824
+ --page-break-screen-label-color: var(--color-fg-muted);
825
+ --stat-label-color: var(--color-fg-muted);
826
+ --stat-change-positive: var(--color-success);
827
+ --stat-change-negative: var(--color-destructive);
828
+ }
829
+
499
830
  /* === tokens/density.css === */
500
- /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6)
831
+ /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6;
832
+ `spacious` added 1.1A-09, SPEC-1.0.md §4)
501
833
 
502
834
  Put `data-density="compact"` on ANY container and its whole subtree renders
503
835
  tighter: spacing steps shrink by --density-scale and interactive controls drop
504
836
  to a shorter height ramp. `data-density="comfortable"` restores the base scale,
505
- so density can be reset on an inner subtree.
837
+ so density can be reset on an inner subtree. `data-density="spacious"` is the
838
+ third point on the ladder, above comfortable: spacing grows and the control
839
+ ramp grows with it, gentler than the spacing multiplier for the same reason
840
+ compact's ramp shrinks gentler — a usable hit target has a ceiling as well as
841
+ a floor.
506
842
 
507
843
  <section data-density="compact"> … dense form / table / toolbar … </section>
844
+ <section data-density="spacious"> … roomy landing hero, kiosk UI … </section>
508
845
 
509
846
  This is 100% CSS. `data-density` is NOT a sixth protocol attribute: no
510
847
  component contract, manifest, controller or audit rule knows about it — CSS
@@ -641,6 +978,57 @@
641
978
  --content-gutter: var(--space-6);
642
979
  }
643
980
 
981
+ /* The third density: roomier than the base scale, for a landing hero or a kiosk
982
+ UI meant to be read at arm's length. Control heights grow slower than the
983
+ spacing multiplier — the same asymmetry compact's ramp has, mirrored. */
984
+ [data-density="spacious"] {
985
+ --density-scale: 1.25;
986
+
987
+ /* ── Spacing scale (× --density-scale) ── */
988
+ --space-0h: calc(0.125rem * var(--density-scale));
989
+ --space-1: calc(0.25rem * var(--density-scale));
990
+ --space-1h: calc(0.375rem * var(--density-scale));
991
+ --space-2: calc(0.5rem * var(--density-scale));
992
+ --space-2h: calc(0.625rem * var(--density-scale));
993
+ --space-3: calc(0.75rem * var(--density-scale));
994
+ --space-3h: calc(0.875rem * var(--density-scale));
995
+ --space-4: calc(1rem * var(--density-scale));
996
+ --space-5: calc(1.25rem * var(--density-scale));
997
+ --space-6: calc(1.5rem * var(--density-scale));
998
+ --space-7: calc(1.75rem * var(--density-scale));
999
+ --space-8: calc(2rem * var(--density-scale));
1000
+ --space-10: calc(2.5rem * var(--density-scale));
1001
+ --space-12: calc(3rem * var(--density-scale));
1002
+ --space-16: calc(4rem * var(--density-scale));
1003
+ --space-20: calc(5rem * var(--density-scale));
1004
+ --space-24: calc(6rem * var(--density-scale));
1005
+ --space-32: calc(8rem * var(--density-scale));
1006
+ --space-40: calc(10rem * var(--density-scale));
1007
+ --space-48: calc(12rem * var(--density-scale));
1008
+ --space-64: calc(16rem * var(--density-scale));
1009
+
1010
+ /* ── Control height ramp ── */
1011
+ --control-height-sm: 36px;
1012
+ --control-height-md: 44px;
1013
+ --control-height-lg: 52px;
1014
+
1015
+ /* ── Aliases re-substituted in this scope (values identical to the base) ── */
1016
+ --button-height-sm: var(--control-height-sm);
1017
+ --button-height-md: var(--control-height-md);
1018
+ --button-height-lg: var(--control-height-lg);
1019
+ --input-height: var(--control-height-md);
1020
+ --card-padding: var(--space-6);
1021
+ --kv-pair-gap: var(--space-3);
1022
+ --kv-grid-gap: var(--space-4);
1023
+ --callout-padding-y: var(--space-3);
1024
+ --callout-padding-x: var(--space-4);
1025
+ --field-gap: var(--space-1h);
1026
+ --section-gap-sm: var(--space-12);
1027
+ --section-gap-md: var(--space-20);
1028
+ --section-gap-lg: var(--space-32);
1029
+ --content-gutter: var(--space-6);
1030
+ }
1031
+
644
1032
  /* === themes/contrast.css === */
645
1033
  /* @ui:theme contrast — WCAG AAA: 7:1 text everywhere, opaque focus rings, no low-contrast muted text; the accessibility-statement theme */
646
1034
 
@@ -703,6 +1091,43 @@
703
1091
  --color-border-strong: oklch(0.55 0 0);
704
1092
  --color-ring: oklch(0.42 0.16 250); /* opaque — a focus ring must never be translucent */
705
1093
 
1094
+ /* ══════════════════════════════════════════════════════════════════════
1095
+ The accessibility statement, said in tokens rather than in selectors.
1096
+ ══════════════════════════════════════════════════════════════════════
1097
+ Everything below used to be a rule this theme wrote ABOUT components —
1098
+ thirteen `:root [data-ui="…"]:focus-visible` selectors and a blanket
1099
+ `:root [data-ui]:disabled` — because 1.0 had no token for a ring width or
1100
+ a disabled dim. It has both now, so the theme states the values and the
1101
+ components apply them. Two things improve in the swap: the ring reaches
1102
+ every focusable surface rather than the thirteen somebody remembered to
1103
+ list, and the dim reaches the parts (a menu item, a calendar day) that
1104
+ carry no `data-ui` of their own and so were never matched. [1.1A-15] */
1105
+
1106
+ /* ── Shape: a visible edge, not a hairline ──
1107
+ The comment above the border colours has claimed "visible, not hairline"
1108
+ since 0.4 while only the COLOUR was ever darkened. 2px is the shape
1109
+ family's `regular`, and SC 1.4.11 is about non-text contrast: a border
1110
+ that carries meaning is easier to see when there is more of it. */
1111
+ --border-width: var(--border-width-md);
1112
+
1113
+ /* ── Focus: the ladder's widest ring, everywhere ──
1114
+ 3px opaque, offset by the family's 2px gap. `base/reset.css` and all
1115
+ thirteen controls that paint their own ring read `--focus-ring-width`
1116
+ (1.1A-02/03), so one declaration is what the thirteen-selector block
1117
+ was reaching for — and it also covers the controls that block missed. */
1118
+ --focus-ring-width: var(--border-width-lg);
1119
+
1120
+ /* ── Decoration: a link's rule is as strong as its colour ──
1121
+ A link must not be identifiable by hue alone (SC 1.4.1); this theme makes
1122
+ the underline thick enough to be the primary signal. */
1123
+ --link-thickness: var(--border-width-md);
1124
+
1125
+ /* ── Honest disabled states ──
1126
+ Perceptibly dimmed, never faded to invisibility: 0.6 rather than the
1127
+ registry's 0.5. Cursor affordance is the component's business — every
1128
+ disabled control in the registry already sets `not-allowed`. */
1129
+ --disabled-opacity: 0.6;
1130
+
706
1131
  /* ── Shadows (crisp, honest depth) ── */
707
1132
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.10);
708
1133
  --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.12), 0 1px 2px oklch(0 0 0 / 0.08);
@@ -820,43 +1245,10 @@
820
1245
  }
821
1246
  }
822
1247
 
823
- /* ══════════════════════════════════════════════════════════════════════════
824
- Focus visibility — an opaque, oversized ring on EVERY interactive control.
825
- ══════════════════════════════════════════════════════════════════════════
826
- The base ships a 2px `:focus-visible` ring; this theme re-asserts a stronger
827
- 3px opaque ring (offset by a 2px gap) on every interactive `data-ui` value so
828
- focus is unmistakable regardless of surface. The `:root` prefix raises
829
- specificity above each primitive's own `[data-ui="…"]:focus-visible` rule, so
830
- this ring wins no matter the stylesheet load order.
831
-
832
- Interactive set (kept in sync with tests/themes/contrast.test.ts):
833
- button, link, input, textarea, select, checkbox, radio, switch, toggle,
834
- slider, tabs, select-custom, date-picker. */
835
- :root [data-ui="button"]:focus-visible,
836
- :root [data-ui="link"]:focus-visible,
837
- :root [data-ui="input"]:focus-visible,
838
- :root [data-ui="textarea"]:focus-visible,
839
- :root [data-ui="select"]:focus-visible,
840
- :root [data-ui="checkbox"]:focus-visible,
841
- :root [data-ui="radio"]:focus-visible,
842
- :root [data-ui="switch"]:focus-visible,
843
- :root [data-ui="toggle"]:focus-visible,
844
- :root [data-ui="slider"] [data-part="thumb"]:focus-visible,
845
- :root [data-ui="tabs"] [data-part="trigger"]:focus-visible,
846
- :root [data-ui="select-custom"] [data-part="trigger"]:focus-visible,
847
- :root [data-ui="date-picker"] [data-part="input"]:focus-visible {
848
- outline: 3px solid var(--color-ring);
849
- outline-offset: 2px;
850
- }
851
-
852
- /* ── Honest disabled states ── */
853
- /* Perceptibly dimmed and marked not-allowed — never faded to invisibility. */
854
- :root [data-ui]:disabled,
855
- :root [data-ui][aria-disabled="true"],
856
- :root [data-ui][data-state="disabled"] {
857
- opacity: 0.6;
858
- cursor: not-allowed;
859
- }
1248
+ /* The focus and disabled rules that used to live here are the `--focus-ring-*`
1249
+ and `--disabled-opacity` declarations in `:root` above. Nothing in this
1250
+ stylesheet selects a component any more — see tests/themes/contrast.test.ts,
1251
+ which gates that from both ends. [1.1A-15] */
860
1252
 
861
1253
  /* === base/reset.css === */
862
1254
  /* @ui:base reset — modern CSS reset for Faqir projects */
@@ -872,11 +1264,38 @@
872
1264
  padding: 0;
873
1265
  }
874
1266
 
1267
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1268
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1269
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1270
+ these three rules; declaring them here (rather than in each theme) is what
1271
+ makes the two authoring forms interchangeable. Nothing else in the registry
1272
+ declares `color-scheme`, so this is purely additive.
1273
+
1274
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1275
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1276
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1277
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1278
+ dark island inside a light page has always worked here. */
1279
+ :root {
1280
+ color-scheme: light;
1281
+ }
1282
+
1283
+ [data-theme="dark"] {
1284
+ color-scheme: dark;
1285
+ }
1286
+
1287
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1288
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1289
+ does for a theme authored in the three-block form. */
1290
+ [data-theme="auto"] {
1291
+ color-scheme: light dark;
1292
+ }
1293
+
875
1294
  html {
876
1295
  -webkit-text-size-adjust: 100%;
877
1296
  -moz-tab-size: 4;
878
1297
  tab-size: 4;
879
- font-family: var(--font-sans);
1298
+ font-family: var(--font-body);
880
1299
  font-size: var(--text-base);
881
1300
  line-height: var(--leading-normal);
882
1301
  color: var(--color-fg);
@@ -887,6 +1306,11 @@ html {
887
1306
 
888
1307
  body {
889
1308
  min-height: 100dvh;
1309
+ /* The page's material. `none` by default (the initial value), so this is a
1310
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1311
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1312
+ covers the viewport, so the two compose instead of overwriting. */
1313
+ background-image: var(--texture-page);
890
1314
  }
891
1315
 
892
1316
  img,
@@ -956,10 +1380,32 @@ table {
956
1380
  }
957
1381
  }
958
1382
 
959
- /* Focus visible — default ring */
1383
+ /* Text selection — the decoration axis reaching the one surface no component
1384
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1385
+ of a themed page that never matched the theme. Both values are tokens
1386
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1387
+ ::selection {
1388
+ background-color: var(--selection-bg);
1389
+ color: var(--selection-fg);
1390
+ }
1391
+
1392
+ /* Focus visible — the default ring, and the only place it is spelled out.
1393
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1394
+ focus once and every element that has not drawn its own ring follows. */
960
1395
  :focus-visible {
961
- outline: 2px solid var(--color-ring);
962
- outline-offset: 2px;
1396
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1397
+ outline-offset: var(--focus-ring-offset);
1398
+ }
1399
+
1400
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1401
+ is not a property focus owns: an element's resting shadow — a card's depth,
1402
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1403
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1404
+ sets a shadow outranks this one, so it lands only on an element nothing else
1405
+ shadows, and it never takes a shadow away. The controls that draw their own
1406
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1407
+ :where(:focus-visible) {
1408
+ box-shadow: var(--focus-shadow);
963
1409
  }
964
1410
 
965
1411
  /* Hidden but accessible */
@@ -988,7 +1434,7 @@ table {
988
1434
  /* @ui:base prose — typography defaults for long-form content */
989
1435
 
990
1436
  [data-ui="prose"] {
991
- font-family: var(--font-sans);
1437
+ font-family: var(--font-body);
992
1438
  font-size: var(--text-base);
993
1439
  line-height: var(--leading-relaxed);
994
1440
  color: var(--color-fg);
@@ -996,29 +1442,45 @@ table {
996
1442
  }
997
1443
 
998
1444
  [data-ui="prose"] h1 {
1445
+ font-family: var(--font-heading);
999
1446
  font-size: var(--text-4xl);
1000
- font-weight: var(--weight-bold);
1001
- line-height: var(--leading-tight);
1447
+ font-weight: var(--heading-weight);
1448
+ letter-spacing: var(--heading-tracking);
1449
+ text-transform: var(--heading-transform);
1450
+ font-variant-caps: var(--heading-caps);
1451
+ line-height: var(--heading-leading);
1002
1452
  margin-block: var(--space-8) var(--space-4);
1003
1453
  }
1004
1454
 
1005
1455
  [data-ui="prose"] h2 {
1456
+ font-family: var(--font-heading);
1006
1457
  font-size: var(--text-3xl);
1007
1458
  font-weight: var(--weight-semibold);
1008
- line-height: var(--leading-tight);
1459
+ letter-spacing: var(--heading-tracking);
1460
+ text-transform: var(--heading-transform);
1461
+ font-variant-caps: var(--heading-caps);
1462
+ line-height: var(--heading-leading);
1009
1463
  margin-block: var(--space-8) var(--space-3);
1010
1464
  }
1011
1465
 
1012
1466
  [data-ui="prose"] h3 {
1467
+ font-family: var(--font-heading);
1013
1468
  font-size: var(--text-2xl);
1014
1469
  font-weight: var(--weight-semibold);
1470
+ letter-spacing: var(--heading-tracking);
1471
+ text-transform: var(--heading-transform);
1472
+ font-variant-caps: var(--heading-caps);
1015
1473
  line-height: var(--leading-snug);
1016
1474
  margin-block: var(--space-6) var(--space-3);
1017
1475
  }
1018
1476
 
1019
1477
  [data-ui="prose"] h4 {
1478
+ font-family: var(--font-heading);
1020
1479
  font-size: var(--text-xl);
1021
1480
  font-weight: var(--weight-semibold);
1481
+ letter-spacing: var(--heading-tracking);
1482
+ text-transform: var(--heading-transform);
1483
+ font-variant-caps: var(--heading-caps);
1022
1484
  line-height: var(--leading-snug);
1023
1485
  margin-block: var(--space-6) var(--space-2);
1024
1486
  }
@@ -1029,8 +1491,8 @@ table {
1029
1491
 
1030
1492
  [data-ui="prose"] a {
1031
1493
  color: var(--color-primary);
1032
- text-decoration: underline;
1033
- text-underline-offset: 2px;
1494
+ text-decoration-line: var(--link-decoration);
1495
+ text-underline-offset: var(--link-underline-offset);
1034
1496
  }
1035
1497
 
1036
1498
  [data-ui="prose"] a:hover {
@@ -1067,7 +1529,7 @@ table {
1067
1529
  }
1068
1530
 
1069
1531
  [data-ui="prose"] blockquote {
1070
- border-inline-start: 3px solid var(--color-border-strong);
1532
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1071
1533
  padding-inline-start: var(--space-4);
1072
1534
  color: var(--color-fg-muted);
1073
1535
  margin-block: var(--space-4);
@@ -1089,9 +1551,15 @@ table {
1089
1551
  margin-block: var(--space-1);
1090
1552
  }
1091
1553
 
1554
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1555
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1556
+ [data-ui="prose"] li::marker {
1557
+ color: var(--marker-color);
1558
+ }
1559
+
1092
1560
  [data-ui="prose"] hr {
1093
1561
  border: none;
1094
- border-block-start: 1px solid var(--color-border);
1562
+ border-block-start: var(--border-width) solid var(--color-border);
1095
1563
  margin-block: var(--space-8);
1096
1564
  }
1097
1565
 
@@ -1110,12 +1578,12 @@ table {
1110
1578
  font-weight: var(--weight-semibold);
1111
1579
  text-align: start;
1112
1580
  padding: var(--space-2) var(--space-3);
1113
- border-block-end: 2px solid var(--color-border-strong);
1581
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1114
1582
  }
1115
1583
 
1116
1584
  [data-ui="prose"] td {
1117
1585
  padding: var(--space-2) var(--space-3);
1118
- border-block-end: 1px solid var(--color-border);
1586
+ border-block-end: var(--border-width) solid var(--color-border);
1119
1587
  }
1120
1588
 
1121
1589
  /* First child no top margin, last child no bottom margin */
@@ -1300,7 +1768,7 @@ table {
1300
1768
 
1301
1769
  /* === primitives/avatar.css === */
1302
1770
  /* @ui:component avatar */
1303
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1771
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1304
1772
 
1305
1773
  /* ── Base ── */
1306
1774
  [data-ui="avatar"] {
@@ -1330,7 +1798,7 @@ table {
1330
1798
  height: 100%;
1331
1799
  background: var(--color-bg-muted);
1332
1800
  color: var(--color-fg-muted);
1333
- font-family: var(--font-sans);
1801
+ font-family: var(--font-ui);
1334
1802
  font-size: var(--text-sm);
1335
1803
  font-weight: var(--weight-medium);
1336
1804
  text-transform: uppercase;
@@ -1355,7 +1823,7 @@ table {
1355
1823
 
1356
1824
  /* === primitives/badge.css === */
1357
1825
  /* @ui:component badge */
1358
- /* @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 */
1826
+ /* @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 */
1359
1827
 
1360
1828
  /* ── Base ── */
1361
1829
  [data-ui="badge"] {
@@ -1365,9 +1833,10 @@ table {
1365
1833
  gap: var(--space-1);
1366
1834
  padding: 0.125rem var(--space-2);
1367
1835
  border-radius: var(--badge-radius, var(--radius-full));
1836
+ corner-shape: var(--corner-shape);
1368
1837
  background: var(--color-bg-muted);
1369
1838
  color: var(--color-fg);
1370
- font-family: var(--badge-font, var(--font-sans));
1839
+ font-family: var(--badge-font, var(--font-ui));
1371
1840
  font-size: var(--text-xs);
1372
1841
  font-weight: var(--weight-medium);
1373
1842
  line-height: 1.5;
@@ -1413,11 +1882,11 @@ table {
1413
1882
 
1414
1883
  /* === primitives/breadcrumb.css === */
1415
1884
  /* @ui:component breadcrumb */
1416
- /* @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 */
1885
+ /* @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 */
1417
1886
 
1418
1887
  /* ── Root ── */
1419
1888
  [data-ui="breadcrumb"] {
1420
- font-family: var(--breadcrumb-font, var(--font-sans));
1889
+ font-family: var(--breadcrumb-font, var(--font-ui));
1421
1890
  font-size: var(--breadcrumb-size, var(--text-sm));
1422
1891
  color: var(--color-fg-muted);
1423
1892
  }
@@ -1443,12 +1912,13 @@ table {
1443
1912
 
1444
1913
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1445
1914
  color: var(--color-primary-hover);
1446
- text-decoration: underline;
1915
+ text-decoration-line: var(--link-decoration);
1447
1916
  }
1448
1917
 
1449
1918
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1450
- outline: 2px solid var(--color-ring);
1451
- outline-offset: 2px;
1919
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1920
+ outline-offset: var(--focus-ring-offset);
1921
+ box-shadow: var(--focus-shadow);
1452
1922
  }
1453
1923
 
1454
1924
  /* ── Separator (presentational) ── */
@@ -1488,7 +1958,7 @@ table {
1488
1958
 
1489
1959
  /* === primitives/button.css === */
1490
1960
  /* @ui:component button */
1491
- /* @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 */
1961
+ /* @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 */
1492
1962
 
1493
1963
  /* ── Base ── */
1494
1964
  [data-ui="button"] {
@@ -1498,18 +1968,21 @@ table {
1498
1968
  gap: var(--space-2);
1499
1969
  height: var(--button-height-md, 40px);
1500
1970
  padding-inline: var(--space-4);
1501
- border: 1px solid var(--color-border);
1971
+ border: var(--border-width) solid var(--color-border);
1502
1972
  border-radius: var(--button-radius, var(--radius-md));
1973
+ corner-shape: var(--corner-shape);
1503
1974
  background: var(--color-bg);
1504
1975
  color: var(--color-fg);
1505
- font-family: var(--font-sans);
1976
+ font-family: var(--font-ui);
1506
1977
  font-size: var(--text-sm);
1507
1978
  font-weight: var(--weight-medium);
1979
+ text-transform: var(--button-text-transform);
1508
1980
  line-height: 1;
1509
1981
  cursor: pointer;
1510
1982
  transition: background var(--duration-fast) var(--ease-default),
1511
1983
  border-color var(--duration-fast) var(--ease-default),
1512
1984
  color var(--duration-fast) var(--ease-default),
1985
+ translate var(--duration-fast) var(--ease-default),
1513
1986
  box-shadow var(--duration-fast) var(--ease-default);
1514
1987
  user-select: none;
1515
1988
  white-space: nowrap;
@@ -1518,11 +1991,16 @@ table {
1518
1991
 
1519
1992
  [data-ui="button"]:hover {
1520
1993
  background: var(--color-bg-muted);
1994
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1995
+ this rule computes what the button computed before the token existed; a
1996
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1997
+ translate: var(--motion-hover-lift);
1521
1998
  }
1522
1999
 
1523
2000
  [data-ui="button"]:focus-visible {
1524
- outline: 2px solid var(--color-ring);
1525
- outline-offset: 2px;
2001
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2002
+ outline-offset: var(--focus-ring-offset);
2003
+ box-shadow: var(--focus-shadow);
1526
2004
  }
1527
2005
 
1528
2006
  /* ── Variants ── */
@@ -1578,7 +2056,7 @@ table {
1578
2056
  padding: 0;
1579
2057
  }
1580
2058
  [data-ui="button"][data-variant="link"]:hover {
1581
- text-decoration: underline;
2059
+ text-decoration-line: var(--link-decoration);
1582
2060
  }
1583
2061
 
1584
2062
  /* ── Sizes ── */
@@ -1597,7 +2075,7 @@ table {
1597
2075
  /* ── States ── */
1598
2076
  [data-ui="button"]:disabled,
1599
2077
  [data-ui="button"][data-state="disabled"] {
1600
- opacity: 0.5;
2078
+ opacity: var(--disabled-opacity);
1601
2079
  cursor: not-allowed;
1602
2080
  pointer-events: none;
1603
2081
  }
@@ -1612,7 +2090,7 @@ table {
1612
2090
  position: absolute;
1613
2091
  width: 1em;
1614
2092
  height: 1em;
1615
- border: 2px solid currentColor;
2093
+ border: var(--border-width-strong) solid currentColor;
1616
2094
  border-inline-end-color: transparent;
1617
2095
  border-radius: var(--radius-full);
1618
2096
  animation: faqir-spin 0.6s linear infinite;
@@ -1659,7 +2137,7 @@ table {
1659
2137
 
1660
2138
  /* === primitives/callout.css === */
1661
2139
  /* @ui:component callout */
1662
- /* @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 */
2140
+ /* @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 */
1663
2141
 
1664
2142
  /* ── Base ── */
1665
2143
  [data-ui="callout"] {
@@ -1668,7 +2146,7 @@ table {
1668
2146
  padding: var(--callout-padding-y) var(--callout-padding-x);
1669
2147
  border-radius: var(--callout-radius);
1670
2148
  border-inline-start: var(--callout-border-left-width) solid;
1671
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2149
+ font-family: var(--doc-font, var(--font-body));
1672
2150
  font-size: var(--callout-font-size);
1673
2151
  line-height: var(--doc-line-height, 1.5);
1674
2152
  }
@@ -1699,6 +2177,7 @@ table {
1699
2177
  /* ── Title ── */
1700
2178
  [data-ui="callout"] [data-part="title"] {
1701
2179
  display: block;
2180
+ font-family: var(--font-heading);
1702
2181
  font-weight: var(--weight-semibold);
1703
2182
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1704
2183
  }
@@ -1725,8 +2204,9 @@ table {
1725
2204
  }
1726
2205
 
1727
2206
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1728
- outline: 2px solid var(--color-ring, var(--color-info));
1729
- outline-offset: 2px;
2207
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2208
+ outline-offset: var(--focus-ring-offset);
2209
+ box-shadow: var(--focus-shadow);
1730
2210
  opacity: 1;
1731
2211
  }
1732
2212
 
@@ -1812,17 +2292,36 @@ table {
1812
2292
 
1813
2293
  /* === primitives/card.css === */
1814
2294
  /* @ui:component card */
1815
- /* @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 */
2295
+ /* @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 */
1816
2296
 
1817
2297
  /* ── Base ── */
1818
2298
  [data-ui="card"] {
1819
2299
  display: flex;
1820
2300
  flex-direction: column;
1821
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2301
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1822
2302
  border-radius: var(--card-radius, var(--radius-lg));
1823
- background: var(--card-bg, var(--color-surface-1));
2303
+ corner-shape: var(--corner-shape);
2304
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2305
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2306
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2307
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1824
2308
  box-shadow: var(--card-shadow, var(--shadow-sm));
1825
2309
  overflow: hidden;
2310
+ transition: translate var(--duration-fast) var(--ease-default);
2311
+ }
2312
+
2313
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2314
+ value of `translate`), so a card sits exactly where it always sat until a
2315
+ theme says surfaces rise under the pointer. */
2316
+ [data-ui="card"]:hover {
2317
+ translate: var(--motion-hover-lift);
2318
+ }
2319
+
2320
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2321
+ [data-ui="card"] {
2322
+ -webkit-backdrop-filter: var(--surface-backdrop);
2323
+ backdrop-filter: var(--surface-backdrop);
2324
+ }
1826
2325
  }
1827
2326
 
1828
2327
  /* ── Variants ── */
@@ -1831,7 +2330,7 @@ table {
1831
2330
  }
1832
2331
 
1833
2332
  [data-ui="card"][data-variant="filled"] {
1834
- background: var(--color-surface-2);
2333
+ background: var(--texture-surface), var(--color-surface-2);
1835
2334
  border-color: var(--color-surface-2-border);
1836
2335
  box-shadow: none;
1837
2336
  }
@@ -1846,7 +2345,7 @@ table {
1846
2345
  }
1847
2346
 
1848
2347
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1849
- font-family: var(--font-sans);
2348
+ font-family: var(--font-heading);
1850
2349
  font-size: var(--text-lg);
1851
2350
  font-weight: var(--weight-semibold);
1852
2351
  line-height: var(--leading-tight);
@@ -1887,9 +2386,19 @@ table {
1887
2386
  padding-top: 0;
1888
2387
  }
1889
2388
 
2389
+ /* ── Motion ── */
2390
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2391
+ theme states one — but the house rule is that a stylesheet which transitions
2392
+ carries its own opt-out, so a reader never has to check the token first. */
2393
+ @media (prefers-reduced-motion: reduce) {
2394
+ [data-ui="card"] {
2395
+ transition: none;
2396
+ }
2397
+ }
2398
+
1890
2399
  /* === primitives/checkbox.css === */
1891
2400
  /* @ui:component checkbox */
1892
- /* @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 */
2401
+ /* @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 */
1893
2402
 
1894
2403
  /* -- Label wrapper -- */
1895
2404
  [data-ui="checkbox-label"] {
@@ -1901,7 +2410,7 @@ table {
1901
2410
 
1902
2411
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1903
2412
  cursor: not-allowed;
1904
- opacity: 0.5;
2413
+ opacity: var(--disabled-opacity);
1905
2414
  }
1906
2415
 
1907
2416
  /* -- Base -- */
@@ -1913,8 +2422,8 @@ table {
1913
2422
  width: var(--checkbox-size, 18px);
1914
2423
  height: var(--checkbox-size, 18px);
1915
2424
  flex-shrink: 0;
1916
- border: 1px solid var(--color-border);
1917
- border-radius: var(--checkbox-radius, var(--radius-sm));
2425
+ border: var(--border-width) solid var(--color-border);
2426
+ border-radius: var(--checkbox-radius);
1918
2427
  background: var(--color-bg);
1919
2428
  cursor: pointer;
1920
2429
  transition: background var(--duration-fast) var(--ease-default),
@@ -1927,8 +2436,9 @@ table {
1927
2436
  }
1928
2437
 
1929
2438
  [data-ui="checkbox"]:focus-visible {
1930
- outline: 2px solid var(--color-ring);
1931
- outline-offset: 2px;
2439
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2440
+ outline-offset: var(--focus-ring-offset);
2441
+ box-shadow: var(--focus-shadow);
1932
2442
  }
1933
2443
 
1934
2444
  /* -- Checked -- */
@@ -2019,7 +2529,7 @@ table {
2019
2529
  The mask has to opt out of the substitution to stay readable. [W3-3] */
2020
2530
  @media (forced-colors: active) {
2021
2531
  [data-ui="checkbox"] {
2022
- border: 1px solid ButtonText;
2532
+ border: var(--border-width) solid ButtonText;
2023
2533
  }
2024
2534
 
2025
2535
  [data-ui="checkbox"]:checked,
@@ -2043,7 +2553,7 @@ table {
2043
2553
 
2044
2554
  /* === primitives/chip.css === */
2045
2555
  /* @ui:component chip */
2046
- /* @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 */
2556
+ /* @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 */
2047
2557
 
2048
2558
  /* ── Base ── */
2049
2559
  [data-ui="chip"] {
@@ -2051,11 +2561,11 @@ table {
2051
2561
  align-items: center;
2052
2562
  gap: var(--space-1);
2053
2563
  padding: var(--space-1) var(--space-2);
2054
- border: 1px solid transparent;
2564
+ border: var(--border-width) solid transparent;
2055
2565
  border-radius: var(--chip-radius, var(--radius-full));
2056
2566
  background: var(--color-bg-muted);
2057
2567
  color: var(--color-fg);
2058
- font-family: var(--chip-font, var(--font-sans));
2568
+ font-family: var(--chip-font, var(--font-ui));
2059
2569
  font-size: var(--text-sm);
2060
2570
  font-weight: var(--weight-medium);
2061
2571
  line-height: 1.2;
@@ -2091,8 +2601,11 @@ table {
2091
2601
  }
2092
2602
 
2093
2603
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2094
- outline: 2px solid var(--color-ring);
2095
- outline-offset: 1px;
2604
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2605
+ /* Half the default gap — the dismiss target is small, and the full ring
2606
+ would collide with the chip's own edge. */
2607
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2608
+ box-shadow: var(--focus-shadow);
2096
2609
  }
2097
2610
 
2098
2611
  /* ── Variants ── */
@@ -2315,12 +2828,12 @@ table {
2315
2828
 
2316
2829
  /* === primitives/collapsible.css === */
2317
2830
  /* @ui:component collapsible */
2318
- /* @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 */
2831
+ /* @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 */
2319
2832
 
2320
2833
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2321
2834
  [data-ui="collapsible"] {
2322
2835
  border-radius: var(--collapsible-radius, var(--radius-md));
2323
- font-family: var(--collapsible-font, var(--font-sans));
2836
+ font-family: var(--collapsible-font, var(--font-ui));
2324
2837
  color: var(--color-fg);
2325
2838
  }
2326
2839
 
@@ -2350,8 +2863,9 @@ table {
2350
2863
  }
2351
2864
 
2352
2865
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2353
- outline: 2px solid var(--color-ring);
2354
- outline-offset: 2px;
2866
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2867
+ outline-offset: var(--focus-ring-offset);
2868
+ box-shadow: var(--focus-shadow);
2355
2869
  }
2356
2870
 
2357
2871
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2360,8 +2874,8 @@ table {
2360
2874
  flex: none;
2361
2875
  width: 0.5em;
2362
2876
  height: 0.5em;
2363
- border-inline-end: 2px solid var(--color-fg-muted);
2364
- border-block-end: 2px solid var(--color-fg-muted);
2877
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2878
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2365
2879
  transform: rotate(45deg);
2366
2880
  transition: transform var(--duration-normal) var(--ease-default);
2367
2881
  }
@@ -2380,7 +2894,7 @@ table {
2380
2894
 
2381
2895
  /* ── Bordered variant ── */
2382
2896
  [data-ui="collapsible"][data-variant="bordered"] {
2383
- border: 1px solid var(--color-border);
2897
+ border: var(--border-width) solid var(--color-border);
2384
2898
  }
2385
2899
 
2386
2900
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2513,13 +3027,13 @@ table {
2513
3027
 
2514
3028
  /* === primitives/description-list.css === */
2515
3029
  /* @ui:component description-list */
2516
- /* @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 */
3030
+ /* @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 */
2517
3031
 
2518
3032
  /* ── Base ── */
2519
3033
  [data-ui="description-list"] {
2520
3034
  margin: 0;
2521
3035
  padding: 0;
2522
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3036
+ font-family: var(--doc-font, var(--font-body));
2523
3037
  }
2524
3038
 
2525
3039
  /* ── Term ── */
@@ -2575,7 +3089,7 @@ table {
2575
3089
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2576
3090
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2577
3091
  padding-bottom: var(--space-4);
2578
- border-bottom: 1px solid var(--color-border);
3092
+ border-bottom: var(--border-width) solid var(--color-border);
2579
3093
  }
2580
3094
 
2581
3095
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2587,7 +3101,7 @@ table {
2587
3101
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2588
3102
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2589
3103
  padding-bottom: var(--space-3);
2590
- border-bottom: 1px solid var(--color-border);
3104
+ border-bottom: var(--border-width) solid var(--color-border);
2591
3105
  }
2592
3106
 
2593
3107
  /* ── Size: Small ── */
@@ -2625,7 +3139,7 @@ table {
2625
3139
 
2626
3140
  /* === primitives/empty-state.css === */
2627
3141
  /* @ui:component empty-state */
2628
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3142
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2629
3143
 
2630
3144
  /* ── Base ── */
2631
3145
  [data-ui="empty-state"] {
@@ -2646,6 +3160,7 @@ table {
2646
3160
 
2647
3161
  /* ── Title ── */
2648
3162
  [data-ui="empty-state"] [data-part="title"] {
3163
+ font-family: var(--font-heading);
2649
3164
  font-size: var(--text-lg);
2650
3165
  font-weight: var(--weight-medium);
2651
3166
  color: var(--color-fg);
@@ -2693,7 +3208,7 @@ table {
2693
3208
 
2694
3209
  /* === primitives/field-group.css === */
2695
3210
  /* @ui:component field-group */
2696
- /* @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 */
3211
+ /* @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 */
2697
3212
 
2698
3213
  /* ── Base / spacing ownership ──
2699
3214
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2705,7 +3220,7 @@ table {
2705
3220
  display: flex;
2706
3221
  flex-direction: column;
2707
3222
  gap: var(--space-2);
2708
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3223
+ font-family: var(--doc-font, var(--font-body));
2709
3224
  }
2710
3225
 
2711
3226
  /* ── Label ── */
@@ -2775,7 +3290,7 @@ table {
2775
3290
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2776
3291
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2777
3292
  border-color: var(--field-error-color);
2778
- box-shadow: 0 0 0 1px var(--field-error-color);
3293
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2779
3294
  }
2780
3295
 
2781
3296
  /* ── State: Validating ──
@@ -2785,7 +3300,7 @@ table {
2785
3300
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2786
3301
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2787
3302
  border-color: var(--field-validating-color);
2788
- box-shadow: 0 0 0 1px var(--field-validating-color);
3303
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2789
3304
  }
2790
3305
 
2791
3306
  /* ── State: Disabled ──
@@ -2804,8 +3319,8 @@ table {
2804
3319
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2805
3320
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2806
3321
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2807
- border-color: var(--color-success, oklch(0.62 0.19 145));
2808
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3322
+ border-color: var(--color-success);
3323
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2809
3324
  }
2810
3325
 
2811
3326
  /* ── Variant: Horizontal ── */
@@ -3110,7 +3625,7 @@ table {
3110
3625
 
3111
3626
  /* === primitives/image.css === */
3112
3627
  /* @ui:component image */
3113
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3628
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3114
3629
 
3115
3630
  /* ── Base ── */
3116
3631
  [data-ui="image"] {
@@ -3134,7 +3649,7 @@ table {
3134
3649
  [data-ui="image"] [data-part="caption"] {
3135
3650
  display: block;
3136
3651
  margin-top: var(--space-2);
3137
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3652
+ font-family: var(--doc-font, var(--font-body));
3138
3653
  font-size: var(--image-caption-size);
3139
3654
  color: var(--image-caption-color);
3140
3655
  line-height: 1.4;
@@ -3231,7 +3746,7 @@ table {
3231
3746
 
3232
3747
  /* === primitives/input.css === */
3233
3748
  /* @ui:component input */
3234
- /* @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 */
3749
+ /* @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 */
3235
3750
 
3236
3751
  /* ── Base ── */
3237
3752
  [data-ui="input"] {
@@ -3239,11 +3754,18 @@ table {
3239
3754
  width: 100%;
3240
3755
  height: var(--input-height, 40px);
3241
3756
  padding-inline: var(--space-3);
3242
- border: 1px solid var(--color-border);
3757
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3758
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3759
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3760
+ is drawn. Identical to the shorthand at every other value of the token. */
3761
+ border-style: solid;
3762
+ border-color: var(--color-border);
3763
+ border-width: var(--input-border-width);
3243
3764
  border-radius: var(--input-radius, var(--radius-md));
3244
- background: var(--input-bg, var(--color-bg));
3765
+ corner-shape: var(--corner-shape);
3766
+ background: var(--input-fill);
3245
3767
  color: var(--color-fg);
3246
- font-family: var(--input-font, var(--font-sans));
3768
+ font-family: var(--input-font, var(--font-ui));
3247
3769
  font-size: var(--text-sm);
3248
3770
  line-height: 1;
3249
3771
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3259,8 +3781,11 @@ table {
3259
3781
  }
3260
3782
 
3261
3783
  [data-ui="input"]:focus {
3262
- outline: 2px solid var(--color-ring);
3263
- outline-offset: -1px;
3784
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3785
+ /* The ring replaces the border rather than sitting outside it: inset by
3786
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3787
+ outline-offset: calc(-1 * var(--input-border-width));
3788
+ box-shadow: var(--focus-shadow);
3264
3789
  border-color: transparent;
3265
3790
  }
3266
3791
 
@@ -3288,7 +3813,7 @@ table {
3288
3813
  }
3289
3814
 
3290
3815
  [data-ui="input"]:disabled {
3291
- opacity: 0.5;
3816
+ opacity: var(--disabled-opacity);
3292
3817
  cursor: not-allowed;
3293
3818
  }
3294
3819
 
@@ -3351,7 +3876,7 @@ table {
3351
3876
 
3352
3877
  /* === primitives/kbd.css === */
3353
3878
  /* @ui:component kbd */
3354
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3879
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3355
3880
 
3356
3881
  /* ── Base ── */
3357
3882
  [data-ui="kbd"] {
@@ -3361,8 +3886,8 @@ table {
3361
3886
  height: 20px;
3362
3887
  min-width: 20px;
3363
3888
  padding-inline: var(--space-1h);
3364
- border: 1px solid var(--color-border);
3365
- border-bottom-width: 2px;
3889
+ border: var(--border-width) solid var(--color-border);
3890
+ border-bottom-width: var(--border-width-strong);
3366
3891
  border-radius: var(--radius-sm);
3367
3892
  background: var(--color-bg-subtle);
3368
3893
  color: var(--color-fg);
@@ -3375,7 +3900,7 @@ table {
3375
3900
 
3376
3901
  /* === primitives/key-value.css === */
3377
3902
  /* @ui:component key-value */
3378
- /* @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 */
3903
+ /* @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 */
3379
3904
 
3380
3905
  /* ── Base ── */
3381
3906
  [data-ui="key-value"] {
@@ -3384,7 +3909,7 @@ table {
3384
3909
  gap: var(--kv-pair-gap);
3385
3910
  margin: 0;
3386
3911
  padding: 0;
3387
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3912
+ font-family: var(--doc-font, var(--font-body));
3388
3913
  }
3389
3914
 
3390
3915
  /* ── Label ── */
@@ -3514,12 +4039,12 @@ table {
3514
4039
 
3515
4040
  /* === primitives/label.css === */
3516
4041
  /* @ui:component label */
3517
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4042
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3518
4043
 
3519
4044
  /* ── Base ── */
3520
4045
  [data-ui="label"] {
3521
4046
  display: block;
3522
- font-family: var(--font-sans);
4047
+ font-family: var(--font-ui);
3523
4048
  font-size: var(--text-sm);
3524
4049
  font-weight: var(--weight-medium);
3525
4050
  color: var(--color-fg);
@@ -3552,21 +4077,21 @@ table {
3552
4077
 
3553
4078
  /* ── States ── */
3554
4079
  [data-ui="label"][data-state="disabled"] {
3555
- opacity: 0.5;
4080
+ opacity: var(--disabled-opacity);
3556
4081
  cursor: not-allowed;
3557
4082
  }
3558
4083
 
3559
4084
  /* === primitives/link.css === */
3560
4085
  /* @ui:component link */
3561
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4086
+ /* @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 */
3562
4087
 
3563
4088
  /* ── Base ── */
3564
4089
  [data-ui="link"] {
3565
4090
  color: var(--color-primary);
3566
4091
  font-family: inherit;
3567
- text-decoration: underline;
3568
- text-decoration-thickness: 1px;
3569
- text-underline-offset: 0.2em;
4092
+ text-decoration-line: var(--link-decoration);
4093
+ text-decoration-thickness: var(--link-thickness);
4094
+ text-underline-offset: var(--link-underline-offset);
3570
4095
  border-radius: var(--radius-sm);
3571
4096
  cursor: pointer;
3572
4097
  }
@@ -3580,8 +4105,9 @@ table {
3580
4105
  }
3581
4106
 
3582
4107
  [data-ui="link"]:focus-visible {
3583
- outline: 2px solid var(--color-ring);
3584
- outline-offset: 2px;
4108
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4109
+ outline-offset: var(--focus-ring-offset);
4110
+ box-shadow: var(--focus-shadow);
3585
4111
  }
3586
4112
 
3587
4113
  /* ── Variants ── */
@@ -3605,7 +4131,7 @@ table {
3605
4131
 
3606
4132
  /* === primitives/nav.css === */
3607
4133
  /* @ui:component nav */
3608
- /* @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 */
4134
+ /* @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 */
3609
4135
 
3610
4136
  /* ── Base ── */
3611
4137
  [data-ui="nav"] {
@@ -3655,14 +4181,14 @@ table {
3655
4181
 
3656
4182
  /* ── Underline variant ── */
3657
4183
  [data-ui="nav"][data-variant="underline"] {
3658
- border-bottom: 1px solid var(--color-border);
4184
+ border-bottom: var(--border-width) solid var(--color-border);
3659
4185
  gap: 0;
3660
4186
  }
3661
4187
 
3662
4188
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3663
4189
  border-radius: 0;
3664
4190
  padding: var(--space-2) var(--space-4);
3665
- border-bottom: 2px solid transparent;
4191
+ border-bottom: var(--border-width-strong) solid transparent;
3666
4192
  margin-bottom: -1px;
3667
4193
  }
3668
4194
 
@@ -3718,7 +4244,7 @@ table {
3718
4244
 
3719
4245
  /* === primitives/page-break.css === */
3720
4246
  /* @ui:component page-break */
3721
- /* @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 */
4247
+ /* @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 */
3722
4248
 
3723
4249
  /* ── Base (Screen) ── */
3724
4250
  [data-ui="page-break"] {
@@ -3733,12 +4259,12 @@ table {
3733
4259
  [data-ui="page-break"]::after {
3734
4260
  content: "";
3735
4261
  flex: 1;
3736
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4262
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3737
4263
  }
3738
4264
 
3739
4265
  /* ── Label (Screen) ── */
3740
4266
  [data-ui="page-break"] {
3741
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4267
+ font-family: var(--doc-font, var(--font-body));
3742
4268
  font-size: var(--page-break-screen-label-size);
3743
4269
  color: var(--page-break-screen-label-color);
3744
4270
  letter-spacing: 0.05em;
@@ -3780,7 +4306,7 @@ table {
3780
4306
 
3781
4307
  /* === primitives/progress.css === */
3782
4308
  /* @ui:component progress */
3783
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4309
+ /* @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 */
3784
4310
 
3785
4311
  /* ── Base ── */
3786
4312
  [data-ui="progress"] {
@@ -3855,7 +4381,7 @@ table {
3855
4381
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3856
4382
  @media (forced-colors: active) {
3857
4383
  [data-ui="progress"] [data-part="track"] {
3858
- border: 1px solid ButtonText;
4384
+ border: var(--border-width) solid ButtonText;
3859
4385
  }
3860
4386
 
3861
4387
  [data-ui="progress"] [data-part="fill"],
@@ -3869,7 +4395,7 @@ table {
3869
4395
 
3870
4396
  /* === primitives/radio.css === */
3871
4397
  /* @ui:component radio */
3872
- /* @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 */
4398
+ /* @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 */
3873
4399
 
3874
4400
  /* -- Radio group -- */
3875
4401
  [data-ui="radio-group"] {
@@ -3891,7 +4417,7 @@ table {
3891
4417
 
3892
4418
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3893
4419
  cursor: not-allowed;
3894
- opacity: 0.5;
4420
+ opacity: var(--disabled-opacity);
3895
4421
  }
3896
4422
 
3897
4423
  /* -- Base -- */
@@ -3903,7 +4429,7 @@ table {
3903
4429
  width: var(--radio-size, 18px);
3904
4430
  height: var(--radio-size, 18px);
3905
4431
  flex-shrink: 0;
3906
- border: 1px solid var(--color-border);
4432
+ border: var(--border-width) solid var(--color-border);
3907
4433
  border-radius: var(--radius-full);
3908
4434
  background: var(--color-bg);
3909
4435
  cursor: pointer;
@@ -3917,8 +4443,9 @@ table {
3917
4443
  }
3918
4444
 
3919
4445
  [data-ui="radio"]:focus-visible {
3920
- outline: 2px solid var(--color-ring);
3921
- outline-offset: 2px;
4446
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4447
+ outline-offset: var(--focus-ring-offset);
4448
+ box-shadow: var(--focus-shadow);
3922
4449
  }
3923
4450
 
3924
4451
  /* -- Checked -- */
@@ -3971,7 +4498,7 @@ table {
3971
4498
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3972
4499
  @media (forced-colors: active) {
3973
4500
  [data-ui="radio"] {
3974
- border: 1px solid ButtonText;
4501
+ border: var(--border-width) solid ButtonText;
3975
4502
  }
3976
4503
 
3977
4504
  [data-ui="radio"]:checked {
@@ -3991,7 +4518,7 @@ table {
3991
4518
 
3992
4519
  /* === primitives/select.css === */
3993
4520
  /* @ui:component select */
3994
- /* @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 */
4521
+ /* @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 */
3995
4522
 
3996
4523
  /* -- Base -- */
3997
4524
  [data-ui="select"] {
@@ -4000,11 +4527,17 @@ table {
4000
4527
  height: var(--select-height, 40px);
4001
4528
  padding-inline: var(--space-3);
4002
4529
  padding-inline-end: var(--space-8, 2rem);
4003
- border: 1px solid var(--color-border);
4530
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4531
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4532
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4533
+ is drawn. Identical to the shorthand at every other value of the token. */
4534
+ border-style: solid;
4535
+ border-color: var(--color-border);
4536
+ border-width: var(--input-border-width);
4004
4537
  border-radius: var(--select-radius, var(--radius-md));
4005
- background: var(--select-bg, var(--color-bg));
4538
+ background: var(--select-bg, var(--input-fill));
4006
4539
  color: var(--color-fg);
4007
- font-family: var(--select-font, var(--font-sans));
4540
+ font-family: var(--select-font, var(--font-ui));
4008
4541
  font-size: var(--text-sm);
4009
4542
  line-height: 1;
4010
4543
  cursor: pointer;
@@ -4034,8 +4567,11 @@ table {
4034
4567
  }
4035
4568
 
4036
4569
  [data-ui="select"]:focus {
4037
- outline: 2px solid var(--color-ring);
4038
- outline-offset: -1px;
4570
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4571
+ /* The ring replaces the border rather than sitting outside it: inset by
4572
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4573
+ outline-offset: calc(-1 * var(--input-border-width));
4574
+ box-shadow: var(--focus-shadow);
4039
4575
  border-color: transparent;
4040
4576
  }
4041
4577
 
@@ -4068,7 +4604,7 @@ table {
4068
4604
  }
4069
4605
 
4070
4606
  [data-ui="select"]:disabled {
4071
- opacity: 0.5;
4607
+ opacity: var(--disabled-opacity);
4072
4608
  cursor: not-allowed;
4073
4609
  }
4074
4610
 
@@ -4081,12 +4617,12 @@ table {
4081
4617
 
4082
4618
  /* === primitives/separator.css === */
4083
4619
  /* @ui:component separator */
4084
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4620
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4085
4621
 
4086
4622
  /* ── Base (horizontal) ── */
4087
4623
  [data-ui="separator"] {
4088
4624
  border: none;
4089
- border-top: 1px solid var(--color-border);
4625
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4090
4626
  margin: 0;
4091
4627
  width: 100%;
4092
4628
  }
@@ -4094,7 +4630,7 @@ table {
4094
4630
  /* ── Vertical ── */
4095
4631
  [data-ui="separator"][data-variant="vertical"] {
4096
4632
  border-top: none;
4097
- border-inline-start: 1px solid var(--color-border);
4633
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4098
4634
  width: auto;
4099
4635
  height: 100%;
4100
4636
  align-self: stretch;
@@ -4112,11 +4648,11 @@ div[data-ui="separator"]::before,
4112
4648
  div[data-ui="separator"]::after {
4113
4649
  content: "";
4114
4650
  flex: 1;
4115
- border-top: 1px solid var(--color-border);
4651
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4116
4652
  }
4117
4653
 
4118
4654
  [data-ui="separator"] [data-part="label"] {
4119
- font-family: var(--font-sans);
4655
+ font-family: var(--font-ui);
4120
4656
  font-size: var(--text-xs);
4121
4657
  color: var(--color-fg-muted);
4122
4658
  white-space: nowrap;
@@ -4154,17 +4690,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4154
4690
 
4155
4691
  /* ── Style: Thick ── */
4156
4692
  [data-ui="separator"][data-style="thick"] {
4157
- border-top-width: 2px;
4693
+ border-top-width: var(--border-width-strong);
4158
4694
  }
4159
4695
 
4160
4696
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4161
4697
  border-top-width: 0;
4162
- border-inline-start-width: 2px;
4698
+ border-inline-start-width: var(--border-width-strong);
4163
4699
  }
4164
4700
 
4165
4701
  div[data-ui="separator"][data-style="thick"]::before,
4166
4702
  div[data-ui="separator"][data-style="thick"]::after {
4167
- border-top-width: 2px;
4703
+ border-top-width: var(--border-width-strong);
4168
4704
  }
4169
4705
 
4170
4706
  /* ── Vertical Sizes ── */
@@ -4182,20 +4718,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4182
4718
 
4183
4719
  /* === primitives/signature.css === */
4184
4720
  /* @ui:component signature */
4185
- /* @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 */
4721
+ /* @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 */
4186
4722
 
4187
4723
  /* ── Base ── */
4188
4724
  [data-ui="signature"] {
4189
4725
  display: flex;
4190
4726
  flex-direction: column;
4191
4727
  gap: var(--space-2);
4192
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4728
+ font-family: var(--doc-font, var(--font-body));
4193
4729
  margin-top: var(--doc-signature-gap);
4194
4730
  }
4195
4731
 
4196
4732
  /* ── Line ── */
4197
4733
  [data-ui="signature"] [data-part="line"] {
4198
- border-top: 1px solid var(--doc-signature-line-color);
4734
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4199
4735
  min-height: 1px;
4200
4736
  }
4201
4737
 
@@ -4298,14 +4834,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4298
4834
 
4299
4835
  /* === primitives/spinner.css === */
4300
4836
  /* @ui:component spinner */
4301
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4837
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4302
4838
 
4303
4839
  /* ── Base ── */
4304
4840
  [data-ui="spinner"] {
4305
4841
  display: inline-block;
4306
4842
  width: 24px;
4307
4843
  height: 24px;
4308
- border: 2px solid var(--color-border);
4844
+ border: var(--border-width-strong) solid var(--color-border);
4309
4845
  border-top-color: var(--color-primary);
4310
4846
  border-radius: var(--radius-full);
4311
4847
  animation: faqir-spin 0.75s linear infinite;
@@ -4321,13 +4857,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4321
4857
  [data-ui="spinner"][data-size="lg"] {
4322
4858
  width: 32px;
4323
4859
  height: 32px;
4324
- border-width: 3px;
4860
+ border-width: var(--border-width-lg);
4325
4861
  }
4326
4862
 
4327
4863
  [data-ui="spinner"][data-size="xl"] {
4328
4864
  width: 48px;
4329
4865
  height: 48px;
4330
- border-width: 3px;
4866
+ border-width: var(--border-width-lg);
4331
4867
  }
4332
4868
 
4333
4869
  /* ── Motion ── */
@@ -4909,14 +5445,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4909
5445
 
4910
5446
  /* === primitives/stat.css === */
4911
5447
  /* @ui:component stat */
4912
- /* @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 */
5448
+ /* @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 */
4913
5449
 
4914
5450
  /* ── Base ── */
4915
5451
  [data-ui="stat"] {
4916
5452
  display: flex;
4917
5453
  flex-direction: column;
4918
5454
  gap: var(--space-1);
4919
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5455
+ font-family: var(--doc-font, var(--font-body));
4920
5456
  }
4921
5457
 
4922
5458
  /* ── Label ── */
@@ -4930,6 +5466,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4930
5466
 
4931
5467
  /* ── Value ── */
4932
5468
  [data-ui="stat"] [data-part="value"] {
5469
+ font-family: var(--font-heading);
4933
5470
  font-size: var(--stat-value-size);
4934
5471
  font-weight: var(--stat-value-weight);
4935
5472
  color: var(--color-fg);
@@ -4988,10 +5525,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4988
5525
  /* ── Variant: Card ── */
4989
5526
  [data-ui="stat"][data-variant="card"] {
4990
5527
  padding: var(--space-4);
4991
- border: 1px solid var(--color-border);
5528
+ border: var(--border-width) solid var(--color-border);
4992
5529
  border-radius: var(--radius-md, 0.375rem);
4993
5530
  background: var(--color-bg);
4994
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5531
+ box-shadow: var(--shadow-sm);
4995
5532
  }
4996
5533
 
4997
5534
  /* ── Value + Change Inline ── */
@@ -5003,7 +5540,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5003
5540
  @media print {
5004
5541
  [data-ui="stat"][data-variant="card"] {
5005
5542
  box-shadow: none;
5006
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5543
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
5007
5544
  }
5008
5545
 
5009
5546
  [data-ui="stat"] {
@@ -5013,7 +5550,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5013
5550
 
5014
5551
  /* === primitives/stepper.css === */
5015
5552
  /* @ui:component stepper */
5016
- /* @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 */
5553
+ /* @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 */
5017
5554
 
5018
5555
  /* ── Base ── */
5019
5556
  [data-ui="stepper"] {
@@ -5092,7 +5629,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5092
5629
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5093
5630
  [data-ui="stepper"] [data-part="connector"] {
5094
5631
  flex: 1;
5095
- height: 2px;
5632
+ height: var(--border-width-strong);
5096
5633
  background: var(--color-border);
5097
5634
  margin: 0 var(--space-1);
5098
5635
  min-width: var(--space-2);
@@ -5160,18 +5697,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5160
5697
 
5161
5698
  /* === primitives/surface.css === */
5162
5699
  /* @ui:component surface */
5163
- /* @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 */
5700
+ /* @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 */
5164
5701
 
5165
5702
  /* ── Base ── */
5166
5703
  [data-ui="surface"] {
5167
- background: var(--color-surface-1);
5704
+ background-color: var(--color-surface-1);
5705
+ background-image: var(--texture-surface);
5168
5706
  border-radius: var(--radius-lg);
5169
- border: 1px solid var(--color-surface-1-border);
5707
+ corner-shape: var(--corner-shape);
5708
+ border: var(--border-width) solid var(--color-surface-1-border);
5170
5709
  }
5171
5710
 
5172
5711
  /* ── Elevation Variants ── */
5173
5712
  [data-ui="surface"][data-variant="flat"] {
5174
- background: var(--color-bg);
5713
+ background-color: var(--color-bg);
5175
5714
  border: none;
5176
5715
  box-shadow: none;
5177
5716
  }
@@ -5181,11 +5720,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5181
5720
  }
5182
5721
 
5183
5722
  [data-ui="surface"][data-variant="overlay"] {
5184
- background: var(--color-surface-2);
5723
+ background-color: var(--color-surface-2);
5185
5724
  box-shadow: var(--shadow-lg);
5186
5725
  border-color: var(--color-surface-2-border);
5187
5726
  }
5188
5727
 
5728
+ /* An overlay is the one surface variant that floats over other content, so it
5729
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5730
+ its own: a browser without backdrop-filter renders the solid surface above
5731
+ and never sees this rule. */
5732
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5733
+ [data-ui="surface"][data-variant="overlay"] {
5734
+ -webkit-backdrop-filter: var(--surface-backdrop);
5735
+ backdrop-filter: var(--surface-backdrop);
5736
+ }
5737
+ }
5738
+
5189
5739
  /* ── Padding Sizes ── */
5190
5740
  [data-ui="surface"][data-size="sm"] {
5191
5741
  padding: var(--space-3);
@@ -5241,7 +5791,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5241
5791
 
5242
5792
  /* === primitives/switch.css === */
5243
5793
  /* @ui:component switch */
5244
- /* @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 */
5794
+ /* @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 */
5245
5795
 
5246
5796
  /* -- Label wrapper -- */
5247
5797
  [data-ui="switch-label"] {
@@ -5253,7 +5803,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5253
5803
 
5254
5804
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5255
5805
  cursor: not-allowed;
5256
- opacity: 0.5;
5806
+ opacity: var(--disabled-opacity);
5257
5807
  }
5258
5808
 
5259
5809
  /* -- Base (track) -- */
@@ -5281,8 +5831,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5281
5831
  width: var(--switch-width, 44px);
5282
5832
  height: var(--switch-height, 24px);
5283
5833
  padding: var(--space-0h, 2px);
5284
- border: 1px solid var(--color-border);
5285
- border-radius: var(--radius-full);
5834
+ border: var(--border-width) solid var(--color-border);
5835
+ border-radius: var(--switch-radius);
5286
5836
  background: var(--switch-bg, var(--color-bg-muted));
5287
5837
  cursor: pointer;
5288
5838
  position: relative;
@@ -5292,8 +5842,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5292
5842
  }
5293
5843
 
5294
5844
  [data-ui="switch"]:focus-visible {
5295
- outline: 2px solid var(--color-ring);
5296
- outline-offset: 2px;
5845
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5846
+ outline-offset: var(--focus-ring-offset);
5847
+ box-shadow: var(--focus-shadow);
5297
5848
  }
5298
5849
 
5299
5850
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5302,7 +5853,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5302
5853
  display: block;
5303
5854
  width: var(--switch-thumb, 18px);
5304
5855
  height: var(--switch-thumb, 18px);
5305
- border-radius: var(--radius-full);
5856
+ border-radius: var(--switch-radius);
5306
5857
  background: var(--color-primary-fg);
5307
5858
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5308
5859
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5314,7 +5865,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5314
5865
  display: block;
5315
5866
  width: var(--switch-thumb, 18px);
5316
5867
  height: var(--switch-thumb, 18px);
5317
- border-radius: var(--radius-full);
5868
+ border-radius: var(--switch-radius);
5318
5869
  background: var(--color-primary-fg);
5319
5870
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5320
5871
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5396,7 +5947,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5396
5947
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5397
5948
  @media (forced-colors: active) {
5398
5949
  [data-ui="switch"] {
5399
- border: 1px solid ButtonText;
5950
+ border: var(--border-width) solid ButtonText;
5400
5951
  background: ButtonFace;
5401
5952
  }
5402
5953
 
@@ -5553,25 +6104,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5553
6104
 
5554
6105
  /* === primitives/text.css === */
5555
6106
  /* @ui:component text */
5556
- /* @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 */
6107
+ /* @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 */
5557
6108
 
5558
6109
  /* ── Heading ── */
5559
6110
  [data-ui="heading"] {
5560
- font-family: var(--font-sans);
5561
- font-weight: var(--weight-bold);
6111
+ font-family: var(--font-heading);
6112
+ font-weight: var(--heading-weight);
5562
6113
  color: var(--color-fg);
5563
- line-height: var(--leading-tight);
5564
- letter-spacing: -0.01em;
6114
+ line-height: var(--heading-leading);
6115
+ text-transform: var(--heading-transform);
6116
+ font-variant-caps: var(--heading-caps);
6117
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6118
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6119
+ headings sets --heading-tracking once and every size follows, instead of
6120
+ each size having to re-derive its own number. */
6121
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5565
6122
  }
5566
6123
 
5567
6124
  [data-ui="heading"][data-size="1"] {
5568
6125
  font-size: var(--text-4xl);
5569
- letter-spacing: -0.02em;
6126
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5570
6127
  }
5571
6128
 
5572
6129
  [data-ui="heading"][data-size="2"] {
5573
6130
  font-size: var(--text-3xl);
5574
- letter-spacing: -0.02em;
6131
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5575
6132
  }
5576
6133
 
5577
6134
  [data-ui="heading"][data-size="3"] {
@@ -5595,7 +6152,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5595
6152
 
5596
6153
  /* ── Text ── */
5597
6154
  [data-ui="text"] {
5598
- font-family: var(--font-sans);
6155
+ font-family: var(--font-body);
5599
6156
  color: var(--color-fg);
5600
6157
  }
5601
6158
 
@@ -5673,7 +6230,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5673
6230
 
5674
6231
  /* === primitives/textarea.css === */
5675
6232
  /* @ui:component textarea */
5676
- /* @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 */
6233
+ /* @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 */
5677
6234
 
5678
6235
  /* -- Base -- */
5679
6236
  [data-ui="textarea"] {
@@ -5681,11 +6238,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5681
6238
  width: 100%;
5682
6239
  min-height: var(--textarea-min-height, 80px);
5683
6240
  padding: var(--space-2) var(--space-3);
5684
- border: 1px solid var(--color-border);
6241
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6242
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6243
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6244
+ is drawn. Identical to the shorthand at every other value of the token. */
6245
+ border-style: solid;
6246
+ border-color: var(--color-border);
6247
+ border-width: var(--input-border-width);
5685
6248
  border-radius: var(--textarea-radius, var(--radius-md));
5686
- background: var(--textarea-bg, var(--color-bg));
6249
+ background: var(--textarea-bg, var(--input-fill));
5687
6250
  color: var(--color-fg);
5688
- font-family: var(--textarea-font, var(--font-sans));
6251
+ font-family: var(--textarea-font, var(--font-ui));
5689
6252
  font-size: var(--text-sm);
5690
6253
  line-height: 1.5;
5691
6254
  resize: vertical;
@@ -5702,8 +6265,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5702
6265
  }
5703
6266
 
5704
6267
  [data-ui="textarea"]:focus {
5705
- outline: 2px solid var(--color-ring);
5706
- outline-offset: -1px;
6268
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6269
+ /* The ring replaces the border rather than sitting outside it: inset by
6270
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6271
+ outline-offset: calc(-1 * var(--input-border-width));
6272
+ box-shadow: var(--focus-shadow);
5707
6273
  border-color: transparent;
5708
6274
  }
5709
6275
 
@@ -5731,7 +6297,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5731
6297
  }
5732
6298
 
5733
6299
  [data-ui="textarea"]:disabled {
5734
- opacity: 0.5;
6300
+ opacity: var(--disabled-opacity);
5735
6301
  cursor: not-allowed;
5736
6302
  resize: none;
5737
6303
  }
@@ -5745,7 +6311,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5745
6311
 
5746
6312
  /* === primitives/toggle.css === */
5747
6313
  /* @ui:component toggle */
5748
- /* @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 */
6314
+ /* @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 */
5749
6315
 
5750
6316
  /* ── Base (off / unpressed) ── */
5751
6317
  [data-ui="toggle"] {
@@ -5754,11 +6320,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5754
6320
  justify-content: center;
5755
6321
  gap: var(--space-1h);
5756
6322
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5757
- border: 1px solid var(--color-border);
6323
+ border: var(--border-width) solid var(--color-border);
5758
6324
  border-radius: var(--toggle-radius, var(--radius-md));
5759
6325
  background: var(--color-bg);
5760
6326
  color: var(--color-fg-muted);
5761
- font-family: var(--toggle-font, var(--font-sans));
6327
+ font-family: var(--toggle-font, var(--font-ui));
5762
6328
  font-size: var(--text-sm);
5763
6329
  font-weight: var(--weight-medium);
5764
6330
  line-height: 1;
@@ -5775,8 +6341,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5775
6341
  }
5776
6342
 
5777
6343
  [data-ui="toggle"]:focus-visible {
5778
- outline: 2px solid var(--color-ring);
5779
- outline-offset: 2px;
6344
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6345
+ outline-offset: var(--focus-ring-offset);
6346
+ box-shadow: var(--focus-shadow);
5780
6347
  }
5781
6348
 
5782
6349
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5793,7 +6360,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5793
6360
 
5794
6361
  /* ── Disabled ── */
5795
6362
  [data-ui="toggle"]:disabled {
5796
- opacity: 0.5;
6363
+ opacity: var(--disabled-opacity);
5797
6364
  cursor: not-allowed;
5798
6365
  }
5799
6366
 
@@ -5817,7 +6384,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5817
6384
 
5818
6385
  /* === primitives/watermark.css === */
5819
6386
  /* @ui:component watermark */
5820
- /* @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 */
6387
+ /* @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 */
5821
6388
 
5822
6389
  [data-ui="watermark"] {
5823
6390
  position: fixed;
@@ -5836,7 +6403,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5836
6403
 
5837
6404
  [data-ui="watermark"] > [data-part="mark"] {
5838
6405
  color: var(--color-fg-muted);
5839
- font-family: var(--doc-font, var(--font-sans));
6406
+ font-family: var(--doc-font, var(--font-body));
5840
6407
  font-size: var(--text-4xl);
5841
6408
  font-weight: var(--weight-bold);
5842
6409
  line-height: var(--leading-tight);
@@ -5894,7 +6461,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5894
6461
 
5895
6462
  /* === recipes/accordion.css === */
5896
6463
  /* @ui:component accordion */
5897
- /* @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 */
6464
+ /* @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 */
5898
6465
 
5899
6466
  /* ── Root ── */
5900
6467
  [data-ui="accordion"] {
@@ -5903,7 +6470,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5903
6470
 
5904
6471
  /* ── Item ── */
5905
6472
  [data-ui="accordion"] [data-part="item"] {
5906
- border-bottom: 1px solid var(--color-border);
6473
+ border-bottom: var(--border-width) solid var(--color-border);
5907
6474
  }
5908
6475
 
5909
6476
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5920,7 +6487,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5920
6487
  border: none;
5921
6488
  background: transparent;
5922
6489
  color: var(--color-fg);
5923
- font-family: var(--font-sans, system-ui, sans-serif);
6490
+ font-family: var(--font-ui);
5924
6491
  font-size: var(--text-base);
5925
6492
  font-weight: var(--weight-medium);
5926
6493
  text-align: start;
@@ -5934,8 +6501,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5934
6501
  }
5935
6502
 
5936
6503
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5937
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5938
- outline-offset: -2px;
6504
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6505
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5939
6506
  border-radius: var(--radius-sm, 0.25rem);
5940
6507
  }
5941
6508
 
@@ -5967,13 +6534,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5967
6534
 
5968
6535
  /* ── Bordered Variant ── */
5969
6536
  [data-ui="accordion"][data-bordered="true"] {
5970
- border: 1px solid var(--color-border);
6537
+ border: var(--border-width) solid var(--color-border);
5971
6538
  border-radius: var(--radius-lg);
5972
6539
  overflow: hidden;
5973
6540
  }
5974
6541
 
5975
6542
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5976
- border-bottom: 1px solid var(--color-border);
6543
+ border-bottom: var(--border-width) solid var(--color-border);
5977
6544
  }
5978
6545
 
5979
6546
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5990,7 +6557,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5990
6557
 
5991
6558
  /* === recipes/alert-dialog.css === */
5992
6559
  /* @ui:component alert-dialog */
5993
- /* @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 */
6560
+ /* @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 */
5994
6561
 
5995
6562
  /* ── Root ── */
5996
6563
  [data-ui="alert-dialog"] {
@@ -6026,7 +6593,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6026
6593
  max-height: 85vh;
6027
6594
  overflow-y: auto;
6028
6595
  background: var(--color-bg);
6029
- border: 1px solid var(--color-border);
6596
+ border: var(--border-width) solid var(--color-border);
6030
6597
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
6031
6598
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
6032
6599
  opacity: 0;
@@ -6072,6 +6639,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6072
6639
  /* ── Title ── */
6073
6640
  [data-ui="alert-dialog"] [data-part="title"] {
6074
6641
  margin: 0;
6642
+ font-family: var(--font-heading);
6075
6643
  font-size: var(--text-lg, 1.125rem);
6076
6644
  font-weight: var(--weight-semibold, 600);
6077
6645
  color: var(--color-fg);
@@ -6111,7 +6679,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6111
6679
 
6112
6680
  /* === recipes/barcode.css === */
6113
6681
  /* @ui:component barcode */
6114
- /* @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 */
6682
+ /* @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 */
6115
6683
 
6116
6684
  [data-ui="barcode"] {
6117
6685
  display: inline-flex;
@@ -6138,7 +6706,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6138
6706
 
6139
6707
  [data-ui="barcode"] > [data-part="caption"] {
6140
6708
  color: var(--doc-legal-color, var(--color-fg-muted));
6141
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6709
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6142
6710
  font-size: var(--doc-legal-size);
6143
6711
  line-height: var(--leading-normal);
6144
6712
  text-align: center;
@@ -6158,7 +6726,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6158
6726
 
6159
6727
  /* === recipes/calendar.css === */
6160
6728
  /* @ui:component calendar */
6161
- /* @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 */
6729
+ /* @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 */
6162
6730
 
6163
6731
  /* ── Root ── */
6164
6732
  [data-ui="calendar"] {
@@ -6191,7 +6759,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6191
6759
  width: 28px;
6192
6760
  height: 28px;
6193
6761
  padding: 0;
6194
- border: 1px solid var(--color-border);
6762
+ border: var(--border-width) solid var(--color-border);
6195
6763
  border-radius: var(--radius-md);
6196
6764
  background: var(--color-bg);
6197
6765
  color: var(--color-fg);
@@ -6207,13 +6775,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6207
6775
 
6208
6776
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6209
6777
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6210
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6211
- outline-offset: 2px;
6778
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6779
+ outline-offset: var(--focus-ring-offset);
6212
6780
  }
6213
6781
 
6214
6782
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6215
6783
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6216
- opacity: 0.4;
6784
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6785
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6786
+ opacity: calc(var(--disabled-opacity) * 0.8);
6217
6787
  cursor: not-allowed;
6218
6788
  }
6219
6789
 
@@ -6248,11 +6818,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6248
6818
  width: 36px;
6249
6819
  height: 36px;
6250
6820
  padding: 0;
6251
- border: 1px solid transparent;
6821
+ border: var(--border-width) solid transparent;
6252
6822
  border-radius: var(--radius-full);
6253
6823
  background: transparent;
6254
6824
  color: var(--color-fg);
6255
- font-family: var(--font-sans, system-ui, sans-serif);
6825
+ font-family: var(--font-ui);
6256
6826
  font-size: var(--text-sm);
6257
6827
  cursor: pointer;
6258
6828
  transition: background var(--duration-fast) var(--ease-default),
@@ -6265,8 +6835,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6265
6835
  }
6266
6836
 
6267
6837
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6268
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6269
- outline-offset: 2px;
6838
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6839
+ outline-offset: var(--focus-ring-offset);
6270
6840
  }
6271
6841
 
6272
6842
  /* ── Today ── */
@@ -6301,7 +6871,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6301
6871
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6302
6872
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6303
6873
  [data-ui="calendar"] [data-part="day"]:disabled {
6304
- opacity: 0.5;
6874
+ opacity: var(--disabled-opacity);
6305
6875
  cursor: not-allowed;
6306
6876
  text-decoration: line-through;
6307
6877
  }
@@ -6365,7 +6935,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6365
6935
 
6366
6936
  /* === recipes/carousel.css === */
6367
6937
  /* @ui:component carousel */
6368
- /* @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 */
6938
+ /* @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 */
6369
6939
 
6370
6940
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6371
6941
  every slide is a snap target. Everything below works with no controller
@@ -6379,7 +6949,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6379
6949
  inline-size: 100%;
6380
6950
  min-inline-size: 0;
6381
6951
  max-inline-size: 100%;
6382
- font-family: var(--carousel-font, var(--font-sans));
6952
+ font-family: var(--carousel-font, var(--font-ui));
6383
6953
  }
6384
6954
 
6385
6955
  /* ── Viewport: the scroll-snap strip ── */
@@ -6405,8 +6975,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6405
6975
  }
6406
6976
 
6407
6977
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6408
- outline: 2px solid var(--color-ring);
6409
- outline-offset: 2px;
6978
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6979
+ outline-offset: var(--focus-ring-offset);
6410
6980
  }
6411
6981
 
6412
6982
  /* ── Slide: one full-width snap target ── */
@@ -6414,7 +6984,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6414
6984
  flex: 0 0 var(--carousel-slide-size, 100%);
6415
6985
  min-inline-size: 0;
6416
6986
  padding: var(--space-4);
6417
- border: 1px solid var(--color-border);
6987
+ border: var(--border-width) solid var(--color-border);
6418
6988
  border-radius: var(--radius-lg);
6419
6989
  background: var(--color-bg);
6420
6990
  color: var(--color-fg);
@@ -6443,7 +7013,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6443
7013
  min-inline-size: 2rem;
6444
7014
  min-block-size: 2rem;
6445
7015
  padding: var(--space-1) var(--space-2);
6446
- border: 1px solid var(--color-border);
7016
+ border: var(--border-width) solid var(--color-border);
6447
7017
  border-radius: var(--radius-md);
6448
7018
  background: var(--color-bg);
6449
7019
  color: var(--color-fg);
@@ -6462,14 +7032,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6462
7032
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6463
7033
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6464
7034
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6465
- outline: 2px solid var(--color-ring);
6466
- outline-offset: 2px;
7035
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7036
+ outline-offset: var(--focus-ring-offset);
6467
7037
  }
6468
7038
 
6469
7039
  /* Boundary contract "stop" — the controller disables the end button. */
6470
7040
  [data-ui="carousel"] [data-part="prev"]:disabled,
6471
7041
  [data-ui="carousel"] [data-part="next"]:disabled {
6472
- opacity: 0.4;
7042
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7043
+ opacity: calc(var(--disabled-opacity) * 0.8);
6473
7044
  cursor: not-allowed;
6474
7045
  }
6475
7046
 
@@ -6478,7 +7049,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6478
7049
  inline-size: 0.625rem;
6479
7050
  block-size: 0.625rem;
6480
7051
  padding: 0;
6481
- border: 1px solid var(--color-border);
7052
+ border: var(--border-width) solid var(--color-border);
6482
7053
  border-radius: 50%;
6483
7054
  background: var(--color-bg-muted);
6484
7055
  cursor: pointer;
@@ -6514,7 +7085,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6514
7085
 
6515
7086
  /* === recipes/combobox.css === */
6516
7087
  /* @ui:component combobox */
6517
- /* @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 */
7088
+ /* @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 */
6518
7089
 
6519
7090
  /* ── Root ── */
6520
7091
  [data-ui="combobox"] {
@@ -6528,11 +7099,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6528
7099
  display: block;
6529
7100
  width: 100%;
6530
7101
  padding: var(--space-2) var(--space-3);
6531
- border: 1px solid var(--color-border);
7102
+ border: var(--border-width) solid var(--color-border);
6532
7103
  border-radius: var(--radius-md);
6533
7104
  background: var(--color-bg);
6534
7105
  color: var(--color-fg);
6535
- font-family: var(--font-sans, system-ui, sans-serif);
7106
+ font-family: var(--font-ui);
6536
7107
  font-size: var(--text-sm);
6537
7108
  line-height: 1.5;
6538
7109
  outline: none;
@@ -6545,8 +7116,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6545
7116
  }
6546
7117
 
6547
7118
  [data-ui="combobox"] [data-part="input"]:focus {
6548
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6549
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7119
+ border-color: var(--focus-ring-color);
7120
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6550
7121
  }
6551
7122
 
6552
7123
  /* ── Listbox ── */
@@ -6558,7 +7129,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6558
7129
  z-index: var(--z-dropdown);
6559
7130
  margin-top: var(--space-1);
6560
7131
  padding: var(--space-1);
6561
- border: 1px solid var(--color-border);
7132
+ border: var(--border-width) solid var(--color-border);
6562
7133
  border-radius: var(--radius-lg);
6563
7134
  background: var(--color-bg);
6564
7135
  box-shadow: var(--shadow-md);
@@ -6643,7 +7214,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6643
7214
 
6644
7215
  /* === recipes/command-palette.css === */
6645
7216
  /* @ui:component command-palette */
6646
- /* @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 */
7217
+ /* @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 */
6647
7218
 
6648
7219
  /* ── Root ── */
6649
7220
  [data-ui="command-palette"] {
@@ -6676,7 +7247,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6676
7247
  display: flex;
6677
7248
  flex-direction: column;
6678
7249
  background: var(--color-bg);
6679
- border: 1px solid var(--color-border);
7250
+ border: var(--border-width) solid var(--color-border);
6680
7251
  border-radius: var(--radius-xl);
6681
7252
  box-shadow: var(--shadow-xl);
6682
7253
  overflow: hidden;
@@ -6708,7 +7279,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6708
7279
  display: flex;
6709
7280
  align-items: center;
6710
7281
  padding: var(--space-3) var(--space-4);
6711
- border-bottom: 1px solid var(--color-border);
7282
+ border-bottom: var(--border-width) solid var(--color-border);
6712
7283
  }
6713
7284
 
6714
7285
  /* ── Search Input ── */
@@ -6718,7 +7289,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6718
7289
  border: none;
6719
7290
  background: transparent;
6720
7291
  color: var(--color-fg);
6721
- font-family: var(--font-sans, system-ui, sans-serif);
7292
+ font-family: var(--font-ui);
6722
7293
  font-size: var(--text-base);
6723
7294
  outline: none;
6724
7295
  }
@@ -6802,7 +7373,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6802
7373
  align-items: center;
6803
7374
  gap: var(--space-1, 0.25rem);
6804
7375
  padding: var(--space-1, 0.25rem) var(--space-2);
6805
- border: 1px solid var(--color-border);
7376
+ border: var(--border-width) solid var(--color-border);
6806
7377
  border-radius: var(--radius-sm, 0.25rem);
6807
7378
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6808
7379
  color: var(--color-fg-muted);
@@ -6831,7 +7402,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6831
7402
 
6832
7403
  /* === recipes/context-menu.css === */
6833
7404
  /* @ui:component context-menu */
6834
- /* @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 */
7405
+ /* @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 */
6835
7406
 
6836
7407
  [data-ui="context-menu"] {
6837
7408
  position: relative;
@@ -6844,12 +7415,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6844
7415
  border-radius: var(--radius-lg);
6845
7416
  background: var(--color-bg-muted);
6846
7417
  color: var(--color-fg);
6847
- font-family: var(--font-sans, system-ui, sans-serif);
7418
+ font-family: var(--font-ui);
6848
7419
  }
6849
7420
 
6850
7421
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6851
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6852
- outline-offset: var(--space-1);
7422
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7423
+ outline-offset: var(--focus-ring-offset);
6853
7424
  }
6854
7425
 
6855
7426
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6881,7 +7452,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6881
7452
  border-radius: var(--radius-md);
6882
7453
  background: transparent;
6883
7454
  color: var(--color-fg);
6884
- font-family: var(--font-sans, system-ui, sans-serif);
7455
+ font-family: var(--font-ui);
6885
7456
  font-size: var(--text-sm);
6886
7457
  font-weight: var(--weight-medium);
6887
7458
  text-align: start;
@@ -6905,15 +7476,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6905
7476
  focus additionally draws the ring, inset so it does not overlap the item
6906
7477
  above. [W3-3] */
6907
7478
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6908
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6909
- outline-offset: calc(var(--space-px) * -2);
7479
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7480
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6910
7481
  }
6911
7482
 
6912
7483
  [data-ui="context-menu"] [data-part="item"]:disabled,
6913
7484
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6914
7485
  color: var(--color-fg-muted);
6915
7486
  cursor: not-allowed;
6916
- opacity: 0.5;
7487
+ opacity: var(--disabled-opacity);
6917
7488
  }
6918
7489
 
6919
7490
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6932,7 +7503,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6932
7503
 
6933
7504
  /* === recipes/date-picker.css === */
6934
7505
  /* @ui:component date-picker */
6935
- /* @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 */
7506
+ /* @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 */
6936
7507
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6937
7508
 
6938
7509
  /* ── Root ── */
@@ -6953,11 +7524,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6953
7524
  width: 100%;
6954
7525
  padding: var(--space-2, 0.5rem) var(--space-3);
6955
7526
  padding-inline-end: var(--space-8, 2.5rem);
6956
- border: 1px solid var(--color-border);
7527
+ border: var(--border-width) solid var(--color-border);
6957
7528
  border-radius: var(--radius-md);
6958
7529
  background: var(--color-bg);
6959
7530
  color: var(--color-fg);
6960
- font-family: var(--font-sans, system-ui, sans-serif);
7531
+ font-family: var(--font-ui);
6961
7532
  font-size: var(--text-sm);
6962
7533
  line-height: 1.5;
6963
7534
  cursor: pointer;
@@ -6969,8 +7540,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6969
7540
  }
6970
7541
 
6971
7542
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6972
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6973
- outline-offset: 2px;
7543
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7544
+ outline-offset: var(--focus-ring-offset);
6974
7545
  border-color: var(--color-primary);
6975
7546
  }
6976
7547
 
@@ -6993,7 +7564,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6993
7564
  z-index: var(--z-dropdown);
6994
7565
  margin-top: var(--space-1);
6995
7566
  padding: var(--space-3);
6996
- border: 1px solid var(--color-border);
7567
+ border: var(--border-width) solid var(--color-border);
6997
7568
  border-radius: var(--radius-lg);
6998
7569
  background: var(--color-bg);
6999
7570
  box-shadow: var(--shadow-lg);
@@ -7032,7 +7603,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7032
7603
 
7033
7604
  /* === recipes/dialog.css === */
7034
7605
  /* @ui:component dialog */
7035
- /* @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 */
7606
+ /* @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 */
7036
7607
 
7037
7608
  /* ── Root ── */
7038
7609
  [data-ui="dialog"] {
@@ -7067,15 +7638,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7067
7638
  width: 90%;
7068
7639
  max-height: 85vh;
7069
7640
  overflow-y: auto;
7070
- background: var(--color-bg);
7071
- border: 1px solid var(--color-border);
7641
+ background: var(--panel-bg);
7642
+ border: var(--border-width) solid var(--color-border);
7072
7643
  border-radius: var(--dialog-radius, var(--radius-xl));
7644
+ corner-shape: var(--corner-shape);
7073
7645
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7074
7646
  opacity: 0;
7075
7647
  transition: opacity var(--duration-normal) var(--ease-out),
7076
7648
  transform var(--duration-normal) var(--ease-out);
7077
7649
  }
7078
7650
 
7651
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7652
+ [data-ui="dialog"] [data-part="panel"] {
7653
+ -webkit-backdrop-filter: var(--surface-backdrop);
7654
+ backdrop-filter: var(--surface-backdrop);
7655
+ }
7656
+ }
7657
+
7079
7658
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7080
7659
  opacity: 1;
7081
7660
  transform: translate(-50%, -50%) scale(1);
@@ -7124,6 +7703,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7124
7703
  /* ── Title ── */
7125
7704
  [data-ui="dialog"] [data-part="title"] {
7126
7705
  margin: 0;
7706
+ font-family: var(--font-heading);
7127
7707
  font-size: var(--text-lg, 1.125rem);
7128
7708
  font-weight: var(--weight-semibold, 600);
7129
7709
  color: var(--color-fg);
@@ -7158,8 +7738,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7158
7738
  }
7159
7739
 
7160
7740
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7161
- outline: 2px solid var(--color-ring);
7162
- outline-offset: 2px;
7741
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7742
+ outline-offset: var(--focus-ring-offset);
7163
7743
  }
7164
7744
 
7165
7745
  /* ── Description ── */
@@ -7195,7 +7775,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7195
7775
 
7196
7776
  /* === recipes/drawer.css === */
7197
7777
  /* @ui:component drawer */
7198
- /* @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 */
7778
+ /* @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 */
7199
7779
 
7200
7780
  /* ── Root ── */
7201
7781
  [data-ui="drawer"] {
@@ -7230,17 +7810,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7230
7810
  flex-direction: column;
7231
7811
  width: var(--drawer-width, 400px);
7232
7812
  max-width: 100vw;
7233
- background: var(--color-bg);
7813
+ background: var(--panel-bg);
7234
7814
  border: none;
7235
7815
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7236
7816
  transition: transform var(--duration-slow) var(--ease-out);
7237
7817
  }
7238
7818
 
7819
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7820
+ [data-ui="drawer"] [data-part="panel"] {
7821
+ -webkit-backdrop-filter: var(--surface-backdrop);
7822
+ backdrop-filter: var(--surface-backdrop);
7823
+ }
7824
+ }
7825
+
7239
7826
  /* ── Side Variants ── */
7240
7827
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7241
7828
  inset-inline-start: 0;
7242
7829
  inset-inline-end: auto;
7243
- border-inline-end: 1px solid var(--color-border);
7830
+ border-inline-end: var(--border-width) solid var(--color-border);
7244
7831
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7245
7832
  transform: translateX(-100%);
7246
7833
  }
@@ -7248,7 +7835,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7248
7835
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7249
7836
  inset-inline-end: 0;
7250
7837
  inset-inline-start: auto;
7251
- border-inline-start: 1px solid var(--color-border);
7838
+ border-inline-start: var(--border-width) solid var(--color-border);
7252
7839
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7253
7840
  transform: translateX(100%);
7254
7841
  }
@@ -7302,6 +7889,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7302
7889
  /* ── Title ── */
7303
7890
  [data-ui="drawer"] [data-part="title"] {
7304
7891
  margin: 0;
7892
+ font-family: var(--font-heading);
7305
7893
  font-size: var(--text-lg, 1.125rem);
7306
7894
  font-weight: var(--weight-semibold, 600);
7307
7895
  color: var(--color-fg);
@@ -7336,8 +7924,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7336
7924
  }
7337
7925
 
7338
7926
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7339
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7340
- outline-offset: 2px;
7927
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7928
+ outline-offset: var(--focus-ring-offset);
7341
7929
  }
7342
7930
 
7343
7931
  /* ── Body ── */
@@ -7356,7 +7944,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7356
7944
  gap: var(--space-3, 0.75rem);
7357
7945
  padding: var(--space-6);
7358
7946
  padding-top: var(--space-4);
7359
- border-top: 1px solid var(--color-border);
7947
+ border-top: var(--border-width) solid var(--color-border);
7360
7948
  flex-shrink: 0;
7361
7949
  }
7362
7950
 
@@ -7370,7 +7958,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7370
7958
 
7371
7959
  /* === recipes/dropdown.css === */
7372
7960
  /* @ui:component dropdown */
7373
- /* @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 */
7961
+ /* @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 */
7374
7962
 
7375
7963
  /* ── Root ── */
7376
7964
  [data-ui="dropdown"] {
@@ -7384,11 +7972,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7384
7972
  align-items: center;
7385
7973
  gap: var(--space-2);
7386
7974
  padding: var(--space-2) var(--space-3);
7387
- border: 1px solid var(--color-border);
7975
+ border: var(--border-width) solid var(--color-border);
7388
7976
  border-radius: var(--radius-md);
7389
7977
  background: var(--color-bg);
7390
7978
  color: var(--color-fg);
7391
- font-family: var(--font-sans, system-ui, sans-serif);
7979
+ font-family: var(--font-ui);
7392
7980
  font-size: var(--text-sm);
7393
7981
  font-weight: var(--weight-medium);
7394
7982
  cursor: pointer;
@@ -7402,8 +7990,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7402
7990
  }
7403
7991
 
7404
7992
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7405
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7406
- outline-offset: 2px;
7993
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7994
+ outline-offset: var(--focus-ring-offset);
7407
7995
  }
7408
7996
 
7409
7997
  /* ── Menu ── */
@@ -7415,9 +8003,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7415
8003
  min-width: 180px;
7416
8004
  margin-top: var(--space-1);
7417
8005
  padding: var(--space-1);
7418
- border: 1px solid var(--color-border);
8006
+ border: var(--border-width) solid var(--color-border);
7419
8007
  border-radius: var(--radius-lg);
7420
- background: var(--color-bg);
8008
+ background: var(--panel-bg);
7421
8009
  box-shadow: var(--shadow-md);
7422
8010
  opacity: 0;
7423
8011
  transform: translateY(-4px);
@@ -7425,6 +8013,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7425
8013
  transform var(--duration-fast) var(--ease-out);
7426
8014
  }
7427
8015
 
8016
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8017
+ [data-ui="dropdown"] [data-part="menu"] {
8018
+ -webkit-backdrop-filter: var(--surface-backdrop);
8019
+ backdrop-filter: var(--surface-backdrop);
8020
+ }
8021
+ }
8022
+
7428
8023
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7429
8024
  opacity: 1;
7430
8025
  transform: translateY(0);
@@ -7447,7 +8042,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7447
8042
  border-radius: var(--radius-md);
7448
8043
  background: transparent;
7449
8044
  color: var(--color-fg);
7450
- font-family: var(--font-sans, system-ui, sans-serif);
8045
+ font-family: var(--font-ui);
7451
8046
  font-size: var(--text-sm);
7452
8047
  text-align: start;
7453
8048
  cursor: pointer;
@@ -7469,12 +8064,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7469
8064
  focus additionally draws the ring, inset so it does not overlap the item
7470
8065
  above. [W3-3] */
7471
8066
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7472
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7473
- outline-offset: -2px;
8067
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8068
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7474
8069
  }
7475
8070
 
7476
8071
  [data-ui="dropdown"] [data-part="item"]:disabled {
7477
- opacity: 0.5;
8072
+ opacity: var(--disabled-opacity);
7478
8073
  cursor: not-allowed;
7479
8074
  pointer-events: none;
7480
8075
  }
@@ -7527,14 +8122,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7527
8122
 
7528
8123
  /* === recipes/file-upload.css === */
7529
8124
  /* @ui:component file-upload */
7530
- /* @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 */
8125
+ /* @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 */
7531
8126
 
7532
8127
  [data-ui="file-upload"] {
7533
8128
  display: grid;
7534
8129
  gap: var(--space-4);
7535
8130
  inline-size: 100%;
7536
8131
  color: var(--color-fg);
7537
- font-family: var(--font-sans);
8132
+ font-family: var(--font-ui);
7538
8133
  }
7539
8134
 
7540
8135
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7569,14 +8164,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7569
8164
  }
7570
8165
 
7571
8166
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7572
- outline: var(--space-px) solid var(--color-ring);
7573
- outline-offset: var(--space-1);
8167
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8168
+ outline-offset: var(--focus-ring-offset);
7574
8169
  }
7575
8170
 
7576
8171
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7577
8172
  border-color: var(--color-primary);
7578
8173
  background: var(--color-primary-subtle);
7579
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8174
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7580
8175
  }
7581
8176
 
7582
8177
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7650,8 +8245,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7650
8245
  }
7651
8246
 
7652
8247
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7653
- outline: var(--space-px) solid var(--color-ring);
7654
- outline-offset: var(--space-1);
8248
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8249
+ outline-offset: var(--focus-ring-offset);
7655
8250
  }
7656
8251
 
7657
8252
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7673,7 +8268,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7673
8268
  }
7674
8269
 
7675
8270
  [data-ui="file-upload"][data-disabled] {
7676
- opacity: 0.5;
8271
+ opacity: var(--disabled-opacity);
7677
8272
  }
7678
8273
 
7679
8274
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7689,7 +8284,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7689
8284
 
7690
8285
  /* === recipes/input-otp.css === */
7691
8286
  /* @ui:component input-otp */
7692
- /* @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 */
8287
+ /* @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 */
7693
8288
 
7694
8289
  /* ── Root ── */
7695
8290
  [data-ui="input-otp"] {
@@ -7704,7 +8299,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7704
8299
  gutter. The transparent input is `inset: 0`, so it follows the box the
7705
8300
  segments settle into however many rows that takes. */
7706
8301
  max-inline-size: 100%;
7707
- font-family: var(--font-sans, system-ui, sans-serif);
8302
+ font-family: var(--font-ui);
7708
8303
  }
7709
8304
 
7710
8305
  /* ── Real input ──
@@ -7749,14 +8344,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7749
8344
  justify-content: center;
7750
8345
  inline-size: var(--input-otp-segment-size);
7751
8346
  block-size: var(--input-otp-segment-size);
7752
- border: 1px solid var(--color-border);
8347
+ border: var(--border-width) solid var(--color-border);
7753
8348
  border-radius: var(--radius-md);
7754
8349
  background: var(--color-bg);
7755
8350
  color: var(--color-fg);
7756
8351
  font-size: var(--text-lg, 1.125rem);
7757
8352
  font-variant-numeric: tabular-nums;
7758
8353
  line-height: 1;
7759
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8354
+ transition: border-color var(--duration-fast) var(--ease-default),
7760
8355
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7761
8356
  }
7762
8357
 
@@ -7768,7 +8363,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7768
8363
  /* Active (caret / selected) segment while focused */
7769
8364
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7770
8365
  border-color: var(--color-ring);
7771
- box-shadow: 0 0 0 1px var(--color-ring);
8366
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7772
8367
  }
7773
8368
 
7774
8369
  /* Blinking caret in the next-to-fill empty slot */
@@ -7816,7 +8411,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7816
8411
 
7817
8412
  /* ── Disabled ── */
7818
8413
  [data-ui="input-otp"][data-disabled] {
7819
- opacity: 0.5;
8414
+ opacity: var(--disabled-opacity);
7820
8415
  cursor: not-allowed;
7821
8416
  }
7822
8417
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7840,7 +8435,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7840
8435
 
7841
8436
  /* === recipes/menubar.css === */
7842
8437
  /* @ui:component menubar */
7843
- /* @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 */
8438
+ /* @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 */
7844
8439
 
7845
8440
  [data-ui="menubar"] {
7846
8441
  position: relative;
@@ -7858,7 +8453,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7858
8453
  border-radius: var(--radius-lg);
7859
8454
  background: var(--color-bg);
7860
8455
  color: var(--color-fg);
7861
- font-family: var(--font-sans);
8456
+ font-family: var(--font-ui);
7862
8457
  }
7863
8458
 
7864
8459
  [data-ui="menubar"] [data-part="group"] {
@@ -7900,7 +8495,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7900
8495
 
7901
8496
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7902
8497
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7903
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8498
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7904
8499
  }
7905
8500
 
7906
8501
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7935,7 +8530,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7935
8530
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7936
8531
  color: var(--color-fg-muted);
7937
8532
  cursor: not-allowed;
7938
- opacity: 0.6;
8533
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8534
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8535
+ it (1.1A-27). */
8536
+ opacity: calc(var(--disabled-opacity) * 1.2);
7939
8537
  }
7940
8538
 
7941
8539
  [data-ui="menubar"] [data-part="separator"] {
@@ -7967,7 +8565,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7967
8565
 
7968
8566
  /* === recipes/pagination.css === */
7969
8567
  /* @ui:component pagination */
7970
- /* @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 */
8568
+ /* @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 */
7971
8569
 
7972
8570
  /* ── Root ── */
7973
8571
  [data-ui="pagination"] {
@@ -8003,11 +8601,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8003
8601
  min-width: 36px;
8004
8602
  height: 36px;
8005
8603
  padding: 0 var(--space-2);
8006
- border: 1px solid var(--color-border);
8604
+ border: var(--border-width) solid var(--color-border);
8007
8605
  border-radius: var(--radius-md);
8008
8606
  background: var(--color-bg);
8009
8607
  color: var(--color-fg);
8010
- font-family: var(--font-sans, system-ui, sans-serif);
8608
+ font-family: var(--font-ui);
8011
8609
  font-size: var(--text-sm);
8012
8610
  font-weight: var(--weight-medium);
8013
8611
  cursor: pointer;
@@ -8028,8 +8626,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8028
8626
  [data-ui="pagination"] [data-part="page"]:focus-visible,
8029
8627
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
8030
8628
  [data-ui="pagination"] [data-part="next"]:focus-visible {
8031
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8032
- outline-offset: 2px;
8629
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8630
+ outline-offset: var(--focus-ring-offset);
8033
8631
  }
8034
8632
 
8035
8633
  /* ── Active page ── */
@@ -8053,7 +8651,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8053
8651
  /* ── Disabled ── */
8054
8652
  [data-ui="pagination"] [data-part="prev"]:disabled,
8055
8653
  [data-ui="pagination"] [data-part="next"]:disabled {
8056
- opacity: 0.5;
8654
+ opacity: var(--disabled-opacity);
8057
8655
  cursor: not-allowed;
8058
8656
  pointer-events: none;
8059
8657
  }
@@ -8123,7 +8721,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8123
8721
 
8124
8722
  /* === recipes/popover.css === */
8125
8723
  /* @ui:component popover */
8126
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8724
+ /* @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 */
8127
8725
 
8128
8726
  /* ── Root ── */
8129
8727
  [data-ui="popover"] {
@@ -8137,11 +8735,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8137
8735
  align-items: center;
8138
8736
  gap: var(--space-2, 0.5rem);
8139
8737
  padding: var(--space-2, 0.5rem) var(--space-3);
8140
- border: 1px solid var(--color-border);
8738
+ border: var(--border-width) solid var(--color-border);
8141
8739
  border-radius: var(--radius-md, 0.375rem);
8142
8740
  background: var(--color-bg);
8143
8741
  color: var(--color-fg);
8144
- font-family: var(--font-sans, system-ui, sans-serif);
8742
+ font-family: var(--font-ui);
8145
8743
  font-size: var(--text-sm, 0.875rem);
8146
8744
  font-weight: var(--weight-medium, 500);
8147
8745
  cursor: pointer;
@@ -8155,8 +8753,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8155
8753
  }
8156
8754
 
8157
8755
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8158
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8159
- outline-offset: 2px;
8756
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8757
+ outline-offset: var(--focus-ring-offset);
8160
8758
  }
8161
8759
 
8162
8760
  /* ── Content ── */
@@ -8165,9 +8763,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8165
8763
  z-index: var(--z-dropdown);
8166
8764
  min-width: 200px;
8167
8765
  padding: var(--space-4);
8168
- border: 1px solid var(--color-border);
8766
+ border: var(--border-width) solid var(--color-border);
8169
8767
  border-radius: var(--radius-lg);
8170
- background: var(--color-bg);
8768
+ background: var(--panel-bg);
8171
8769
  color: var(--color-fg);
8172
8770
  box-shadow: var(--shadow-md);
8173
8771
  opacity: 0;
@@ -8176,6 +8774,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8176
8774
  transform var(--duration-fast) var(--ease-default);
8177
8775
  }
8178
8776
 
8777
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8778
+ [data-ui="popover"] [data-part="content"] {
8779
+ -webkit-backdrop-filter: var(--surface-backdrop);
8780
+ backdrop-filter: var(--surface-backdrop);
8781
+ }
8782
+ }
8783
+
8179
8784
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8180
8785
  opacity: 1;
8181
8786
  transform: scale(1);
@@ -8263,8 +8868,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8263
8868
  position: absolute;
8264
8869
  width: 8px;
8265
8870
  height: 8px;
8266
- background: var(--color-bg);
8267
- border: 1px solid var(--color-border);
8871
+ background: var(--panel-bg);
8872
+ border: var(--border-width) solid var(--color-border);
8268
8873
  transform: rotate(45deg);
8269
8874
  }
8270
8875
 
@@ -8365,8 +8970,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8365
8970
  }
8366
8971
 
8367
8972
  [data-ui="popover"] [data-part="close"]:focus-visible {
8368
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8369
- outline-offset: 2px;
8973
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8974
+ outline-offset: var(--focus-ring-offset);
8370
8975
  }
8371
8976
 
8372
8977
  /* ── Motion ── */
@@ -8379,7 +8984,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8379
8984
 
8380
8985
  /* === recipes/qr-code.css === */
8381
8986
  /* @ui:component qr-code */
8382
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8987
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8383
8988
 
8384
8989
  /* ── Base ── */
8385
8990
  [data-ui="qr-code"] {
@@ -8397,7 +9002,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8397
9002
 
8398
9003
  /* ── Caption ── */
8399
9004
  [data-ui="qr-code"] [data-part="caption"] {
8400
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
9005
+ font-family: var(--doc-font, var(--font-body));
8401
9006
  font-size: var(--doc-legal-size, var(--text-xs));
8402
9007
  color: var(--doc-legal-color, var(--color-fg-muted));
8403
9008
  text-align: center;
@@ -8438,7 +9043,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8438
9043
 
8439
9044
  /* === recipes/select-custom.css === */
8440
9045
  /* @ui:component select-custom */
8441
- /* @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 */
9046
+ /* @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 */
8442
9047
 
8443
9048
  /* ── Root ── */
8444
9049
  [data-ui="select-custom"] {
@@ -8455,11 +9060,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8455
9060
  width: 100%;
8456
9061
  min-width: 180px;
8457
9062
  padding: var(--space-2) var(--space-3);
8458
- border: 1px solid var(--color-border);
9063
+ border: var(--border-width) solid var(--color-border);
8459
9064
  border-radius: var(--radius-md);
8460
9065
  background: var(--color-bg);
8461
9066
  color: var(--color-fg);
8462
- font-family: var(--font-sans, system-ui, sans-serif);
9067
+ font-family: var(--font-ui);
8463
9068
  font-size: var(--text-sm);
8464
9069
  cursor: pointer;
8465
9070
  white-space: nowrap;
@@ -8472,8 +9077,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8472
9077
  }
8473
9078
 
8474
9079
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8475
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8476
- outline-offset: 2px;
9080
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9081
+ outline-offset: var(--focus-ring-offset);
8477
9082
  }
8478
9083
 
8479
9084
  /* ── Value ── */
@@ -8509,7 +9114,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8509
9114
  z-index: var(--z-dropdown);
8510
9115
  margin-top: var(--space-1);
8511
9116
  padding: var(--space-1);
8512
- border: 1px solid var(--color-border);
9117
+ border: var(--border-width) solid var(--color-border);
8513
9118
  border-radius: var(--radius-lg);
8514
9119
  background: var(--color-bg);
8515
9120
  box-shadow: var(--shadow-md);
@@ -8533,11 +9138,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8533
9138
  padding: var(--space-2) var(--space-3);
8534
9139
  margin-bottom: var(--space-1);
8535
9140
  border: none;
8536
- border-bottom: 1px solid var(--color-border);
9141
+ border-bottom: var(--border-width) solid var(--color-border);
8537
9142
  border-radius: 0;
8538
9143
  background: transparent;
8539
9144
  color: var(--color-fg);
8540
- font-family: var(--font-sans, system-ui, sans-serif);
9145
+ font-family: var(--font-ui);
8541
9146
  font-size: var(--text-sm);
8542
9147
  outline: none;
8543
9148
  }
@@ -8631,7 +9236,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8631
9236
 
8632
9237
  /* === recipes/sheet.css === */
8633
9238
  /* @ui:component sheet */
8634
- /* @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 */
9239
+ /* @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 */
8635
9240
 
8636
9241
  /* ── Root ── */
8637
9242
  [data-ui="sheet"] {
@@ -8662,11 +9267,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8662
9267
  z-index: var(--z-modal);
8663
9268
  display: flex;
8664
9269
  flex-direction: column;
8665
- background: var(--color-bg);
9270
+ background: var(--panel-bg);
8666
9271
  box-shadow: var(--shadow-xl);
8667
9272
  transition: transform var(--duration-slow) var(--ease-out);
8668
9273
  }
8669
9274
 
9275
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9276
+ [data-ui="sheet"] [data-part="panel"] {
9277
+ -webkit-backdrop-filter: var(--surface-backdrop);
9278
+ backdrop-filter: var(--surface-backdrop);
9279
+ }
9280
+ }
9281
+
8670
9282
  /* ── Side: Bottom ── */
8671
9283
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8672
9284
  bottom: 0;
@@ -8694,7 +9306,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8694
9306
  bottom: 0;
8695
9307
  max-width: 100vw;
8696
9308
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8697
- border-inline-end: 1px solid var(--color-border);
9309
+ border-inline-end: var(--border-width) solid var(--color-border);
8698
9310
  transform: translateX(-100%);
8699
9311
  }
8700
9312
 
@@ -8705,7 +9317,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8705
9317
  bottom: 0;
8706
9318
  max-width: 100vw;
8707
9319
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8708
- border-inline-start: 1px solid var(--color-border);
9320
+ border-inline-start: var(--border-width) solid var(--color-border);
8709
9321
  transform: translateX(100%);
8710
9322
  }
8711
9323
 
@@ -8782,6 +9394,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8782
9394
  /* ── Title ── */
8783
9395
  [data-ui="sheet"] [data-part="title"] {
8784
9396
  margin: 0;
9397
+ font-family: var(--font-heading);
8785
9398
  font-size: var(--text-lg, 1.125rem);
8786
9399
  font-weight: var(--weight-semibold, 600);
8787
9400
  color: var(--color-fg);
@@ -8816,8 +9429,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8816
9429
  }
8817
9430
 
8818
9431
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8819
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8820
- outline-offset: 2px;
9432
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9433
+ outline-offset: var(--focus-ring-offset);
8821
9434
  }
8822
9435
 
8823
9436
  /* ── Body ── */
@@ -8838,7 +9451,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8838
9451
 
8839
9452
  /* === recipes/sidebar.css === */
8840
9453
  /* @ui:component sidebar */
8841
- /* @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 */
9454
+ /* @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 */
8842
9455
 
8843
9456
  /* ── Root ──
8844
9457
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8882,7 +9495,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8882
9495
  flex-direction: column;
8883
9496
  gap: var(--space-2);
8884
9497
  background: var(--sidebar-bg);
8885
- border-inline-end: 1px solid var(--color-border);
9498
+ border-inline-end: var(--border-width) solid var(--color-border);
8886
9499
  border-start-end-radius: var(--radius-lg, 0.5rem);
8887
9500
  border-end-end-radius: var(--radius-lg, 0.5rem);
8888
9501
  box-shadow: var(--shadow-xl);
@@ -8963,8 +9576,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8963
9576
  }
8964
9577
 
8965
9578
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8966
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8967
- outline-offset: 2px;
9579
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9580
+ outline-offset: var(--focus-ring-offset);
8968
9581
  }
8969
9582
 
8970
9583
  /* ── Navigation ── */
@@ -9000,8 +9613,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9000
9613
  }
9001
9614
 
9002
9615
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
9003
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9004
- outline-offset: -2px;
9616
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9617
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9005
9618
  }
9006
9619
 
9007
9620
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -9028,7 +9641,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9028
9641
  [data-ui="sidebar"] [data-part="footer"] {
9029
9642
  flex-shrink: 0;
9030
9643
  padding: var(--space-3) var(--space-4);
9031
- border-block-start: 1px solid var(--color-border);
9644
+ border-block-start: var(--border-width) solid var(--color-border);
9032
9645
  }
9033
9646
 
9034
9647
  /* ── Rail (icons only) ── */
@@ -9121,7 +9734,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9121
9734
 
9122
9735
  /* === recipes/slider.css === */
9123
9736
  /* @ui:component slider */
9124
- /* @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 */
9737
+ /* @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 */
9125
9738
 
9126
9739
  /* ── Root ── */
9127
9740
  [data-ui="slider"] {
@@ -9171,28 +9784,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9171
9784
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9172
9785
  transform: translate(-50%, -50%);
9173
9786
  background: var(--color-bg, white);
9174
- border: 2px solid var(--color-primary);
9787
+ border: var(--border-width-strong) solid var(--color-primary);
9175
9788
  border-radius: var(--radius-full, 9999px);
9176
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9789
+ box-shadow: var(--shadow-sm);
9177
9790
  cursor: grab;
9178
9791
  touch-action: none;
9179
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9792
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9180
9793
  }
9181
9794
 
9182
9795
  [data-ui="slider"] [data-part="thumb"]:hover {
9183
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9184
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9796
+ box-shadow: var(--shadow-sm),
9797
+ 0 0 0 4px var(--color-primary-subtle);
9185
9798
  }
9186
9799
 
9187
9800
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9188
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9189
- outline-offset: 2px;
9801
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9802
+ outline-offset: var(--focus-ring-offset);
9190
9803
  }
9191
9804
 
9192
9805
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9193
9806
  cursor: grabbing;
9194
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9195
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9807
+ box-shadow: var(--shadow-sm),
9808
+ 0 0 0 5px var(--color-primary-subtle);
9196
9809
  }
9197
9810
 
9198
9811
  /* ── Value output ── */
@@ -9200,7 +9813,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9200
9813
  flex: 0 0 auto;
9201
9814
  min-inline-size: 3ch;
9202
9815
  color: var(--color-fg-muted);
9203
- font-family: var(--font-sans, system-ui, sans-serif);
9816
+ font-family: var(--font-ui);
9204
9817
  font-size: var(--text-sm);
9205
9818
  font-variant-numeric: tabular-nums;
9206
9819
  text-align: end;
@@ -9219,7 +9832,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9219
9832
 
9220
9833
  /* ── Disabled ── */
9221
9834
  [data-ui="slider"][data-disabled] {
9222
- opacity: 0.5;
9835
+ opacity: var(--disabled-opacity);
9223
9836
  cursor: not-allowed;
9224
9837
  pointer-events: none;
9225
9838
  }
@@ -9237,7 +9850,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9237
9850
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9238
9851
  @media (forced-colors: active) {
9239
9852
  [data-ui="slider"] [data-part="track"] {
9240
- border: 1px solid ButtonText;
9853
+ border: var(--border-width) solid ButtonText;
9241
9854
  }
9242
9855
 
9243
9856
  [data-ui="slider"] [data-part="range"] {
@@ -9248,7 +9861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9248
9861
  [data-ui="slider"] [data-part="thumb"] {
9249
9862
  forced-color-adjust: none;
9250
9863
  background: ButtonText;
9251
- border: 1px solid ButtonFace;
9864
+ border: var(--border-width) solid ButtonFace;
9252
9865
  }
9253
9866
 
9254
9867
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9258,7 +9871,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9258
9871
 
9259
9872
  /* === recipes/table.css === */
9260
9873
  /* @ui:component table */
9261
- /* @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 */
9874
+ /* @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 */
9262
9875
 
9263
9876
  /* ── Root ── */
9264
9877
  [data-ui="table"] {
@@ -9284,7 +9897,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9284
9897
  width: 100%;
9285
9898
  border-collapse: separate;
9286
9899
  border-spacing: 0;
9287
- font-family: var(--font-sans, system-ui, sans-serif);
9900
+ font-family: var(--font-body);
9288
9901
  }
9289
9902
 
9290
9903
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9306,7 +9919,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9306
9919
  font-weight: var(--weight-semibold);
9307
9920
  color: var(--color-fg-muted);
9308
9921
  background: var(--color-bg);
9309
- border-bottom: 2px solid var(--color-border);
9922
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9310
9923
  white-space: nowrap;
9311
9924
  user-select: none;
9312
9925
  }
@@ -9364,8 +9977,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9364
9977
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9365
9978
  [data-ui="table"] [data-part="th"]:focus-visible,
9366
9979
  [data-ui="table"] [data-part="td"]:focus-visible {
9367
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9368
- outline-offset: -2px;
9980
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9981
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9369
9982
  }
9370
9983
 
9371
9984
  /* ── Data Cell ── */
@@ -9373,7 +9986,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9373
9986
  padding: var(--space-3) var(--space-4);
9374
9987
  font-size: var(--text-sm);
9375
9988
  color: var(--color-fg);
9376
- border-bottom: 1px solid var(--color-border);
9989
+ border-bottom: var(--border-width) solid var(--color-border);
9377
9990
  background: var(--color-bg);
9378
9991
  transition: background var(--duration-fast) var(--ease-default);
9379
9992
  }
@@ -9402,31 +10015,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9402
10015
  Static fallback via nth-child; once the controller stamps data-stripe on the
9403
10016
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9404
10017
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9405
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10018
+ background: var(--stripe-bg);
9406
10019
  }
9407
10020
 
9408
10021
  [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"] {
9409
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10022
+ background: var(--stripe-bg);
9410
10023
  }
9411
10024
 
9412
10025
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9413
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10026
+ background: var(--stripe-bg);
9414
10027
  }
9415
10028
 
9416
10029
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9417
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10030
+ background: var(--stripe-bg);
9418
10031
  }
9419
10032
 
9420
10033
  /* ── Bordered Variant ── */
9421
10034
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9422
- border: 1px solid var(--color-border);
10035
+ border: var(--border-width) solid var(--color-border);
9423
10036
  border-radius: var(--radius-md, 0.375rem);
9424
10037
  overflow: hidden;
9425
10038
  }
9426
10039
 
9427
10040
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9428
10041
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9429
- border: 1px solid var(--color-border);
10042
+ border: var(--border-width) solid var(--color-border);
9430
10043
  }
9431
10044
 
9432
10045
  /* ── Size: Small ── */
@@ -9454,7 +10067,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9454
10067
  /* ── Footer ── */
9455
10068
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9456
10069
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9457
- border-top: 2px solid var(--color-border);
10070
+ border-top: var(--border-width-strong) solid var(--color-border);
9458
10071
  border-bottom: none;
9459
10072
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9460
10073
  }
@@ -9580,7 +10193,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9580
10193
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9581
10194
  padding: var(--space-1) var(--space-2);
9582
10195
  background: var(--color-bg);
9583
- border-bottom: 1px solid var(--color-border);
10196
+ border-bottom: var(--border-width) solid var(--color-border);
9584
10197
  }
9585
10198
 
9586
10199
  [data-ui="table"] [data-part="filter-input"],
@@ -9592,14 +10205,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9592
10205
  font-size: var(--text-xs);
9593
10206
  color: var(--color-fg);
9594
10207
  background: var(--color-bg);
9595
- border: 1px solid var(--color-border);
10208
+ border: var(--border-width) solid var(--color-border);
9596
10209
  border-radius: var(--radius-sm);
9597
10210
  }
9598
10211
 
9599
10212
  [data-ui="table"] [data-part="filter-input"]:focus,
9600
10213
  [data-ui="table"] [data-part="filter"]:focus {
9601
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9602
- outline-offset: -1px;
10214
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10215
+ outline-offset: calc(-1 * var(--border-width));
9603
10216
  border-color: var(--color-primary);
9604
10217
  }
9605
10218
 
@@ -9620,7 +10233,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9620
10233
  text-align: inherit;
9621
10234
  color: var(--color-fg);
9622
10235
  background: var(--color-bg);
9623
- border: 1px solid var(--color-primary);
10236
+ border: var(--border-width) solid var(--color-primary);
9624
10237
  border-radius: var(--radius-sm);
9625
10238
  outline: none;
9626
10239
  }
@@ -9673,11 +10286,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9673
10286
  }
9674
10287
 
9675
10288
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9676
- border-block-start: 2px solid var(--color-primary);
10289
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9677
10290
  }
9678
10291
 
9679
10292
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9680
- border-block-end: 2px solid var(--color-primary);
10293
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9681
10294
  }
9682
10295
 
9683
10296
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9685,11 +10298,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9685
10298
  }
9686
10299
 
9687
10300
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9688
- border-inline-start: 2px solid var(--color-primary);
10301
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9689
10302
  }
9690
10303
 
9691
10304
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9692
- border-inline-end: 2px solid var(--color-primary);
10305
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9693
10306
  }
9694
10307
 
9695
10308
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9762,11 +10375,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9762
10375
  }
9763
10376
 
9764
10377
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9765
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10378
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9766
10379
  }
9767
10380
 
9768
10381
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9769
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10382
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9770
10383
  }
9771
10384
 
9772
10385
  /* ── Column Visibility ── */
@@ -9838,7 +10451,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9838
10451
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9839
10452
  display: block;
9840
10453
  margin-block-end: var(--space-3);
9841
- border: 1px solid var(--color-border);
10454
+ border: var(--border-width) solid var(--color-border);
9842
10455
  border-radius: var(--radius-md);
9843
10456
  background: var(--color-bg);
9844
10457
  overflow: hidden;
@@ -9852,7 +10465,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9852
10465
  gap: var(--space-4);
9853
10466
  text-align: end;
9854
10467
  border-bottom: none;
9855
- border-block-end: 1px solid var(--color-border);
10468
+ border-block-end: var(--border-width) solid var(--color-border);
9856
10469
  }
9857
10470
 
9858
10471
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9949,7 +10562,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9949
10562
 
9950
10563
  /* === recipes/tabs.css === */
9951
10564
  /* @ui:component tabs */
9952
- /* @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 */
10565
+ /* @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 */
9953
10566
 
9954
10567
  /* ── Root ── */
9955
10568
  [data-ui="tabs"] {
@@ -9978,7 +10591,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9978
10591
  border: none;
9979
10592
  background: transparent;
9980
10593
  color: var(--color-fg-muted);
9981
- font-family: var(--font-sans, system-ui, sans-serif);
10594
+ font-family: var(--font-ui);
9982
10595
  font-size: var(--text-sm);
9983
10596
  font-weight: var(--weight-medium);
9984
10597
  cursor: pointer;
@@ -9993,8 +10606,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9993
10606
  }
9994
10607
 
9995
10608
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9996
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9997
- outline-offset: -2px;
10609
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10610
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9998
10611
  border-radius: var(--radius-md);
9999
10612
  }
10000
10613
 
@@ -10004,12 +10617,12 @@ div[data-ui="separator"][data-style="thick"]::after {
10004
10617
 
10005
10618
  /* ── Underline Variant ── */
10006
10619
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
10007
- border-bottom: 1px solid var(--color-border);
10620
+ border-bottom: var(--border-width) solid var(--color-border);
10008
10621
  gap: 0;
10009
10622
  }
10010
10623
 
10011
10624
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
10012
- border-bottom: 2px solid transparent;
10625
+ border-bottom: var(--border-width-strong) solid transparent;
10013
10626
  margin-bottom: -1px;
10014
10627
  border-radius: 0;
10015
10628
  }
@@ -10041,17 +10654,17 @@ div[data-ui="separator"][data-style="thick"]::after {
10041
10654
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
10042
10655
  background: var(--color-bg);
10043
10656
  color: var(--color-fg);
10044
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10657
+ box-shadow: var(--shadow-xs);
10045
10658
  }
10046
10659
 
10047
10660
  /* ── Enclosed Variant ── */
10048
10661
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
10049
- border-bottom: 1px solid var(--color-border);
10662
+ border-bottom: var(--border-width) solid var(--color-border);
10050
10663
  gap: 0;
10051
10664
  }
10052
10665
 
10053
10666
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10054
- border: 1px solid transparent;
10667
+ border: var(--border-width) solid transparent;
10055
10668
  border-bottom: none;
10056
10669
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10057
10670
  margin-bottom: -1px;
@@ -10096,8 +10709,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10096
10709
  @media (forced-colors: active) {
10097
10710
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10098
10711
  /* An outline the OS preserves, on every variant. */
10099
- outline: 2px solid Highlight;
10100
- outline-offset: -2px;
10712
+ outline: var(--border-width-strong) solid Highlight;
10713
+ outline-offset: calc(-1 * var(--border-width-strong));
10101
10714
  }
10102
10715
 
10103
10716
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10112,7 +10725,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10112
10725
 
10113
10726
  /* === recipes/tag-input.css === */
10114
10727
  /* @ui:component tag-input */
10115
- /* @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 */
10728
+ /* @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 */
10116
10729
 
10117
10730
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10118
10731
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10133,7 +10746,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10133
10746
  gap: var(--space-1h);
10134
10747
  width: 100%;
10135
10748
  padding: var(--space-1h) var(--space-2);
10136
- border: 1px solid var(--color-border);
10749
+ border: var(--border-width) solid var(--color-border);
10137
10750
  border-radius: var(--radius-md);
10138
10751
  background: var(--color-bg);
10139
10752
  list-style: none;
@@ -10142,8 +10755,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10142
10755
  }
10143
10756
 
10144
10757
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10145
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10146
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10758
+ border-color: var(--focus-ring-color);
10759
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10147
10760
  }
10148
10761
 
10149
10762
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10154,7 +10767,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10154
10767
  border: none;
10155
10768
  background: transparent;
10156
10769
  color: var(--color-fg);
10157
- font-family: var(--font-sans, system-ui, sans-serif);
10770
+ font-family: var(--font-ui);
10158
10771
  font-size: var(--text-sm);
10159
10772
  line-height: 1.5;
10160
10773
  outline: none;
@@ -10173,7 +10786,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10173
10786
  z-index: var(--z-dropdown);
10174
10787
  margin-top: var(--space-1);
10175
10788
  padding: var(--space-1);
10176
- border: 1px solid var(--color-border);
10789
+ border: var(--border-width) solid var(--color-border);
10177
10790
  border-radius: var(--radius-lg);
10178
10791
  background: var(--color-bg);
10179
10792
  box-shadow: var(--shadow-md);
@@ -10220,7 +10833,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10220
10833
 
10221
10834
  /* === recipes/toast.css === */
10222
10835
  /* @ui:component toast */
10223
- /* @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 */
10836
+ /* @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 */
10224
10837
 
10225
10838
  /* ── Container ── */
10226
10839
  [data-ui="toast"][data-part="container"] {
@@ -10269,8 +10882,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10269
10882
  max-width: 380px;
10270
10883
  width: max-content;
10271
10884
  padding: var(--space-3) var(--space-4);
10272
- background: var(--color-bg);
10273
- border: 1px solid var(--color-border);
10885
+ background: var(--panel-bg);
10886
+ border: var(--border-width) solid var(--color-border);
10274
10887
  border-radius: var(--radius-lg);
10275
10888
  box-shadow: var(--shadow-lg);
10276
10889
  pointer-events: auto;
@@ -10280,6 +10893,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10280
10893
  transform var(--duration-normal) var(--ease-out);
10281
10894
  }
10282
10895
 
10896
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10897
+ [data-ui="toast"] [data-part="toast"] {
10898
+ -webkit-backdrop-filter: var(--surface-backdrop);
10899
+ backdrop-filter: var(--surface-backdrop);
10900
+ }
10901
+ }
10902
+
10283
10903
  /* ── State: Entering ── */
10284
10904
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10285
10905
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10319,7 +10939,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10319
10939
 
10320
10940
  /* ── Tone Variants ── */
10321
10941
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10322
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10942
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10323
10943
  }
10324
10944
 
10325
10945
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10327,7 +10947,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10327
10947
  }
10328
10948
 
10329
10949
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10330
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10950
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10331
10951
  }
10332
10952
 
10333
10953
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10335,7 +10955,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10335
10955
  }
10336
10956
 
10337
10957
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10338
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10958
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10339
10959
  }
10340
10960
 
10341
10961
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10357,7 +10977,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10357
10977
  /* ── Message ── */
10358
10978
  [data-ui="toast"] [data-part="message"] {
10359
10979
  flex: 1;
10360
- font-family: var(--font-sans, system-ui, sans-serif);
10980
+ font-family: var(--font-ui);
10361
10981
  font-size: var(--text-sm);
10362
10982
  font-weight: var(--weight-medium);
10363
10983
  color: var(--color-fg);
@@ -10368,11 +10988,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10368
10988
  [data-ui="toast"] [data-part="action"] {
10369
10989
  flex-shrink: 0;
10370
10990
  padding: var(--space-1, 0.25rem) var(--space-2);
10371
- border: 1px solid var(--color-border);
10991
+ border: var(--border-width) solid var(--color-border);
10372
10992
  border-radius: var(--radius-md, 0.375rem);
10373
10993
  background: transparent;
10374
10994
  color: var(--color-fg);
10375
- font-family: var(--font-sans, system-ui, sans-serif);
10995
+ font-family: var(--font-ui);
10376
10996
  font-size: var(--text-xs, 0.75rem);
10377
10997
  font-weight: var(--weight-medium);
10378
10998
  cursor: pointer;
@@ -10385,8 +11005,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10385
11005
  }
10386
11006
 
10387
11007
  [data-ui="toast"] [data-part="action"]:focus-visible {
10388
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10389
- outline-offset: 2px;
11008
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11009
+ outline-offset: var(--focus-ring-offset);
10390
11010
  }
10391
11011
 
10392
11012
  /* ── Close Button ── */
@@ -10412,8 +11032,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10412
11032
  }
10413
11033
 
10414
11034
  [data-ui="toast"] [data-part="close"]:focus-visible {
10415
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10416
- outline-offset: 2px;
11035
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11036
+ outline-offset: var(--focus-ring-offset);
10417
11037
  }
10418
11038
 
10419
11039
  /* ── Motion ── */
@@ -10426,14 +11046,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10426
11046
 
10427
11047
  /* === recipes/toggle-group.css === */
10428
11048
  /* @ui:component toggle-group */
10429
- /* @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 */
11049
+ /* @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 */
10430
11050
 
10431
11051
  /* ── Root: a segmented row of toggle buttons ── */
10432
11052
  [data-ui="toggle-group"] {
10433
11053
  display: inline-flex;
10434
11054
  gap: var(--space-1);
10435
11055
  padding: var(--space-1);
10436
- border: 1px solid var(--color-border);
11056
+ border: var(--border-width) solid var(--color-border);
10437
11057
  border-radius: var(--radius-md);
10438
11058
  background: var(--color-bg);
10439
11059
  }
@@ -10448,7 +11068,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10448
11068
  border-radius: var(--radius-md);
10449
11069
  background: transparent;
10450
11070
  color: var(--color-fg-muted);
10451
- font-family: var(--toggle-group-font, var(--font-sans));
11071
+ font-family: var(--toggle-group-font, var(--font-ui));
10452
11072
  font-size: var(--text-sm);
10453
11073
  font-weight: var(--weight-medium);
10454
11074
  line-height: 1;
@@ -10489,13 +11109,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10489
11109
 
10490
11110
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10491
11111
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10492
- outline: 2px solid var(--color-ring);
10493
- outline-offset: 2px;
11112
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11113
+ outline-offset: var(--focus-ring-offset);
10494
11114
  }
10495
11115
 
10496
11116
  /* ── Disabled control ── */
10497
11117
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10498
- opacity: 0.5;
11118
+ opacity: var(--disabled-opacity);
10499
11119
  cursor: not-allowed;
10500
11120
  }
10501
11121
 
@@ -10508,7 +11128,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10508
11128
 
10509
11129
  /* === recipes/tooltip.css === */
10510
11130
  /* @ui:component tooltip */
10511
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11131
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10512
11132
 
10513
11133
  /* ── Root ── */
10514
11134
  [data-ui="tooltip"] {
@@ -10529,7 +11149,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10529
11149
  color: var(--color-bg);
10530
11150
  border-radius: var(--radius-md);
10531
11151
  padding: var(--space-1h, 0.375rem) var(--space-2);
10532
- font-family: var(--font-sans, system-ui, sans-serif);
11152
+ font-family: var(--font-ui);
10533
11153
  font-size: var(--text-xs, 0.75rem);
10534
11154
  line-height: 1.4;
10535
11155
  white-space: nowrap;
@@ -10540,6 +11160,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10540
11160
  transform var(--duration-fast) var(--ease-default);
10541
11161
  }
10542
11162
 
11163
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11164
+ [data-ui="tooltip"] [data-part="content"] {
11165
+ -webkit-backdrop-filter: var(--surface-backdrop);
11166
+ backdrop-filter: var(--surface-backdrop);
11167
+ }
11168
+ }
11169
+
10543
11170
  /* Default position (top) when no variant is specified */
10544
11171
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10545
11172
  bottom: 100%;
@@ -10655,7 +11282,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10655
11282
 
10656
11283
  /* === recipes/tree-view.css === */
10657
11284
  /* @ui:component tree-view */
10658
- /* @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 */
11285
+ /* @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 */
10659
11286
 
10660
11287
  [data-ui="tree-view"],
10661
11288
  [data-ui="tree-view"] [data-part="group"] {
@@ -10668,7 +11295,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10668
11295
  inline-size: 100%;
10669
11296
  padding: var(--space-1);
10670
11297
  color: var(--color-fg);
10671
- font-family: var(--font-sans);
11298
+ font-family: var(--font-ui);
10672
11299
  font-size: var(--text-sm);
10673
11300
  }
10674
11301
 
@@ -10696,8 +11323,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10696
11323
  }
10697
11324
 
10698
11325
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10699
- outline: var(--space-px) solid var(--color-ring);
10700
- outline-offset: var(--space-px);
11326
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11327
+ outline-offset: var(--focus-ring-offset);
10701
11328
  }
10702
11329
 
10703
11330
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10736,7 +11363,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10736
11363
 
10737
11364
  /* === patterns/auth-form.css === */
10738
11365
  /* @ui:component auth-form */
10739
- /* @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 */
11366
+ /* @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 */
10740
11367
 
10741
11368
  /* ── Root Container ── */
10742
11369
  [data-ui="auth-form"] {
@@ -10744,7 +11371,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10744
11371
  align-items: center;
10745
11372
  justify-content: center;
10746
11373
  width: 100%;
10747
- font-family: var(--font-sans);
11374
+ font-family: var(--font-body);
10748
11375
  }
10749
11376
 
10750
11377
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10776,9 +11403,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10776
11403
 
10777
11404
  [data-ui="auth-form"] [data-part="title"] {
10778
11405
  margin: 0;
11406
+ font-family: var(--font-heading);
10779
11407
  font-size: var(--text-xl);
10780
- font-weight: var(--weight-bold);
10781
- line-height: var(--leading-tight);
11408
+ font-weight: var(--heading-weight);
11409
+ letter-spacing: var(--heading-tracking);
11410
+ text-transform: var(--heading-transform);
11411
+ font-variant-caps: var(--heading-caps);
11412
+ line-height: var(--heading-leading);
10782
11413
  color: var(--color-fg);
10783
11414
  }
10784
11415
 
@@ -10795,7 +11426,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10795
11426
  margin: var(--space-4) var(--space-6) 0;
10796
11427
  padding: var(--space-3);
10797
11428
  background: var(--color-destructive-subtle);
10798
- border: 1px solid var(--color-destructive);
11429
+ border: var(--border-width) solid var(--color-destructive);
10799
11430
  border-radius: var(--radius-lg);
10800
11431
  color: var(--color-destructive);
10801
11432
  font-size: var(--text-sm);
@@ -10873,13 +11504,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10873
11504
  }
10874
11505
 
10875
11506
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10876
- text-decoration: underline;
11507
+ text-decoration-line: var(--link-decoration);
10877
11508
  color: var(--color-primary-hover);
10878
11509
  }
10879
11510
 
10880
11511
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10881
- outline: 2px solid var(--color-ring);
10882
- outline-offset: 2px;
11512
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11513
+ outline-offset: var(--focus-ring-offset);
10883
11514
  border-radius: var(--radius-sm, 0.25rem);
10884
11515
  }
10885
11516
 
@@ -11007,8 +11638,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11007
11638
  max-width: var(--auth-form-max-width, 400px);
11008
11639
  border-radius: var(--card-radius, var(--radius-lg));
11009
11640
  box-shadow: var(--card-shadow, var(--shadow-sm));
11010
- border-inline-start: 1px solid var(--card-border, var(--color-border));
11011
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11641
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11642
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
11012
11643
  }
11013
11644
  }
11014
11645
 
@@ -11023,7 +11654,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11023
11654
 
11024
11655
  /* === patterns/crud-table.css === */
11025
11656
  /* @ui:component crud-table */
11026
- /* @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 */
11657
+ /* @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 */
11027
11658
 
11028
11659
  /* ── Root ── */
11029
11660
  [data-ui="crud-table"] {
@@ -11031,7 +11662,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11031
11662
  flex-direction: column;
11032
11663
  gap: var(--space-4);
11033
11664
  width: 100%;
11034
- font-family: var(--font-sans, system-ui, sans-serif);
11665
+ font-family: var(--font-body);
11035
11666
  }
11036
11667
 
11037
11668
  /* ── Toolbar ── */
@@ -11089,7 +11720,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11089
11720
  gap: var(--space-3);
11090
11721
  padding: var(--space-3) var(--space-4);
11091
11722
  background: var(--color-bg-subtle);
11092
- border: 1px solid var(--color-border);
11723
+ border: var(--border-width) solid var(--color-border);
11093
11724
  border-radius: var(--radius-md);
11094
11725
  }
11095
11726
 
@@ -11104,7 +11735,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11104
11735
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11105
11736
  width: 100%;
11106
11737
  overflow-x: auto;
11107
- border: 1px solid var(--color-border);
11738
+ border: var(--border-width) solid var(--color-border);
11108
11739
  border-radius: var(--radius-lg);
11109
11740
  background: var(--color-bg);
11110
11741
  }
@@ -11134,7 +11765,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11134
11765
  padding: var(--space-8) var(--space-4);
11135
11766
  text-align: center;
11136
11767
  min-height: 240px;
11137
- border: 1px dashed var(--color-border);
11768
+ border: var(--border-width) dashed var(--color-border);
11138
11769
  border-radius: var(--radius-lg);
11139
11770
  background: var(--color-bg);
11140
11771
  }
@@ -11247,7 +11878,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11247
11878
 
11248
11879
  /* === patterns/dashboard-shell.css === */
11249
11880
  /* @ui:component dashboard-shell */
11250
- /* @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 */
11881
+ /* @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 */
11251
11882
 
11252
11883
  /* ── Shell Grid Layout ──
11253
11884
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11272,7 +11903,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11272
11903
  "footer";
11273
11904
  min-height: 100vh;
11274
11905
  background: var(--color-bg);
11275
- font-family: var(--font-sans);
11906
+ font-family: var(--font-body);
11276
11907
  color: var(--color-fg);
11277
11908
  }
11278
11909
 
@@ -11296,7 +11927,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11296
11927
  gap: var(--space-2);
11297
11928
  padding: var(--space-4);
11298
11929
  background: var(--color-bg-subtle);
11299
- border-inline-end: 1px solid var(--color-border);
11930
+ border-inline-end: var(--border-width) solid var(--color-border);
11300
11931
  overflow-y: auto;
11301
11932
  position: fixed;
11302
11933
  top: 0;
@@ -11316,7 +11947,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11316
11947
 
11317
11948
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11318
11949
  border-inline-end: none;
11319
- border-inline-start: 1px solid var(--color-border);
11950
+ border-inline-start: var(--border-width) solid var(--color-border);
11320
11951
  inset-inline-start: auto;
11321
11952
  inset-inline-end: 0;
11322
11953
  transform: translateX(100%);
@@ -11391,7 +12022,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11391
12022
  gap: var(--space-3);
11392
12023
  padding: var(--space-2) var(--space-3);
11393
12024
  border-radius: var(--radius-md);
11394
- font-family: var(--font-sans);
12025
+ font-family: var(--font-ui);
11395
12026
  font-size: var(--text-sm);
11396
12027
  font-weight: var(--weight-medium);
11397
12028
  line-height: var(--leading-normal);
@@ -11410,8 +12041,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11410
12041
  }
11411
12042
 
11412
12043
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11413
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11414
- outline-offset: -2px;
12044
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12045
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11415
12046
  }
11416
12047
 
11417
12048
  /* ── Nav Item Active ── */
@@ -11458,7 +12089,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11458
12089
  gap: var(--space-2);
11459
12090
  padding: 0 var(--space-3);
11460
12091
  background: var(--color-bg);
11461
- border-bottom: 1px solid var(--color-border);
12092
+ border-bottom: var(--border-width) solid var(--color-border);
11462
12093
  position: sticky;
11463
12094
  top: 0;
11464
12095
  z-index: var(--z-sticky);
@@ -11539,7 +12170,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11539
12170
  align-items: center;
11540
12171
  gap: var(--space-3);
11541
12172
  padding: var(--space-4) var(--space-6);
11542
- border-top: 1px solid var(--color-border);
12173
+ border-top: var(--border-width) solid var(--color-border);
11543
12174
  font-size: var(--text-xs);
11544
12175
  color: var(--color-fg-muted);
11545
12176
  }
@@ -11622,7 +12253,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11622
12253
 
11623
12254
  /* === patterns/document.css === */
11624
12255
  /* @ui:component document */
11625
- /* @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 */
12256
+ /* @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 */
11626
12257
 
11627
12258
  /* ── Page Rules ── */
11628
12259
  @page {
@@ -11662,14 +12293,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11662
12293
  max-width: var(--doc-max-width);
11663
12294
  margin: var(--space-4) auto;
11664
12295
  padding: var(--space-6) var(--space-4);
11665
- background: var(--color-bg, #fff);
12296
+ background-color: var(--color-bg, #fff);
12297
+ background-image: var(--texture-page);
11666
12298
  color: var(--color-fg);
11667
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12299
+ font-family: var(--doc-font, var(--font-body));
11668
12300
  font-size: var(--doc-font-size);
11669
12301
  line-height: var(--doc-line-height);
11670
- box-shadow: var(--shadow-lg,
11671
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11672
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12302
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12303
+ colour no theme could reach. --shadow-lg is always defined by the token
12304
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12305
+ than re-tokenised. */
12306
+ box-shadow: var(--shadow-lg);
11673
12307
  border-radius: 0;
11674
12308
  position: relative;
11675
12309
  }
@@ -11685,7 +12319,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11685
12319
  [data-ui="document"] > [data-part="header"] {
11686
12320
  margin-block-end: var(--doc-section-gap);
11687
12321
  padding-block-end: var(--doc-component-gap);
11688
- border-block-end: 1px solid var(--color-border);
12322
+ border-block-end: var(--border-width) solid var(--color-border);
11689
12323
  }
11690
12324
 
11691
12325
  /* ── Body ── */
@@ -11695,13 +12329,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11695
12329
  gap: var(--doc-section-gap);
11696
12330
  }
11697
12331
 
12332
+ /* ── Headings ──
12333
+ The document's own heading face and weight (1.1A-21): a print theme sets
12334
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12335
+ from the body copy (document-serif's Times titles over Georgia text). Both
12336
+ default to the page's heading role in tokens/document.css, and each falls
12337
+ back to what a heading rendered before the tokens had a reader. A heading
12338
+ that carries its own data-weight keeps it — that is the author asking. */
12339
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12340
+ font-family: var(--doc-heading-font, var(--font-body));
12341
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12342
+ }
12343
+
11698
12344
  /* ── Running footer ──
11699
12345
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11700
12346
  [data-ui="document"] > [data-part="doc-footer"],
11701
12347
  [data-ui="document"] > [data-part="footer"] {
11702
12348
  margin-block-start: var(--doc-section-gap);
11703
12349
  padding-block-start: var(--doc-component-gap);
11704
- border-block-start: 1px solid var(--color-border);
12350
+ border-block-start: var(--border-width) solid var(--color-border);
11705
12351
  font-size: var(--doc-legal-size);
11706
12352
  color: var(--doc-legal-color);
11707
12353
  }
@@ -11739,7 +12385,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11739
12385
 
11740
12386
  /* ── Variant: Report ── */
11741
12387
  [data-ui="document"][data-variant="report"] {
11742
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12388
+ /* A report is serif-set by definition. It re-points the document's own font
12389
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12390
+ (key-value, callout, signature — all of which read --doc-font) follows the
12391
+ report into serif instead of staying sans inside a serif page. `report` is
12392
+ the author asking for serif; a theme that wants its own document face
12393
+ declares --doc-font at :root, which this variant deliberately outranks. */
12394
+ --doc-font: Georgia, 'Times New Roman', serif;
11743
12395
  line-height: 1.6;
11744
12396
  }
11745
12397
 
@@ -11834,7 +12486,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11834
12486
  z-index: var(--z-raised);
11835
12487
  margin-block-end: 0;
11836
12488
  padding-block-end: var(--doc-running-gap);
11837
- border-block-end: 1px solid var(--doc-print-border-color);
12489
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11838
12490
  background: var(--doc-bg);
11839
12491
  transform: translateZ(0);
11840
12492
  }
@@ -11850,7 +12502,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11850
12502
  z-index: var(--z-raised);
11851
12503
  margin-block-start: 0;
11852
12504
  padding-block-start: var(--doc-running-gap);
11853
- border-block-start: 1px solid var(--doc-print-border-color);
12505
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11854
12506
  background: var(--doc-bg);
11855
12507
  transform: translateZ(0);
11856
12508
  }
@@ -11879,7 +12531,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11879
12531
 
11880
12532
  /* === patterns/empty-state.css === */
11881
12533
  /* @ui:component empty-state */
11882
- /* @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 */
12534
+ /* @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 */
11883
12535
 
11884
12536
  /* ── Root ── */
11885
12537
  [data-ui="empty-state"] {
@@ -11890,7 +12542,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11890
12542
  text-align: center;
11891
12543
  padding: var(--space-8) var(--space-6);
11892
12544
  gap: var(--space-3);
11893
- font-family: var(--font-sans, system-ui, sans-serif);
12545
+ font-family: var(--font-body);
11894
12546
  }
11895
12547
 
11896
12548
  /* ── Icon ── */
@@ -11913,10 +12565,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11913
12565
 
11914
12566
  /* ── Title ── */
11915
12567
  [data-ui="empty-state"] [data-part="title"] {
11916
- font-family: var(--font-sans, system-ui, sans-serif);
12568
+ font-family: var(--font-heading);
11917
12569
  font-size: var(--text-lg);
11918
12570
  font-weight: var(--weight-semibold);
11919
- line-height: var(--leading-tight);
12571
+ letter-spacing: var(--heading-tracking);
12572
+ text-transform: var(--heading-transform);
12573
+ font-variant-caps: var(--heading-caps);
12574
+ line-height: var(--heading-leading);
11920
12575
  color: var(--color-fg);
11921
12576
  margin: 0;
11922
12577
  }
@@ -12014,7 +12669,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12014
12669
 
12015
12670
  /* === patterns/feature-grid.css === */
12016
12671
  /* @ui:component feature-grid */
12017
- /* @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 */
12672
+ /* @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 */
12018
12673
 
12019
12674
  /* ── Root ──
12020
12675
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12024,7 +12679,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12024
12679
  gap: var(--space-4);
12025
12680
  padding-block: var(--space-12);
12026
12681
  padding-inline: var(--space-4);
12027
- font-family: var(--font-sans, system-ui, sans-serif);
12682
+ font-family: var(--font-body);
12028
12683
  color: var(--color-fg);
12029
12684
  background: var(--color-bg);
12030
12685
  }
@@ -12166,7 +12821,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12166
12821
  max-inline-size: var(--measure-narrow);
12167
12822
  margin-inline: auto;
12168
12823
  padding-block: var(--space-8);
12169
- font-family: var(--font-sans);
12824
+ font-family: var(--font-body);
12170
12825
  }
12171
12826
 
12172
12827
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12186,7 +12841,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12186
12841
 
12187
12842
  /* === patterns/hero.css === */
12188
12843
  /* @ui:component hero */
12189
- /* @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 */
12844
+ /* @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 */
12190
12845
 
12191
12846
  /* ── Root ──
12192
12847
  A one-column grid by default; the layout variants only change how that grid
@@ -12200,9 +12855,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12200
12855
  gap: var(--space-4);
12201
12856
  padding-block: var(--space-12);
12202
12857
  padding-inline: var(--space-4);
12203
- font-family: var(--font-sans, system-ui, sans-serif);
12858
+ font-family: var(--font-body);
12204
12859
  color: var(--color-fg);
12205
- background: var(--color-bg);
12860
+ background-color: var(--color-bg);
12861
+ background-image: var(--texture-surface);
12206
12862
  }
12207
12863
 
12208
12864
  /* ── Eyebrow ── */
@@ -12214,9 +12870,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12214
12870
  /* ── Headline ── */
12215
12871
  [data-ui="hero"] [data-part="headline"] {
12216
12872
  margin: 0;
12873
+ font-family: var(--font-heading);
12217
12874
  font-size: var(--text-3xl);
12218
- font-weight: var(--weight-bold);
12219
- line-height: var(--leading-tight);
12875
+ font-weight: var(--heading-weight);
12876
+ letter-spacing: var(--heading-tracking);
12877
+ text-transform: var(--heading-transform);
12878
+ font-variant-caps: var(--heading-caps);
12879
+ line-height: var(--heading-leading);
12220
12880
  color: var(--color-fg);
12221
12881
  text-wrap: balance;
12222
12882
  }
@@ -12335,7 +12995,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12335
12995
 
12336
12996
  /* === patterns/inbox.css === */
12337
12997
  /* @ui:component inbox */
12338
- /* @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 */
12998
+ /* @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 */
12339
12999
 
12340
13000
  /* ── Root ──
12341
13001
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12355,7 +13015,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12355
13015
  overflow: hidden;
12356
13016
  border: var(--space-px, 1px) solid var(--color-border);
12357
13017
  border-radius: var(--radius-lg);
12358
- font-family: var(--font-sans, system-ui, sans-serif);
13018
+ font-family: var(--font-body);
12359
13019
  color: var(--color-fg);
12360
13020
  background: var(--color-bg);
12361
13021
  }
@@ -12447,8 +13107,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12447
13107
  }
12448
13108
 
12449
13109
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12450
- outline: 2px solid var(--color-ring);
12451
- outline-offset: 2px;
13110
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13111
+ outline-offset: var(--focus-ring-offset);
12452
13112
  }
12453
13113
 
12454
13114
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12607,7 +13267,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12607
13267
 
12608
13268
  /* === patterns/pricing.css === */
12609
13269
  /* @ui:component pricing */
12610
- /* @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 */
13270
+ /* @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 */
12611
13271
 
12612
13272
  /* ── Root ──
12613
13273
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12617,7 +13277,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12617
13277
  gap: var(--space-4);
12618
13278
  padding-block: var(--space-12);
12619
13279
  padding-inline: var(--space-4);
12620
- font-family: var(--font-sans, system-ui, sans-serif);
13280
+ font-family: var(--font-body);
12621
13281
  color: var(--color-fg);
12622
13282
  background: var(--color-bg);
12623
13283
  }
@@ -12667,9 +13327,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12667
13327
 
12668
13328
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12669
13329
  margin: 0;
13330
+ font-family: var(--font-heading);
12670
13331
  font-size: var(--text-lg);
12671
13332
  font-weight: var(--weight-semibold);
12672
- line-height: var(--leading-tight);
13333
+ letter-spacing: var(--heading-tracking);
13334
+ text-transform: var(--heading-transform);
13335
+ font-variant-caps: var(--heading-caps);
13336
+ line-height: var(--heading-leading);
12673
13337
  }
12674
13338
 
12675
13339
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12730,7 +13394,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12730
13394
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12731
13395
  border-color: var(--color-primary);
12732
13396
  box-shadow: var(--shadow-md);
12733
- outline: var(--space-px, 1px) solid var(--color-primary);
13397
+ outline: var(--border-width-strong) solid var(--color-primary);
12734
13398
  }
12735
13399
 
12736
13400
  /* ── Footnote ── */
@@ -12775,14 +13439,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12775
13439
 
12776
13440
  /* === patterns/search-results.css === */
12777
13441
  /* @ui:component search-results */
12778
- /* @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 */
13442
+ /* @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 */
12779
13443
 
12780
13444
  /* ── Root ── */
12781
13445
  [data-ui="search-results"] {
12782
13446
  display: flex;
12783
13447
  flex-direction: column;
12784
13448
  gap: var(--space-4);
12785
- font-family: var(--font-sans, system-ui, sans-serif);
13449
+ font-family: var(--font-body);
12786
13450
  }
12787
13451
 
12788
13452
  /* ── Search Input ── */
@@ -12810,7 +13474,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12810
13474
  justify-content: space-between;
12811
13475
  gap: var(--space-4);
12812
13476
  padding-bottom: var(--space-2);
12813
- border-bottom: 1px solid var(--color-border);
13477
+ border-bottom: var(--border-width) solid var(--color-border);
12814
13478
  }
12815
13479
 
12816
13480
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12845,7 +13509,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12845
13509
  flex-direction: column;
12846
13510
  gap: var(--space-2);
12847
13511
  padding: var(--space-4);
12848
- border: 1px solid var(--color-border);
13512
+ border: var(--border-width) solid var(--color-border);
12849
13513
  border-radius: var(--radius-md);
12850
13514
  background: var(--color-bg);
12851
13515
  transition: background var(--duration-fast) var(--ease-default),
@@ -12904,7 +13568,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12904
13568
  display: flex;
12905
13569
  justify-content: center;
12906
13570
  padding-top: var(--space-4);
12907
- border-top: 1px solid var(--color-border);
13571
+ border-top: var(--border-width) solid var(--color-border);
12908
13572
  }
12909
13573
 
12910
13574
  /* ── Loading ── */
@@ -12944,7 +13608,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12944
13608
 
12945
13609
  /* ── Error State ── */
12946
13610
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12947
- border: 1px solid var(--color-border);
13611
+ border: var(--border-width) solid var(--color-border);
12948
13612
  border-radius: var(--radius-md);
12949
13613
  padding: var(--space-6);
12950
13614
  text-align: center;
@@ -12953,8 +13617,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12953
13617
 
12954
13618
  /* ── Focus management ── */
12955
13619
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12956
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12957
- outline-offset: 2px;
13620
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13621
+ outline-offset: var(--focus-ring-offset);
12958
13622
  }
12959
13623
 
12960
13624
  /* ── Motion ── */
@@ -12970,7 +13634,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12970
13634
 
12971
13635
  /* === patterns/settings-page.css === */
12972
13636
  /* @ui:component settings-page */
12973
- /* @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 */
13637
+ /* @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 */
12974
13638
 
12975
13639
  /* ── Root ── */
12976
13640
  [data-ui="settings-page"] {
@@ -12980,7 +13644,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12980
13644
  width: 100%;
12981
13645
  max-width: 768px;
12982
13646
  margin-inline: auto;
12983
- font-family: var(--font-sans, system-ui, sans-serif);
13647
+ font-family: var(--font-body);
12984
13648
  color: var(--color-fg);
12985
13649
  }
12986
13650
 
@@ -12994,9 +13658,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12994
13658
  /* ── Title ── */
12995
13659
  [data-ui="settings-page"] [data-part="title"] {
12996
13660
  margin: 0;
13661
+ font-family: var(--font-heading);
12997
13662
  font-size: var(--text-xl, 1.25rem);
12998
13663
  font-weight: var(--weight-semibold, 600);
12999
- line-height: var(--leading-tight);
13664
+ letter-spacing: var(--heading-tracking);
13665
+ text-transform: var(--heading-transform);
13666
+ font-variant-caps: var(--heading-caps);
13667
+ line-height: var(--heading-leading);
13000
13668
  color: var(--color-fg);
13001
13669
  }
13002
13670
 
@@ -13060,7 +13728,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13060
13728
  gap: var(--space-3, 0.75rem);
13061
13729
  padding: var(--space-4);
13062
13730
  background: var(--color-bg);
13063
- border-top: 1px solid var(--color-border);
13731
+ border-top: var(--border-width) solid var(--color-border);
13064
13732
  border-radius: var(--radius-lg);
13065
13733
  box-shadow: var(--shadow-md);
13066
13734
  position: sticky;
@@ -13124,7 +13792,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13124
13792
  flex-direction: row;
13125
13793
  flex-wrap: wrap;
13126
13794
  border-inline-end: none;
13127
- border-bottom: 1px solid var(--color-border);
13795
+ border-bottom: var(--border-width) solid var(--color-border);
13128
13796
  padding-inline-end: 0;
13129
13797
  position: static;
13130
13798
  }
@@ -13143,7 +13811,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13143
13811
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13144
13812
  flex-direction: column;
13145
13813
  border-bottom: none;
13146
- border-inline-end: 1px solid var(--color-border);
13814
+ border-inline-end: var(--border-width) solid var(--color-border);
13147
13815
  padding-inline-end: var(--space-4);
13148
13816
  position: sticky;
13149
13817
  top: var(--space-4);
@@ -13161,7 +13829,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13161
13829
  justify-content: flex-start;
13162
13830
  text-align: start;
13163
13831
  border-bottom: none;
13164
- border-inline-start: 2px solid transparent;
13832
+ border-inline-start: var(--border-width-strong) solid transparent;
13165
13833
  margin-bottom: 0;
13166
13834
  margin-inline-end: -1px;
13167
13835
  padding: var(--space-2) var(--space-3);
@@ -13195,7 +13863,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13195
13863
 
13196
13864
  /* === patterns/site-footer.css === */
13197
13865
  /* @ui:component site-footer */
13198
- /* @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 */
13866
+ /* @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 */
13199
13867
 
13200
13868
  /* ── Root ──
13201
13869
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13205,11 +13873,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13205
13873
  gap: var(--space-8);
13206
13874
  padding-block: var(--space-10);
13207
13875
  padding-inline: var(--space-4);
13208
- font-family: var(--font-sans, system-ui, sans-serif);
13876
+ font-family: var(--font-body);
13209
13877
  font-size: var(--text-sm);
13210
13878
  color: var(--color-fg-muted);
13211
13879
  background: var(--color-bg-subtle);
13212
- border-block-start: 1px solid var(--color-border);
13880
+ border-block-start: var(--border-width) solid var(--color-border);
13213
13881
  }
13214
13882
 
13215
13883
  /* ── Brand ── */
@@ -13341,7 +14009,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13341
14009
 
13342
14010
  /* === patterns/stats-dashboard.css === */
13343
14011
  /* @ui:component stats-dashboard */
13344
- /* @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 */
14012
+ /* @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 */
13345
14013
 
13346
14014
  /* ── Root ──
13347
14015
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13354,7 +14022,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13354
14022
  gap: var(--space-3);
13355
14023
  padding-block: var(--space-8);
13356
14024
  padding-inline: var(--space-4);
13357
- font-family: var(--font-sans, system-ui, sans-serif);
14025
+ font-family: var(--font-body);
13358
14026
  color: var(--color-fg);
13359
14027
  background: var(--color-bg);
13360
14028
  }
@@ -13428,9 +14096,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13428
14096
 
13429
14097
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13430
14098
  margin: 0;
14099
+ font-family: var(--font-heading);
13431
14100
  font-size: var(--text-lg);
13432
14101
  font-weight: var(--weight-semibold);
13433
- line-height: var(--leading-tight);
14102
+ letter-spacing: var(--heading-tracking);
14103
+ text-transform: var(--heading-transform);
14104
+ font-variant-caps: var(--heading-caps);
14105
+ line-height: var(--heading-leading);
13434
14106
  }
13435
14107
 
13436
14108
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13521,7 +14193,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13521
14193
  gap: var(--space-6);
13522
14194
  max-inline-size: var(--measure-narrow);
13523
14195
  margin-inline: auto;
13524
- font-family: var(--font-sans);
14196
+ font-family: var(--font-body);
13525
14197
  }
13526
14198
 
13527
14199
  [data-ui="wizard"] [data-part="heading"] {