@faqir-ui/core 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +89 -52
  4. package/dist/faqir-core.min.js +3 -3
  5. package/dist/faqir-core.min.js.map +3 -3
  6. package/dist/faqir-core.mjs +61 -54
  7. package/dist/faqir.aurora.css +1209 -507
  8. package/dist/faqir.brutalist.css +1184 -489
  9. package/dist/faqir.candy.css +14152 -0
  10. package/dist/faqir.clinical.css +14152 -0
  11. package/dist/faqir.contrast.css +1198 -526
  12. package/dist/faqir.default.css +1261 -588
  13. package/dist/faqir.document-serif.css +1211 -491
  14. package/dist/faqir.document.css +1193 -490
  15. package/dist/faqir.editorial-document.css +14116 -0
  16. package/dist/faqir.editorial.css +14152 -0
  17. package/dist/faqir.fintech.css +14152 -0
  18. package/dist/faqir.glass.css +1214 -517
  19. package/dist/faqir.ink-document.css +14116 -0
  20. package/dist/faqir.ink.css +14127 -0
  21. package/dist/faqir.luxe.css +14211 -0
  22. package/dist/faqir.midnight.css +1229 -507
  23. package/dist/faqir.neo.css +14153 -0
  24. package/dist/faqir.neumorph.css +14151 -0
  25. package/dist/faqir.nordic.css +14151 -0
  26. package/dist/faqir.organic.css +14152 -0
  27. package/dist/faqir.paper.css +1200 -508
  28. package/dist/faqir.slate.css +1296 -564
  29. package/dist/faqir.soft.css +1180 -494
  30. package/dist/faqir.sunset.css +14153 -0
  31. package/dist/faqir.swiss-document.css +14116 -0
  32. package/dist/faqir.swiss.css +14153 -0
  33. package/dist/faqir.terminal.css +1187 -491
  34. package/dist/plugins/faqir-collapse.js +1 -1
  35. package/dist/plugins/faqir-intersect.js +2 -0
  36. package/dist/plugins/faqir-mask.js +27 -17
  37. package/dist/plugins/faqir-rules.js +63 -0
  38. package/dist/plugins/faqir-validate.js +471 -58
  39. package/dist/sri.json +36 -20
  40. package/faqir-core.d.ts +111 -5
  41. package/package.json +1 -1
@@ -131,6 +131,18 @@
131
131
  --font-mono: ui-monospace, 'Cascadia Code', 'JetBrains Mono', monospace;
132
132
  --font-serif: 'Georgia', 'Times New Roman', serif;
133
133
 
134
+ /* ── Font Roles (task 1.1A-01) ──
135
+ The three families above are the PALETTE; these three are the ROLES that
136
+ components actually read. A theme re-points a role once and every heading,
137
+ every paragraph and every control follows — "serif headings on a sans body"
138
+ is one declaration rather than sixty-four stylesheet edits. Components never
139
+ read --font-sans / --font-serif directly (gated by
140
+ tests/tokens/role-tokens.test.ts); --font-mono stays readable by name,
141
+ because "this is code" is a semantic choice, not a stylistic one. */
142
+ --font-heading: var(--font-sans); /* h1–h6, hero headline, card/dialog titles, stat values, doc headings */
143
+ --font-body: var(--font-sans); /* prose, text, document body, descriptions */
144
+ --font-ui: var(--font-sans); /* controls: button, input, select, badge, chip, tabs, menus */
145
+
134
146
  /* ── Font Sizes ── */
135
147
  --text-xs: 0.75rem; /* 12px */
136
148
  --text-sm: 0.875rem; /* 14px */
@@ -153,10 +165,29 @@
153
165
  --weight-medium: 500;
154
166
  --weight-semibold: 600;
155
167
  --weight-bold: 700;
168
+
169
+ /* ── Heading Voice (task 1.1A-01) ──
170
+ What makes a heading sound like the theme rather than like the body text one
171
+ size up: how heavy it is, how tightly the letters sit, whether it shouts, and
172
+ how close its own lines run. The defaults reproduce today's primary heading
173
+ exactly, so a project that sets none of them renders unchanged. A heading
174
+ that deliberately steps DOWN from the primary voice (prose h2–h4, a semibold
175
+ step below h1) keeps its own weight and leading and takes family, tracking
176
+ and case from the voice — the step is the design, not a value to re-derive. */
177
+ --heading-weight: var(--weight-bold);
178
+ --heading-tracking: 0em; /* letter-spacing — carries a unit so it
179
+ composes inside calc() where a heading
180
+ already has its own optical tightening */
181
+ --heading-transform: none; /* text-transform */
182
+ --heading-caps: normal; /* font-variant-caps — small caps are a
183
+ variant, not a transform (1.1A-25), so
184
+ they get a knob of their own that sits
185
+ beside --heading-transform */
186
+ --heading-leading: var(--leading-tight);
156
187
  }
157
188
 
158
189
  /* === tokens/effects.css === */
159
- /* @ui:tokens effects — radii, shadows, z-index */
190
+ /* @ui:tokens effects — radii, shape, shadows, focus, z-index */
160
191
 
161
192
  :root {
162
193
  /* ── Radii ── */
@@ -168,12 +199,49 @@
168
199
  --radius-2xl: 1rem; /* 16px */
169
200
  --radius-full: 9999px;
170
201
 
171
- /* ── Shadows ── */
172
- --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.04);
173
- --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
174
- --shadow-md: 0 4px 6px oklch(0 0 0 / 0.05), 0 2px 4px oklch(0 0 0 / 0.04);
175
- --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.06), 0 4px 6px oklch(0 0 0 / 0.04);
176
- --shadow-xl: 0 20px 25px oklch(0 0 0 / 0.08), 0 8px 10px oklch(0 0 0 / 0.04);
202
+ /* ── Shape ── */
203
+ /* The weight of an edge. A component names the ROLE (--border-width, or
204
+ --border-width-strong where the design leans on a thicker rule), never a
205
+ step, so a theme re-points every edge it ships with one declaration. */
206
+ --border-width-sm: 1px;
207
+ --border-width-md: 2px;
208
+ --border-width-lg: 3px;
209
+ --border-width: var(--border-width-sm); /* the default component border */
210
+ --border-width-strong: var(--border-width-md); /* emphasis: keycap, thick rule, active tab */
211
+ /* Progressive: CSS Borders 4. A browser without the property ignores it; a
212
+ value it does not know resolves to `round`, which is today's rendering. */
213
+ --corner-shape: round; /* bevel | scoop | notch where supported */
214
+
215
+ /* ── Depth ── */
216
+ /* The colour every shadow is cast in, as BARE OKLCH channels (L C H, no
217
+ `oklch()` around them) so each step can still set its own alpha:
218
+ `oklch(var(--shadow-color) / 0.06)`. A theme tints its depth warm, or
219
+ removes it entirely, with one declaration instead of rewriting five
220
+ multi-layer values. `0 0 0` is black — today's rendering, exactly. */
221
+ --shadow-color: 0 0 0;
222
+
223
+ --shadow-xs: 0 1px 2px oklch(var(--shadow-color) / 0.04);
224
+ --shadow-sm: 0 1px 3px oklch(var(--shadow-color) / 0.06), 0 1px 2px oklch(var(--shadow-color) / 0.04);
225
+ --shadow-md: 0 4px 6px oklch(var(--shadow-color) / 0.05), 0 2px 4px oklch(var(--shadow-color) / 0.04);
226
+ --shadow-lg: 0 10px 15px oklch(var(--shadow-color) / 0.06), 0 4px 6px oklch(var(--shadow-color) / 0.04);
227
+ --shadow-xl: 0 20px 25px oklch(var(--shadow-color) / 0.08), 0 8px 10px oklch(var(--shadow-color) / 0.04);
228
+
229
+ /* What an elevated surface does to whatever shows through it. Every surface
230
+ that can float — card, surface[data-variant="overlay"] and the seven
231
+ floating recipes — declares `backdrop-filter: var(--surface-backdrop)`
232
+ inside the same `@supports` guard, so a frosted theme is a token rather
233
+ than a stylesheet that reaches into seven components by selector.
234
+ `none` is the initial value of the property: no-op until a theme speaks. */
235
+ --surface-backdrop: none;
236
+
237
+ /* ── Focus ── */
238
+ /* base/reset.css owns the default ring and reads only these. Every control
239
+ that draws its own ring reads them too, so a theme changes focus once. */
240
+ --focus-ring-width: 2px;
241
+ --focus-ring-offset: 2px;
242
+ --focus-ring-style: solid;
243
+ --focus-ring-color: var(--color-ring);
244
+ --focus-shadow: none; /* a glow theme puts a shadow behind the ring */
177
245
 
178
246
  /* ── Z-Index ── */
179
247
  --z-base: 0;
@@ -186,8 +254,74 @@
186
254
  --z-max: 9999;
187
255
  }
188
256
 
257
+ /* ── Scheme islands ── */
258
+ /* The ring colour, restated where a scheme can change below the root: declared
259
+ on `:root` alone it resolves `--color-ring` once, from the page, and a nested
260
+ `data-theme="dark"` region would draw the light ring. See the same block in
261
+ tokens/aliases.css. `--focus-shadow` is deliberately NOT restated — it is a
262
+ depth value a theme owns, and restating it would replace the theme's glow
263
+ with `none` inside every island. */
264
+ [data-theme],
265
+ [data-skin] {
266
+ --focus-ring-color: var(--color-ring);
267
+ }
268
+
269
+ /* === tokens/textures.css === */
270
+ /* @ui:tokens textures — named surface materials (SVG data URIs) */
271
+
272
+ /* ══════════════════════════════════════════════════════════════════════════
273
+ The material palette.
274
+ ══════════════════════════════════════════════════════════════════════════
275
+ Six named textures, each a self-contained `url("data:image/svg+xml,…")` that
276
+ tiles. Nothing here is consumed directly: components read the two ROLE tokens
277
+ in `aliases.css` — `--texture-page` (body, document) and `--texture-surface`
278
+ (surface, card, hero) — both `none` by default, so the registry renders
279
+ exactly as it did before this file existed. A theme opts in with one
280
+ declaration:
281
+
282
+ --texture-page: var(--texture-grain);
283
+
284
+ This file is deliberately OUTSIDE the themeable surface (see
285
+ `NON_SURFACE_TOKEN_FILES` in `src/theme-manifest.ts`): a theme re-points the
286
+ two role tokens, it does not inherit six data URIs into its manifest.
287
+
288
+ On `currentColor`: the tint is written as `currentColor` so the markup states
289
+ its intent and a theme can re-point the whole token, but a data-URI SVG used
290
+ as `background-image` is its own document — `currentColor` there resolves to
291
+ that document's initial colour (black), not to the host element's `color`.
292
+ That IS the intended neutral for grain and paper, which are meant to darken a
293
+ surface slightly; the alpha in each texture, not the hue, is what carries the
294
+ effect. A theme wanting a different tint ships its own URI.
295
+
296
+ Every texture keeps its alpha low enough to survive on both schemes, and each
297
+ `<svg>` carries explicit `width`/`height` so the tile size is the token's,
298
+ not the browser's default 300×150.
299
+ ══════════════════════════════════════════════════════════════════════════ */
300
+
301
+ :root {
302
+ /* Film grain — fractal noise masking a flat currentColor fill. The mask is
303
+ what makes this a tint rather than the turbulence's own rainbow. */
304
+ --texture-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/mask%3E%3Crect width='160' height='160' fill='currentColor' mask='url(%23m)' opacity='0.14'/%3E%3C/svg%3E");
305
+
306
+ /* Paper fibre — lower frequency, more octaves, softer than grain. */
307
+ --texture-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.04 0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='200' height='200' filter='url(%23p)'/%3E%3C/mask%3E%3Crect width='200' height='200' fill='currentColor' mask='url(%23m)' opacity='0.1'/%3E%3C/svg%3E");
308
+
309
+ /* Dot field — one dot per 16px cell. */
310
+ --texture-dots: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='2' cy='2' r='1' fill='currentColor' opacity='0.18'/%3E%3C/svg%3E");
311
+
312
+ /* Graph-paper grid — hairlines on a 24px cell. */
313
+ --texture-grid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M24 0H0v24' fill='none' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
314
+
315
+ /* Diagonal hatching — 45°, 8px pitch. */
316
+ --texture-stripes: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M-2 2 2-2M0 8 8 0M6 10l4-4' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
317
+
318
+ /* Soft gradient mesh — three offset radial blooms, the only non-tiling
319
+ texture here (it is sized to cover, not to repeat). */
320
+ --texture-mesh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3CradialGradient id='a' cx='20%25' cy='20%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.18'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='b' cx='80%25' cy='30%25' r='55%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.14'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='c' cx='50%25' cy='90%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.12'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3Crect width='640' height='640' fill='url(%23a)'/%3E%3Crect width='640' height='640' fill='url(%23b)'/%3E%3Crect width='640' height='640' fill='url(%23c)'/%3E%3C/svg%3E");
321
+ }
322
+
189
323
  /* === tokens/motion.css === */
190
- /* @ui:tokens motion — easings and durations */
324
+ /* @ui:tokens motion — easings, durations and motion personality */
191
325
 
192
326
  :root {
193
327
  /* ── Easings ── */
@@ -216,6 +350,35 @@
216
350
  /* Preset geometry */
217
351
  --motion-slide-distance: 0.5rem; /* slide-up travel */
218
352
  --motion-scale-from: 0.95; /* scale start/end factor */
353
+
354
+ /* ── Personality (1.1A-05 · §5.2 `motion`) ── */
355
+ /* The easing PALETTE gained a spring. Like --ease-bounce it has no consumer
356
+ of its own: a theme that wants everything to overshoot re-points
357
+ --ease-default at it, exactly as a serif theme re-points --font-body.
358
+ The declaration here is the cubic-bezier APPROXIMATION, because a custom
359
+ property stores whatever tokens it is given — a browser without `linear()`
360
+ would accept the spring happily and then drop every `transition` that used
361
+ it, landing on the initial easing rather than on a fallback. The @supports
362
+ block below is what makes the upgrade conditional. The approximation is
363
+ the bounce curve, deliberately: an overshoot-and-settle cubic-bezier is the
364
+ closest a browser without `linear()` can come to a spring. */
365
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
366
+
367
+ /* How far an interactive surface rises under the pointer. A `translate`
368
+ VALUE, not a length: `none` is the initial value of that property, so the
369
+ default registry computes exactly what it computed before this token
370
+ existed, and a theme states the lift as `0 -1px`. `translate` rather than
371
+ `transform` so a component's own transform is never clobbered. */
372
+ --motion-hover-lift: none;
373
+ }
374
+
375
+ /* The real spring, where `linear()` is understood (Chrome 113+, Safari 17.2+,
376
+ Firefox 112+). Declared second so it wins; guarded so it is never declared at
377
+ all where it would be meaningless. */
378
+ @supports (animation-timing-function: linear(0, 1)) {
379
+ :root {
380
+ --ease-spring: linear(0, 0.3 6%, 0.7 13%, 0.95 20%, 1.03 27%, 1 40%, 1);
381
+ }
219
382
  }
220
383
 
221
384
  /* === tokens/semantic.css === */
@@ -307,27 +470,123 @@
307
470
  --section-gap-lg: var(--space-32); /* 8rem — spacious, one idea per screen */
308
471
  --content-gutter: var(--space-6); /* 1.5rem — page padding-inline */
309
472
 
473
+ /* ── Material ── */
474
+ /* The two textures a theme actually points at. Components never name a
475
+ texture from `tokens/textures.css` directly — they read one of these, so a
476
+ theme re-points two tokens rather than every surface in the registry.
477
+ `--texture-page` dresses the page itself (body, document);
478
+ `--texture-surface` dresses the things that sit ON it (surface, card,
479
+ hero). Both `none`: the initial value of `background-image`, so the
480
+ default registry renders exactly as it did before they existed. */
481
+ --texture-page: none;
482
+ --texture-surface: none;
483
+
484
+ /* ── Decoration (1.1A-05 · §5.2 `decoration`) ── */
485
+ /* The marks a theme draws that are not edges, fills or type: how a link is
486
+ underlined, how a divider is dashed, what selected text looks like, what
487
+ colour a list bullet is. Every default is the value the registry already
488
+ rendered, so this section is a set of handles, not a restyle.
489
+ `--marker-color` is `currentColor` — the initial value of `::marker`'s
490
+ colour — rather than the accent, so a list only changes when a theme says
491
+ it should. */
492
+ --link-decoration: underline;
493
+ --link-underline-offset: 0.2em;
494
+ --link-thickness: 1px;
495
+ --divider-style: solid;
496
+ /* The divider's own width, following the edge by default (1.1A-26). A theme
497
+ that asks for a `double` divider raises it to at least 3px: a double rule
498
+ only splits into two lines from 3px, and the family's 1px hairline would
499
+ paint it as one. */
500
+ --divider-width: var(--border-width);
501
+ /* The zebra, so a theme dials the stripe without restating the four selectors
502
+ the table's striped variant needs (stamped and nth-child, each with a hover
503
+ twin). Deliberately NOT `--table-stripe`: `--table-level`,
504
+ `--table-thead-h` and `--table-pin-offset` are stamped and MEASURED per
505
+ element by the table controller, so claiming the `--table-*` namespace for
506
+ a theme token would put runtime state on the themeable surface. */
507
+ --stripe-bg: var(--color-bg-subtle);
508
+ --selection-bg: var(--color-primary-subtle);
509
+ --selection-fg: var(--color-fg);
510
+ --marker-color: currentColor;
511
+ /* How far a disabled control is dimmed. Seventeen rules across the primitives
512
+ and recipes each spelled `opacity: 0.5`, which left a theme with an opinion
513
+ about disabled legibility no way to state it except by out-specifying every
514
+ one of them — which is exactly what `themes/contrast.css` did, with a
515
+ blanket `:root [data-ui]:disabled` rule, until 1.1A-15 turned it into this
516
+ one declaration. `0.5` is the value those seventeen rules already held. */
517
+ --disabled-opacity: 0.5;
518
+
310
519
  /* ── Button ── */
311
520
  --button-radius: var(--radius-md);
312
521
  --button-height-sm: var(--control-height-sm);
313
522
  --button-height-md: var(--control-height-md);
314
523
  --button-height-lg: var(--control-height-lg);
315
- --button-font: var(--font-sans);
524
+ --button-font: var(--font-ui);
316
525
  --button-weight: var(--weight-medium);
526
+ --button-text-transform: none;
317
527
 
318
528
  /* ── Card ── */
319
529
  --card-radius: var(--radius-lg);
320
530
  --card-shadow: var(--shadow-sm);
321
531
  --card-border: var(--color-surface-1-border);
532
+ --card-border-width: var(--border-width);
322
533
  --card-bg: var(--color-surface-1);
323
534
  --card-padding: var(--space-6);
324
535
 
325
536
  /* ── Input ── */
326
- --input-radius: var(--radius-md);
327
- --input-height: var(--control-height-md);
328
- --input-border: var(--color-border);
329
- --input-bg: var(--color-bg);
330
- --input-font: var(--font-sans);
537
+ /* The text-control silhouette. `--input-border-width` (1.1A-02) is the edge;
538
+ `--input-fill` is what the control paints, and `input`, `textarea` and
539
+ `select` all read it, so one declaration fills every text control.
540
+ `--input-fill` defaults to `--input-bg`, so a project that sets `--input-bg`
541
+ on `:root` — the 1.0 way to fill every input — still gets it. Set BELOW the
542
+ root, `--input-bg` no longer reaches the control: `--input-fill` has already
543
+ resolved it on `:root`, which is where a theme flips the fill, and a
544
+ per-element `--input-bg` winning over that would need the component to tell
545
+ "set here" from "inherited", which CSS cannot. To fill one input, or every
546
+ input in a region, set `--input-fill` there instead. `--input-bg-filled` is
547
+ the value a "filled" theme points `--input-fill` at — named here so the
548
+ silhouette is a token a theme flips rather than a colour it has to pick. */
549
+ --input-radius: var(--radius-md);
550
+ --input-height: var(--control-height-md);
551
+ --input-border: var(--color-border);
552
+ --input-border-width: var(--border-width);
553
+ --input-bg: var(--color-bg);
554
+ --input-bg-filled: var(--color-bg-subtle);
555
+ --input-fill: var(--input-bg);
556
+ --input-font: var(--font-ui);
557
+
558
+ /* ── Checkbox / Switch ── */
559
+ /* The two control shapes that do not follow `--radius-md`: a checkbox is a
560
+ small square with a small radius, a switch is a pill. Both were literal
561
+ `var(--radius-*)` reads in the components; named here, a theme squares its
562
+ switches without touching the radius ladder every other surface uses.
563
+
564
+ The geometry beside them is not decoration — it is the rest of the
565
+ namespace. Naming ONE token `--checkbox-radius` makes `--checkbox-*` a
566
+ token family, and the registry audit then (rightly) reads every other
567
+ `--checkbox-…`/`--switch-…` the components carried as a token wearing a
568
+ fallback as a disguise. They were always the default geometry; these are
569
+ the values the fallbacks already held, said once. */
570
+ --checkbox-size: 18px;
571
+ --checkbox-radius: var(--radius-sm);
572
+ --switch-width: 44px;
573
+ --switch-height: 24px;
574
+ --switch-thumb: 18px;
575
+ --switch-travel: 20px;
576
+ --switch-radius: var(--radius-full);
577
+ --switch-bg: var(--color-bg-muted);
578
+ --switch-thumb-shadow: var(--shadow-xs);
579
+
580
+ /* ── Floating panels ── */
581
+ /* What a panel that floats above the page is filled with: the dialog and
582
+ sheet panels, the drawer, the popover content (and its arrow), the dropdown
583
+ menu and the toast. They all painted `var(--color-bg)` directly, which left
584
+ a theme no way to make a floating surface differ from the page — the frost
585
+ half of that pairing is `--surface-backdrop` (1.1A-04), and a blur behind an
586
+ opaque fill renders nothing, so the fill has to be a token too. `card` has
587
+ had `--card-bg` since 1.0; this is the same handle for the things that have
588
+ no surface of their own. [1.1A-14] */
589
+ --panel-bg: var(--color-bg);
331
590
 
332
591
  /* ── Dialog ── */
333
592
  --dialog-radius: var(--radius-xl);
@@ -336,7 +595,7 @@
336
595
 
337
596
  /* ── Badge ── */
338
597
  --badge-radius: var(--radius-full);
339
- --badge-font: var(--font-sans);
598
+ --badge-font: var(--font-ui);
340
599
 
341
600
  /* ── Avatar ── */
342
601
  --avatar-radius: var(--radius-full);
@@ -345,6 +604,39 @@
345
604
  --avatar-size-lg: 56px;
346
605
  }
347
606
 
607
+ /* ── Scheme islands ── */
608
+ /* The colour aliases above, restated wherever a scheme can change below the
609
+ root. A custom property resolves its var() on the element that DECLARES it,
610
+ so `--panel-bg: var(--color-bg)` on `:root` is computed once, from the page's
611
+ colours, and a nested `<div data-theme="dark">` inherits that light value
612
+ even though its own `--color-bg` is dark — a white dialog on a dark island.
613
+ Components that read `var(--color-bg)` directly never had the problem; the
614
+ aliases 1.1 routed them through did. Restating the declaration on
615
+ `[data-theme]` and `[data-skin]` makes it resolve again there.
616
+
617
+ Only colours are restated. Geometry does not change with the scheme, and
618
+ shadows are the depth axis every theme owns on `:root`: restating either here
619
+ would replace a theme's own value with the default inside every island. A
620
+ theme that overrides one of THESE on `:root` and wants it honoured in an
621
+ island says so on the same selectors.
622
+
623
+ The values must match the `:root` declarations above exactly;
624
+ `tests/tokens/scheme-islands.test.ts` fails if they drift. */
625
+ [data-theme],
626
+ [data-skin] {
627
+ --stripe-bg: var(--color-bg-subtle);
628
+ --selection-bg: var(--color-primary-subtle);
629
+ --selection-fg: var(--color-fg);
630
+ --card-border: var(--color-surface-1-border);
631
+ --card-bg: var(--color-surface-1);
632
+ --input-border: var(--color-border);
633
+ --input-bg: var(--color-bg);
634
+ --input-bg-filled: var(--color-bg-subtle);
635
+ --input-fill: var(--input-bg);
636
+ --switch-bg: var(--color-bg-muted);
637
+ --panel-bg: var(--color-bg);
638
+ }
639
+
348
640
  /* === tokens/document.css === */
349
641
  /* @ui:tokens document — structural tokens for document/print rendering */
350
642
  /* These tokens control page geometry, document typography, table density,
@@ -376,10 +668,10 @@
376
668
  Separate from the base typography tokens because documents have
377
669
  different optimal sizes than screen UIs. 14px body + 12px legal
378
670
  is standard for A4 business documents. */
379
- --doc-font: var(--font-sans);
671
+ --doc-font: var(--font-body);
380
672
  --doc-font-size: var(--text-sm); /* 14px — optimal for A4 */
381
673
  --doc-line-height: var(--leading-normal); /* 1.5 */
382
- --doc-heading-font: var(--font-sans);
674
+ --doc-heading-font: var(--font-heading);
383
675
  --doc-heading-weight: var(--weight-bold);
384
676
  --doc-heading-size: var(--text-xl); /* 20px for doc titles */
385
677
  --doc-subheading-size: var(--text-lg); /* 18px for section titles */
@@ -430,6 +722,16 @@
430
722
  --doc-print-border-color: oklch(0.60 0 0); /* medium gray borders in print */
431
723
  }
432
724
 
725
+ /* ── Scheme islands ── */
726
+ /* `--doc-legal-color` is the one document colour screen components read (the
727
+ key-value label and the image caption), so it is restated where a scheme can
728
+ change below the root — see the same block in tokens/aliases.css. The rest
729
+ of this file is print ink, which does not follow the scheme. */
730
+ [data-theme],
731
+ [data-skin] {
732
+ --doc-legal-color: var(--color-fg-muted);
733
+ }
734
+
433
735
  /* === tokens/doc-aliases.css === */
434
736
  /* @ui:tokens doc-aliases — component-level document tokens */
435
737
  /* Maps document-layer tokens to specific primitive/recipe attribute selectors.
@@ -476,7 +778,10 @@
476
778
  --field-error-size: var(--doc-legal-size);
477
779
  --field-error-color: var(--color-destructive);
478
780
  --field-validating-color: var(--color-fg-muted); /* async validation in flight */
479
- --field-disabled-opacity: 0.55; /* honest disabled affordance */
781
+ /* The role `--disabled-opacity` sets for every control, nudged 10% lighter:
782
+ 0.55 at the 0.5 default, which is the value this alias always held, and it
783
+ follows a theme that states the role (1.1A-27). */
784
+ --field-disabled-opacity: calc(var(--disabled-opacity) * 1.1);
480
785
  --field-required-color: var(--color-destructive);
481
786
  --field-required-marker: ' *'; /* appended to required labels */
482
787
 
@@ -496,15 +801,47 @@
496
801
  --stat-change-negative: var(--color-destructive);
497
802
  }
498
803
 
804
+ /* ── Scheme islands ── */
805
+ /* The colour aliases above, restated where a scheme can change below the root —
806
+ a custom property resolves its var() on the element that declares it, so a
807
+ `:root`-only alias would carry the page's light value into a nested
808
+ `data-theme="dark"` region. See the same block in tokens/aliases.css; the
809
+ values must match the `:root` declarations above exactly. */
810
+ [data-theme],
811
+ [data-skin] {
812
+ --kv-label-color: var(--doc-legal-color);
813
+ --kv-value-color: var(--color-fg);
814
+ --callout-bg: var(--color-bg-subtle);
815
+ --callout-fg: var(--color-fg);
816
+ --image-border: var(--color-border);
817
+ --image-caption-color: var(--doc-legal-color);
818
+ --field-label-color: var(--color-fg);
819
+ --field-description-color: var(--color-fg-muted);
820
+ --field-error-color: var(--color-destructive);
821
+ --field-validating-color: var(--color-fg-muted);
822
+ --field-required-color: var(--color-destructive);
823
+ --page-break-screen-color: var(--color-border);
824
+ --page-break-screen-label-color: var(--color-fg-muted);
825
+ --stat-label-color: var(--color-fg-muted);
826
+ --stat-change-positive: var(--color-success);
827
+ --stat-change-negative: var(--color-destructive);
828
+ }
829
+
499
830
  /* === tokens/density.css === */
500
- /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6)
831
+ /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6;
832
+ `spacious` added 1.1A-09, SPEC-1.0.md §4)
501
833
 
502
834
  Put `data-density="compact"` on ANY container and its whole subtree renders
503
835
  tighter: spacing steps shrink by --density-scale and interactive controls drop
504
836
  to a shorter height ramp. `data-density="comfortable"` restores the base scale,
505
- so density can be reset on an inner subtree.
837
+ so density can be reset on an inner subtree. `data-density="spacious"` is the
838
+ third point on the ladder, above comfortable: spacing grows and the control
839
+ ramp grows with it, gentler than the spacing multiplier for the same reason
840
+ compact's ramp shrinks gentler — a usable hit target has a ceiling as well as
841
+ a floor.
506
842
 
507
843
  <section data-density="compact"> … dense form / table / toolbar … </section>
844
+ <section data-density="spacious"> … roomy landing hero, kiosk UI … </section>
508
845
 
509
846
  This is 100% CSS. `data-density` is NOT a sixth protocol attribute: no
510
847
  component contract, manifest, controller or audit rule knows about it — CSS
@@ -641,6 +978,57 @@
641
978
  --content-gutter: var(--space-6);
642
979
  }
643
980
 
981
+ /* The third density: roomier than the base scale, for a landing hero or a kiosk
982
+ UI meant to be read at arm's length. Control heights grow slower than the
983
+ spacing multiplier — the same asymmetry compact's ramp has, mirrored. */
984
+ [data-density="spacious"] {
985
+ --density-scale: 1.25;
986
+
987
+ /* ── Spacing scale (× --density-scale) ── */
988
+ --space-0h: calc(0.125rem * var(--density-scale));
989
+ --space-1: calc(0.25rem * var(--density-scale));
990
+ --space-1h: calc(0.375rem * var(--density-scale));
991
+ --space-2: calc(0.5rem * var(--density-scale));
992
+ --space-2h: calc(0.625rem * var(--density-scale));
993
+ --space-3: calc(0.75rem * var(--density-scale));
994
+ --space-3h: calc(0.875rem * var(--density-scale));
995
+ --space-4: calc(1rem * var(--density-scale));
996
+ --space-5: calc(1.25rem * var(--density-scale));
997
+ --space-6: calc(1.5rem * var(--density-scale));
998
+ --space-7: calc(1.75rem * var(--density-scale));
999
+ --space-8: calc(2rem * var(--density-scale));
1000
+ --space-10: calc(2.5rem * var(--density-scale));
1001
+ --space-12: calc(3rem * var(--density-scale));
1002
+ --space-16: calc(4rem * var(--density-scale));
1003
+ --space-20: calc(5rem * var(--density-scale));
1004
+ --space-24: calc(6rem * var(--density-scale));
1005
+ --space-32: calc(8rem * var(--density-scale));
1006
+ --space-40: calc(10rem * var(--density-scale));
1007
+ --space-48: calc(12rem * var(--density-scale));
1008
+ --space-64: calc(16rem * var(--density-scale));
1009
+
1010
+ /* ── Control height ramp ── */
1011
+ --control-height-sm: 36px;
1012
+ --control-height-md: 44px;
1013
+ --control-height-lg: 52px;
1014
+
1015
+ /* ── Aliases re-substituted in this scope (values identical to the base) ── */
1016
+ --button-height-sm: var(--control-height-sm);
1017
+ --button-height-md: var(--control-height-md);
1018
+ --button-height-lg: var(--control-height-lg);
1019
+ --input-height: var(--control-height-md);
1020
+ --card-padding: var(--space-6);
1021
+ --kv-pair-gap: var(--space-3);
1022
+ --kv-grid-gap: var(--space-4);
1023
+ --callout-padding-y: var(--space-3);
1024
+ --callout-padding-x: var(--space-4);
1025
+ --field-gap: var(--space-1h);
1026
+ --section-gap-sm: var(--space-12);
1027
+ --section-gap-md: var(--space-20);
1028
+ --section-gap-lg: var(--space-32);
1029
+ --content-gutter: var(--space-6);
1030
+ }
1031
+
644
1032
  /* === themes/document.css === */
645
1033
  /* @ui:theme document — clean, professional, PDF-optimized business document theme */
646
1034
  /* @ui:schemes light — single-scheme: documents are always light/white for print. */
@@ -711,7 +1099,6 @@
711
1099
  /* ── Component overrides ── */
712
1100
  --card-radius: 0;
713
1101
  --card-shadow: none;
714
- --card-border: var(--color-border);
715
1102
  --button-radius: 0;
716
1103
  --input-radius: 0;
717
1104
  --badge-radius: var(--space-1); /* slight rounding for badges only */
@@ -737,6 +1124,42 @@
737
1124
  /* ── Typography: optimize for print ── */
738
1125
  --font-sans: 'Arial', 'Helvetica Neue', system-ui, sans-serif;
739
1126
  --font-mono: 'Courier New', ui-monospace, monospace;
1127
+
1128
+ /* ══════════════════════════════════════════════════════════════════════
1129
+ The identity, in tokens. Flat, sharp and untextured since 0.6; the two
1130
+ things it could not state before 1.1 are below. [1.1A-15]
1131
+ ══════════════════════════════════════════════════════════════════════ */
1132
+
1133
+ /* ── Motion: none ──
1134
+ Paper does not animate. Every duration is zero, which is what makes the
1135
+ `motion` axis derive `none` — and it is safe rather than merely quiet:
1136
+ `registry/core/motion.js` reads the computed duration and resolves
1137
+ immediately when there is none, and the engine's `runMotion` carries a
1138
+ timeout fallback, so a controller that waits for a transition to finish
1139
+ still completes. A PDF renderer never runs the transition either, so this
1140
+ makes the screen render match the printed one instead of differing from
1141
+ it for a fifth of a second. */
1142
+ --duration-instant: 0ms;
1143
+ --duration-fast: 0ms;
1144
+ --duration-normal: 0ms;
1145
+ --duration-slow: 0ms;
1146
+ --duration-slower: 0ms;
1147
+
1148
+ /* ── Decoration: the underline sits on the baseline ──
1149
+ `plain`, not the base layer's `offset`: a 0.2em gap is a screen
1150
+ affordance, and in print a rule that floats below its text reads as a
1151
+ separate mark rather than as an underline. Hairline thickness is kept, so
1152
+ a link is still identifiable by its rule and not only by its colour. */
1153
+ --link-underline-offset: 0.02em;
1154
+ --link-thickness: var(--border-width-sm);
1155
+ }
1156
+
1157
+ :root,
1158
+ [data-theme] {
1159
+ /* The token layer re-resolves these aliases on every scheme island
1160
+ (tokens/aliases.css), so a `:root`-only override would fall back to the
1161
+ default inside a nested `data-theme` region. */
1162
+ --card-border: var(--color-border);
740
1163
  }
741
1164
 
742
1165
  /* Document theme has NO dark mode — documents are always light/white for print */
@@ -769,11 +1192,38 @@
769
1192
  padding: 0;
770
1193
  }
771
1194
 
1195
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1196
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1197
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1198
+ these three rules; declaring them here (rather than in each theme) is what
1199
+ makes the two authoring forms interchangeable. Nothing else in the registry
1200
+ declares `color-scheme`, so this is purely additive.
1201
+
1202
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1203
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1204
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1205
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1206
+ dark island inside a light page has always worked here. */
1207
+ :root {
1208
+ color-scheme: light;
1209
+ }
1210
+
1211
+ [data-theme="dark"] {
1212
+ color-scheme: dark;
1213
+ }
1214
+
1215
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1216
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1217
+ does for a theme authored in the three-block form. */
1218
+ [data-theme="auto"] {
1219
+ color-scheme: light dark;
1220
+ }
1221
+
772
1222
  html {
773
1223
  -webkit-text-size-adjust: 100%;
774
1224
  -moz-tab-size: 4;
775
1225
  tab-size: 4;
776
- font-family: var(--font-sans);
1226
+ font-family: var(--font-body);
777
1227
  font-size: var(--text-base);
778
1228
  line-height: var(--leading-normal);
779
1229
  color: var(--color-fg);
@@ -784,6 +1234,11 @@ html {
784
1234
 
785
1235
  body {
786
1236
  min-height: 100dvh;
1237
+ /* The page's material. `none` by default (the initial value), so this is a
1238
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1239
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1240
+ covers the viewport, so the two compose instead of overwriting. */
1241
+ background-image: var(--texture-page);
787
1242
  }
788
1243
 
789
1244
  img,
@@ -853,10 +1308,32 @@ table {
853
1308
  }
854
1309
  }
855
1310
 
856
- /* Focus visible — default ring */
1311
+ /* Text selection — the decoration axis reaching the one surface no component
1312
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1313
+ of a themed page that never matched the theme. Both values are tokens
1314
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1315
+ ::selection {
1316
+ background-color: var(--selection-bg);
1317
+ color: var(--selection-fg);
1318
+ }
1319
+
1320
+ /* Focus visible — the default ring, and the only place it is spelled out.
1321
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1322
+ focus once and every element that has not drawn its own ring follows. */
857
1323
  :focus-visible {
858
- outline: 2px solid var(--color-ring);
859
- outline-offset: 2px;
1324
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1325
+ outline-offset: var(--focus-ring-offset);
1326
+ }
1327
+
1328
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1329
+ is not a property focus owns: an element's resting shadow — a card's depth,
1330
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1331
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1332
+ sets a shadow outranks this one, so it lands only on an element nothing else
1333
+ shadows, and it never takes a shadow away. The controls that draw their own
1334
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1335
+ :where(:focus-visible) {
1336
+ box-shadow: var(--focus-shadow);
860
1337
  }
861
1338
 
862
1339
  /* Hidden but accessible */
@@ -885,7 +1362,7 @@ table {
885
1362
  /* @ui:base prose — typography defaults for long-form content */
886
1363
 
887
1364
  [data-ui="prose"] {
888
- font-family: var(--font-sans);
1365
+ font-family: var(--font-body);
889
1366
  font-size: var(--text-base);
890
1367
  line-height: var(--leading-relaxed);
891
1368
  color: var(--color-fg);
@@ -893,29 +1370,45 @@ table {
893
1370
  }
894
1371
 
895
1372
  [data-ui="prose"] h1 {
1373
+ font-family: var(--font-heading);
896
1374
  font-size: var(--text-4xl);
897
- font-weight: var(--weight-bold);
898
- line-height: var(--leading-tight);
1375
+ font-weight: var(--heading-weight);
1376
+ letter-spacing: var(--heading-tracking);
1377
+ text-transform: var(--heading-transform);
1378
+ font-variant-caps: var(--heading-caps);
1379
+ line-height: var(--heading-leading);
899
1380
  margin-block: var(--space-8) var(--space-4);
900
1381
  }
901
1382
 
902
1383
  [data-ui="prose"] h2 {
1384
+ font-family: var(--font-heading);
903
1385
  font-size: var(--text-3xl);
904
1386
  font-weight: var(--weight-semibold);
905
- line-height: var(--leading-tight);
1387
+ letter-spacing: var(--heading-tracking);
1388
+ text-transform: var(--heading-transform);
1389
+ font-variant-caps: var(--heading-caps);
1390
+ line-height: var(--heading-leading);
906
1391
  margin-block: var(--space-8) var(--space-3);
907
1392
  }
908
1393
 
909
1394
  [data-ui="prose"] h3 {
1395
+ font-family: var(--font-heading);
910
1396
  font-size: var(--text-2xl);
911
1397
  font-weight: var(--weight-semibold);
1398
+ letter-spacing: var(--heading-tracking);
1399
+ text-transform: var(--heading-transform);
1400
+ font-variant-caps: var(--heading-caps);
912
1401
  line-height: var(--leading-snug);
913
1402
  margin-block: var(--space-6) var(--space-3);
914
1403
  }
915
1404
 
916
1405
  [data-ui="prose"] h4 {
1406
+ font-family: var(--font-heading);
917
1407
  font-size: var(--text-xl);
918
1408
  font-weight: var(--weight-semibold);
1409
+ letter-spacing: var(--heading-tracking);
1410
+ text-transform: var(--heading-transform);
1411
+ font-variant-caps: var(--heading-caps);
919
1412
  line-height: var(--leading-snug);
920
1413
  margin-block: var(--space-6) var(--space-2);
921
1414
  }
@@ -926,8 +1419,8 @@ table {
926
1419
 
927
1420
  [data-ui="prose"] a {
928
1421
  color: var(--color-primary);
929
- text-decoration: underline;
930
- text-underline-offset: 2px;
1422
+ text-decoration-line: var(--link-decoration);
1423
+ text-underline-offset: var(--link-underline-offset);
931
1424
  }
932
1425
 
933
1426
  [data-ui="prose"] a:hover {
@@ -964,7 +1457,7 @@ table {
964
1457
  }
965
1458
 
966
1459
  [data-ui="prose"] blockquote {
967
- border-inline-start: 3px solid var(--color-border-strong);
1460
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
968
1461
  padding-inline-start: var(--space-4);
969
1462
  color: var(--color-fg-muted);
970
1463
  margin-block: var(--space-4);
@@ -986,9 +1479,15 @@ table {
986
1479
  margin-block: var(--space-1);
987
1480
  }
988
1481
 
1482
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1483
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1484
+ [data-ui="prose"] li::marker {
1485
+ color: var(--marker-color);
1486
+ }
1487
+
989
1488
  [data-ui="prose"] hr {
990
1489
  border: none;
991
- border-block-start: 1px solid var(--color-border);
1490
+ border-block-start: var(--border-width) solid var(--color-border);
992
1491
  margin-block: var(--space-8);
993
1492
  }
994
1493
 
@@ -1007,12 +1506,12 @@ table {
1007
1506
  font-weight: var(--weight-semibold);
1008
1507
  text-align: start;
1009
1508
  padding: var(--space-2) var(--space-3);
1010
- border-block-end: 2px solid var(--color-border-strong);
1509
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1011
1510
  }
1012
1511
 
1013
1512
  [data-ui="prose"] td {
1014
1513
  padding: var(--space-2) var(--space-3);
1015
- border-block-end: 1px solid var(--color-border);
1514
+ border-block-end: var(--border-width) solid var(--color-border);
1016
1515
  }
1017
1516
 
1018
1517
  /* First child no top margin, last child no bottom margin */
@@ -1197,7 +1696,7 @@ table {
1197
1696
 
1198
1697
  /* === primitives/avatar.css === */
1199
1698
  /* @ui:component avatar */
1200
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1699
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1201
1700
 
1202
1701
  /* ── Base ── */
1203
1702
  [data-ui="avatar"] {
@@ -1227,7 +1726,7 @@ table {
1227
1726
  height: 100%;
1228
1727
  background: var(--color-bg-muted);
1229
1728
  color: var(--color-fg-muted);
1230
- font-family: var(--font-sans);
1729
+ font-family: var(--font-ui);
1231
1730
  font-size: var(--text-sm);
1232
1731
  font-weight: var(--weight-medium);
1233
1732
  text-transform: uppercase;
@@ -1252,7 +1751,7 @@ table {
1252
1751
 
1253
1752
  /* === primitives/badge.css === */
1254
1753
  /* @ui:component badge */
1255
- /* @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 */
1754
+ /* @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 */
1256
1755
 
1257
1756
  /* ── Base ── */
1258
1757
  [data-ui="badge"] {
@@ -1262,9 +1761,10 @@ table {
1262
1761
  gap: var(--space-1);
1263
1762
  padding: 0.125rem var(--space-2);
1264
1763
  border-radius: var(--badge-radius, var(--radius-full));
1764
+ corner-shape: var(--corner-shape);
1265
1765
  background: var(--color-bg-muted);
1266
1766
  color: var(--color-fg);
1267
- font-family: var(--badge-font, var(--font-sans));
1767
+ font-family: var(--badge-font, var(--font-ui));
1268
1768
  font-size: var(--text-xs);
1269
1769
  font-weight: var(--weight-medium);
1270
1770
  line-height: 1.5;
@@ -1310,11 +1810,11 @@ table {
1310
1810
 
1311
1811
  /* === primitives/breadcrumb.css === */
1312
1812
  /* @ui:component breadcrumb */
1313
- /* @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 */
1813
+ /* @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 */
1314
1814
 
1315
1815
  /* ── Root ── */
1316
1816
  [data-ui="breadcrumb"] {
1317
- font-family: var(--breadcrumb-font, var(--font-sans));
1817
+ font-family: var(--breadcrumb-font, var(--font-ui));
1318
1818
  font-size: var(--breadcrumb-size, var(--text-sm));
1319
1819
  color: var(--color-fg-muted);
1320
1820
  }
@@ -1340,12 +1840,13 @@ table {
1340
1840
 
1341
1841
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1342
1842
  color: var(--color-primary-hover);
1343
- text-decoration: underline;
1843
+ text-decoration-line: var(--link-decoration);
1344
1844
  }
1345
1845
 
1346
1846
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1347
- outline: 2px solid var(--color-ring);
1348
- outline-offset: 2px;
1847
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1848
+ outline-offset: var(--focus-ring-offset);
1849
+ box-shadow: var(--focus-shadow);
1349
1850
  }
1350
1851
 
1351
1852
  /* ── Separator (presentational) ── */
@@ -1385,7 +1886,7 @@ table {
1385
1886
 
1386
1887
  /* === primitives/button.css === */
1387
1888
  /* @ui:component button */
1388
- /* @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 */
1889
+ /* @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 */
1389
1890
 
1390
1891
  /* ── Base ── */
1391
1892
  [data-ui="button"] {
@@ -1395,18 +1896,21 @@ table {
1395
1896
  gap: var(--space-2);
1396
1897
  height: var(--button-height-md, 40px);
1397
1898
  padding-inline: var(--space-4);
1398
- border: 1px solid var(--color-border);
1899
+ border: var(--border-width) solid var(--color-border);
1399
1900
  border-radius: var(--button-radius, var(--radius-md));
1901
+ corner-shape: var(--corner-shape);
1400
1902
  background: var(--color-bg);
1401
1903
  color: var(--color-fg);
1402
- font-family: var(--font-sans);
1904
+ font-family: var(--font-ui);
1403
1905
  font-size: var(--text-sm);
1404
1906
  font-weight: var(--weight-medium);
1907
+ text-transform: var(--button-text-transform);
1405
1908
  line-height: 1;
1406
1909
  cursor: pointer;
1407
1910
  transition: background var(--duration-fast) var(--ease-default),
1408
1911
  border-color var(--duration-fast) var(--ease-default),
1409
1912
  color var(--duration-fast) var(--ease-default),
1913
+ translate var(--duration-fast) var(--ease-default),
1410
1914
  box-shadow var(--duration-fast) var(--ease-default);
1411
1915
  user-select: none;
1412
1916
  white-space: nowrap;
@@ -1415,11 +1919,16 @@ table {
1415
1919
 
1416
1920
  [data-ui="button"]:hover {
1417
1921
  background: var(--color-bg-muted);
1922
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1923
+ this rule computes what the button computed before the token existed; a
1924
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1925
+ translate: var(--motion-hover-lift);
1418
1926
  }
1419
1927
 
1420
1928
  [data-ui="button"]:focus-visible {
1421
- outline: 2px solid var(--color-ring);
1422
- outline-offset: 2px;
1929
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1930
+ outline-offset: var(--focus-ring-offset);
1931
+ box-shadow: var(--focus-shadow);
1423
1932
  }
1424
1933
 
1425
1934
  /* ── Variants ── */
@@ -1475,7 +1984,7 @@ table {
1475
1984
  padding: 0;
1476
1985
  }
1477
1986
  [data-ui="button"][data-variant="link"]:hover {
1478
- text-decoration: underline;
1987
+ text-decoration-line: var(--link-decoration);
1479
1988
  }
1480
1989
 
1481
1990
  /* ── Sizes ── */
@@ -1494,7 +2003,7 @@ table {
1494
2003
  /* ── States ── */
1495
2004
  [data-ui="button"]:disabled,
1496
2005
  [data-ui="button"][data-state="disabled"] {
1497
- opacity: 0.5;
2006
+ opacity: var(--disabled-opacity);
1498
2007
  cursor: not-allowed;
1499
2008
  pointer-events: none;
1500
2009
  }
@@ -1509,7 +2018,7 @@ table {
1509
2018
  position: absolute;
1510
2019
  width: 1em;
1511
2020
  height: 1em;
1512
- border: 2px solid currentColor;
2021
+ border: var(--border-width-strong) solid currentColor;
1513
2022
  border-inline-end-color: transparent;
1514
2023
  border-radius: var(--radius-full);
1515
2024
  animation: faqir-spin 0.6s linear infinite;
@@ -1556,7 +2065,7 @@ table {
1556
2065
 
1557
2066
  /* === primitives/callout.css === */
1558
2067
  /* @ui:component callout */
1559
- /* @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 */
2068
+ /* @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 */
1560
2069
 
1561
2070
  /* ── Base ── */
1562
2071
  [data-ui="callout"] {
@@ -1565,7 +2074,7 @@ table {
1565
2074
  padding: var(--callout-padding-y) var(--callout-padding-x);
1566
2075
  border-radius: var(--callout-radius);
1567
2076
  border-inline-start: var(--callout-border-left-width) solid;
1568
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2077
+ font-family: var(--doc-font, var(--font-body));
1569
2078
  font-size: var(--callout-font-size);
1570
2079
  line-height: var(--doc-line-height, 1.5);
1571
2080
  }
@@ -1596,6 +2105,7 @@ table {
1596
2105
  /* ── Title ── */
1597
2106
  [data-ui="callout"] [data-part="title"] {
1598
2107
  display: block;
2108
+ font-family: var(--font-heading);
1599
2109
  font-weight: var(--weight-semibold);
1600
2110
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1601
2111
  }
@@ -1622,8 +2132,9 @@ table {
1622
2132
  }
1623
2133
 
1624
2134
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1625
- outline: 2px solid var(--color-ring, var(--color-info));
1626
- outline-offset: 2px;
2135
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2136
+ outline-offset: var(--focus-ring-offset);
2137
+ box-shadow: var(--focus-shadow);
1627
2138
  opacity: 1;
1628
2139
  }
1629
2140
 
@@ -1709,17 +2220,36 @@ table {
1709
2220
 
1710
2221
  /* === primitives/card.css === */
1711
2222
  /* @ui:component card */
1712
- /* @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 */
2223
+ /* @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 */
1713
2224
 
1714
2225
  /* ── Base ── */
1715
2226
  [data-ui="card"] {
1716
2227
  display: flex;
1717
2228
  flex-direction: column;
1718
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2229
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1719
2230
  border-radius: var(--card-radius, var(--radius-lg));
1720
- background: var(--card-bg, var(--color-surface-1));
2231
+ corner-shape: var(--corner-shape);
2232
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2233
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2234
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2235
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1721
2236
  box-shadow: var(--card-shadow, var(--shadow-sm));
1722
2237
  overflow: hidden;
2238
+ transition: translate var(--duration-fast) var(--ease-default);
2239
+ }
2240
+
2241
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2242
+ value of `translate`), so a card sits exactly where it always sat until a
2243
+ theme says surfaces rise under the pointer. */
2244
+ [data-ui="card"]:hover {
2245
+ translate: var(--motion-hover-lift);
2246
+ }
2247
+
2248
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2249
+ [data-ui="card"] {
2250
+ -webkit-backdrop-filter: var(--surface-backdrop);
2251
+ backdrop-filter: var(--surface-backdrop);
2252
+ }
1723
2253
  }
1724
2254
 
1725
2255
  /* ── Variants ── */
@@ -1728,7 +2258,7 @@ table {
1728
2258
  }
1729
2259
 
1730
2260
  [data-ui="card"][data-variant="filled"] {
1731
- background: var(--color-surface-2);
2261
+ background: var(--texture-surface), var(--color-surface-2);
1732
2262
  border-color: var(--color-surface-2-border);
1733
2263
  box-shadow: none;
1734
2264
  }
@@ -1743,7 +2273,7 @@ table {
1743
2273
  }
1744
2274
 
1745
2275
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1746
- font-family: var(--font-sans);
2276
+ font-family: var(--font-heading);
1747
2277
  font-size: var(--text-lg);
1748
2278
  font-weight: var(--weight-semibold);
1749
2279
  line-height: var(--leading-tight);
@@ -1784,9 +2314,19 @@ table {
1784
2314
  padding-top: 0;
1785
2315
  }
1786
2316
 
2317
+ /* ── Motion ── */
2318
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2319
+ theme states one — but the house rule is that a stylesheet which transitions
2320
+ carries its own opt-out, so a reader never has to check the token first. */
2321
+ @media (prefers-reduced-motion: reduce) {
2322
+ [data-ui="card"] {
2323
+ transition: none;
2324
+ }
2325
+ }
2326
+
1787
2327
  /* === primitives/checkbox.css === */
1788
2328
  /* @ui:component checkbox */
1789
- /* @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 */
2329
+ /* @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 */
1790
2330
 
1791
2331
  /* -- Label wrapper -- */
1792
2332
  [data-ui="checkbox-label"] {
@@ -1798,7 +2338,7 @@ table {
1798
2338
 
1799
2339
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1800
2340
  cursor: not-allowed;
1801
- opacity: 0.5;
2341
+ opacity: var(--disabled-opacity);
1802
2342
  }
1803
2343
 
1804
2344
  /* -- Base -- */
@@ -1810,8 +2350,8 @@ table {
1810
2350
  width: var(--checkbox-size, 18px);
1811
2351
  height: var(--checkbox-size, 18px);
1812
2352
  flex-shrink: 0;
1813
- border: 1px solid var(--color-border);
1814
- border-radius: var(--checkbox-radius, var(--radius-sm));
2353
+ border: var(--border-width) solid var(--color-border);
2354
+ border-radius: var(--checkbox-radius);
1815
2355
  background: var(--color-bg);
1816
2356
  cursor: pointer;
1817
2357
  transition: background var(--duration-fast) var(--ease-default),
@@ -1824,8 +2364,9 @@ table {
1824
2364
  }
1825
2365
 
1826
2366
  [data-ui="checkbox"]:focus-visible {
1827
- outline: 2px solid var(--color-ring);
1828
- outline-offset: 2px;
2367
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2368
+ outline-offset: var(--focus-ring-offset);
2369
+ box-shadow: var(--focus-shadow);
1829
2370
  }
1830
2371
 
1831
2372
  /* -- Checked -- */
@@ -1916,7 +2457,7 @@ table {
1916
2457
  The mask has to opt out of the substitution to stay readable. [W3-3] */
1917
2458
  @media (forced-colors: active) {
1918
2459
  [data-ui="checkbox"] {
1919
- border: 1px solid ButtonText;
2460
+ border: var(--border-width) solid ButtonText;
1920
2461
  }
1921
2462
 
1922
2463
  [data-ui="checkbox"]:checked,
@@ -1940,7 +2481,7 @@ table {
1940
2481
 
1941
2482
  /* === primitives/chip.css === */
1942
2483
  /* @ui:component chip */
1943
- /* @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 */
2484
+ /* @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 */
1944
2485
 
1945
2486
  /* ── Base ── */
1946
2487
  [data-ui="chip"] {
@@ -1948,11 +2489,11 @@ table {
1948
2489
  align-items: center;
1949
2490
  gap: var(--space-1);
1950
2491
  padding: var(--space-1) var(--space-2);
1951
- border: 1px solid transparent;
2492
+ border: var(--border-width) solid transparent;
1952
2493
  border-radius: var(--chip-radius, var(--radius-full));
1953
2494
  background: var(--color-bg-muted);
1954
2495
  color: var(--color-fg);
1955
- font-family: var(--chip-font, var(--font-sans));
2496
+ font-family: var(--chip-font, var(--font-ui));
1956
2497
  font-size: var(--text-sm);
1957
2498
  font-weight: var(--weight-medium);
1958
2499
  line-height: 1.2;
@@ -1988,8 +2529,11 @@ table {
1988
2529
  }
1989
2530
 
1990
2531
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
1991
- outline: 2px solid var(--color-ring);
1992
- outline-offset: 1px;
2532
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2533
+ /* Half the default gap — the dismiss target is small, and the full ring
2534
+ would collide with the chip's own edge. */
2535
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2536
+ box-shadow: var(--focus-shadow);
1993
2537
  }
1994
2538
 
1995
2539
  /* ── Variants ── */
@@ -2212,12 +2756,12 @@ table {
2212
2756
 
2213
2757
  /* === primitives/collapsible.css === */
2214
2758
  /* @ui:component collapsible */
2215
- /* @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 */
2759
+ /* @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 */
2216
2760
 
2217
2761
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2218
2762
  [data-ui="collapsible"] {
2219
2763
  border-radius: var(--collapsible-radius, var(--radius-md));
2220
- font-family: var(--collapsible-font, var(--font-sans));
2764
+ font-family: var(--collapsible-font, var(--font-ui));
2221
2765
  color: var(--color-fg);
2222
2766
  }
2223
2767
 
@@ -2247,8 +2791,9 @@ table {
2247
2791
  }
2248
2792
 
2249
2793
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2250
- outline: 2px solid var(--color-ring);
2251
- outline-offset: 2px;
2794
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2795
+ outline-offset: var(--focus-ring-offset);
2796
+ box-shadow: var(--focus-shadow);
2252
2797
  }
2253
2798
 
2254
2799
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2257,8 +2802,8 @@ table {
2257
2802
  flex: none;
2258
2803
  width: 0.5em;
2259
2804
  height: 0.5em;
2260
- border-inline-end: 2px solid var(--color-fg-muted);
2261
- border-block-end: 2px solid var(--color-fg-muted);
2805
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2806
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2262
2807
  transform: rotate(45deg);
2263
2808
  transition: transform var(--duration-normal) var(--ease-default);
2264
2809
  }
@@ -2277,7 +2822,7 @@ table {
2277
2822
 
2278
2823
  /* ── Bordered variant ── */
2279
2824
  [data-ui="collapsible"][data-variant="bordered"] {
2280
- border: 1px solid var(--color-border);
2825
+ border: var(--border-width) solid var(--color-border);
2281
2826
  }
2282
2827
 
2283
2828
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2410,13 +2955,13 @@ table {
2410
2955
 
2411
2956
  /* === primitives/description-list.css === */
2412
2957
  /* @ui:component description-list */
2413
- /* @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 */
2958
+ /* @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 */
2414
2959
 
2415
2960
  /* ── Base ── */
2416
2961
  [data-ui="description-list"] {
2417
2962
  margin: 0;
2418
2963
  padding: 0;
2419
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2964
+ font-family: var(--doc-font, var(--font-body));
2420
2965
  }
2421
2966
 
2422
2967
  /* ── Term ── */
@@ -2472,7 +3017,7 @@ table {
2472
3017
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2473
3018
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2474
3019
  padding-bottom: var(--space-4);
2475
- border-bottom: 1px solid var(--color-border);
3020
+ border-bottom: var(--border-width) solid var(--color-border);
2476
3021
  }
2477
3022
 
2478
3023
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2484,7 +3029,7 @@ table {
2484
3029
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2485
3030
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2486
3031
  padding-bottom: var(--space-3);
2487
- border-bottom: 1px solid var(--color-border);
3032
+ border-bottom: var(--border-width) solid var(--color-border);
2488
3033
  }
2489
3034
 
2490
3035
  /* ── Size: Small ── */
@@ -2522,7 +3067,7 @@ table {
2522
3067
 
2523
3068
  /* === primitives/empty-state.css === */
2524
3069
  /* @ui:component empty-state */
2525
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3070
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2526
3071
 
2527
3072
  /* ── Base ── */
2528
3073
  [data-ui="empty-state"] {
@@ -2543,6 +3088,7 @@ table {
2543
3088
 
2544
3089
  /* ── Title ── */
2545
3090
  [data-ui="empty-state"] [data-part="title"] {
3091
+ font-family: var(--font-heading);
2546
3092
  font-size: var(--text-lg);
2547
3093
  font-weight: var(--weight-medium);
2548
3094
  color: var(--color-fg);
@@ -2590,7 +3136,7 @@ table {
2590
3136
 
2591
3137
  /* === primitives/field-group.css === */
2592
3138
  /* @ui:component field-group */
2593
- /* @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 */
3139
+ /* @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 */
2594
3140
 
2595
3141
  /* ── Base / spacing ownership ──
2596
3142
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2602,7 +3148,7 @@ table {
2602
3148
  display: flex;
2603
3149
  flex-direction: column;
2604
3150
  gap: var(--space-2);
2605
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3151
+ font-family: var(--doc-font, var(--font-body));
2606
3152
  }
2607
3153
 
2608
3154
  /* ── Label ── */
@@ -2672,7 +3218,7 @@ table {
2672
3218
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2673
3219
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2674
3220
  border-color: var(--field-error-color);
2675
- box-shadow: 0 0 0 1px var(--field-error-color);
3221
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2676
3222
  }
2677
3223
 
2678
3224
  /* ── State: Validating ──
@@ -2682,7 +3228,7 @@ table {
2682
3228
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2683
3229
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2684
3230
  border-color: var(--field-validating-color);
2685
- box-shadow: 0 0 0 1px var(--field-validating-color);
3231
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2686
3232
  }
2687
3233
 
2688
3234
  /* ── State: Disabled ──
@@ -2701,8 +3247,8 @@ table {
2701
3247
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2702
3248
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2703
3249
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2704
- border-color: var(--color-success, oklch(0.62 0.19 145));
2705
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3250
+ border-color: var(--color-success);
3251
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2706
3252
  }
2707
3253
 
2708
3254
  /* ── Variant: Horizontal ── */
@@ -3007,7 +3553,7 @@ table {
3007
3553
 
3008
3554
  /* === primitives/image.css === */
3009
3555
  /* @ui:component image */
3010
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3556
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3011
3557
 
3012
3558
  /* ── Base ── */
3013
3559
  [data-ui="image"] {
@@ -3031,7 +3577,7 @@ table {
3031
3577
  [data-ui="image"] [data-part="caption"] {
3032
3578
  display: block;
3033
3579
  margin-top: var(--space-2);
3034
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3580
+ font-family: var(--doc-font, var(--font-body));
3035
3581
  font-size: var(--image-caption-size);
3036
3582
  color: var(--image-caption-color);
3037
3583
  line-height: 1.4;
@@ -3128,7 +3674,7 @@ table {
3128
3674
 
3129
3675
  /* === primitives/input.css === */
3130
3676
  /* @ui:component input */
3131
- /* @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 */
3677
+ /* @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 */
3132
3678
 
3133
3679
  /* ── Base ── */
3134
3680
  [data-ui="input"] {
@@ -3136,11 +3682,18 @@ table {
3136
3682
  width: 100%;
3137
3683
  height: var(--input-height, 40px);
3138
3684
  padding-inline: var(--space-3);
3139
- border: 1px solid var(--color-border);
3685
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3686
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3687
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3688
+ is drawn. Identical to the shorthand at every other value of the token. */
3689
+ border-style: solid;
3690
+ border-color: var(--color-border);
3691
+ border-width: var(--input-border-width);
3140
3692
  border-radius: var(--input-radius, var(--radius-md));
3141
- background: var(--input-bg, var(--color-bg));
3693
+ corner-shape: var(--corner-shape);
3694
+ background: var(--input-fill);
3142
3695
  color: var(--color-fg);
3143
- font-family: var(--input-font, var(--font-sans));
3696
+ font-family: var(--input-font, var(--font-ui));
3144
3697
  font-size: var(--text-sm);
3145
3698
  line-height: 1;
3146
3699
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3156,8 +3709,11 @@ table {
3156
3709
  }
3157
3710
 
3158
3711
  [data-ui="input"]:focus {
3159
- outline: 2px solid var(--color-ring);
3160
- outline-offset: -1px;
3712
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3713
+ /* The ring replaces the border rather than sitting outside it: inset by
3714
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3715
+ outline-offset: calc(-1 * var(--input-border-width));
3716
+ box-shadow: var(--focus-shadow);
3161
3717
  border-color: transparent;
3162
3718
  }
3163
3719
 
@@ -3185,7 +3741,7 @@ table {
3185
3741
  }
3186
3742
 
3187
3743
  [data-ui="input"]:disabled {
3188
- opacity: 0.5;
3744
+ opacity: var(--disabled-opacity);
3189
3745
  cursor: not-allowed;
3190
3746
  }
3191
3747
 
@@ -3248,7 +3804,7 @@ table {
3248
3804
 
3249
3805
  /* === primitives/kbd.css === */
3250
3806
  /* @ui:component kbd */
3251
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3807
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3252
3808
 
3253
3809
  /* ── Base ── */
3254
3810
  [data-ui="kbd"] {
@@ -3258,8 +3814,8 @@ table {
3258
3814
  height: 20px;
3259
3815
  min-width: 20px;
3260
3816
  padding-inline: var(--space-1h);
3261
- border: 1px solid var(--color-border);
3262
- border-bottom-width: 2px;
3817
+ border: var(--border-width) solid var(--color-border);
3818
+ border-bottom-width: var(--border-width-strong);
3263
3819
  border-radius: var(--radius-sm);
3264
3820
  background: var(--color-bg-subtle);
3265
3821
  color: var(--color-fg);
@@ -3272,7 +3828,7 @@ table {
3272
3828
 
3273
3829
  /* === primitives/key-value.css === */
3274
3830
  /* @ui:component key-value */
3275
- /* @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 */
3831
+ /* @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 */
3276
3832
 
3277
3833
  /* ── Base ── */
3278
3834
  [data-ui="key-value"] {
@@ -3281,7 +3837,7 @@ table {
3281
3837
  gap: var(--kv-pair-gap);
3282
3838
  margin: 0;
3283
3839
  padding: 0;
3284
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3840
+ font-family: var(--doc-font, var(--font-body));
3285
3841
  }
3286
3842
 
3287
3843
  /* ── Label ── */
@@ -3411,12 +3967,12 @@ table {
3411
3967
 
3412
3968
  /* === primitives/label.css === */
3413
3969
  /* @ui:component label */
3414
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
3970
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3415
3971
 
3416
3972
  /* ── Base ── */
3417
3973
  [data-ui="label"] {
3418
3974
  display: block;
3419
- font-family: var(--font-sans);
3975
+ font-family: var(--font-ui);
3420
3976
  font-size: var(--text-sm);
3421
3977
  font-weight: var(--weight-medium);
3422
3978
  color: var(--color-fg);
@@ -3449,21 +4005,21 @@ table {
3449
4005
 
3450
4006
  /* ── States ── */
3451
4007
  [data-ui="label"][data-state="disabled"] {
3452
- opacity: 0.5;
4008
+ opacity: var(--disabled-opacity);
3453
4009
  cursor: not-allowed;
3454
4010
  }
3455
4011
 
3456
4012
  /* === primitives/link.css === */
3457
4013
  /* @ui:component link */
3458
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4014
+ /* @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 */
3459
4015
 
3460
4016
  /* ── Base ── */
3461
4017
  [data-ui="link"] {
3462
4018
  color: var(--color-primary);
3463
4019
  font-family: inherit;
3464
- text-decoration: underline;
3465
- text-decoration-thickness: 1px;
3466
- text-underline-offset: 0.2em;
4020
+ text-decoration-line: var(--link-decoration);
4021
+ text-decoration-thickness: var(--link-thickness);
4022
+ text-underline-offset: var(--link-underline-offset);
3467
4023
  border-radius: var(--radius-sm);
3468
4024
  cursor: pointer;
3469
4025
  }
@@ -3477,8 +4033,9 @@ table {
3477
4033
  }
3478
4034
 
3479
4035
  [data-ui="link"]:focus-visible {
3480
- outline: 2px solid var(--color-ring);
3481
- outline-offset: 2px;
4036
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4037
+ outline-offset: var(--focus-ring-offset);
4038
+ box-shadow: var(--focus-shadow);
3482
4039
  }
3483
4040
 
3484
4041
  /* ── Variants ── */
@@ -3502,7 +4059,7 @@ table {
3502
4059
 
3503
4060
  /* === primitives/nav.css === */
3504
4061
  /* @ui:component nav */
3505
- /* @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 */
4062
+ /* @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 */
3506
4063
 
3507
4064
  /* ── Base ── */
3508
4065
  [data-ui="nav"] {
@@ -3552,14 +4109,14 @@ table {
3552
4109
 
3553
4110
  /* ── Underline variant ── */
3554
4111
  [data-ui="nav"][data-variant="underline"] {
3555
- border-bottom: 1px solid var(--color-border);
4112
+ border-bottom: var(--border-width) solid var(--color-border);
3556
4113
  gap: 0;
3557
4114
  }
3558
4115
 
3559
4116
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3560
4117
  border-radius: 0;
3561
4118
  padding: var(--space-2) var(--space-4);
3562
- border-bottom: 2px solid transparent;
4119
+ border-bottom: var(--border-width-strong) solid transparent;
3563
4120
  margin-bottom: -1px;
3564
4121
  }
3565
4122
 
@@ -3615,7 +4172,7 @@ table {
3615
4172
 
3616
4173
  /* === primitives/page-break.css === */
3617
4174
  /* @ui:component page-break */
3618
- /* @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 */
4175
+ /* @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 */
3619
4176
 
3620
4177
  /* ── Base (Screen) ── */
3621
4178
  [data-ui="page-break"] {
@@ -3630,12 +4187,12 @@ table {
3630
4187
  [data-ui="page-break"]::after {
3631
4188
  content: "";
3632
4189
  flex: 1;
3633
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4190
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3634
4191
  }
3635
4192
 
3636
4193
  /* ── Label (Screen) ── */
3637
4194
  [data-ui="page-break"] {
3638
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4195
+ font-family: var(--doc-font, var(--font-body));
3639
4196
  font-size: var(--page-break-screen-label-size);
3640
4197
  color: var(--page-break-screen-label-color);
3641
4198
  letter-spacing: 0.05em;
@@ -3677,7 +4234,7 @@ table {
3677
4234
 
3678
4235
  /* === primitives/progress.css === */
3679
4236
  /* @ui:component progress */
3680
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4237
+ /* @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 */
3681
4238
 
3682
4239
  /* ── Base ── */
3683
4240
  [data-ui="progress"] {
@@ -3752,7 +4309,7 @@ table {
3752
4309
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3753
4310
  @media (forced-colors: active) {
3754
4311
  [data-ui="progress"] [data-part="track"] {
3755
- border: 1px solid ButtonText;
4312
+ border: var(--border-width) solid ButtonText;
3756
4313
  }
3757
4314
 
3758
4315
  [data-ui="progress"] [data-part="fill"],
@@ -3766,7 +4323,7 @@ table {
3766
4323
 
3767
4324
  /* === primitives/radio.css === */
3768
4325
  /* @ui:component radio */
3769
- /* @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 */
4326
+ /* @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 */
3770
4327
 
3771
4328
  /* -- Radio group -- */
3772
4329
  [data-ui="radio-group"] {
@@ -3788,7 +4345,7 @@ table {
3788
4345
 
3789
4346
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3790
4347
  cursor: not-allowed;
3791
- opacity: 0.5;
4348
+ opacity: var(--disabled-opacity);
3792
4349
  }
3793
4350
 
3794
4351
  /* -- Base -- */
@@ -3800,7 +4357,7 @@ table {
3800
4357
  width: var(--radio-size, 18px);
3801
4358
  height: var(--radio-size, 18px);
3802
4359
  flex-shrink: 0;
3803
- border: 1px solid var(--color-border);
4360
+ border: var(--border-width) solid var(--color-border);
3804
4361
  border-radius: var(--radius-full);
3805
4362
  background: var(--color-bg);
3806
4363
  cursor: pointer;
@@ -3814,8 +4371,9 @@ table {
3814
4371
  }
3815
4372
 
3816
4373
  [data-ui="radio"]:focus-visible {
3817
- outline: 2px solid var(--color-ring);
3818
- outline-offset: 2px;
4374
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4375
+ outline-offset: var(--focus-ring-offset);
4376
+ box-shadow: var(--focus-shadow);
3819
4377
  }
3820
4378
 
3821
4379
  /* -- Checked -- */
@@ -3868,7 +4426,7 @@ table {
3868
4426
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3869
4427
  @media (forced-colors: active) {
3870
4428
  [data-ui="radio"] {
3871
- border: 1px solid ButtonText;
4429
+ border: var(--border-width) solid ButtonText;
3872
4430
  }
3873
4431
 
3874
4432
  [data-ui="radio"]:checked {
@@ -3888,7 +4446,7 @@ table {
3888
4446
 
3889
4447
  /* === primitives/select.css === */
3890
4448
  /* @ui:component select */
3891
- /* @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 */
4449
+ /* @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 */
3892
4450
 
3893
4451
  /* -- Base -- */
3894
4452
  [data-ui="select"] {
@@ -3897,11 +4455,17 @@ table {
3897
4455
  height: var(--select-height, 40px);
3898
4456
  padding-inline: var(--space-3);
3899
4457
  padding-inline-end: var(--space-8, 2rem);
3900
- border: 1px solid var(--color-border);
4458
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4459
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4460
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4461
+ is drawn. Identical to the shorthand at every other value of the token. */
4462
+ border-style: solid;
4463
+ border-color: var(--color-border);
4464
+ border-width: var(--input-border-width);
3901
4465
  border-radius: var(--select-radius, var(--radius-md));
3902
- background: var(--select-bg, var(--color-bg));
4466
+ background: var(--select-bg, var(--input-fill));
3903
4467
  color: var(--color-fg);
3904
- font-family: var(--select-font, var(--font-sans));
4468
+ font-family: var(--select-font, var(--font-ui));
3905
4469
  font-size: var(--text-sm);
3906
4470
  line-height: 1;
3907
4471
  cursor: pointer;
@@ -3931,8 +4495,11 @@ table {
3931
4495
  }
3932
4496
 
3933
4497
  [data-ui="select"]:focus {
3934
- outline: 2px solid var(--color-ring);
3935
- outline-offset: -1px;
4498
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4499
+ /* The ring replaces the border rather than sitting outside it: inset by
4500
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4501
+ outline-offset: calc(-1 * var(--input-border-width));
4502
+ box-shadow: var(--focus-shadow);
3936
4503
  border-color: transparent;
3937
4504
  }
3938
4505
 
@@ -3965,7 +4532,7 @@ table {
3965
4532
  }
3966
4533
 
3967
4534
  [data-ui="select"]:disabled {
3968
- opacity: 0.5;
4535
+ opacity: var(--disabled-opacity);
3969
4536
  cursor: not-allowed;
3970
4537
  }
3971
4538
 
@@ -3978,12 +4545,12 @@ table {
3978
4545
 
3979
4546
  /* === primitives/separator.css === */
3980
4547
  /* @ui:component separator */
3981
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4548
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
3982
4549
 
3983
4550
  /* ── Base (horizontal) ── */
3984
4551
  [data-ui="separator"] {
3985
4552
  border: none;
3986
- border-top: 1px solid var(--color-border);
4553
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
3987
4554
  margin: 0;
3988
4555
  width: 100%;
3989
4556
  }
@@ -3991,7 +4558,7 @@ table {
3991
4558
  /* ── Vertical ── */
3992
4559
  [data-ui="separator"][data-variant="vertical"] {
3993
4560
  border-top: none;
3994
- border-inline-start: 1px solid var(--color-border);
4561
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
3995
4562
  width: auto;
3996
4563
  height: 100%;
3997
4564
  align-self: stretch;
@@ -4009,11 +4576,11 @@ div[data-ui="separator"]::before,
4009
4576
  div[data-ui="separator"]::after {
4010
4577
  content: "";
4011
4578
  flex: 1;
4012
- border-top: 1px solid var(--color-border);
4579
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4013
4580
  }
4014
4581
 
4015
4582
  [data-ui="separator"] [data-part="label"] {
4016
- font-family: var(--font-sans);
4583
+ font-family: var(--font-ui);
4017
4584
  font-size: var(--text-xs);
4018
4585
  color: var(--color-fg-muted);
4019
4586
  white-space: nowrap;
@@ -4051,17 +4618,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4051
4618
 
4052
4619
  /* ── Style: Thick ── */
4053
4620
  [data-ui="separator"][data-style="thick"] {
4054
- border-top-width: 2px;
4621
+ border-top-width: var(--border-width-strong);
4055
4622
  }
4056
4623
 
4057
4624
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4058
4625
  border-top-width: 0;
4059
- border-inline-start-width: 2px;
4626
+ border-inline-start-width: var(--border-width-strong);
4060
4627
  }
4061
4628
 
4062
4629
  div[data-ui="separator"][data-style="thick"]::before,
4063
4630
  div[data-ui="separator"][data-style="thick"]::after {
4064
- border-top-width: 2px;
4631
+ border-top-width: var(--border-width-strong);
4065
4632
  }
4066
4633
 
4067
4634
  /* ── Vertical Sizes ── */
@@ -4079,20 +4646,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4079
4646
 
4080
4647
  /* === primitives/signature.css === */
4081
4648
  /* @ui:component signature */
4082
- /* @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 */
4649
+ /* @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 */
4083
4650
 
4084
4651
  /* ── Base ── */
4085
4652
  [data-ui="signature"] {
4086
4653
  display: flex;
4087
4654
  flex-direction: column;
4088
4655
  gap: var(--space-2);
4089
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4656
+ font-family: var(--doc-font, var(--font-body));
4090
4657
  margin-top: var(--doc-signature-gap);
4091
4658
  }
4092
4659
 
4093
4660
  /* ── Line ── */
4094
4661
  [data-ui="signature"] [data-part="line"] {
4095
- border-top: 1px solid var(--doc-signature-line-color);
4662
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4096
4663
  min-height: 1px;
4097
4664
  }
4098
4665
 
@@ -4195,14 +4762,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4195
4762
 
4196
4763
  /* === primitives/spinner.css === */
4197
4764
  /* @ui:component spinner */
4198
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4765
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4199
4766
 
4200
4767
  /* ── Base ── */
4201
4768
  [data-ui="spinner"] {
4202
4769
  display: inline-block;
4203
4770
  width: 24px;
4204
4771
  height: 24px;
4205
- border: 2px solid var(--color-border);
4772
+ border: var(--border-width-strong) solid var(--color-border);
4206
4773
  border-top-color: var(--color-primary);
4207
4774
  border-radius: var(--radius-full);
4208
4775
  animation: faqir-spin 0.75s linear infinite;
@@ -4218,13 +4785,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4218
4785
  [data-ui="spinner"][data-size="lg"] {
4219
4786
  width: 32px;
4220
4787
  height: 32px;
4221
- border-width: 3px;
4788
+ border-width: var(--border-width-lg);
4222
4789
  }
4223
4790
 
4224
4791
  [data-ui="spinner"][data-size="xl"] {
4225
4792
  width: 48px;
4226
4793
  height: 48px;
4227
- border-width: 3px;
4794
+ border-width: var(--border-width-lg);
4228
4795
  }
4229
4796
 
4230
4797
  /* ── Motion ── */
@@ -4806,14 +5373,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4806
5373
 
4807
5374
  /* === primitives/stat.css === */
4808
5375
  /* @ui:component stat */
4809
- /* @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 */
5376
+ /* @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 */
4810
5377
 
4811
5378
  /* ── Base ── */
4812
5379
  [data-ui="stat"] {
4813
5380
  display: flex;
4814
5381
  flex-direction: column;
4815
5382
  gap: var(--space-1);
4816
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5383
+ font-family: var(--doc-font, var(--font-body));
4817
5384
  }
4818
5385
 
4819
5386
  /* ── Label ── */
@@ -4827,6 +5394,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4827
5394
 
4828
5395
  /* ── Value ── */
4829
5396
  [data-ui="stat"] [data-part="value"] {
5397
+ font-family: var(--font-heading);
4830
5398
  font-size: var(--stat-value-size);
4831
5399
  font-weight: var(--stat-value-weight);
4832
5400
  color: var(--color-fg);
@@ -4885,10 +5453,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4885
5453
  /* ── Variant: Card ── */
4886
5454
  [data-ui="stat"][data-variant="card"] {
4887
5455
  padding: var(--space-4);
4888
- border: 1px solid var(--color-border);
5456
+ border: var(--border-width) solid var(--color-border);
4889
5457
  border-radius: var(--radius-md, 0.375rem);
4890
5458
  background: var(--color-bg);
4891
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5459
+ box-shadow: var(--shadow-sm);
4892
5460
  }
4893
5461
 
4894
5462
  /* ── Value + Change Inline ── */
@@ -4900,7 +5468,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4900
5468
  @media print {
4901
5469
  [data-ui="stat"][data-variant="card"] {
4902
5470
  box-shadow: none;
4903
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5471
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
4904
5472
  }
4905
5473
 
4906
5474
  [data-ui="stat"] {
@@ -4910,7 +5478,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4910
5478
 
4911
5479
  /* === primitives/stepper.css === */
4912
5480
  /* @ui:component stepper */
4913
- /* @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 */
5481
+ /* @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 */
4914
5482
 
4915
5483
  /* ── Base ── */
4916
5484
  [data-ui="stepper"] {
@@ -4989,7 +5557,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4989
5557
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
4990
5558
  [data-ui="stepper"] [data-part="connector"] {
4991
5559
  flex: 1;
4992
- height: 2px;
5560
+ height: var(--border-width-strong);
4993
5561
  background: var(--color-border);
4994
5562
  margin: 0 var(--space-1);
4995
5563
  min-width: var(--space-2);
@@ -5057,18 +5625,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5057
5625
 
5058
5626
  /* === primitives/surface.css === */
5059
5627
  /* @ui:component surface */
5060
- /* @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 */
5628
+ /* @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 */
5061
5629
 
5062
5630
  /* ── Base ── */
5063
5631
  [data-ui="surface"] {
5064
- background: var(--color-surface-1);
5632
+ background-color: var(--color-surface-1);
5633
+ background-image: var(--texture-surface);
5065
5634
  border-radius: var(--radius-lg);
5066
- border: 1px solid var(--color-surface-1-border);
5635
+ corner-shape: var(--corner-shape);
5636
+ border: var(--border-width) solid var(--color-surface-1-border);
5067
5637
  }
5068
5638
 
5069
5639
  /* ── Elevation Variants ── */
5070
5640
  [data-ui="surface"][data-variant="flat"] {
5071
- background: var(--color-bg);
5641
+ background-color: var(--color-bg);
5072
5642
  border: none;
5073
5643
  box-shadow: none;
5074
5644
  }
@@ -5078,11 +5648,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5078
5648
  }
5079
5649
 
5080
5650
  [data-ui="surface"][data-variant="overlay"] {
5081
- background: var(--color-surface-2);
5651
+ background-color: var(--color-surface-2);
5082
5652
  box-shadow: var(--shadow-lg);
5083
5653
  border-color: var(--color-surface-2-border);
5084
5654
  }
5085
5655
 
5656
+ /* An overlay is the one surface variant that floats over other content, so it
5657
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5658
+ its own: a browser without backdrop-filter renders the solid surface above
5659
+ and never sees this rule. */
5660
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5661
+ [data-ui="surface"][data-variant="overlay"] {
5662
+ -webkit-backdrop-filter: var(--surface-backdrop);
5663
+ backdrop-filter: var(--surface-backdrop);
5664
+ }
5665
+ }
5666
+
5086
5667
  /* ── Padding Sizes ── */
5087
5668
  [data-ui="surface"][data-size="sm"] {
5088
5669
  padding: var(--space-3);
@@ -5138,7 +5719,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5138
5719
 
5139
5720
  /* === primitives/switch.css === */
5140
5721
  /* @ui:component switch */
5141
- /* @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 */
5722
+ /* @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 */
5142
5723
 
5143
5724
  /* -- Label wrapper -- */
5144
5725
  [data-ui="switch-label"] {
@@ -5150,7 +5731,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5150
5731
 
5151
5732
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5152
5733
  cursor: not-allowed;
5153
- opacity: 0.5;
5734
+ opacity: var(--disabled-opacity);
5154
5735
  }
5155
5736
 
5156
5737
  /* -- Base (track) -- */
@@ -5178,8 +5759,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5178
5759
  width: var(--switch-width, 44px);
5179
5760
  height: var(--switch-height, 24px);
5180
5761
  padding: var(--space-0h, 2px);
5181
- border: 1px solid var(--color-border);
5182
- border-radius: var(--radius-full);
5762
+ border: var(--border-width) solid var(--color-border);
5763
+ border-radius: var(--switch-radius);
5183
5764
  background: var(--switch-bg, var(--color-bg-muted));
5184
5765
  cursor: pointer;
5185
5766
  position: relative;
@@ -5189,8 +5770,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5189
5770
  }
5190
5771
 
5191
5772
  [data-ui="switch"]:focus-visible {
5192
- outline: 2px solid var(--color-ring);
5193
- outline-offset: 2px;
5773
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5774
+ outline-offset: var(--focus-ring-offset);
5775
+ box-shadow: var(--focus-shadow);
5194
5776
  }
5195
5777
 
5196
5778
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5199,7 +5781,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5199
5781
  display: block;
5200
5782
  width: var(--switch-thumb, 18px);
5201
5783
  height: var(--switch-thumb, 18px);
5202
- border-radius: var(--radius-full);
5784
+ border-radius: var(--switch-radius);
5203
5785
  background: var(--color-primary-fg);
5204
5786
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5205
5787
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5211,7 +5793,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5211
5793
  display: block;
5212
5794
  width: var(--switch-thumb, 18px);
5213
5795
  height: var(--switch-thumb, 18px);
5214
- border-radius: var(--radius-full);
5796
+ border-radius: var(--switch-radius);
5215
5797
  background: var(--color-primary-fg);
5216
5798
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5217
5799
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5293,7 +5875,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5293
5875
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5294
5876
  @media (forced-colors: active) {
5295
5877
  [data-ui="switch"] {
5296
- border: 1px solid ButtonText;
5878
+ border: var(--border-width) solid ButtonText;
5297
5879
  background: ButtonFace;
5298
5880
  }
5299
5881
 
@@ -5450,25 +6032,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5450
6032
 
5451
6033
  /* === primitives/text.css === */
5452
6034
  /* @ui:component text */
5453
- /* @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 */
6035
+ /* @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 */
5454
6036
 
5455
6037
  /* ── Heading ── */
5456
6038
  [data-ui="heading"] {
5457
- font-family: var(--font-sans);
5458
- font-weight: var(--weight-bold);
6039
+ font-family: var(--font-heading);
6040
+ font-weight: var(--heading-weight);
5459
6041
  color: var(--color-fg);
5460
- line-height: var(--leading-tight);
5461
- letter-spacing: -0.01em;
6042
+ line-height: var(--heading-leading);
6043
+ text-transform: var(--heading-transform);
6044
+ font-variant-caps: var(--heading-caps);
6045
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6046
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6047
+ headings sets --heading-tracking once and every size follows, instead of
6048
+ each size having to re-derive its own number. */
6049
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5462
6050
  }
5463
6051
 
5464
6052
  [data-ui="heading"][data-size="1"] {
5465
6053
  font-size: var(--text-4xl);
5466
- letter-spacing: -0.02em;
6054
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5467
6055
  }
5468
6056
 
5469
6057
  [data-ui="heading"][data-size="2"] {
5470
6058
  font-size: var(--text-3xl);
5471
- letter-spacing: -0.02em;
6059
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5472
6060
  }
5473
6061
 
5474
6062
  [data-ui="heading"][data-size="3"] {
@@ -5492,7 +6080,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5492
6080
 
5493
6081
  /* ── Text ── */
5494
6082
  [data-ui="text"] {
5495
- font-family: var(--font-sans);
6083
+ font-family: var(--font-body);
5496
6084
  color: var(--color-fg);
5497
6085
  }
5498
6086
 
@@ -5570,7 +6158,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5570
6158
 
5571
6159
  /* === primitives/textarea.css === */
5572
6160
  /* @ui:component textarea */
5573
- /* @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 */
6161
+ /* @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 */
5574
6162
 
5575
6163
  /* -- Base -- */
5576
6164
  [data-ui="textarea"] {
@@ -5578,11 +6166,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5578
6166
  width: 100%;
5579
6167
  min-height: var(--textarea-min-height, 80px);
5580
6168
  padding: var(--space-2) var(--space-3);
5581
- border: 1px solid var(--color-border);
6169
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6170
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6171
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6172
+ is drawn. Identical to the shorthand at every other value of the token. */
6173
+ border-style: solid;
6174
+ border-color: var(--color-border);
6175
+ border-width: var(--input-border-width);
5582
6176
  border-radius: var(--textarea-radius, var(--radius-md));
5583
- background: var(--textarea-bg, var(--color-bg));
6177
+ background: var(--textarea-bg, var(--input-fill));
5584
6178
  color: var(--color-fg);
5585
- font-family: var(--textarea-font, var(--font-sans));
6179
+ font-family: var(--textarea-font, var(--font-ui));
5586
6180
  font-size: var(--text-sm);
5587
6181
  line-height: 1.5;
5588
6182
  resize: vertical;
@@ -5599,8 +6193,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5599
6193
  }
5600
6194
 
5601
6195
  [data-ui="textarea"]:focus {
5602
- outline: 2px solid var(--color-ring);
5603
- outline-offset: -1px;
6196
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6197
+ /* The ring replaces the border rather than sitting outside it: inset by
6198
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6199
+ outline-offset: calc(-1 * var(--input-border-width));
6200
+ box-shadow: var(--focus-shadow);
5604
6201
  border-color: transparent;
5605
6202
  }
5606
6203
 
@@ -5628,7 +6225,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5628
6225
  }
5629
6226
 
5630
6227
  [data-ui="textarea"]:disabled {
5631
- opacity: 0.5;
6228
+ opacity: var(--disabled-opacity);
5632
6229
  cursor: not-allowed;
5633
6230
  resize: none;
5634
6231
  }
@@ -5642,7 +6239,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5642
6239
 
5643
6240
  /* === primitives/toggle.css === */
5644
6241
  /* @ui:component toggle */
5645
- /* @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 */
6242
+ /* @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 */
5646
6243
 
5647
6244
  /* ── Base (off / unpressed) ── */
5648
6245
  [data-ui="toggle"] {
@@ -5651,11 +6248,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5651
6248
  justify-content: center;
5652
6249
  gap: var(--space-1h);
5653
6250
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5654
- border: 1px solid var(--color-border);
6251
+ border: var(--border-width) solid var(--color-border);
5655
6252
  border-radius: var(--toggle-radius, var(--radius-md));
5656
6253
  background: var(--color-bg);
5657
6254
  color: var(--color-fg-muted);
5658
- font-family: var(--toggle-font, var(--font-sans));
6255
+ font-family: var(--toggle-font, var(--font-ui));
5659
6256
  font-size: var(--text-sm);
5660
6257
  font-weight: var(--weight-medium);
5661
6258
  line-height: 1;
@@ -5672,8 +6269,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5672
6269
  }
5673
6270
 
5674
6271
  [data-ui="toggle"]:focus-visible {
5675
- outline: 2px solid var(--color-ring);
5676
- outline-offset: 2px;
6272
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6273
+ outline-offset: var(--focus-ring-offset);
6274
+ box-shadow: var(--focus-shadow);
5677
6275
  }
5678
6276
 
5679
6277
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5690,7 +6288,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5690
6288
 
5691
6289
  /* ── Disabled ── */
5692
6290
  [data-ui="toggle"]:disabled {
5693
- opacity: 0.5;
6291
+ opacity: var(--disabled-opacity);
5694
6292
  cursor: not-allowed;
5695
6293
  }
5696
6294
 
@@ -5714,7 +6312,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5714
6312
 
5715
6313
  /* === primitives/watermark.css === */
5716
6314
  /* @ui:component watermark */
5717
- /* @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 */
6315
+ /* @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 */
5718
6316
 
5719
6317
  [data-ui="watermark"] {
5720
6318
  position: fixed;
@@ -5733,7 +6331,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5733
6331
 
5734
6332
  [data-ui="watermark"] > [data-part="mark"] {
5735
6333
  color: var(--color-fg-muted);
5736
- font-family: var(--doc-font, var(--font-sans));
6334
+ font-family: var(--doc-font, var(--font-body));
5737
6335
  font-size: var(--text-4xl);
5738
6336
  font-weight: var(--weight-bold);
5739
6337
  line-height: var(--leading-tight);
@@ -5791,7 +6389,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5791
6389
 
5792
6390
  /* === recipes/accordion.css === */
5793
6391
  /* @ui:component accordion */
5794
- /* @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 */
6392
+ /* @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 */
5795
6393
 
5796
6394
  /* ── Root ── */
5797
6395
  [data-ui="accordion"] {
@@ -5800,7 +6398,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5800
6398
 
5801
6399
  /* ── Item ── */
5802
6400
  [data-ui="accordion"] [data-part="item"] {
5803
- border-bottom: 1px solid var(--color-border);
6401
+ border-bottom: var(--border-width) solid var(--color-border);
5804
6402
  }
5805
6403
 
5806
6404
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5817,7 +6415,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5817
6415
  border: none;
5818
6416
  background: transparent;
5819
6417
  color: var(--color-fg);
5820
- font-family: var(--font-sans, system-ui, sans-serif);
6418
+ font-family: var(--font-ui);
5821
6419
  font-size: var(--text-base);
5822
6420
  font-weight: var(--weight-medium);
5823
6421
  text-align: start;
@@ -5831,8 +6429,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5831
6429
  }
5832
6430
 
5833
6431
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5834
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5835
- outline-offset: -2px;
6432
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6433
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5836
6434
  border-radius: var(--radius-sm, 0.25rem);
5837
6435
  }
5838
6436
 
@@ -5864,13 +6462,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5864
6462
 
5865
6463
  /* ── Bordered Variant ── */
5866
6464
  [data-ui="accordion"][data-bordered="true"] {
5867
- border: 1px solid var(--color-border);
6465
+ border: var(--border-width) solid var(--color-border);
5868
6466
  border-radius: var(--radius-lg);
5869
6467
  overflow: hidden;
5870
6468
  }
5871
6469
 
5872
6470
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5873
- border-bottom: 1px solid var(--color-border);
6471
+ border-bottom: var(--border-width) solid var(--color-border);
5874
6472
  }
5875
6473
 
5876
6474
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5887,7 +6485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5887
6485
 
5888
6486
  /* === recipes/alert-dialog.css === */
5889
6487
  /* @ui:component alert-dialog */
5890
- /* @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 */
6488
+ /* @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 */
5891
6489
 
5892
6490
  /* ── Root ── */
5893
6491
  [data-ui="alert-dialog"] {
@@ -5923,7 +6521,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5923
6521
  max-height: 85vh;
5924
6522
  overflow-y: auto;
5925
6523
  background: var(--color-bg);
5926
- border: 1px solid var(--color-border);
6524
+ border: var(--border-width) solid var(--color-border);
5927
6525
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
5928
6526
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
5929
6527
  opacity: 0;
@@ -5969,6 +6567,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5969
6567
  /* ── Title ── */
5970
6568
  [data-ui="alert-dialog"] [data-part="title"] {
5971
6569
  margin: 0;
6570
+ font-family: var(--font-heading);
5972
6571
  font-size: var(--text-lg, 1.125rem);
5973
6572
  font-weight: var(--weight-semibold, 600);
5974
6573
  color: var(--color-fg);
@@ -6008,7 +6607,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6008
6607
 
6009
6608
  /* === recipes/barcode.css === */
6010
6609
  /* @ui:component barcode */
6011
- /* @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 */
6610
+ /* @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 */
6012
6611
 
6013
6612
  [data-ui="barcode"] {
6014
6613
  display: inline-flex;
@@ -6035,7 +6634,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6035
6634
 
6036
6635
  [data-ui="barcode"] > [data-part="caption"] {
6037
6636
  color: var(--doc-legal-color, var(--color-fg-muted));
6038
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6637
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6039
6638
  font-size: var(--doc-legal-size);
6040
6639
  line-height: var(--leading-normal);
6041
6640
  text-align: center;
@@ -6055,7 +6654,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6055
6654
 
6056
6655
  /* === recipes/calendar.css === */
6057
6656
  /* @ui:component calendar */
6058
- /* @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 */
6657
+ /* @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 */
6059
6658
 
6060
6659
  /* ── Root ── */
6061
6660
  [data-ui="calendar"] {
@@ -6088,7 +6687,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6088
6687
  width: 28px;
6089
6688
  height: 28px;
6090
6689
  padding: 0;
6091
- border: 1px solid var(--color-border);
6690
+ border: var(--border-width) solid var(--color-border);
6092
6691
  border-radius: var(--radius-md);
6093
6692
  background: var(--color-bg);
6094
6693
  color: var(--color-fg);
@@ -6104,13 +6703,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6104
6703
 
6105
6704
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6106
6705
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6107
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6108
- outline-offset: 2px;
6706
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6707
+ outline-offset: var(--focus-ring-offset);
6109
6708
  }
6110
6709
 
6111
6710
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6112
6711
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6113
- opacity: 0.4;
6712
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6713
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6714
+ opacity: calc(var(--disabled-opacity) * 0.8);
6114
6715
  cursor: not-allowed;
6115
6716
  }
6116
6717
 
@@ -6145,11 +6746,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6145
6746
  width: 36px;
6146
6747
  height: 36px;
6147
6748
  padding: 0;
6148
- border: 1px solid transparent;
6749
+ border: var(--border-width) solid transparent;
6149
6750
  border-radius: var(--radius-full);
6150
6751
  background: transparent;
6151
6752
  color: var(--color-fg);
6152
- font-family: var(--font-sans, system-ui, sans-serif);
6753
+ font-family: var(--font-ui);
6153
6754
  font-size: var(--text-sm);
6154
6755
  cursor: pointer;
6155
6756
  transition: background var(--duration-fast) var(--ease-default),
@@ -6162,8 +6763,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6162
6763
  }
6163
6764
 
6164
6765
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6165
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6166
- outline-offset: 2px;
6766
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6767
+ outline-offset: var(--focus-ring-offset);
6167
6768
  }
6168
6769
 
6169
6770
  /* ── Today ── */
@@ -6198,7 +6799,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6198
6799
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6199
6800
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6200
6801
  [data-ui="calendar"] [data-part="day"]:disabled {
6201
- opacity: 0.5;
6802
+ opacity: var(--disabled-opacity);
6202
6803
  cursor: not-allowed;
6203
6804
  text-decoration: line-through;
6204
6805
  }
@@ -6262,7 +6863,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6262
6863
 
6263
6864
  /* === recipes/carousel.css === */
6264
6865
  /* @ui:component carousel */
6265
- /* @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 */
6866
+ /* @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 */
6266
6867
 
6267
6868
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6268
6869
  every slide is a snap target. Everything below works with no controller
@@ -6276,7 +6877,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6276
6877
  inline-size: 100%;
6277
6878
  min-inline-size: 0;
6278
6879
  max-inline-size: 100%;
6279
- font-family: var(--carousel-font, var(--font-sans));
6880
+ font-family: var(--carousel-font, var(--font-ui));
6280
6881
  }
6281
6882
 
6282
6883
  /* ── Viewport: the scroll-snap strip ── */
@@ -6302,8 +6903,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6302
6903
  }
6303
6904
 
6304
6905
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6305
- outline: 2px solid var(--color-ring);
6306
- outline-offset: 2px;
6906
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6907
+ outline-offset: var(--focus-ring-offset);
6307
6908
  }
6308
6909
 
6309
6910
  /* ── Slide: one full-width snap target ── */
@@ -6311,7 +6912,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6311
6912
  flex: 0 0 var(--carousel-slide-size, 100%);
6312
6913
  min-inline-size: 0;
6313
6914
  padding: var(--space-4);
6314
- border: 1px solid var(--color-border);
6915
+ border: var(--border-width) solid var(--color-border);
6315
6916
  border-radius: var(--radius-lg);
6316
6917
  background: var(--color-bg);
6317
6918
  color: var(--color-fg);
@@ -6340,7 +6941,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6340
6941
  min-inline-size: 2rem;
6341
6942
  min-block-size: 2rem;
6342
6943
  padding: var(--space-1) var(--space-2);
6343
- border: 1px solid var(--color-border);
6944
+ border: var(--border-width) solid var(--color-border);
6344
6945
  border-radius: var(--radius-md);
6345
6946
  background: var(--color-bg);
6346
6947
  color: var(--color-fg);
@@ -6359,14 +6960,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6359
6960
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6360
6961
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6361
6962
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6362
- outline: 2px solid var(--color-ring);
6363
- outline-offset: 2px;
6963
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6964
+ outline-offset: var(--focus-ring-offset);
6364
6965
  }
6365
6966
 
6366
6967
  /* Boundary contract "stop" — the controller disables the end button. */
6367
6968
  [data-ui="carousel"] [data-part="prev"]:disabled,
6368
6969
  [data-ui="carousel"] [data-part="next"]:disabled {
6369
- opacity: 0.4;
6970
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
6971
+ opacity: calc(var(--disabled-opacity) * 0.8);
6370
6972
  cursor: not-allowed;
6371
6973
  }
6372
6974
 
@@ -6375,7 +6977,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6375
6977
  inline-size: 0.625rem;
6376
6978
  block-size: 0.625rem;
6377
6979
  padding: 0;
6378
- border: 1px solid var(--color-border);
6980
+ border: var(--border-width) solid var(--color-border);
6379
6981
  border-radius: 50%;
6380
6982
  background: var(--color-bg-muted);
6381
6983
  cursor: pointer;
@@ -6411,7 +7013,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6411
7013
 
6412
7014
  /* === recipes/combobox.css === */
6413
7015
  /* @ui:component combobox */
6414
- /* @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 */
7016
+ /* @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 */
6415
7017
 
6416
7018
  /* ── Root ── */
6417
7019
  [data-ui="combobox"] {
@@ -6425,11 +7027,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6425
7027
  display: block;
6426
7028
  width: 100%;
6427
7029
  padding: var(--space-2) var(--space-3);
6428
- border: 1px solid var(--color-border);
7030
+ border: var(--border-width) solid var(--color-border);
6429
7031
  border-radius: var(--radius-md);
6430
7032
  background: var(--color-bg);
6431
7033
  color: var(--color-fg);
6432
- font-family: var(--font-sans, system-ui, sans-serif);
7034
+ font-family: var(--font-ui);
6433
7035
  font-size: var(--text-sm);
6434
7036
  line-height: 1.5;
6435
7037
  outline: none;
@@ -6442,8 +7044,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6442
7044
  }
6443
7045
 
6444
7046
  [data-ui="combobox"] [data-part="input"]:focus {
6445
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6446
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7047
+ border-color: var(--focus-ring-color);
7048
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6447
7049
  }
6448
7050
 
6449
7051
  /* ── Listbox ── */
@@ -6455,7 +7057,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6455
7057
  z-index: var(--z-dropdown);
6456
7058
  margin-top: var(--space-1);
6457
7059
  padding: var(--space-1);
6458
- border: 1px solid var(--color-border);
7060
+ border: var(--border-width) solid var(--color-border);
6459
7061
  border-radius: var(--radius-lg);
6460
7062
  background: var(--color-bg);
6461
7063
  box-shadow: var(--shadow-md);
@@ -6540,7 +7142,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6540
7142
 
6541
7143
  /* === recipes/command-palette.css === */
6542
7144
  /* @ui:component command-palette */
6543
- /* @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 */
7145
+ /* @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 */
6544
7146
 
6545
7147
  /* ── Root ── */
6546
7148
  [data-ui="command-palette"] {
@@ -6573,7 +7175,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6573
7175
  display: flex;
6574
7176
  flex-direction: column;
6575
7177
  background: var(--color-bg);
6576
- border: 1px solid var(--color-border);
7178
+ border: var(--border-width) solid var(--color-border);
6577
7179
  border-radius: var(--radius-xl);
6578
7180
  box-shadow: var(--shadow-xl);
6579
7181
  overflow: hidden;
@@ -6605,7 +7207,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6605
7207
  display: flex;
6606
7208
  align-items: center;
6607
7209
  padding: var(--space-3) var(--space-4);
6608
- border-bottom: 1px solid var(--color-border);
7210
+ border-bottom: var(--border-width) solid var(--color-border);
6609
7211
  }
6610
7212
 
6611
7213
  /* ── Search Input ── */
@@ -6615,7 +7217,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6615
7217
  border: none;
6616
7218
  background: transparent;
6617
7219
  color: var(--color-fg);
6618
- font-family: var(--font-sans, system-ui, sans-serif);
7220
+ font-family: var(--font-ui);
6619
7221
  font-size: var(--text-base);
6620
7222
  outline: none;
6621
7223
  }
@@ -6699,7 +7301,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6699
7301
  align-items: center;
6700
7302
  gap: var(--space-1, 0.25rem);
6701
7303
  padding: var(--space-1, 0.25rem) var(--space-2);
6702
- border: 1px solid var(--color-border);
7304
+ border: var(--border-width) solid var(--color-border);
6703
7305
  border-radius: var(--radius-sm, 0.25rem);
6704
7306
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6705
7307
  color: var(--color-fg-muted);
@@ -6728,7 +7330,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6728
7330
 
6729
7331
  /* === recipes/context-menu.css === */
6730
7332
  /* @ui:component context-menu */
6731
- /* @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 */
7333
+ /* @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 */
6732
7334
 
6733
7335
  [data-ui="context-menu"] {
6734
7336
  position: relative;
@@ -6741,12 +7343,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6741
7343
  border-radius: var(--radius-lg);
6742
7344
  background: var(--color-bg-muted);
6743
7345
  color: var(--color-fg);
6744
- font-family: var(--font-sans, system-ui, sans-serif);
7346
+ font-family: var(--font-ui);
6745
7347
  }
6746
7348
 
6747
7349
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6748
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6749
- outline-offset: var(--space-1);
7350
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7351
+ outline-offset: var(--focus-ring-offset);
6750
7352
  }
6751
7353
 
6752
7354
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6778,7 +7380,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6778
7380
  border-radius: var(--radius-md);
6779
7381
  background: transparent;
6780
7382
  color: var(--color-fg);
6781
- font-family: var(--font-sans, system-ui, sans-serif);
7383
+ font-family: var(--font-ui);
6782
7384
  font-size: var(--text-sm);
6783
7385
  font-weight: var(--weight-medium);
6784
7386
  text-align: start;
@@ -6802,15 +7404,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6802
7404
  focus additionally draws the ring, inset so it does not overlap the item
6803
7405
  above. [W3-3] */
6804
7406
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6805
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6806
- outline-offset: calc(var(--space-px) * -2);
7407
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7408
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6807
7409
  }
6808
7410
 
6809
7411
  [data-ui="context-menu"] [data-part="item"]:disabled,
6810
7412
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6811
7413
  color: var(--color-fg-muted);
6812
7414
  cursor: not-allowed;
6813
- opacity: 0.5;
7415
+ opacity: var(--disabled-opacity);
6814
7416
  }
6815
7417
 
6816
7418
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6829,7 +7431,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6829
7431
 
6830
7432
  /* === recipes/date-picker.css === */
6831
7433
  /* @ui:component date-picker */
6832
- /* @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 */
7434
+ /* @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 */
6833
7435
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6834
7436
 
6835
7437
  /* ── Root ── */
@@ -6850,11 +7452,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6850
7452
  width: 100%;
6851
7453
  padding: var(--space-2, 0.5rem) var(--space-3);
6852
7454
  padding-inline-end: var(--space-8, 2.5rem);
6853
- border: 1px solid var(--color-border);
7455
+ border: var(--border-width) solid var(--color-border);
6854
7456
  border-radius: var(--radius-md);
6855
7457
  background: var(--color-bg);
6856
7458
  color: var(--color-fg);
6857
- font-family: var(--font-sans, system-ui, sans-serif);
7459
+ font-family: var(--font-ui);
6858
7460
  font-size: var(--text-sm);
6859
7461
  line-height: 1.5;
6860
7462
  cursor: pointer;
@@ -6866,8 +7468,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6866
7468
  }
6867
7469
 
6868
7470
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6869
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6870
- outline-offset: 2px;
7471
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7472
+ outline-offset: var(--focus-ring-offset);
6871
7473
  border-color: var(--color-primary);
6872
7474
  }
6873
7475
 
@@ -6890,7 +7492,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6890
7492
  z-index: var(--z-dropdown);
6891
7493
  margin-top: var(--space-1);
6892
7494
  padding: var(--space-3);
6893
- border: 1px solid var(--color-border);
7495
+ border: var(--border-width) solid var(--color-border);
6894
7496
  border-radius: var(--radius-lg);
6895
7497
  background: var(--color-bg);
6896
7498
  box-shadow: var(--shadow-lg);
@@ -6929,7 +7531,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6929
7531
 
6930
7532
  /* === recipes/dialog.css === */
6931
7533
  /* @ui:component dialog */
6932
- /* @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 */
7534
+ /* @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 */
6933
7535
 
6934
7536
  /* ── Root ── */
6935
7537
  [data-ui="dialog"] {
@@ -6964,15 +7566,23 @@ div[data-ui="separator"][data-style="thick"]::after {
6964
7566
  width: 90%;
6965
7567
  max-height: 85vh;
6966
7568
  overflow-y: auto;
6967
- background: var(--color-bg);
6968
- border: 1px solid var(--color-border);
7569
+ background: var(--panel-bg);
7570
+ border: var(--border-width) solid var(--color-border);
6969
7571
  border-radius: var(--dialog-radius, var(--radius-xl));
7572
+ corner-shape: var(--corner-shape);
6970
7573
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
6971
7574
  opacity: 0;
6972
7575
  transition: opacity var(--duration-normal) var(--ease-out),
6973
7576
  transform var(--duration-normal) var(--ease-out);
6974
7577
  }
6975
7578
 
7579
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7580
+ [data-ui="dialog"] [data-part="panel"] {
7581
+ -webkit-backdrop-filter: var(--surface-backdrop);
7582
+ backdrop-filter: var(--surface-backdrop);
7583
+ }
7584
+ }
7585
+
6976
7586
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
6977
7587
  opacity: 1;
6978
7588
  transform: translate(-50%, -50%) scale(1);
@@ -7021,6 +7631,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7021
7631
  /* ── Title ── */
7022
7632
  [data-ui="dialog"] [data-part="title"] {
7023
7633
  margin: 0;
7634
+ font-family: var(--font-heading);
7024
7635
  font-size: var(--text-lg, 1.125rem);
7025
7636
  font-weight: var(--weight-semibold, 600);
7026
7637
  color: var(--color-fg);
@@ -7055,8 +7666,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7055
7666
  }
7056
7667
 
7057
7668
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7058
- outline: 2px solid var(--color-ring);
7059
- outline-offset: 2px;
7669
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7670
+ outline-offset: var(--focus-ring-offset);
7060
7671
  }
7061
7672
 
7062
7673
  /* ── Description ── */
@@ -7092,7 +7703,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7092
7703
 
7093
7704
  /* === recipes/drawer.css === */
7094
7705
  /* @ui:component drawer */
7095
- /* @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 */
7706
+ /* @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 */
7096
7707
 
7097
7708
  /* ── Root ── */
7098
7709
  [data-ui="drawer"] {
@@ -7127,17 +7738,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7127
7738
  flex-direction: column;
7128
7739
  width: var(--drawer-width, 400px);
7129
7740
  max-width: 100vw;
7130
- background: var(--color-bg);
7741
+ background: var(--panel-bg);
7131
7742
  border: none;
7132
7743
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7133
7744
  transition: transform var(--duration-slow) var(--ease-out);
7134
7745
  }
7135
7746
 
7747
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7748
+ [data-ui="drawer"] [data-part="panel"] {
7749
+ -webkit-backdrop-filter: var(--surface-backdrop);
7750
+ backdrop-filter: var(--surface-backdrop);
7751
+ }
7752
+ }
7753
+
7136
7754
  /* ── Side Variants ── */
7137
7755
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7138
7756
  inset-inline-start: 0;
7139
7757
  inset-inline-end: auto;
7140
- border-inline-end: 1px solid var(--color-border);
7758
+ border-inline-end: var(--border-width) solid var(--color-border);
7141
7759
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7142
7760
  transform: translateX(-100%);
7143
7761
  }
@@ -7145,7 +7763,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7145
7763
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7146
7764
  inset-inline-end: 0;
7147
7765
  inset-inline-start: auto;
7148
- border-inline-start: 1px solid var(--color-border);
7766
+ border-inline-start: var(--border-width) solid var(--color-border);
7149
7767
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7150
7768
  transform: translateX(100%);
7151
7769
  }
@@ -7199,6 +7817,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7199
7817
  /* ── Title ── */
7200
7818
  [data-ui="drawer"] [data-part="title"] {
7201
7819
  margin: 0;
7820
+ font-family: var(--font-heading);
7202
7821
  font-size: var(--text-lg, 1.125rem);
7203
7822
  font-weight: var(--weight-semibold, 600);
7204
7823
  color: var(--color-fg);
@@ -7233,8 +7852,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7233
7852
  }
7234
7853
 
7235
7854
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7236
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7237
- outline-offset: 2px;
7855
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7856
+ outline-offset: var(--focus-ring-offset);
7238
7857
  }
7239
7858
 
7240
7859
  /* ── Body ── */
@@ -7253,7 +7872,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7253
7872
  gap: var(--space-3, 0.75rem);
7254
7873
  padding: var(--space-6);
7255
7874
  padding-top: var(--space-4);
7256
- border-top: 1px solid var(--color-border);
7875
+ border-top: var(--border-width) solid var(--color-border);
7257
7876
  flex-shrink: 0;
7258
7877
  }
7259
7878
 
@@ -7267,7 +7886,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7267
7886
 
7268
7887
  /* === recipes/dropdown.css === */
7269
7888
  /* @ui:component dropdown */
7270
- /* @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 */
7889
+ /* @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 */
7271
7890
 
7272
7891
  /* ── Root ── */
7273
7892
  [data-ui="dropdown"] {
@@ -7281,11 +7900,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7281
7900
  align-items: center;
7282
7901
  gap: var(--space-2);
7283
7902
  padding: var(--space-2) var(--space-3);
7284
- border: 1px solid var(--color-border);
7903
+ border: var(--border-width) solid var(--color-border);
7285
7904
  border-radius: var(--radius-md);
7286
7905
  background: var(--color-bg);
7287
7906
  color: var(--color-fg);
7288
- font-family: var(--font-sans, system-ui, sans-serif);
7907
+ font-family: var(--font-ui);
7289
7908
  font-size: var(--text-sm);
7290
7909
  font-weight: var(--weight-medium);
7291
7910
  cursor: pointer;
@@ -7299,8 +7918,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7299
7918
  }
7300
7919
 
7301
7920
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7302
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7303
- outline-offset: 2px;
7921
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7922
+ outline-offset: var(--focus-ring-offset);
7304
7923
  }
7305
7924
 
7306
7925
  /* ── Menu ── */
@@ -7312,9 +7931,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7312
7931
  min-width: 180px;
7313
7932
  margin-top: var(--space-1);
7314
7933
  padding: var(--space-1);
7315
- border: 1px solid var(--color-border);
7934
+ border: var(--border-width) solid var(--color-border);
7316
7935
  border-radius: var(--radius-lg);
7317
- background: var(--color-bg);
7936
+ background: var(--panel-bg);
7318
7937
  box-shadow: var(--shadow-md);
7319
7938
  opacity: 0;
7320
7939
  transform: translateY(-4px);
@@ -7322,6 +7941,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7322
7941
  transform var(--duration-fast) var(--ease-out);
7323
7942
  }
7324
7943
 
7944
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7945
+ [data-ui="dropdown"] [data-part="menu"] {
7946
+ -webkit-backdrop-filter: var(--surface-backdrop);
7947
+ backdrop-filter: var(--surface-backdrop);
7948
+ }
7949
+ }
7950
+
7325
7951
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7326
7952
  opacity: 1;
7327
7953
  transform: translateY(0);
@@ -7344,7 +7970,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7344
7970
  border-radius: var(--radius-md);
7345
7971
  background: transparent;
7346
7972
  color: var(--color-fg);
7347
- font-family: var(--font-sans, system-ui, sans-serif);
7973
+ font-family: var(--font-ui);
7348
7974
  font-size: var(--text-sm);
7349
7975
  text-align: start;
7350
7976
  cursor: pointer;
@@ -7366,12 +7992,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7366
7992
  focus additionally draws the ring, inset so it does not overlap the item
7367
7993
  above. [W3-3] */
7368
7994
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7369
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7370
- outline-offset: -2px;
7995
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7996
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7371
7997
  }
7372
7998
 
7373
7999
  [data-ui="dropdown"] [data-part="item"]:disabled {
7374
- opacity: 0.5;
8000
+ opacity: var(--disabled-opacity);
7375
8001
  cursor: not-allowed;
7376
8002
  pointer-events: none;
7377
8003
  }
@@ -7424,14 +8050,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7424
8050
 
7425
8051
  /* === recipes/file-upload.css === */
7426
8052
  /* @ui:component file-upload */
7427
- /* @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 */
8053
+ /* @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 */
7428
8054
 
7429
8055
  [data-ui="file-upload"] {
7430
8056
  display: grid;
7431
8057
  gap: var(--space-4);
7432
8058
  inline-size: 100%;
7433
8059
  color: var(--color-fg);
7434
- font-family: var(--font-sans);
8060
+ font-family: var(--font-ui);
7435
8061
  }
7436
8062
 
7437
8063
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7466,14 +8092,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7466
8092
  }
7467
8093
 
7468
8094
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7469
- outline: var(--space-px) solid var(--color-ring);
7470
- outline-offset: var(--space-1);
8095
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8096
+ outline-offset: var(--focus-ring-offset);
7471
8097
  }
7472
8098
 
7473
8099
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7474
8100
  border-color: var(--color-primary);
7475
8101
  background: var(--color-primary-subtle);
7476
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8102
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7477
8103
  }
7478
8104
 
7479
8105
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7547,8 +8173,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7547
8173
  }
7548
8174
 
7549
8175
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7550
- outline: var(--space-px) solid var(--color-ring);
7551
- outline-offset: var(--space-1);
8176
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8177
+ outline-offset: var(--focus-ring-offset);
7552
8178
  }
7553
8179
 
7554
8180
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7570,7 +8196,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7570
8196
  }
7571
8197
 
7572
8198
  [data-ui="file-upload"][data-disabled] {
7573
- opacity: 0.5;
8199
+ opacity: var(--disabled-opacity);
7574
8200
  }
7575
8201
 
7576
8202
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7586,7 +8212,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7586
8212
 
7587
8213
  /* === recipes/input-otp.css === */
7588
8214
  /* @ui:component input-otp */
7589
- /* @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 */
8215
+ /* @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 */
7590
8216
 
7591
8217
  /* ── Root ── */
7592
8218
  [data-ui="input-otp"] {
@@ -7601,7 +8227,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7601
8227
  gutter. The transparent input is `inset: 0`, so it follows the box the
7602
8228
  segments settle into however many rows that takes. */
7603
8229
  max-inline-size: 100%;
7604
- font-family: var(--font-sans, system-ui, sans-serif);
8230
+ font-family: var(--font-ui);
7605
8231
  }
7606
8232
 
7607
8233
  /* ── Real input ──
@@ -7646,14 +8272,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7646
8272
  justify-content: center;
7647
8273
  inline-size: var(--input-otp-segment-size);
7648
8274
  block-size: var(--input-otp-segment-size);
7649
- border: 1px solid var(--color-border);
8275
+ border: var(--border-width) solid var(--color-border);
7650
8276
  border-radius: var(--radius-md);
7651
8277
  background: var(--color-bg);
7652
8278
  color: var(--color-fg);
7653
8279
  font-size: var(--text-lg, 1.125rem);
7654
8280
  font-variant-numeric: tabular-nums;
7655
8281
  line-height: 1;
7656
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8282
+ transition: border-color var(--duration-fast) var(--ease-default),
7657
8283
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7658
8284
  }
7659
8285
 
@@ -7665,7 +8291,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7665
8291
  /* Active (caret / selected) segment while focused */
7666
8292
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7667
8293
  border-color: var(--color-ring);
7668
- box-shadow: 0 0 0 1px var(--color-ring);
8294
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7669
8295
  }
7670
8296
 
7671
8297
  /* Blinking caret in the next-to-fill empty slot */
@@ -7713,7 +8339,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7713
8339
 
7714
8340
  /* ── Disabled ── */
7715
8341
  [data-ui="input-otp"][data-disabled] {
7716
- opacity: 0.5;
8342
+ opacity: var(--disabled-opacity);
7717
8343
  cursor: not-allowed;
7718
8344
  }
7719
8345
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7737,7 +8363,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7737
8363
 
7738
8364
  /* === recipes/menubar.css === */
7739
8365
  /* @ui:component menubar */
7740
- /* @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 */
8366
+ /* @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 */
7741
8367
 
7742
8368
  [data-ui="menubar"] {
7743
8369
  position: relative;
@@ -7755,7 +8381,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7755
8381
  border-radius: var(--radius-lg);
7756
8382
  background: var(--color-bg);
7757
8383
  color: var(--color-fg);
7758
- font-family: var(--font-sans);
8384
+ font-family: var(--font-ui);
7759
8385
  }
7760
8386
 
7761
8387
  [data-ui="menubar"] [data-part="group"] {
@@ -7797,7 +8423,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7797
8423
 
7798
8424
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7799
8425
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7800
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8426
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7801
8427
  }
7802
8428
 
7803
8429
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7832,7 +8458,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7832
8458
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7833
8459
  color: var(--color-fg-muted);
7834
8460
  cursor: not-allowed;
7835
- opacity: 0.6;
8461
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8462
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8463
+ it (1.1A-27). */
8464
+ opacity: calc(var(--disabled-opacity) * 1.2);
7836
8465
  }
7837
8466
 
7838
8467
  [data-ui="menubar"] [data-part="separator"] {
@@ -7864,7 +8493,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7864
8493
 
7865
8494
  /* === recipes/pagination.css === */
7866
8495
  /* @ui:component pagination */
7867
- /* @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 */
8496
+ /* @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 */
7868
8497
 
7869
8498
  /* ── Root ── */
7870
8499
  [data-ui="pagination"] {
@@ -7900,11 +8529,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7900
8529
  min-width: 36px;
7901
8530
  height: 36px;
7902
8531
  padding: 0 var(--space-2);
7903
- border: 1px solid var(--color-border);
8532
+ border: var(--border-width) solid var(--color-border);
7904
8533
  border-radius: var(--radius-md);
7905
8534
  background: var(--color-bg);
7906
8535
  color: var(--color-fg);
7907
- font-family: var(--font-sans, system-ui, sans-serif);
8536
+ font-family: var(--font-ui);
7908
8537
  font-size: var(--text-sm);
7909
8538
  font-weight: var(--weight-medium);
7910
8539
  cursor: pointer;
@@ -7925,8 +8554,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7925
8554
  [data-ui="pagination"] [data-part="page"]:focus-visible,
7926
8555
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
7927
8556
  [data-ui="pagination"] [data-part="next"]:focus-visible {
7928
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7929
- outline-offset: 2px;
8557
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8558
+ outline-offset: var(--focus-ring-offset);
7930
8559
  }
7931
8560
 
7932
8561
  /* ── Active page ── */
@@ -7950,7 +8579,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7950
8579
  /* ── Disabled ── */
7951
8580
  [data-ui="pagination"] [data-part="prev"]:disabled,
7952
8581
  [data-ui="pagination"] [data-part="next"]:disabled {
7953
- opacity: 0.5;
8582
+ opacity: var(--disabled-opacity);
7954
8583
  cursor: not-allowed;
7955
8584
  pointer-events: none;
7956
8585
  }
@@ -8020,7 +8649,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8020
8649
 
8021
8650
  /* === recipes/popover.css === */
8022
8651
  /* @ui:component popover */
8023
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8652
+ /* @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 */
8024
8653
 
8025
8654
  /* ── Root ── */
8026
8655
  [data-ui="popover"] {
@@ -8034,11 +8663,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8034
8663
  align-items: center;
8035
8664
  gap: var(--space-2, 0.5rem);
8036
8665
  padding: var(--space-2, 0.5rem) var(--space-3);
8037
- border: 1px solid var(--color-border);
8666
+ border: var(--border-width) solid var(--color-border);
8038
8667
  border-radius: var(--radius-md, 0.375rem);
8039
8668
  background: var(--color-bg);
8040
8669
  color: var(--color-fg);
8041
- font-family: var(--font-sans, system-ui, sans-serif);
8670
+ font-family: var(--font-ui);
8042
8671
  font-size: var(--text-sm, 0.875rem);
8043
8672
  font-weight: var(--weight-medium, 500);
8044
8673
  cursor: pointer;
@@ -8052,8 +8681,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8052
8681
  }
8053
8682
 
8054
8683
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8055
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8056
- outline-offset: 2px;
8684
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8685
+ outline-offset: var(--focus-ring-offset);
8057
8686
  }
8058
8687
 
8059
8688
  /* ── Content ── */
@@ -8062,9 +8691,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8062
8691
  z-index: var(--z-dropdown);
8063
8692
  min-width: 200px;
8064
8693
  padding: var(--space-4);
8065
- border: 1px solid var(--color-border);
8694
+ border: var(--border-width) solid var(--color-border);
8066
8695
  border-radius: var(--radius-lg);
8067
- background: var(--color-bg);
8696
+ background: var(--panel-bg);
8068
8697
  color: var(--color-fg);
8069
8698
  box-shadow: var(--shadow-md);
8070
8699
  opacity: 0;
@@ -8073,6 +8702,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8073
8702
  transform var(--duration-fast) var(--ease-default);
8074
8703
  }
8075
8704
 
8705
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8706
+ [data-ui="popover"] [data-part="content"] {
8707
+ -webkit-backdrop-filter: var(--surface-backdrop);
8708
+ backdrop-filter: var(--surface-backdrop);
8709
+ }
8710
+ }
8711
+
8076
8712
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8077
8713
  opacity: 1;
8078
8714
  transform: scale(1);
@@ -8160,8 +8796,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8160
8796
  position: absolute;
8161
8797
  width: 8px;
8162
8798
  height: 8px;
8163
- background: var(--color-bg);
8164
- border: 1px solid var(--color-border);
8799
+ background: var(--panel-bg);
8800
+ border: var(--border-width) solid var(--color-border);
8165
8801
  transform: rotate(45deg);
8166
8802
  }
8167
8803
 
@@ -8262,8 +8898,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8262
8898
  }
8263
8899
 
8264
8900
  [data-ui="popover"] [data-part="close"]:focus-visible {
8265
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8266
- outline-offset: 2px;
8901
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8902
+ outline-offset: var(--focus-ring-offset);
8267
8903
  }
8268
8904
 
8269
8905
  /* ── Motion ── */
@@ -8276,7 +8912,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8276
8912
 
8277
8913
  /* === recipes/qr-code.css === */
8278
8914
  /* @ui:component qr-code */
8279
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8915
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8280
8916
 
8281
8917
  /* ── Base ── */
8282
8918
  [data-ui="qr-code"] {
@@ -8294,7 +8930,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8294
8930
 
8295
8931
  /* ── Caption ── */
8296
8932
  [data-ui="qr-code"] [data-part="caption"] {
8297
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
8933
+ font-family: var(--doc-font, var(--font-body));
8298
8934
  font-size: var(--doc-legal-size, var(--text-xs));
8299
8935
  color: var(--doc-legal-color, var(--color-fg-muted));
8300
8936
  text-align: center;
@@ -8335,7 +8971,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8335
8971
 
8336
8972
  /* === recipes/select-custom.css === */
8337
8973
  /* @ui:component select-custom */
8338
- /* @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 */
8974
+ /* @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 */
8339
8975
 
8340
8976
  /* ── Root ── */
8341
8977
  [data-ui="select-custom"] {
@@ -8352,11 +8988,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8352
8988
  width: 100%;
8353
8989
  min-width: 180px;
8354
8990
  padding: var(--space-2) var(--space-3);
8355
- border: 1px solid var(--color-border);
8991
+ border: var(--border-width) solid var(--color-border);
8356
8992
  border-radius: var(--radius-md);
8357
8993
  background: var(--color-bg);
8358
8994
  color: var(--color-fg);
8359
- font-family: var(--font-sans, system-ui, sans-serif);
8995
+ font-family: var(--font-ui);
8360
8996
  font-size: var(--text-sm);
8361
8997
  cursor: pointer;
8362
8998
  white-space: nowrap;
@@ -8369,8 +9005,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8369
9005
  }
8370
9006
 
8371
9007
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8372
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8373
- outline-offset: 2px;
9008
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9009
+ outline-offset: var(--focus-ring-offset);
8374
9010
  }
8375
9011
 
8376
9012
  /* ── Value ── */
@@ -8406,7 +9042,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8406
9042
  z-index: var(--z-dropdown);
8407
9043
  margin-top: var(--space-1);
8408
9044
  padding: var(--space-1);
8409
- border: 1px solid var(--color-border);
9045
+ border: var(--border-width) solid var(--color-border);
8410
9046
  border-radius: var(--radius-lg);
8411
9047
  background: var(--color-bg);
8412
9048
  box-shadow: var(--shadow-md);
@@ -8430,11 +9066,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8430
9066
  padding: var(--space-2) var(--space-3);
8431
9067
  margin-bottom: var(--space-1);
8432
9068
  border: none;
8433
- border-bottom: 1px solid var(--color-border);
9069
+ border-bottom: var(--border-width) solid var(--color-border);
8434
9070
  border-radius: 0;
8435
9071
  background: transparent;
8436
9072
  color: var(--color-fg);
8437
- font-family: var(--font-sans, system-ui, sans-serif);
9073
+ font-family: var(--font-ui);
8438
9074
  font-size: var(--text-sm);
8439
9075
  outline: none;
8440
9076
  }
@@ -8528,7 +9164,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8528
9164
 
8529
9165
  /* === recipes/sheet.css === */
8530
9166
  /* @ui:component sheet */
8531
- /* @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 */
9167
+ /* @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 */
8532
9168
 
8533
9169
  /* ── Root ── */
8534
9170
  [data-ui="sheet"] {
@@ -8559,11 +9195,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8559
9195
  z-index: var(--z-modal);
8560
9196
  display: flex;
8561
9197
  flex-direction: column;
8562
- background: var(--color-bg);
9198
+ background: var(--panel-bg);
8563
9199
  box-shadow: var(--shadow-xl);
8564
9200
  transition: transform var(--duration-slow) var(--ease-out);
8565
9201
  }
8566
9202
 
9203
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9204
+ [data-ui="sheet"] [data-part="panel"] {
9205
+ -webkit-backdrop-filter: var(--surface-backdrop);
9206
+ backdrop-filter: var(--surface-backdrop);
9207
+ }
9208
+ }
9209
+
8567
9210
  /* ── Side: Bottom ── */
8568
9211
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8569
9212
  bottom: 0;
@@ -8591,7 +9234,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8591
9234
  bottom: 0;
8592
9235
  max-width: 100vw;
8593
9236
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8594
- border-inline-end: 1px solid var(--color-border);
9237
+ border-inline-end: var(--border-width) solid var(--color-border);
8595
9238
  transform: translateX(-100%);
8596
9239
  }
8597
9240
 
@@ -8602,7 +9245,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8602
9245
  bottom: 0;
8603
9246
  max-width: 100vw;
8604
9247
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8605
- border-inline-start: 1px solid var(--color-border);
9248
+ border-inline-start: var(--border-width) solid var(--color-border);
8606
9249
  transform: translateX(100%);
8607
9250
  }
8608
9251
 
@@ -8679,6 +9322,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8679
9322
  /* ── Title ── */
8680
9323
  [data-ui="sheet"] [data-part="title"] {
8681
9324
  margin: 0;
9325
+ font-family: var(--font-heading);
8682
9326
  font-size: var(--text-lg, 1.125rem);
8683
9327
  font-weight: var(--weight-semibold, 600);
8684
9328
  color: var(--color-fg);
@@ -8713,8 +9357,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8713
9357
  }
8714
9358
 
8715
9359
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8716
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8717
- outline-offset: 2px;
9360
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9361
+ outline-offset: var(--focus-ring-offset);
8718
9362
  }
8719
9363
 
8720
9364
  /* ── Body ── */
@@ -8735,7 +9379,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8735
9379
 
8736
9380
  /* === recipes/sidebar.css === */
8737
9381
  /* @ui:component sidebar */
8738
- /* @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 */
9382
+ /* @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 */
8739
9383
 
8740
9384
  /* ── Root ──
8741
9385
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8779,7 +9423,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8779
9423
  flex-direction: column;
8780
9424
  gap: var(--space-2);
8781
9425
  background: var(--sidebar-bg);
8782
- border-inline-end: 1px solid var(--color-border);
9426
+ border-inline-end: var(--border-width) solid var(--color-border);
8783
9427
  border-start-end-radius: var(--radius-lg, 0.5rem);
8784
9428
  border-end-end-radius: var(--radius-lg, 0.5rem);
8785
9429
  box-shadow: var(--shadow-xl);
@@ -8860,8 +9504,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8860
9504
  }
8861
9505
 
8862
9506
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8863
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8864
- outline-offset: 2px;
9507
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9508
+ outline-offset: var(--focus-ring-offset);
8865
9509
  }
8866
9510
 
8867
9511
  /* ── Navigation ── */
@@ -8897,8 +9541,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8897
9541
  }
8898
9542
 
8899
9543
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
8900
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8901
- outline-offset: -2px;
9544
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9545
+ outline-offset: calc(-1 * var(--focus-ring-offset));
8902
9546
  }
8903
9547
 
8904
9548
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -8925,7 +9569,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8925
9569
  [data-ui="sidebar"] [data-part="footer"] {
8926
9570
  flex-shrink: 0;
8927
9571
  padding: var(--space-3) var(--space-4);
8928
- border-block-start: 1px solid var(--color-border);
9572
+ border-block-start: var(--border-width) solid var(--color-border);
8929
9573
  }
8930
9574
 
8931
9575
  /* ── Rail (icons only) ── */
@@ -9018,7 +9662,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9018
9662
 
9019
9663
  /* === recipes/slider.css === */
9020
9664
  /* @ui:component slider */
9021
- /* @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 */
9665
+ /* @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 */
9022
9666
 
9023
9667
  /* ── Root ── */
9024
9668
  [data-ui="slider"] {
@@ -9068,28 +9712,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9068
9712
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9069
9713
  transform: translate(-50%, -50%);
9070
9714
  background: var(--color-bg, white);
9071
- border: 2px solid var(--color-primary);
9715
+ border: var(--border-width-strong) solid var(--color-primary);
9072
9716
  border-radius: var(--radius-full, 9999px);
9073
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9717
+ box-shadow: var(--shadow-sm);
9074
9718
  cursor: grab;
9075
9719
  touch-action: none;
9076
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9720
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9077
9721
  }
9078
9722
 
9079
9723
  [data-ui="slider"] [data-part="thumb"]:hover {
9080
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9081
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9724
+ box-shadow: var(--shadow-sm),
9725
+ 0 0 0 4px var(--color-primary-subtle);
9082
9726
  }
9083
9727
 
9084
9728
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9085
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9086
- outline-offset: 2px;
9729
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9730
+ outline-offset: var(--focus-ring-offset);
9087
9731
  }
9088
9732
 
9089
9733
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9090
9734
  cursor: grabbing;
9091
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9092
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9735
+ box-shadow: var(--shadow-sm),
9736
+ 0 0 0 5px var(--color-primary-subtle);
9093
9737
  }
9094
9738
 
9095
9739
  /* ── Value output ── */
@@ -9097,7 +9741,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9097
9741
  flex: 0 0 auto;
9098
9742
  min-inline-size: 3ch;
9099
9743
  color: var(--color-fg-muted);
9100
- font-family: var(--font-sans, system-ui, sans-serif);
9744
+ font-family: var(--font-ui);
9101
9745
  font-size: var(--text-sm);
9102
9746
  font-variant-numeric: tabular-nums;
9103
9747
  text-align: end;
@@ -9116,7 +9760,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9116
9760
 
9117
9761
  /* ── Disabled ── */
9118
9762
  [data-ui="slider"][data-disabled] {
9119
- opacity: 0.5;
9763
+ opacity: var(--disabled-opacity);
9120
9764
  cursor: not-allowed;
9121
9765
  pointer-events: none;
9122
9766
  }
@@ -9134,7 +9778,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9134
9778
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9135
9779
  @media (forced-colors: active) {
9136
9780
  [data-ui="slider"] [data-part="track"] {
9137
- border: 1px solid ButtonText;
9781
+ border: var(--border-width) solid ButtonText;
9138
9782
  }
9139
9783
 
9140
9784
  [data-ui="slider"] [data-part="range"] {
@@ -9145,7 +9789,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9145
9789
  [data-ui="slider"] [data-part="thumb"] {
9146
9790
  forced-color-adjust: none;
9147
9791
  background: ButtonText;
9148
- border: 1px solid ButtonFace;
9792
+ border: var(--border-width) solid ButtonFace;
9149
9793
  }
9150
9794
 
9151
9795
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9155,7 +9799,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9155
9799
 
9156
9800
  /* === recipes/table.css === */
9157
9801
  /* @ui:component table */
9158
- /* @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 */
9802
+ /* @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 */
9159
9803
 
9160
9804
  /* ── Root ── */
9161
9805
  [data-ui="table"] {
@@ -9181,7 +9825,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9181
9825
  width: 100%;
9182
9826
  border-collapse: separate;
9183
9827
  border-spacing: 0;
9184
- font-family: var(--font-sans, system-ui, sans-serif);
9828
+ font-family: var(--font-body);
9185
9829
  }
9186
9830
 
9187
9831
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9203,7 +9847,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9203
9847
  font-weight: var(--weight-semibold);
9204
9848
  color: var(--color-fg-muted);
9205
9849
  background: var(--color-bg);
9206
- border-bottom: 2px solid var(--color-border);
9850
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9207
9851
  white-space: nowrap;
9208
9852
  user-select: none;
9209
9853
  }
@@ -9261,8 +9905,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9261
9905
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9262
9906
  [data-ui="table"] [data-part="th"]:focus-visible,
9263
9907
  [data-ui="table"] [data-part="td"]:focus-visible {
9264
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9265
- outline-offset: -2px;
9908
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9909
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9266
9910
  }
9267
9911
 
9268
9912
  /* ── Data Cell ── */
@@ -9270,7 +9914,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9270
9914
  padding: var(--space-3) var(--space-4);
9271
9915
  font-size: var(--text-sm);
9272
9916
  color: var(--color-fg);
9273
- border-bottom: 1px solid var(--color-border);
9917
+ border-bottom: var(--border-width) solid var(--color-border);
9274
9918
  background: var(--color-bg);
9275
9919
  transition: background var(--duration-fast) var(--ease-default);
9276
9920
  }
@@ -9299,31 +9943,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9299
9943
  Static fallback via nth-child; once the controller stamps data-stripe on the
9300
9944
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9301
9945
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9302
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
9946
+ background: var(--stripe-bg);
9303
9947
  }
9304
9948
 
9305
9949
  [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"] {
9306
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
9950
+ background: var(--stripe-bg);
9307
9951
  }
9308
9952
 
9309
9953
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9310
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
9954
+ background: var(--stripe-bg);
9311
9955
  }
9312
9956
 
9313
9957
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9314
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
9958
+ background: var(--stripe-bg);
9315
9959
  }
9316
9960
 
9317
9961
  /* ── Bordered Variant ── */
9318
9962
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9319
- border: 1px solid var(--color-border);
9963
+ border: var(--border-width) solid var(--color-border);
9320
9964
  border-radius: var(--radius-md, 0.375rem);
9321
9965
  overflow: hidden;
9322
9966
  }
9323
9967
 
9324
9968
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9325
9969
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9326
- border: 1px solid var(--color-border);
9970
+ border: var(--border-width) solid var(--color-border);
9327
9971
  }
9328
9972
 
9329
9973
  /* ── Size: Small ── */
@@ -9351,7 +9995,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9351
9995
  /* ── Footer ── */
9352
9996
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9353
9997
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9354
- border-top: 2px solid var(--color-border);
9998
+ border-top: var(--border-width-strong) solid var(--color-border);
9355
9999
  border-bottom: none;
9356
10000
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9357
10001
  }
@@ -9477,7 +10121,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9477
10121
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9478
10122
  padding: var(--space-1) var(--space-2);
9479
10123
  background: var(--color-bg);
9480
- border-bottom: 1px solid var(--color-border);
10124
+ border-bottom: var(--border-width) solid var(--color-border);
9481
10125
  }
9482
10126
 
9483
10127
  [data-ui="table"] [data-part="filter-input"],
@@ -9489,14 +10133,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9489
10133
  font-size: var(--text-xs);
9490
10134
  color: var(--color-fg);
9491
10135
  background: var(--color-bg);
9492
- border: 1px solid var(--color-border);
10136
+ border: var(--border-width) solid var(--color-border);
9493
10137
  border-radius: var(--radius-sm);
9494
10138
  }
9495
10139
 
9496
10140
  [data-ui="table"] [data-part="filter-input"]:focus,
9497
10141
  [data-ui="table"] [data-part="filter"]:focus {
9498
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9499
- outline-offset: -1px;
10142
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10143
+ outline-offset: calc(-1 * var(--border-width));
9500
10144
  border-color: var(--color-primary);
9501
10145
  }
9502
10146
 
@@ -9517,7 +10161,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9517
10161
  text-align: inherit;
9518
10162
  color: var(--color-fg);
9519
10163
  background: var(--color-bg);
9520
- border: 1px solid var(--color-primary);
10164
+ border: var(--border-width) solid var(--color-primary);
9521
10165
  border-radius: var(--radius-sm);
9522
10166
  outline: none;
9523
10167
  }
@@ -9570,11 +10214,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9570
10214
  }
9571
10215
 
9572
10216
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9573
- border-block-start: 2px solid var(--color-primary);
10217
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9574
10218
  }
9575
10219
 
9576
10220
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9577
- border-block-end: 2px solid var(--color-primary);
10221
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9578
10222
  }
9579
10223
 
9580
10224
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9582,11 +10226,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9582
10226
  }
9583
10227
 
9584
10228
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9585
- border-inline-start: 2px solid var(--color-primary);
10229
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9586
10230
  }
9587
10231
 
9588
10232
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9589
- border-inline-end: 2px solid var(--color-primary);
10233
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9590
10234
  }
9591
10235
 
9592
10236
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9659,11 +10303,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9659
10303
  }
9660
10304
 
9661
10305
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9662
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10306
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9663
10307
  }
9664
10308
 
9665
10309
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9666
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10310
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9667
10311
  }
9668
10312
 
9669
10313
  /* ── Column Visibility ── */
@@ -9735,7 +10379,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9735
10379
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9736
10380
  display: block;
9737
10381
  margin-block-end: var(--space-3);
9738
- border: 1px solid var(--color-border);
10382
+ border: var(--border-width) solid var(--color-border);
9739
10383
  border-radius: var(--radius-md);
9740
10384
  background: var(--color-bg);
9741
10385
  overflow: hidden;
@@ -9749,7 +10393,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9749
10393
  gap: var(--space-4);
9750
10394
  text-align: end;
9751
10395
  border-bottom: none;
9752
- border-block-end: 1px solid var(--color-border);
10396
+ border-block-end: var(--border-width) solid var(--color-border);
9753
10397
  }
9754
10398
 
9755
10399
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9846,7 +10490,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9846
10490
 
9847
10491
  /* === recipes/tabs.css === */
9848
10492
  /* @ui:component tabs */
9849
- /* @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 */
10493
+ /* @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 */
9850
10494
 
9851
10495
  /* ── Root ── */
9852
10496
  [data-ui="tabs"] {
@@ -9875,7 +10519,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9875
10519
  border: none;
9876
10520
  background: transparent;
9877
10521
  color: var(--color-fg-muted);
9878
- font-family: var(--font-sans, system-ui, sans-serif);
10522
+ font-family: var(--font-ui);
9879
10523
  font-size: var(--text-sm);
9880
10524
  font-weight: var(--weight-medium);
9881
10525
  cursor: pointer;
@@ -9890,8 +10534,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9890
10534
  }
9891
10535
 
9892
10536
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9893
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9894
- outline-offset: -2px;
10537
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10538
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9895
10539
  border-radius: var(--radius-md);
9896
10540
  }
9897
10541
 
@@ -9901,12 +10545,12 @@ div[data-ui="separator"][data-style="thick"]::after {
9901
10545
 
9902
10546
  /* ── Underline Variant ── */
9903
10547
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
9904
- border-bottom: 1px solid var(--color-border);
10548
+ border-bottom: var(--border-width) solid var(--color-border);
9905
10549
  gap: 0;
9906
10550
  }
9907
10551
 
9908
10552
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
9909
- border-bottom: 2px solid transparent;
10553
+ border-bottom: var(--border-width-strong) solid transparent;
9910
10554
  margin-bottom: -1px;
9911
10555
  border-radius: 0;
9912
10556
  }
@@ -9938,17 +10582,17 @@ div[data-ui="separator"][data-style="thick"]::after {
9938
10582
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
9939
10583
  background: var(--color-bg);
9940
10584
  color: var(--color-fg);
9941
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10585
+ box-shadow: var(--shadow-xs);
9942
10586
  }
9943
10587
 
9944
10588
  /* ── Enclosed Variant ── */
9945
10589
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
9946
- border-bottom: 1px solid var(--color-border);
10590
+ border-bottom: var(--border-width) solid var(--color-border);
9947
10591
  gap: 0;
9948
10592
  }
9949
10593
 
9950
10594
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
9951
- border: 1px solid transparent;
10595
+ border: var(--border-width) solid transparent;
9952
10596
  border-bottom: none;
9953
10597
  border-radius: var(--radius-md) var(--radius-md) 0 0;
9954
10598
  margin-bottom: -1px;
@@ -9993,8 +10637,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9993
10637
  @media (forced-colors: active) {
9994
10638
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
9995
10639
  /* An outline the OS preserves, on every variant. */
9996
- outline: 2px solid Highlight;
9997
- outline-offset: -2px;
10640
+ outline: var(--border-width-strong) solid Highlight;
10641
+ outline-offset: calc(-1 * var(--border-width-strong));
9998
10642
  }
9999
10643
 
10000
10644
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10009,7 +10653,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10009
10653
 
10010
10654
  /* === recipes/tag-input.css === */
10011
10655
  /* @ui:component tag-input */
10012
- /* @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 */
10656
+ /* @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 */
10013
10657
 
10014
10658
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10015
10659
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10030,7 +10674,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10030
10674
  gap: var(--space-1h);
10031
10675
  width: 100%;
10032
10676
  padding: var(--space-1h) var(--space-2);
10033
- border: 1px solid var(--color-border);
10677
+ border: var(--border-width) solid var(--color-border);
10034
10678
  border-radius: var(--radius-md);
10035
10679
  background: var(--color-bg);
10036
10680
  list-style: none;
@@ -10039,8 +10683,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10039
10683
  }
10040
10684
 
10041
10685
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10042
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10043
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10686
+ border-color: var(--focus-ring-color);
10687
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10044
10688
  }
10045
10689
 
10046
10690
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10051,7 +10695,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10051
10695
  border: none;
10052
10696
  background: transparent;
10053
10697
  color: var(--color-fg);
10054
- font-family: var(--font-sans, system-ui, sans-serif);
10698
+ font-family: var(--font-ui);
10055
10699
  font-size: var(--text-sm);
10056
10700
  line-height: 1.5;
10057
10701
  outline: none;
@@ -10070,7 +10714,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10070
10714
  z-index: var(--z-dropdown);
10071
10715
  margin-top: var(--space-1);
10072
10716
  padding: var(--space-1);
10073
- border: 1px solid var(--color-border);
10717
+ border: var(--border-width) solid var(--color-border);
10074
10718
  border-radius: var(--radius-lg);
10075
10719
  background: var(--color-bg);
10076
10720
  box-shadow: var(--shadow-md);
@@ -10117,7 +10761,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10117
10761
 
10118
10762
  /* === recipes/toast.css === */
10119
10763
  /* @ui:component toast */
10120
- /* @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 */
10764
+ /* @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 */
10121
10765
 
10122
10766
  /* ── Container ── */
10123
10767
  [data-ui="toast"][data-part="container"] {
@@ -10166,8 +10810,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10166
10810
  max-width: 380px;
10167
10811
  width: max-content;
10168
10812
  padding: var(--space-3) var(--space-4);
10169
- background: var(--color-bg);
10170
- border: 1px solid var(--color-border);
10813
+ background: var(--panel-bg);
10814
+ border: var(--border-width) solid var(--color-border);
10171
10815
  border-radius: var(--radius-lg);
10172
10816
  box-shadow: var(--shadow-lg);
10173
10817
  pointer-events: auto;
@@ -10177,6 +10821,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10177
10821
  transform var(--duration-normal) var(--ease-out);
10178
10822
  }
10179
10823
 
10824
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10825
+ [data-ui="toast"] [data-part="toast"] {
10826
+ -webkit-backdrop-filter: var(--surface-backdrop);
10827
+ backdrop-filter: var(--surface-backdrop);
10828
+ }
10829
+ }
10830
+
10180
10831
  /* ── State: Entering ── */
10181
10832
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10182
10833
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10216,7 +10867,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10216
10867
 
10217
10868
  /* ── Tone Variants ── */
10218
10869
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10219
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10870
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10220
10871
  }
10221
10872
 
10222
10873
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10224,7 +10875,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10224
10875
  }
10225
10876
 
10226
10877
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10227
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10878
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10228
10879
  }
10229
10880
 
10230
10881
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10232,7 +10883,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10232
10883
  }
10233
10884
 
10234
10885
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10235
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10886
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10236
10887
  }
10237
10888
 
10238
10889
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10254,7 +10905,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10254
10905
  /* ── Message ── */
10255
10906
  [data-ui="toast"] [data-part="message"] {
10256
10907
  flex: 1;
10257
- font-family: var(--font-sans, system-ui, sans-serif);
10908
+ font-family: var(--font-ui);
10258
10909
  font-size: var(--text-sm);
10259
10910
  font-weight: var(--weight-medium);
10260
10911
  color: var(--color-fg);
@@ -10265,11 +10916,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10265
10916
  [data-ui="toast"] [data-part="action"] {
10266
10917
  flex-shrink: 0;
10267
10918
  padding: var(--space-1, 0.25rem) var(--space-2);
10268
- border: 1px solid var(--color-border);
10919
+ border: var(--border-width) solid var(--color-border);
10269
10920
  border-radius: var(--radius-md, 0.375rem);
10270
10921
  background: transparent;
10271
10922
  color: var(--color-fg);
10272
- font-family: var(--font-sans, system-ui, sans-serif);
10923
+ font-family: var(--font-ui);
10273
10924
  font-size: var(--text-xs, 0.75rem);
10274
10925
  font-weight: var(--weight-medium);
10275
10926
  cursor: pointer;
@@ -10282,8 +10933,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10282
10933
  }
10283
10934
 
10284
10935
  [data-ui="toast"] [data-part="action"]:focus-visible {
10285
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10286
- outline-offset: 2px;
10936
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10937
+ outline-offset: var(--focus-ring-offset);
10287
10938
  }
10288
10939
 
10289
10940
  /* ── Close Button ── */
@@ -10309,8 +10960,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10309
10960
  }
10310
10961
 
10311
10962
  [data-ui="toast"] [data-part="close"]:focus-visible {
10312
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10313
- outline-offset: 2px;
10963
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10964
+ outline-offset: var(--focus-ring-offset);
10314
10965
  }
10315
10966
 
10316
10967
  /* ── Motion ── */
@@ -10323,14 +10974,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10323
10974
 
10324
10975
  /* === recipes/toggle-group.css === */
10325
10976
  /* @ui:component toggle-group */
10326
- /* @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 */
10977
+ /* @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 */
10327
10978
 
10328
10979
  /* ── Root: a segmented row of toggle buttons ── */
10329
10980
  [data-ui="toggle-group"] {
10330
10981
  display: inline-flex;
10331
10982
  gap: var(--space-1);
10332
10983
  padding: var(--space-1);
10333
- border: 1px solid var(--color-border);
10984
+ border: var(--border-width) solid var(--color-border);
10334
10985
  border-radius: var(--radius-md);
10335
10986
  background: var(--color-bg);
10336
10987
  }
@@ -10345,7 +10996,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10345
10996
  border-radius: var(--radius-md);
10346
10997
  background: transparent;
10347
10998
  color: var(--color-fg-muted);
10348
- font-family: var(--toggle-group-font, var(--font-sans));
10999
+ font-family: var(--toggle-group-font, var(--font-ui));
10349
11000
  font-size: var(--text-sm);
10350
11001
  font-weight: var(--weight-medium);
10351
11002
  line-height: 1;
@@ -10386,13 +11037,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10386
11037
 
10387
11038
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10388
11039
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10389
- outline: 2px solid var(--color-ring);
10390
- outline-offset: 2px;
11040
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11041
+ outline-offset: var(--focus-ring-offset);
10391
11042
  }
10392
11043
 
10393
11044
  /* ── Disabled control ── */
10394
11045
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10395
- opacity: 0.5;
11046
+ opacity: var(--disabled-opacity);
10396
11047
  cursor: not-allowed;
10397
11048
  }
10398
11049
 
@@ -10405,7 +11056,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10405
11056
 
10406
11057
  /* === recipes/tooltip.css === */
10407
11058
  /* @ui:component tooltip */
10408
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11059
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10409
11060
 
10410
11061
  /* ── Root ── */
10411
11062
  [data-ui="tooltip"] {
@@ -10426,7 +11077,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10426
11077
  color: var(--color-bg);
10427
11078
  border-radius: var(--radius-md);
10428
11079
  padding: var(--space-1h, 0.375rem) var(--space-2);
10429
- font-family: var(--font-sans, system-ui, sans-serif);
11080
+ font-family: var(--font-ui);
10430
11081
  font-size: var(--text-xs, 0.75rem);
10431
11082
  line-height: 1.4;
10432
11083
  white-space: nowrap;
@@ -10437,6 +11088,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10437
11088
  transform var(--duration-fast) var(--ease-default);
10438
11089
  }
10439
11090
 
11091
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11092
+ [data-ui="tooltip"] [data-part="content"] {
11093
+ -webkit-backdrop-filter: var(--surface-backdrop);
11094
+ backdrop-filter: var(--surface-backdrop);
11095
+ }
11096
+ }
11097
+
10440
11098
  /* Default position (top) when no variant is specified */
10441
11099
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10442
11100
  bottom: 100%;
@@ -10552,7 +11210,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10552
11210
 
10553
11211
  /* === recipes/tree-view.css === */
10554
11212
  /* @ui:component tree-view */
10555
- /* @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 */
11213
+ /* @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 */
10556
11214
 
10557
11215
  [data-ui="tree-view"],
10558
11216
  [data-ui="tree-view"] [data-part="group"] {
@@ -10565,7 +11223,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10565
11223
  inline-size: 100%;
10566
11224
  padding: var(--space-1);
10567
11225
  color: var(--color-fg);
10568
- font-family: var(--font-sans);
11226
+ font-family: var(--font-ui);
10569
11227
  font-size: var(--text-sm);
10570
11228
  }
10571
11229
 
@@ -10593,8 +11251,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10593
11251
  }
10594
11252
 
10595
11253
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10596
- outline: var(--space-px) solid var(--color-ring);
10597
- outline-offset: var(--space-px);
11254
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11255
+ outline-offset: var(--focus-ring-offset);
10598
11256
  }
10599
11257
 
10600
11258
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10633,7 +11291,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10633
11291
 
10634
11292
  /* === patterns/auth-form.css === */
10635
11293
  /* @ui:component auth-form */
10636
- /* @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 */
11294
+ /* @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 */
10637
11295
 
10638
11296
  /* ── Root Container ── */
10639
11297
  [data-ui="auth-form"] {
@@ -10641,7 +11299,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10641
11299
  align-items: center;
10642
11300
  justify-content: center;
10643
11301
  width: 100%;
10644
- font-family: var(--font-sans);
11302
+ font-family: var(--font-body);
10645
11303
  }
10646
11304
 
10647
11305
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10673,9 +11331,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10673
11331
 
10674
11332
  [data-ui="auth-form"] [data-part="title"] {
10675
11333
  margin: 0;
11334
+ font-family: var(--font-heading);
10676
11335
  font-size: var(--text-xl);
10677
- font-weight: var(--weight-bold);
10678
- line-height: var(--leading-tight);
11336
+ font-weight: var(--heading-weight);
11337
+ letter-spacing: var(--heading-tracking);
11338
+ text-transform: var(--heading-transform);
11339
+ font-variant-caps: var(--heading-caps);
11340
+ line-height: var(--heading-leading);
10679
11341
  color: var(--color-fg);
10680
11342
  }
10681
11343
 
@@ -10692,7 +11354,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10692
11354
  margin: var(--space-4) var(--space-6) 0;
10693
11355
  padding: var(--space-3);
10694
11356
  background: var(--color-destructive-subtle);
10695
- border: 1px solid var(--color-destructive);
11357
+ border: var(--border-width) solid var(--color-destructive);
10696
11358
  border-radius: var(--radius-lg);
10697
11359
  color: var(--color-destructive);
10698
11360
  font-size: var(--text-sm);
@@ -10770,13 +11432,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10770
11432
  }
10771
11433
 
10772
11434
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10773
- text-decoration: underline;
11435
+ text-decoration-line: var(--link-decoration);
10774
11436
  color: var(--color-primary-hover);
10775
11437
  }
10776
11438
 
10777
11439
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10778
- outline: 2px solid var(--color-ring);
10779
- outline-offset: 2px;
11440
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11441
+ outline-offset: var(--focus-ring-offset);
10780
11442
  border-radius: var(--radius-sm, 0.25rem);
10781
11443
  }
10782
11444
 
@@ -10904,8 +11566,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10904
11566
  max-width: var(--auth-form-max-width, 400px);
10905
11567
  border-radius: var(--card-radius, var(--radius-lg));
10906
11568
  box-shadow: var(--card-shadow, var(--shadow-sm));
10907
- border-inline-start: 1px solid var(--card-border, var(--color-border));
10908
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11569
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11570
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
10909
11571
  }
10910
11572
  }
10911
11573
 
@@ -10920,7 +11582,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10920
11582
 
10921
11583
  /* === patterns/crud-table.css === */
10922
11584
  /* @ui:component crud-table */
10923
- /* @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 */
11585
+ /* @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 */
10924
11586
 
10925
11587
  /* ── Root ── */
10926
11588
  [data-ui="crud-table"] {
@@ -10928,7 +11590,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10928
11590
  flex-direction: column;
10929
11591
  gap: var(--space-4);
10930
11592
  width: 100%;
10931
- font-family: var(--font-sans, system-ui, sans-serif);
11593
+ font-family: var(--font-body);
10932
11594
  }
10933
11595
 
10934
11596
  /* ── Toolbar ── */
@@ -10986,7 +11648,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10986
11648
  gap: var(--space-3);
10987
11649
  padding: var(--space-3) var(--space-4);
10988
11650
  background: var(--color-bg-subtle);
10989
- border: 1px solid var(--color-border);
11651
+ border: var(--border-width) solid var(--color-border);
10990
11652
  border-radius: var(--radius-md);
10991
11653
  }
10992
11654
 
@@ -11001,7 +11663,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11001
11663
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11002
11664
  width: 100%;
11003
11665
  overflow-x: auto;
11004
- border: 1px solid var(--color-border);
11666
+ border: var(--border-width) solid var(--color-border);
11005
11667
  border-radius: var(--radius-lg);
11006
11668
  background: var(--color-bg);
11007
11669
  }
@@ -11031,7 +11693,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11031
11693
  padding: var(--space-8) var(--space-4);
11032
11694
  text-align: center;
11033
11695
  min-height: 240px;
11034
- border: 1px dashed var(--color-border);
11696
+ border: var(--border-width) dashed var(--color-border);
11035
11697
  border-radius: var(--radius-lg);
11036
11698
  background: var(--color-bg);
11037
11699
  }
@@ -11144,7 +11806,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11144
11806
 
11145
11807
  /* === patterns/dashboard-shell.css === */
11146
11808
  /* @ui:component dashboard-shell */
11147
- /* @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 */
11809
+ /* @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 */
11148
11810
 
11149
11811
  /* ── Shell Grid Layout ──
11150
11812
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11169,7 +11831,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11169
11831
  "footer";
11170
11832
  min-height: 100vh;
11171
11833
  background: var(--color-bg);
11172
- font-family: var(--font-sans);
11834
+ font-family: var(--font-body);
11173
11835
  color: var(--color-fg);
11174
11836
  }
11175
11837
 
@@ -11193,7 +11855,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11193
11855
  gap: var(--space-2);
11194
11856
  padding: var(--space-4);
11195
11857
  background: var(--color-bg-subtle);
11196
- border-inline-end: 1px solid var(--color-border);
11858
+ border-inline-end: var(--border-width) solid var(--color-border);
11197
11859
  overflow-y: auto;
11198
11860
  position: fixed;
11199
11861
  top: 0;
@@ -11213,7 +11875,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11213
11875
 
11214
11876
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11215
11877
  border-inline-end: none;
11216
- border-inline-start: 1px solid var(--color-border);
11878
+ border-inline-start: var(--border-width) solid var(--color-border);
11217
11879
  inset-inline-start: auto;
11218
11880
  inset-inline-end: 0;
11219
11881
  transform: translateX(100%);
@@ -11288,7 +11950,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11288
11950
  gap: var(--space-3);
11289
11951
  padding: var(--space-2) var(--space-3);
11290
11952
  border-radius: var(--radius-md);
11291
- font-family: var(--font-sans);
11953
+ font-family: var(--font-ui);
11292
11954
  font-size: var(--text-sm);
11293
11955
  font-weight: var(--weight-medium);
11294
11956
  line-height: var(--leading-normal);
@@ -11307,8 +11969,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11307
11969
  }
11308
11970
 
11309
11971
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11310
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11311
- outline-offset: -2px;
11972
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11973
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11312
11974
  }
11313
11975
 
11314
11976
  /* ── Nav Item Active ── */
@@ -11355,7 +12017,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11355
12017
  gap: var(--space-2);
11356
12018
  padding: 0 var(--space-3);
11357
12019
  background: var(--color-bg);
11358
- border-bottom: 1px solid var(--color-border);
12020
+ border-bottom: var(--border-width) solid var(--color-border);
11359
12021
  position: sticky;
11360
12022
  top: 0;
11361
12023
  z-index: var(--z-sticky);
@@ -11436,7 +12098,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11436
12098
  align-items: center;
11437
12099
  gap: var(--space-3);
11438
12100
  padding: var(--space-4) var(--space-6);
11439
- border-top: 1px solid var(--color-border);
12101
+ border-top: var(--border-width) solid var(--color-border);
11440
12102
  font-size: var(--text-xs);
11441
12103
  color: var(--color-fg-muted);
11442
12104
  }
@@ -11519,7 +12181,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11519
12181
 
11520
12182
  /* === patterns/document.css === */
11521
12183
  /* @ui:component document */
11522
- /* @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 */
12184
+ /* @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 */
11523
12185
 
11524
12186
  /* ── Page Rules ── */
11525
12187
  @page {
@@ -11559,14 +12221,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11559
12221
  max-width: var(--doc-max-width);
11560
12222
  margin: var(--space-4) auto;
11561
12223
  padding: var(--space-6) var(--space-4);
11562
- background: var(--color-bg, #fff);
12224
+ background-color: var(--color-bg, #fff);
12225
+ background-image: var(--texture-page);
11563
12226
  color: var(--color-fg);
11564
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12227
+ font-family: var(--doc-font, var(--font-body));
11565
12228
  font-size: var(--doc-font-size);
11566
12229
  line-height: var(--doc-line-height);
11567
- box-shadow: var(--shadow-lg,
11568
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11569
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12230
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12231
+ colour no theme could reach. --shadow-lg is always defined by the token
12232
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12233
+ than re-tokenised. */
12234
+ box-shadow: var(--shadow-lg);
11570
12235
  border-radius: 0;
11571
12236
  position: relative;
11572
12237
  }
@@ -11582,7 +12247,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11582
12247
  [data-ui="document"] > [data-part="header"] {
11583
12248
  margin-block-end: var(--doc-section-gap);
11584
12249
  padding-block-end: var(--doc-component-gap);
11585
- border-block-end: 1px solid var(--color-border);
12250
+ border-block-end: var(--border-width) solid var(--color-border);
11586
12251
  }
11587
12252
 
11588
12253
  /* ── Body ── */
@@ -11592,13 +12257,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11592
12257
  gap: var(--doc-section-gap);
11593
12258
  }
11594
12259
 
12260
+ /* ── Headings ──
12261
+ The document's own heading face and weight (1.1A-21): a print theme sets
12262
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12263
+ from the body copy (document-serif's Times titles over Georgia text). Both
12264
+ default to the page's heading role in tokens/document.css, and each falls
12265
+ back to what a heading rendered before the tokens had a reader. A heading
12266
+ that carries its own data-weight keeps it — that is the author asking. */
12267
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12268
+ font-family: var(--doc-heading-font, var(--font-body));
12269
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12270
+ }
12271
+
11595
12272
  /* ── Running footer ──
11596
12273
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11597
12274
  [data-ui="document"] > [data-part="doc-footer"],
11598
12275
  [data-ui="document"] > [data-part="footer"] {
11599
12276
  margin-block-start: var(--doc-section-gap);
11600
12277
  padding-block-start: var(--doc-component-gap);
11601
- border-block-start: 1px solid var(--color-border);
12278
+ border-block-start: var(--border-width) solid var(--color-border);
11602
12279
  font-size: var(--doc-legal-size);
11603
12280
  color: var(--doc-legal-color);
11604
12281
  }
@@ -11636,7 +12313,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11636
12313
 
11637
12314
  /* ── Variant: Report ── */
11638
12315
  [data-ui="document"][data-variant="report"] {
11639
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12316
+ /* A report is serif-set by definition. It re-points the document's own font
12317
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12318
+ (key-value, callout, signature — all of which read --doc-font) follows the
12319
+ report into serif instead of staying sans inside a serif page. `report` is
12320
+ the author asking for serif; a theme that wants its own document face
12321
+ declares --doc-font at :root, which this variant deliberately outranks. */
12322
+ --doc-font: Georgia, 'Times New Roman', serif;
11640
12323
  line-height: 1.6;
11641
12324
  }
11642
12325
 
@@ -11731,7 +12414,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11731
12414
  z-index: var(--z-raised);
11732
12415
  margin-block-end: 0;
11733
12416
  padding-block-end: var(--doc-running-gap);
11734
- border-block-end: 1px solid var(--doc-print-border-color);
12417
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11735
12418
  background: var(--doc-bg);
11736
12419
  transform: translateZ(0);
11737
12420
  }
@@ -11747,7 +12430,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11747
12430
  z-index: var(--z-raised);
11748
12431
  margin-block-start: 0;
11749
12432
  padding-block-start: var(--doc-running-gap);
11750
- border-block-start: 1px solid var(--doc-print-border-color);
12433
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11751
12434
  background: var(--doc-bg);
11752
12435
  transform: translateZ(0);
11753
12436
  }
@@ -11776,7 +12459,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11776
12459
 
11777
12460
  /* === patterns/empty-state.css === */
11778
12461
  /* @ui:component empty-state */
11779
- /* @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 */
12462
+ /* @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 */
11780
12463
 
11781
12464
  /* ── Root ── */
11782
12465
  [data-ui="empty-state"] {
@@ -11787,7 +12470,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11787
12470
  text-align: center;
11788
12471
  padding: var(--space-8) var(--space-6);
11789
12472
  gap: var(--space-3);
11790
- font-family: var(--font-sans, system-ui, sans-serif);
12473
+ font-family: var(--font-body);
11791
12474
  }
11792
12475
 
11793
12476
  /* ── Icon ── */
@@ -11810,10 +12493,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11810
12493
 
11811
12494
  /* ── Title ── */
11812
12495
  [data-ui="empty-state"] [data-part="title"] {
11813
- font-family: var(--font-sans, system-ui, sans-serif);
12496
+ font-family: var(--font-heading);
11814
12497
  font-size: var(--text-lg);
11815
12498
  font-weight: var(--weight-semibold);
11816
- line-height: var(--leading-tight);
12499
+ letter-spacing: var(--heading-tracking);
12500
+ text-transform: var(--heading-transform);
12501
+ font-variant-caps: var(--heading-caps);
12502
+ line-height: var(--heading-leading);
11817
12503
  color: var(--color-fg);
11818
12504
  margin: 0;
11819
12505
  }
@@ -11911,7 +12597,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11911
12597
 
11912
12598
  /* === patterns/feature-grid.css === */
11913
12599
  /* @ui:component feature-grid */
11914
- /* @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 */
12600
+ /* @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 */
11915
12601
 
11916
12602
  /* ── Root ──
11917
12603
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -11921,7 +12607,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11921
12607
  gap: var(--space-4);
11922
12608
  padding-block: var(--space-12);
11923
12609
  padding-inline: var(--space-4);
11924
- font-family: var(--font-sans, system-ui, sans-serif);
12610
+ font-family: var(--font-body);
11925
12611
  color: var(--color-fg);
11926
12612
  background: var(--color-bg);
11927
12613
  }
@@ -12063,7 +12749,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12063
12749
  max-inline-size: var(--measure-narrow);
12064
12750
  margin-inline: auto;
12065
12751
  padding-block: var(--space-8);
12066
- font-family: var(--font-sans);
12752
+ font-family: var(--font-body);
12067
12753
  }
12068
12754
 
12069
12755
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12083,7 +12769,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12083
12769
 
12084
12770
  /* === patterns/hero.css === */
12085
12771
  /* @ui:component hero */
12086
- /* @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 */
12772
+ /* @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 */
12087
12773
 
12088
12774
  /* ── Root ──
12089
12775
  A one-column grid by default; the layout variants only change how that grid
@@ -12097,9 +12783,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12097
12783
  gap: var(--space-4);
12098
12784
  padding-block: var(--space-12);
12099
12785
  padding-inline: var(--space-4);
12100
- font-family: var(--font-sans, system-ui, sans-serif);
12786
+ font-family: var(--font-body);
12101
12787
  color: var(--color-fg);
12102
- background: var(--color-bg);
12788
+ background-color: var(--color-bg);
12789
+ background-image: var(--texture-surface);
12103
12790
  }
12104
12791
 
12105
12792
  /* ── Eyebrow ── */
@@ -12111,9 +12798,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12111
12798
  /* ── Headline ── */
12112
12799
  [data-ui="hero"] [data-part="headline"] {
12113
12800
  margin: 0;
12801
+ font-family: var(--font-heading);
12114
12802
  font-size: var(--text-3xl);
12115
- font-weight: var(--weight-bold);
12116
- line-height: var(--leading-tight);
12803
+ font-weight: var(--heading-weight);
12804
+ letter-spacing: var(--heading-tracking);
12805
+ text-transform: var(--heading-transform);
12806
+ font-variant-caps: var(--heading-caps);
12807
+ line-height: var(--heading-leading);
12117
12808
  color: var(--color-fg);
12118
12809
  text-wrap: balance;
12119
12810
  }
@@ -12232,7 +12923,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12232
12923
 
12233
12924
  /* === patterns/inbox.css === */
12234
12925
  /* @ui:component inbox */
12235
- /* @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 */
12926
+ /* @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 */
12236
12927
 
12237
12928
  /* ── Root ──
12238
12929
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12252,7 +12943,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12252
12943
  overflow: hidden;
12253
12944
  border: var(--space-px, 1px) solid var(--color-border);
12254
12945
  border-radius: var(--radius-lg);
12255
- font-family: var(--font-sans, system-ui, sans-serif);
12946
+ font-family: var(--font-body);
12256
12947
  color: var(--color-fg);
12257
12948
  background: var(--color-bg);
12258
12949
  }
@@ -12344,8 +13035,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12344
13035
  }
12345
13036
 
12346
13037
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12347
- outline: 2px solid var(--color-ring);
12348
- outline-offset: 2px;
13038
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13039
+ outline-offset: var(--focus-ring-offset);
12349
13040
  }
12350
13041
 
12351
13042
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12504,7 +13195,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12504
13195
 
12505
13196
  /* === patterns/pricing.css === */
12506
13197
  /* @ui:component pricing */
12507
- /* @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 */
13198
+ /* @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 */
12508
13199
 
12509
13200
  /* ── Root ──
12510
13201
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12514,7 +13205,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12514
13205
  gap: var(--space-4);
12515
13206
  padding-block: var(--space-12);
12516
13207
  padding-inline: var(--space-4);
12517
- font-family: var(--font-sans, system-ui, sans-serif);
13208
+ font-family: var(--font-body);
12518
13209
  color: var(--color-fg);
12519
13210
  background: var(--color-bg);
12520
13211
  }
@@ -12564,9 +13255,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12564
13255
 
12565
13256
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12566
13257
  margin: 0;
13258
+ font-family: var(--font-heading);
12567
13259
  font-size: var(--text-lg);
12568
13260
  font-weight: var(--weight-semibold);
12569
- line-height: var(--leading-tight);
13261
+ letter-spacing: var(--heading-tracking);
13262
+ text-transform: var(--heading-transform);
13263
+ font-variant-caps: var(--heading-caps);
13264
+ line-height: var(--heading-leading);
12570
13265
  }
12571
13266
 
12572
13267
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12627,7 +13322,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12627
13322
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12628
13323
  border-color: var(--color-primary);
12629
13324
  box-shadow: var(--shadow-md);
12630
- outline: var(--space-px, 1px) solid var(--color-primary);
13325
+ outline: var(--border-width-strong) solid var(--color-primary);
12631
13326
  }
12632
13327
 
12633
13328
  /* ── Footnote ── */
@@ -12672,14 +13367,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12672
13367
 
12673
13368
  /* === patterns/search-results.css === */
12674
13369
  /* @ui:component search-results */
12675
- /* @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 */
13370
+ /* @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 */
12676
13371
 
12677
13372
  /* ── Root ── */
12678
13373
  [data-ui="search-results"] {
12679
13374
  display: flex;
12680
13375
  flex-direction: column;
12681
13376
  gap: var(--space-4);
12682
- font-family: var(--font-sans, system-ui, sans-serif);
13377
+ font-family: var(--font-body);
12683
13378
  }
12684
13379
 
12685
13380
  /* ── Search Input ── */
@@ -12707,7 +13402,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12707
13402
  justify-content: space-between;
12708
13403
  gap: var(--space-4);
12709
13404
  padding-bottom: var(--space-2);
12710
- border-bottom: 1px solid var(--color-border);
13405
+ border-bottom: var(--border-width) solid var(--color-border);
12711
13406
  }
12712
13407
 
12713
13408
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12742,7 +13437,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12742
13437
  flex-direction: column;
12743
13438
  gap: var(--space-2);
12744
13439
  padding: var(--space-4);
12745
- border: 1px solid var(--color-border);
13440
+ border: var(--border-width) solid var(--color-border);
12746
13441
  border-radius: var(--radius-md);
12747
13442
  background: var(--color-bg);
12748
13443
  transition: background var(--duration-fast) var(--ease-default),
@@ -12801,7 +13496,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12801
13496
  display: flex;
12802
13497
  justify-content: center;
12803
13498
  padding-top: var(--space-4);
12804
- border-top: 1px solid var(--color-border);
13499
+ border-top: var(--border-width) solid var(--color-border);
12805
13500
  }
12806
13501
 
12807
13502
  /* ── Loading ── */
@@ -12841,7 +13536,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12841
13536
 
12842
13537
  /* ── Error State ── */
12843
13538
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12844
- border: 1px solid var(--color-border);
13539
+ border: var(--border-width) solid var(--color-border);
12845
13540
  border-radius: var(--radius-md);
12846
13541
  padding: var(--space-6);
12847
13542
  text-align: center;
@@ -12850,8 +13545,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12850
13545
 
12851
13546
  /* ── Focus management ── */
12852
13547
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12853
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12854
- outline-offset: 2px;
13548
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13549
+ outline-offset: var(--focus-ring-offset);
12855
13550
  }
12856
13551
 
12857
13552
  /* ── Motion ── */
@@ -12867,7 +13562,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12867
13562
 
12868
13563
  /* === patterns/settings-page.css === */
12869
13564
  /* @ui:component settings-page */
12870
- /* @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 */
13565
+ /* @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 */
12871
13566
 
12872
13567
  /* ── Root ── */
12873
13568
  [data-ui="settings-page"] {
@@ -12877,7 +13572,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12877
13572
  width: 100%;
12878
13573
  max-width: 768px;
12879
13574
  margin-inline: auto;
12880
- font-family: var(--font-sans, system-ui, sans-serif);
13575
+ font-family: var(--font-body);
12881
13576
  color: var(--color-fg);
12882
13577
  }
12883
13578
 
@@ -12891,9 +13586,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12891
13586
  /* ── Title ── */
12892
13587
  [data-ui="settings-page"] [data-part="title"] {
12893
13588
  margin: 0;
13589
+ font-family: var(--font-heading);
12894
13590
  font-size: var(--text-xl, 1.25rem);
12895
13591
  font-weight: var(--weight-semibold, 600);
12896
- line-height: var(--leading-tight);
13592
+ letter-spacing: var(--heading-tracking);
13593
+ text-transform: var(--heading-transform);
13594
+ font-variant-caps: var(--heading-caps);
13595
+ line-height: var(--heading-leading);
12897
13596
  color: var(--color-fg);
12898
13597
  }
12899
13598
 
@@ -12957,7 +13656,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12957
13656
  gap: var(--space-3, 0.75rem);
12958
13657
  padding: var(--space-4);
12959
13658
  background: var(--color-bg);
12960
- border-top: 1px solid var(--color-border);
13659
+ border-top: var(--border-width) solid var(--color-border);
12961
13660
  border-radius: var(--radius-lg);
12962
13661
  box-shadow: var(--shadow-md);
12963
13662
  position: sticky;
@@ -13021,7 +13720,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13021
13720
  flex-direction: row;
13022
13721
  flex-wrap: wrap;
13023
13722
  border-inline-end: none;
13024
- border-bottom: 1px solid var(--color-border);
13723
+ border-bottom: var(--border-width) solid var(--color-border);
13025
13724
  padding-inline-end: 0;
13026
13725
  position: static;
13027
13726
  }
@@ -13040,7 +13739,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13040
13739
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13041
13740
  flex-direction: column;
13042
13741
  border-bottom: none;
13043
- border-inline-end: 1px solid var(--color-border);
13742
+ border-inline-end: var(--border-width) solid var(--color-border);
13044
13743
  padding-inline-end: var(--space-4);
13045
13744
  position: sticky;
13046
13745
  top: var(--space-4);
@@ -13058,7 +13757,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13058
13757
  justify-content: flex-start;
13059
13758
  text-align: start;
13060
13759
  border-bottom: none;
13061
- border-inline-start: 2px solid transparent;
13760
+ border-inline-start: var(--border-width-strong) solid transparent;
13062
13761
  margin-bottom: 0;
13063
13762
  margin-inline-end: -1px;
13064
13763
  padding: var(--space-2) var(--space-3);
@@ -13092,7 +13791,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13092
13791
 
13093
13792
  /* === patterns/site-footer.css === */
13094
13793
  /* @ui:component site-footer */
13095
- /* @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 */
13794
+ /* @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 */
13096
13795
 
13097
13796
  /* ── Root ──
13098
13797
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13102,11 +13801,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13102
13801
  gap: var(--space-8);
13103
13802
  padding-block: var(--space-10);
13104
13803
  padding-inline: var(--space-4);
13105
- font-family: var(--font-sans, system-ui, sans-serif);
13804
+ font-family: var(--font-body);
13106
13805
  font-size: var(--text-sm);
13107
13806
  color: var(--color-fg-muted);
13108
13807
  background: var(--color-bg-subtle);
13109
- border-block-start: 1px solid var(--color-border);
13808
+ border-block-start: var(--border-width) solid var(--color-border);
13110
13809
  }
13111
13810
 
13112
13811
  /* ── Brand ── */
@@ -13238,7 +13937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13238
13937
 
13239
13938
  /* === patterns/stats-dashboard.css === */
13240
13939
  /* @ui:component stats-dashboard */
13241
- /* @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 */
13940
+ /* @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 */
13242
13941
 
13243
13942
  /* ── Root ──
13244
13943
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13251,7 +13950,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13251
13950
  gap: var(--space-3);
13252
13951
  padding-block: var(--space-8);
13253
13952
  padding-inline: var(--space-4);
13254
- font-family: var(--font-sans, system-ui, sans-serif);
13953
+ font-family: var(--font-body);
13255
13954
  color: var(--color-fg);
13256
13955
  background: var(--color-bg);
13257
13956
  }
@@ -13325,9 +14024,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13325
14024
 
13326
14025
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13327
14026
  margin: 0;
14027
+ font-family: var(--font-heading);
13328
14028
  font-size: var(--text-lg);
13329
14029
  font-weight: var(--weight-semibold);
13330
- line-height: var(--leading-tight);
14030
+ letter-spacing: var(--heading-tracking);
14031
+ text-transform: var(--heading-transform);
14032
+ font-variant-caps: var(--heading-caps);
14033
+ line-height: var(--heading-leading);
13331
14034
  }
13332
14035
 
13333
14036
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13418,7 +14121,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13418
14121
  gap: var(--space-6);
13419
14122
  max-inline-size: var(--measure-narrow);
13420
14123
  margin-inline: auto;
13421
- font-family: var(--font-sans);
14124
+ font-family: var(--font-body);
13422
14125
  }
13423
14126
 
13424
14127
  [data-ui="wizard"] [data-part="heading"] {