@faqir-ui/core 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +45 -5
  2. package/cdn.json +38 -22
  3. package/dist/faqir-core.js +121 -57
  4. package/dist/faqir-core.min.js +3 -3
  5. package/dist/faqir-core.min.js.map +3 -3
  6. package/dist/faqir-core.mjs +75 -59
  7. package/dist/faqir.aurora.css +1209 -507
  8. package/dist/faqir.brutalist.css +1184 -489
  9. package/dist/faqir.candy.css +14152 -0
  10. package/dist/faqir.clinical.css +14152 -0
  11. package/dist/faqir.contrast.css +1198 -526
  12. package/dist/faqir.default.css +1261 -588
  13. package/dist/faqir.document-serif.css +1211 -491
  14. package/dist/faqir.document.css +1193 -490
  15. package/dist/faqir.editorial-document.css +14116 -0
  16. package/dist/faqir.editorial.css +14152 -0
  17. package/dist/faqir.fintech.css +14152 -0
  18. package/dist/faqir.glass.css +1214 -517
  19. package/dist/faqir.ink-document.css +14116 -0
  20. package/dist/faqir.ink.css +14127 -0
  21. package/dist/faqir.luxe.css +14211 -0
  22. package/dist/faqir.midnight.css +1229 -507
  23. package/dist/faqir.neo.css +14153 -0
  24. package/dist/faqir.neumorph.css +14151 -0
  25. package/dist/faqir.nordic.css +14151 -0
  26. package/dist/faqir.organic.css +14152 -0
  27. package/dist/faqir.paper.css +1200 -508
  28. package/dist/faqir.slate.css +1296 -564
  29. package/dist/faqir.soft.css +1180 -494
  30. package/dist/faqir.sunset.css +14153 -0
  31. package/dist/faqir.swiss-document.css +14116 -0
  32. package/dist/faqir.swiss.css +14153 -0
  33. package/dist/faqir.terminal.css +1187 -491
  34. package/dist/plugins/faqir-collapse.js +1 -1
  35. package/dist/plugins/faqir-intersect.js +2 -0
  36. package/dist/plugins/faqir-mask.js +27 -17
  37. package/dist/plugins/faqir-rules.js +63 -0
  38. package/dist/plugins/faqir-validate.js +471 -58
  39. package/dist/sri.json +36 -20
  40. package/faqir-core.d.ts +119 -6
  41. package/package.json +1 -1
@@ -131,6 +131,18 @@
131
131
  --font-mono: ui-monospace, 'Cascadia Code', 'JetBrains Mono', monospace;
132
132
  --font-serif: 'Georgia', 'Times New Roman', serif;
133
133
 
134
+ /* ── Font Roles (task 1.1A-01) ──
135
+ The three families above are the PALETTE; these three are the ROLES that
136
+ components actually read. A theme re-points a role once and every heading,
137
+ every paragraph and every control follows — "serif headings on a sans body"
138
+ is one declaration rather than sixty-four stylesheet edits. Components never
139
+ read --font-sans / --font-serif directly (gated by
140
+ tests/tokens/role-tokens.test.ts); --font-mono stays readable by name,
141
+ because "this is code" is a semantic choice, not a stylistic one. */
142
+ --font-heading: var(--font-sans); /* h1–h6, hero headline, card/dialog titles, stat values, doc headings */
143
+ --font-body: var(--font-sans); /* prose, text, document body, descriptions */
144
+ --font-ui: var(--font-sans); /* controls: button, input, select, badge, chip, tabs, menus */
145
+
134
146
  /* ── Font Sizes ── */
135
147
  --text-xs: 0.75rem; /* 12px */
136
148
  --text-sm: 0.875rem; /* 14px */
@@ -153,10 +165,29 @@
153
165
  --weight-medium: 500;
154
166
  --weight-semibold: 600;
155
167
  --weight-bold: 700;
168
+
169
+ /* ── Heading Voice (task 1.1A-01) ──
170
+ What makes a heading sound like the theme rather than like the body text one
171
+ size up: how heavy it is, how tightly the letters sit, whether it shouts, and
172
+ how close its own lines run. The defaults reproduce today's primary heading
173
+ exactly, so a project that sets none of them renders unchanged. A heading
174
+ that deliberately steps DOWN from the primary voice (prose h2–h4, a semibold
175
+ step below h1) keeps its own weight and leading and takes family, tracking
176
+ and case from the voice — the step is the design, not a value to re-derive. */
177
+ --heading-weight: var(--weight-bold);
178
+ --heading-tracking: 0em; /* letter-spacing — carries a unit so it
179
+ composes inside calc() where a heading
180
+ already has its own optical tightening */
181
+ --heading-transform: none; /* text-transform */
182
+ --heading-caps: normal; /* font-variant-caps — small caps are a
183
+ variant, not a transform (1.1A-25), so
184
+ they get a knob of their own that sits
185
+ beside --heading-transform */
186
+ --heading-leading: var(--leading-tight);
156
187
  }
157
188
 
158
189
  /* === tokens/effects.css === */
159
- /* @ui:tokens effects — radii, shadows, z-index */
190
+ /* @ui:tokens effects — radii, shape, shadows, focus, z-index */
160
191
 
161
192
  :root {
162
193
  /* ── Radii ── */
@@ -168,12 +199,49 @@
168
199
  --radius-2xl: 1rem; /* 16px */
169
200
  --radius-full: 9999px;
170
201
 
171
- /* ── Shadows ── */
172
- --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.04);
173
- --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
174
- --shadow-md: 0 4px 6px oklch(0 0 0 / 0.05), 0 2px 4px oklch(0 0 0 / 0.04);
175
- --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.06), 0 4px 6px oklch(0 0 0 / 0.04);
176
- --shadow-xl: 0 20px 25px oklch(0 0 0 / 0.08), 0 8px 10px oklch(0 0 0 / 0.04);
202
+ /* ── Shape ── */
203
+ /* The weight of an edge. A component names the ROLE (--border-width, or
204
+ --border-width-strong where the design leans on a thicker rule), never a
205
+ step, so a theme re-points every edge it ships with one declaration. */
206
+ --border-width-sm: 1px;
207
+ --border-width-md: 2px;
208
+ --border-width-lg: 3px;
209
+ --border-width: var(--border-width-sm); /* the default component border */
210
+ --border-width-strong: var(--border-width-md); /* emphasis: keycap, thick rule, active tab */
211
+ /* Progressive: CSS Borders 4. A browser without the property ignores it; a
212
+ value it does not know resolves to `round`, which is today's rendering. */
213
+ --corner-shape: round; /* bevel | scoop | notch where supported */
214
+
215
+ /* ── Depth ── */
216
+ /* The colour every shadow is cast in, as BARE OKLCH channels (L C H, no
217
+ `oklch()` around them) so each step can still set its own alpha:
218
+ `oklch(var(--shadow-color) / 0.06)`. A theme tints its depth warm, or
219
+ removes it entirely, with one declaration instead of rewriting five
220
+ multi-layer values. `0 0 0` is black — today's rendering, exactly. */
221
+ --shadow-color: 0 0 0;
222
+
223
+ --shadow-xs: 0 1px 2px oklch(var(--shadow-color) / 0.04);
224
+ --shadow-sm: 0 1px 3px oklch(var(--shadow-color) / 0.06), 0 1px 2px oklch(var(--shadow-color) / 0.04);
225
+ --shadow-md: 0 4px 6px oklch(var(--shadow-color) / 0.05), 0 2px 4px oklch(var(--shadow-color) / 0.04);
226
+ --shadow-lg: 0 10px 15px oklch(var(--shadow-color) / 0.06), 0 4px 6px oklch(var(--shadow-color) / 0.04);
227
+ --shadow-xl: 0 20px 25px oklch(var(--shadow-color) / 0.08), 0 8px 10px oklch(var(--shadow-color) / 0.04);
228
+
229
+ /* What an elevated surface does to whatever shows through it. Every surface
230
+ that can float — card, surface[data-variant="overlay"] and the seven
231
+ floating recipes — declares `backdrop-filter: var(--surface-backdrop)`
232
+ inside the same `@supports` guard, so a frosted theme is a token rather
233
+ than a stylesheet that reaches into seven components by selector.
234
+ `none` is the initial value of the property: no-op until a theme speaks. */
235
+ --surface-backdrop: none;
236
+
237
+ /* ── Focus ── */
238
+ /* base/reset.css owns the default ring and reads only these. Every control
239
+ that draws its own ring reads them too, so a theme changes focus once. */
240
+ --focus-ring-width: 2px;
241
+ --focus-ring-offset: 2px;
242
+ --focus-ring-style: solid;
243
+ --focus-ring-color: var(--color-ring);
244
+ --focus-shadow: none; /* a glow theme puts a shadow behind the ring */
177
245
 
178
246
  /* ── Z-Index ── */
179
247
  --z-base: 0;
@@ -186,8 +254,74 @@
186
254
  --z-max: 9999;
187
255
  }
188
256
 
257
+ /* ── Scheme islands ── */
258
+ /* The ring colour, restated where a scheme can change below the root: declared
259
+ on `:root` alone it resolves `--color-ring` once, from the page, and a nested
260
+ `data-theme="dark"` region would draw the light ring. See the same block in
261
+ tokens/aliases.css. `--focus-shadow` is deliberately NOT restated — it is a
262
+ depth value a theme owns, and restating it would replace the theme's glow
263
+ with `none` inside every island. */
264
+ [data-theme],
265
+ [data-skin] {
266
+ --focus-ring-color: var(--color-ring);
267
+ }
268
+
269
+ /* === tokens/textures.css === */
270
+ /* @ui:tokens textures — named surface materials (SVG data URIs) */
271
+
272
+ /* ══════════════════════════════════════════════════════════════════════════
273
+ The material palette.
274
+ ══════════════════════════════════════════════════════════════════════════
275
+ Six named textures, each a self-contained `url("data:image/svg+xml,…")` that
276
+ tiles. Nothing here is consumed directly: components read the two ROLE tokens
277
+ in `aliases.css` — `--texture-page` (body, document) and `--texture-surface`
278
+ (surface, card, hero) — both `none` by default, so the registry renders
279
+ exactly as it did before this file existed. A theme opts in with one
280
+ declaration:
281
+
282
+ --texture-page: var(--texture-grain);
283
+
284
+ This file is deliberately OUTSIDE the themeable surface (see
285
+ `NON_SURFACE_TOKEN_FILES` in `src/theme-manifest.ts`): a theme re-points the
286
+ two role tokens, it does not inherit six data URIs into its manifest.
287
+
288
+ On `currentColor`: the tint is written as `currentColor` so the markup states
289
+ its intent and a theme can re-point the whole token, but a data-URI SVG used
290
+ as `background-image` is its own document — `currentColor` there resolves to
291
+ that document's initial colour (black), not to the host element's `color`.
292
+ That IS the intended neutral for grain and paper, which are meant to darken a
293
+ surface slightly; the alpha in each texture, not the hue, is what carries the
294
+ effect. A theme wanting a different tint ships its own URI.
295
+
296
+ Every texture keeps its alpha low enough to survive on both schemes, and each
297
+ `<svg>` carries explicit `width`/`height` so the tile size is the token's,
298
+ not the browser's default 300×150.
299
+ ══════════════════════════════════════════════════════════════════════════ */
300
+
301
+ :root {
302
+ /* Film grain — fractal noise masking a flat currentColor fill. The mask is
303
+ what makes this a tint rather than the turbulence's own rainbow. */
304
+ --texture-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/mask%3E%3Crect width='160' height='160' fill='currentColor' mask='url(%23m)' opacity='0.14'/%3E%3C/svg%3E");
305
+
306
+ /* Paper fibre — lower frequency, more octaves, softer than grain. */
307
+ --texture-paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.04 0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Cmask id='m'%3E%3Crect width='200' height='200' filter='url(%23p)'/%3E%3C/mask%3E%3Crect width='200' height='200' fill='currentColor' mask='url(%23m)' opacity='0.1'/%3E%3C/svg%3E");
308
+
309
+ /* Dot field — one dot per 16px cell. */
310
+ --texture-dots: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='2' cy='2' r='1' fill='currentColor' opacity='0.18'/%3E%3C/svg%3E");
311
+
312
+ /* Graph-paper grid — hairlines on a 24px cell. */
313
+ --texture-grid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M24 0H0v24' fill='none' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
314
+
315
+ /* Diagonal hatching — 45°, 8px pitch. */
316
+ --texture-stripes: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M-2 2 2-2M0 8 8 0M6 10l4-4' stroke='currentColor' stroke-width='1' opacity='0.12'/%3E%3C/svg%3E");
317
+
318
+ /* Soft gradient mesh — three offset radial blooms, the only non-tiling
319
+ texture here (it is sized to cover, not to repeat). */
320
+ --texture-mesh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3CradialGradient id='a' cx='20%25' cy='20%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.18'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='b' cx='80%25' cy='30%25' r='55%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.14'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='c' cx='50%25' cy='90%25' r='60%25'%3E%3Cstop offset='0%25' stop-color='currentColor' stop-opacity='0.12'/%3E%3Cstop offset='100%25' stop-color='currentColor' stop-opacity='0'/%3E%3C/radialGradient%3E%3Crect width='640' height='640' fill='url(%23a)'/%3E%3Crect width='640' height='640' fill='url(%23b)'/%3E%3Crect width='640' height='640' fill='url(%23c)'/%3E%3C/svg%3E");
321
+ }
322
+
189
323
  /* === tokens/motion.css === */
190
- /* @ui:tokens motion — easings and durations */
324
+ /* @ui:tokens motion — easings, durations and motion personality */
191
325
 
192
326
  :root {
193
327
  /* ── Easings ── */
@@ -216,6 +350,35 @@
216
350
  /* Preset geometry */
217
351
  --motion-slide-distance: 0.5rem; /* slide-up travel */
218
352
  --motion-scale-from: 0.95; /* scale start/end factor */
353
+
354
+ /* ── Personality (1.1A-05 · §5.2 `motion`) ── */
355
+ /* The easing PALETTE gained a spring. Like --ease-bounce it has no consumer
356
+ of its own: a theme that wants everything to overshoot re-points
357
+ --ease-default at it, exactly as a serif theme re-points --font-body.
358
+ The declaration here is the cubic-bezier APPROXIMATION, because a custom
359
+ property stores whatever tokens it is given — a browser without `linear()`
360
+ would accept the spring happily and then drop every `transition` that used
361
+ it, landing on the initial easing rather than on a fallback. The @supports
362
+ block below is what makes the upgrade conditional. The approximation is
363
+ the bounce curve, deliberately: an overshoot-and-settle cubic-bezier is the
364
+ closest a browser without `linear()` can come to a spring. */
365
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
366
+
367
+ /* How far an interactive surface rises under the pointer. A `translate`
368
+ VALUE, not a length: `none` is the initial value of that property, so the
369
+ default registry computes exactly what it computed before this token
370
+ existed, and a theme states the lift as `0 -1px`. `translate` rather than
371
+ `transform` so a component's own transform is never clobbered. */
372
+ --motion-hover-lift: none;
373
+ }
374
+
375
+ /* The real spring, where `linear()` is understood (Chrome 113+, Safari 17.2+,
376
+ Firefox 112+). Declared second so it wins; guarded so it is never declared at
377
+ all where it would be meaningless. */
378
+ @supports (animation-timing-function: linear(0, 1)) {
379
+ :root {
380
+ --ease-spring: linear(0, 0.3 6%, 0.7 13%, 0.95 20%, 1.03 27%, 1 40%, 1);
381
+ }
219
382
  }
220
383
 
221
384
  /* === tokens/semantic.css === */
@@ -307,27 +470,123 @@
307
470
  --section-gap-lg: var(--space-32); /* 8rem — spacious, one idea per screen */
308
471
  --content-gutter: var(--space-6); /* 1.5rem — page padding-inline */
309
472
 
473
+ /* ── Material ── */
474
+ /* The two textures a theme actually points at. Components never name a
475
+ texture from `tokens/textures.css` directly — they read one of these, so a
476
+ theme re-points two tokens rather than every surface in the registry.
477
+ `--texture-page` dresses the page itself (body, document);
478
+ `--texture-surface` dresses the things that sit ON it (surface, card,
479
+ hero). Both `none`: the initial value of `background-image`, so the
480
+ default registry renders exactly as it did before they existed. */
481
+ --texture-page: none;
482
+ --texture-surface: none;
483
+
484
+ /* ── Decoration (1.1A-05 · §5.2 `decoration`) ── */
485
+ /* The marks a theme draws that are not edges, fills or type: how a link is
486
+ underlined, how a divider is dashed, what selected text looks like, what
487
+ colour a list bullet is. Every default is the value the registry already
488
+ rendered, so this section is a set of handles, not a restyle.
489
+ `--marker-color` is `currentColor` — the initial value of `::marker`'s
490
+ colour — rather than the accent, so a list only changes when a theme says
491
+ it should. */
492
+ --link-decoration: underline;
493
+ --link-underline-offset: 0.2em;
494
+ --link-thickness: 1px;
495
+ --divider-style: solid;
496
+ /* The divider's own width, following the edge by default (1.1A-26). A theme
497
+ that asks for a `double` divider raises it to at least 3px: a double rule
498
+ only splits into two lines from 3px, and the family's 1px hairline would
499
+ paint it as one. */
500
+ --divider-width: var(--border-width);
501
+ /* The zebra, so a theme dials the stripe without restating the four selectors
502
+ the table's striped variant needs (stamped and nth-child, each with a hover
503
+ twin). Deliberately NOT `--table-stripe`: `--table-level`,
504
+ `--table-thead-h` and `--table-pin-offset` are stamped and MEASURED per
505
+ element by the table controller, so claiming the `--table-*` namespace for
506
+ a theme token would put runtime state on the themeable surface. */
507
+ --stripe-bg: var(--color-bg-subtle);
508
+ --selection-bg: var(--color-primary-subtle);
509
+ --selection-fg: var(--color-fg);
510
+ --marker-color: currentColor;
511
+ /* How far a disabled control is dimmed. Seventeen rules across the primitives
512
+ and recipes each spelled `opacity: 0.5`, which left a theme with an opinion
513
+ about disabled legibility no way to state it except by out-specifying every
514
+ one of them — which is exactly what `themes/contrast.css` did, with a
515
+ blanket `:root [data-ui]:disabled` rule, until 1.1A-15 turned it into this
516
+ one declaration. `0.5` is the value those seventeen rules already held. */
517
+ --disabled-opacity: 0.5;
518
+
310
519
  /* ── Button ── */
311
520
  --button-radius: var(--radius-md);
312
521
  --button-height-sm: var(--control-height-sm);
313
522
  --button-height-md: var(--control-height-md);
314
523
  --button-height-lg: var(--control-height-lg);
315
- --button-font: var(--font-sans);
524
+ --button-font: var(--font-ui);
316
525
  --button-weight: var(--weight-medium);
526
+ --button-text-transform: none;
317
527
 
318
528
  /* ── Card ── */
319
529
  --card-radius: var(--radius-lg);
320
530
  --card-shadow: var(--shadow-sm);
321
531
  --card-border: var(--color-surface-1-border);
532
+ --card-border-width: var(--border-width);
322
533
  --card-bg: var(--color-surface-1);
323
534
  --card-padding: var(--space-6);
324
535
 
325
536
  /* ── Input ── */
326
- --input-radius: var(--radius-md);
327
- --input-height: var(--control-height-md);
328
- --input-border: var(--color-border);
329
- --input-bg: var(--color-bg);
330
- --input-font: var(--font-sans);
537
+ /* The text-control silhouette. `--input-border-width` (1.1A-02) is the edge;
538
+ `--input-fill` is what the control paints, and `input`, `textarea` and
539
+ `select` all read it, so one declaration fills every text control.
540
+ `--input-fill` defaults to `--input-bg`, so a project that sets `--input-bg`
541
+ on `:root` — the 1.0 way to fill every input — still gets it. Set BELOW the
542
+ root, `--input-bg` no longer reaches the control: `--input-fill` has already
543
+ resolved it on `:root`, which is where a theme flips the fill, and a
544
+ per-element `--input-bg` winning over that would need the component to tell
545
+ "set here" from "inherited", which CSS cannot. To fill one input, or every
546
+ input in a region, set `--input-fill` there instead. `--input-bg-filled` is
547
+ the value a "filled" theme points `--input-fill` at — named here so the
548
+ silhouette is a token a theme flips rather than a colour it has to pick. */
549
+ --input-radius: var(--radius-md);
550
+ --input-height: var(--control-height-md);
551
+ --input-border: var(--color-border);
552
+ --input-border-width: var(--border-width);
553
+ --input-bg: var(--color-bg);
554
+ --input-bg-filled: var(--color-bg-subtle);
555
+ --input-fill: var(--input-bg);
556
+ --input-font: var(--font-ui);
557
+
558
+ /* ── Checkbox / Switch ── */
559
+ /* The two control shapes that do not follow `--radius-md`: a checkbox is a
560
+ small square with a small radius, a switch is a pill. Both were literal
561
+ `var(--radius-*)` reads in the components; named here, a theme squares its
562
+ switches without touching the radius ladder every other surface uses.
563
+
564
+ The geometry beside them is not decoration — it is the rest of the
565
+ namespace. Naming ONE token `--checkbox-radius` makes `--checkbox-*` a
566
+ token family, and the registry audit then (rightly) reads every other
567
+ `--checkbox-…`/`--switch-…` the components carried as a token wearing a
568
+ fallback as a disguise. They were always the default geometry; these are
569
+ the values the fallbacks already held, said once. */
570
+ --checkbox-size: 18px;
571
+ --checkbox-radius: var(--radius-sm);
572
+ --switch-width: 44px;
573
+ --switch-height: 24px;
574
+ --switch-thumb: 18px;
575
+ --switch-travel: 20px;
576
+ --switch-radius: var(--radius-full);
577
+ --switch-bg: var(--color-bg-muted);
578
+ --switch-thumb-shadow: var(--shadow-xs);
579
+
580
+ /* ── Floating panels ── */
581
+ /* What a panel that floats above the page is filled with: the dialog and
582
+ sheet panels, the drawer, the popover content (and its arrow), the dropdown
583
+ menu and the toast. They all painted `var(--color-bg)` directly, which left
584
+ a theme no way to make a floating surface differ from the page — the frost
585
+ half of that pairing is `--surface-backdrop` (1.1A-04), and a blur behind an
586
+ opaque fill renders nothing, so the fill has to be a token too. `card` has
587
+ had `--card-bg` since 1.0; this is the same handle for the things that have
588
+ no surface of their own. [1.1A-14] */
589
+ --panel-bg: var(--color-bg);
331
590
 
332
591
  /* ── Dialog ── */
333
592
  --dialog-radius: var(--radius-xl);
@@ -336,7 +595,7 @@
336
595
 
337
596
  /* ── Badge ── */
338
597
  --badge-radius: var(--radius-full);
339
- --badge-font: var(--font-sans);
598
+ --badge-font: var(--font-ui);
340
599
 
341
600
  /* ── Avatar ── */
342
601
  --avatar-radius: var(--radius-full);
@@ -345,6 +604,39 @@
345
604
  --avatar-size-lg: 56px;
346
605
  }
347
606
 
607
+ /* ── Scheme islands ── */
608
+ /* The colour aliases above, restated wherever a scheme can change below the
609
+ root. A custom property resolves its var() on the element that DECLARES it,
610
+ so `--panel-bg: var(--color-bg)` on `:root` is computed once, from the page's
611
+ colours, and a nested `<div data-theme="dark">` inherits that light value
612
+ even though its own `--color-bg` is dark — a white dialog on a dark island.
613
+ Components that read `var(--color-bg)` directly never had the problem; the
614
+ aliases 1.1 routed them through did. Restating the declaration on
615
+ `[data-theme]` and `[data-skin]` makes it resolve again there.
616
+
617
+ Only colours are restated. Geometry does not change with the scheme, and
618
+ shadows are the depth axis every theme owns on `:root`: restating either here
619
+ would replace a theme's own value with the default inside every island. A
620
+ theme that overrides one of THESE on `:root` and wants it honoured in an
621
+ island says so on the same selectors.
622
+
623
+ The values must match the `:root` declarations above exactly;
624
+ `tests/tokens/scheme-islands.test.ts` fails if they drift. */
625
+ [data-theme],
626
+ [data-skin] {
627
+ --stripe-bg: var(--color-bg-subtle);
628
+ --selection-bg: var(--color-primary-subtle);
629
+ --selection-fg: var(--color-fg);
630
+ --card-border: var(--color-surface-1-border);
631
+ --card-bg: var(--color-surface-1);
632
+ --input-border: var(--color-border);
633
+ --input-bg: var(--color-bg);
634
+ --input-bg-filled: var(--color-bg-subtle);
635
+ --input-fill: var(--input-bg);
636
+ --switch-bg: var(--color-bg-muted);
637
+ --panel-bg: var(--color-bg);
638
+ }
639
+
348
640
  /* === tokens/document.css === */
349
641
  /* @ui:tokens document — structural tokens for document/print rendering */
350
642
  /* These tokens control page geometry, document typography, table density,
@@ -376,10 +668,10 @@
376
668
  Separate from the base typography tokens because documents have
377
669
  different optimal sizes than screen UIs. 14px body + 12px legal
378
670
  is standard for A4 business documents. */
379
- --doc-font: var(--font-sans);
671
+ --doc-font: var(--font-body);
380
672
  --doc-font-size: var(--text-sm); /* 14px — optimal for A4 */
381
673
  --doc-line-height: var(--leading-normal); /* 1.5 */
382
- --doc-heading-font: var(--font-sans);
674
+ --doc-heading-font: var(--font-heading);
383
675
  --doc-heading-weight: var(--weight-bold);
384
676
  --doc-heading-size: var(--text-xl); /* 20px for doc titles */
385
677
  --doc-subheading-size: var(--text-lg); /* 18px for section titles */
@@ -430,6 +722,16 @@
430
722
  --doc-print-border-color: oklch(0.60 0 0); /* medium gray borders in print */
431
723
  }
432
724
 
725
+ /* ── Scheme islands ── */
726
+ /* `--doc-legal-color` is the one document colour screen components read (the
727
+ key-value label and the image caption), so it is restated where a scheme can
728
+ change below the root — see the same block in tokens/aliases.css. The rest
729
+ of this file is print ink, which does not follow the scheme. */
730
+ [data-theme],
731
+ [data-skin] {
732
+ --doc-legal-color: var(--color-fg-muted);
733
+ }
734
+
433
735
  /* === tokens/doc-aliases.css === */
434
736
  /* @ui:tokens doc-aliases — component-level document tokens */
435
737
  /* Maps document-layer tokens to specific primitive/recipe attribute selectors.
@@ -476,7 +778,10 @@
476
778
  --field-error-size: var(--doc-legal-size);
477
779
  --field-error-color: var(--color-destructive);
478
780
  --field-validating-color: var(--color-fg-muted); /* async validation in flight */
479
- --field-disabled-opacity: 0.55; /* honest disabled affordance */
781
+ /* The role `--disabled-opacity` sets for every control, nudged 10% lighter:
782
+ 0.55 at the 0.5 default, which is the value this alias always held, and it
783
+ follows a theme that states the role (1.1A-27). */
784
+ --field-disabled-opacity: calc(var(--disabled-opacity) * 1.1);
480
785
  --field-required-color: var(--color-destructive);
481
786
  --field-required-marker: ' *'; /* appended to required labels */
482
787
 
@@ -496,15 +801,47 @@
496
801
  --stat-change-negative: var(--color-destructive);
497
802
  }
498
803
 
804
+ /* ── Scheme islands ── */
805
+ /* The colour aliases above, restated where a scheme can change below the root —
806
+ a custom property resolves its var() on the element that declares it, so a
807
+ `:root`-only alias would carry the page's light value into a nested
808
+ `data-theme="dark"` region. See the same block in tokens/aliases.css; the
809
+ values must match the `:root` declarations above exactly. */
810
+ [data-theme],
811
+ [data-skin] {
812
+ --kv-label-color: var(--doc-legal-color);
813
+ --kv-value-color: var(--color-fg);
814
+ --callout-bg: var(--color-bg-subtle);
815
+ --callout-fg: var(--color-fg);
816
+ --image-border: var(--color-border);
817
+ --image-caption-color: var(--doc-legal-color);
818
+ --field-label-color: var(--color-fg);
819
+ --field-description-color: var(--color-fg-muted);
820
+ --field-error-color: var(--color-destructive);
821
+ --field-validating-color: var(--color-fg-muted);
822
+ --field-required-color: var(--color-destructive);
823
+ --page-break-screen-color: var(--color-border);
824
+ --page-break-screen-label-color: var(--color-fg-muted);
825
+ --stat-label-color: var(--color-fg-muted);
826
+ --stat-change-positive: var(--color-success);
827
+ --stat-change-negative: var(--color-destructive);
828
+ }
829
+
499
830
  /* === tokens/density.css === */
500
- /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6)
831
+ /* @ui:tokens density — [data-density] subtree modifier (task 0.7-11, FAQIR-NEXT §B6;
832
+ `spacious` added 1.1A-09, SPEC-1.0.md §4)
501
833
 
502
834
  Put `data-density="compact"` on ANY container and its whole subtree renders
503
835
  tighter: spacing steps shrink by --density-scale and interactive controls drop
504
836
  to a shorter height ramp. `data-density="comfortable"` restores the base scale,
505
- so density can be reset on an inner subtree.
837
+ so density can be reset on an inner subtree. `data-density="spacious"` is the
838
+ third point on the ladder, above comfortable: spacing grows and the control
839
+ ramp grows with it, gentler than the spacing multiplier for the same reason
840
+ compact's ramp shrinks gentler — a usable hit target has a ceiling as well as
841
+ a floor.
506
842
 
507
843
  <section data-density="compact"> … dense form / table / toolbar … </section>
844
+ <section data-density="spacious"> … roomy landing hero, kiosk UI … </section>
508
845
 
509
846
  This is 100% CSS. `data-density` is NOT a sixth protocol attribute: no
510
847
  component contract, manifest, controller or audit rule knows about it — CSS
@@ -641,6 +978,57 @@
641
978
  --content-gutter: var(--space-6);
642
979
  }
643
980
 
981
+ /* The third density: roomier than the base scale, for a landing hero or a kiosk
982
+ UI meant to be read at arm's length. Control heights grow slower than the
983
+ spacing multiplier — the same asymmetry compact's ramp has, mirrored. */
984
+ [data-density="spacious"] {
985
+ --density-scale: 1.25;
986
+
987
+ /* ── Spacing scale (× --density-scale) ── */
988
+ --space-0h: calc(0.125rem * var(--density-scale));
989
+ --space-1: calc(0.25rem * var(--density-scale));
990
+ --space-1h: calc(0.375rem * var(--density-scale));
991
+ --space-2: calc(0.5rem * var(--density-scale));
992
+ --space-2h: calc(0.625rem * var(--density-scale));
993
+ --space-3: calc(0.75rem * var(--density-scale));
994
+ --space-3h: calc(0.875rem * var(--density-scale));
995
+ --space-4: calc(1rem * var(--density-scale));
996
+ --space-5: calc(1.25rem * var(--density-scale));
997
+ --space-6: calc(1.5rem * var(--density-scale));
998
+ --space-7: calc(1.75rem * var(--density-scale));
999
+ --space-8: calc(2rem * var(--density-scale));
1000
+ --space-10: calc(2.5rem * var(--density-scale));
1001
+ --space-12: calc(3rem * var(--density-scale));
1002
+ --space-16: calc(4rem * var(--density-scale));
1003
+ --space-20: calc(5rem * var(--density-scale));
1004
+ --space-24: calc(6rem * var(--density-scale));
1005
+ --space-32: calc(8rem * var(--density-scale));
1006
+ --space-40: calc(10rem * var(--density-scale));
1007
+ --space-48: calc(12rem * var(--density-scale));
1008
+ --space-64: calc(16rem * var(--density-scale));
1009
+
1010
+ /* ── Control height ramp ── */
1011
+ --control-height-sm: 36px;
1012
+ --control-height-md: 44px;
1013
+ --control-height-lg: 52px;
1014
+
1015
+ /* ── Aliases re-substituted in this scope (values identical to the base) ── */
1016
+ --button-height-sm: var(--control-height-sm);
1017
+ --button-height-md: var(--control-height-md);
1018
+ --button-height-lg: var(--control-height-lg);
1019
+ --input-height: var(--control-height-md);
1020
+ --card-padding: var(--space-6);
1021
+ --kv-pair-gap: var(--space-3);
1022
+ --kv-grid-gap: var(--space-4);
1023
+ --callout-padding-y: var(--space-3);
1024
+ --callout-padding-x: var(--space-4);
1025
+ --field-gap: var(--space-1h);
1026
+ --section-gap-sm: var(--space-12);
1027
+ --section-gap-md: var(--space-20);
1028
+ --section-gap-lg: var(--space-32);
1029
+ --content-gutter: var(--space-6);
1030
+ }
1031
+
644
1032
  /* === themes/brutalist.css === */
645
1033
  /* @ui:theme brutalist — high-contrast, raw, minimal theme with no shadows or rounding */
646
1034
 
@@ -705,6 +1093,33 @@
705
1093
  --radius-2xl: 0;
706
1094
  --radius-full: 0;
707
1095
 
1096
+ /* ── Shape (the theme's whole argument, finally in tokens) ──
1097
+ Brutalism is a heavy rule around everything. Until the shape family existed
1098
+ the theme could only say it in colour (`--color-border: black`) and every
1099
+ edge in the registry stayed a hairline; now the ROLE is re-pointed and all
1100
+ 139 of them thicken together. */
1101
+ --border-width: var(--border-width-lg); /* 3px — the default edge */
1102
+ --border-width-strong: var(--border-width-lg); /* nothing is emphasised: everything shouts */
1103
+
1104
+ /* ── Focus (bold, and flush against the edge it belongs to) ── */
1105
+ --focus-ring-width: var(--border-width-lg);
1106
+ --focus-ring-offset: 0;
1107
+
1108
+ /* ── Type voice (a headline is a stencil) ── */
1109
+ --heading-tracking: 0.06em;
1110
+ --heading-transform: uppercase;
1111
+ --button-text-transform: uppercase;
1112
+
1113
+ /* ── Decoration (a link is a link; you can see the line from across the room) ── */
1114
+ --link-decoration: underline;
1115
+ --link-thickness: var(--border-width-md);
1116
+ --link-underline-offset: 0.1em;
1117
+
1118
+ /* ── Motion (minimal — the state changes, it does not travel) ── */
1119
+ --duration-fast: 60ms;
1120
+ --duration-normal: 100ms;
1121
+ --duration-slow: 140ms;
1122
+
708
1123
  /* ── Component Aliases (enforce brutalist styling) ── */
709
1124
  --button-radius: 0;
710
1125
  --card-radius: 0;
@@ -839,11 +1254,38 @@
839
1254
  padding: 0;
840
1255
  }
841
1256
 
1257
+ /* Colour scheme — the one place `data-theme` is translated into the platform's
1258
+ own scheme signal. `light-dark()` in a theme reads `color-scheme`, not
1259
+ `data-theme`, so a one-block theme [1.1A-06] resolves nothing at all without
1260
+ these three rules; declaring them here (rather than in each theme) is what
1261
+ makes the two authoring forms interchangeable. Nothing else in the registry
1262
+ declares `color-scheme`, so this is purely additive.
1263
+
1264
+ Specificity does the mapping: `:root` is (0,0,1) and each attribute selector
1265
+ is (0,1,0), so `<html data-theme="dark">` takes the dark rule over the root
1266
+ default while a bare `<html>` — and `data-theme="light"` — keeps light. The
1267
+ same rules apply to a NESTED element carrying `data-theme`, which is how a
1268
+ dark island inside a light page has always worked here. */
1269
+ :root {
1270
+ color-scheme: light;
1271
+ }
1272
+
1273
+ [data-theme="dark"] {
1274
+ color-scheme: dark;
1275
+ }
1276
+
1277
+ /* `auto` hands the choice to the OS: `light dark` means "either, system first",
1278
+ which is exactly what the `@media (prefers-color-scheme: dark)` mirror block
1279
+ does for a theme authored in the three-block form. */
1280
+ [data-theme="auto"] {
1281
+ color-scheme: light dark;
1282
+ }
1283
+
842
1284
  html {
843
1285
  -webkit-text-size-adjust: 100%;
844
1286
  -moz-tab-size: 4;
845
1287
  tab-size: 4;
846
- font-family: var(--font-sans);
1288
+ font-family: var(--font-body);
847
1289
  font-size: var(--text-base);
848
1290
  line-height: var(--leading-normal);
849
1291
  color: var(--color-fg);
@@ -854,6 +1296,11 @@ html {
854
1296
 
855
1297
  body {
856
1298
  min-height: 100dvh;
1299
+ /* The page's material. `none` by default (the initial value), so this is a
1300
+ no-op until a theme points --texture-page at one of tokens/textures.css.
1301
+ `html` keeps the background COLOUR; the texture rides on `body`, which
1302
+ covers the viewport, so the two compose instead of overwriting. */
1303
+ background-image: var(--texture-page);
857
1304
  }
858
1305
 
859
1306
  img,
@@ -923,10 +1370,32 @@ table {
923
1370
  }
924
1371
  }
925
1372
 
926
- /* Focus visible — default ring */
1373
+ /* Text selection — the decoration axis reaching the one surface no component
1374
+ owns. Until 1.1 the highlight was whatever the OS drew, which is the one part
1375
+ of a themed page that never matched the theme. Both values are tokens
1376
+ (tokens/aliases.css § Decoration), so a theme states its selection once. */
1377
+ ::selection {
1378
+ background-color: var(--selection-bg);
1379
+ color: var(--selection-fg);
1380
+ }
1381
+
1382
+ /* Focus visible — the default ring, and the only place it is spelled out.
1383
+ Every value is a token (tokens/effects.css § Focus), so a theme states its
1384
+ focus once and every element that has not drawn its own ring follows. */
927
1385
  :focus-visible {
928
- outline: 2px solid var(--color-ring);
929
- outline-offset: 2px;
1386
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1387
+ outline-offset: var(--focus-ring-offset);
1388
+ }
1389
+
1390
+ /* The glow a theme may put behind the ring, at zero specificity. `box-shadow`
1391
+ is not a property focus owns: an element's resting shadow — a card's depth,
1392
+ an author's own — lives there too, and a (0,1,0) rule here replaced it with
1393
+ `none` (the default) on every keyboard focus. Under `:where()` ANY rule that
1394
+ sets a shadow outranks this one, so it lands only on an element nothing else
1395
+ shadows, and it never takes a shadow away. The controls that draw their own
1396
+ ring read `--focus-shadow` in their own `:focus-visible` rules. */
1397
+ :where(:focus-visible) {
1398
+ box-shadow: var(--focus-shadow);
930
1399
  }
931
1400
 
932
1401
  /* Hidden but accessible */
@@ -955,7 +1424,7 @@ table {
955
1424
  /* @ui:base prose — typography defaults for long-form content */
956
1425
 
957
1426
  [data-ui="prose"] {
958
- font-family: var(--font-sans);
1427
+ font-family: var(--font-body);
959
1428
  font-size: var(--text-base);
960
1429
  line-height: var(--leading-relaxed);
961
1430
  color: var(--color-fg);
@@ -963,29 +1432,45 @@ table {
963
1432
  }
964
1433
 
965
1434
  [data-ui="prose"] h1 {
1435
+ font-family: var(--font-heading);
966
1436
  font-size: var(--text-4xl);
967
- font-weight: var(--weight-bold);
968
- line-height: var(--leading-tight);
1437
+ font-weight: var(--heading-weight);
1438
+ letter-spacing: var(--heading-tracking);
1439
+ text-transform: var(--heading-transform);
1440
+ font-variant-caps: var(--heading-caps);
1441
+ line-height: var(--heading-leading);
969
1442
  margin-block: var(--space-8) var(--space-4);
970
1443
  }
971
1444
 
972
1445
  [data-ui="prose"] h2 {
1446
+ font-family: var(--font-heading);
973
1447
  font-size: var(--text-3xl);
974
1448
  font-weight: var(--weight-semibold);
975
- line-height: var(--leading-tight);
1449
+ letter-spacing: var(--heading-tracking);
1450
+ text-transform: var(--heading-transform);
1451
+ font-variant-caps: var(--heading-caps);
1452
+ line-height: var(--heading-leading);
976
1453
  margin-block: var(--space-8) var(--space-3);
977
1454
  }
978
1455
 
979
1456
  [data-ui="prose"] h3 {
1457
+ font-family: var(--font-heading);
980
1458
  font-size: var(--text-2xl);
981
1459
  font-weight: var(--weight-semibold);
1460
+ letter-spacing: var(--heading-tracking);
1461
+ text-transform: var(--heading-transform);
1462
+ font-variant-caps: var(--heading-caps);
982
1463
  line-height: var(--leading-snug);
983
1464
  margin-block: var(--space-6) var(--space-3);
984
1465
  }
985
1466
 
986
1467
  [data-ui="prose"] h4 {
1468
+ font-family: var(--font-heading);
987
1469
  font-size: var(--text-xl);
988
1470
  font-weight: var(--weight-semibold);
1471
+ letter-spacing: var(--heading-tracking);
1472
+ text-transform: var(--heading-transform);
1473
+ font-variant-caps: var(--heading-caps);
989
1474
  line-height: var(--leading-snug);
990
1475
  margin-block: var(--space-6) var(--space-2);
991
1476
  }
@@ -996,8 +1481,8 @@ table {
996
1481
 
997
1482
  [data-ui="prose"] a {
998
1483
  color: var(--color-primary);
999
- text-decoration: underline;
1000
- text-underline-offset: 2px;
1484
+ text-decoration-line: var(--link-decoration);
1485
+ text-underline-offset: var(--link-underline-offset);
1001
1486
  }
1002
1487
 
1003
1488
  [data-ui="prose"] a:hover {
@@ -1034,7 +1519,7 @@ table {
1034
1519
  }
1035
1520
 
1036
1521
  [data-ui="prose"] blockquote {
1037
- border-inline-start: 3px solid var(--color-border-strong);
1522
+ border-inline-start: var(--border-width-lg) solid var(--color-border-strong);
1038
1523
  padding-inline-start: var(--space-4);
1039
1524
  color: var(--color-fg-muted);
1040
1525
  margin-block: var(--space-4);
@@ -1056,9 +1541,15 @@ table {
1056
1541
  margin-block: var(--space-1);
1057
1542
  }
1058
1543
 
1544
+ /* The bullet. `currentColor` by default — the initial value — so a list looks
1545
+ exactly as it did; a theme that wants accented markers sets --marker-color. */
1546
+ [data-ui="prose"] li::marker {
1547
+ color: var(--marker-color);
1548
+ }
1549
+
1059
1550
  [data-ui="prose"] hr {
1060
1551
  border: none;
1061
- border-block-start: 1px solid var(--color-border);
1552
+ border-block-start: var(--border-width) solid var(--color-border);
1062
1553
  margin-block: var(--space-8);
1063
1554
  }
1064
1555
 
@@ -1077,12 +1568,12 @@ table {
1077
1568
  font-weight: var(--weight-semibold);
1078
1569
  text-align: start;
1079
1570
  padding: var(--space-2) var(--space-3);
1080
- border-block-end: 2px solid var(--color-border-strong);
1571
+ border-block-end: var(--border-width-strong) solid var(--color-border-strong);
1081
1572
  }
1082
1573
 
1083
1574
  [data-ui="prose"] td {
1084
1575
  padding: var(--space-2) var(--space-3);
1085
- border-block-end: 1px solid var(--color-border);
1576
+ border-block-end: var(--border-width) solid var(--color-border);
1086
1577
  }
1087
1578
 
1088
1579
  /* First child no top margin, last child no bottom margin */
@@ -1267,7 +1758,7 @@ table {
1267
1758
 
1268
1759
  /* === primitives/avatar.css === */
1269
1760
  /* @ui:component avatar */
1270
- /* @ui:tokens color-bg-muted color-fg-muted radius-full font-sans text-xs text-sm weight-medium */
1761
+ /* @ui:tokens color-bg-muted color-fg-muted radius-full font-ui text-xs text-sm weight-medium */
1271
1762
 
1272
1763
  /* ── Base ── */
1273
1764
  [data-ui="avatar"] {
@@ -1297,7 +1788,7 @@ table {
1297
1788
  height: 100%;
1298
1789
  background: var(--color-bg-muted);
1299
1790
  color: var(--color-fg-muted);
1300
- font-family: var(--font-sans);
1791
+ font-family: var(--font-ui);
1301
1792
  font-size: var(--text-sm);
1302
1793
  font-weight: var(--weight-medium);
1303
1794
  text-transform: uppercase;
@@ -1322,7 +1813,7 @@ table {
1322
1813
 
1323
1814
  /* === primitives/badge.css === */
1324
1815
  /* @ui:component badge */
1325
- /* @ui:tokens color-bg-muted color-fg color-primary color-primary-fg color-primary-subtle color-secondary color-secondary-fg color-destructive color-destructive-fg color-destructive-subtle color-success color-success-subtle color-warning color-warning-subtle radius-full space-1 space-2 font-sans text-xs text-sm weight-medium */
1816
+ /* @ui:tokens color-bg-muted color-fg color-primary color-primary-fg color-primary-subtle color-secondary color-secondary-fg color-destructive color-destructive-fg color-destructive-subtle color-success color-success-subtle color-warning color-warning-subtle radius-full space-1 space-2 font-ui text-xs text-sm weight-medium corner-shape */
1326
1817
 
1327
1818
  /* ── Base ── */
1328
1819
  [data-ui="badge"] {
@@ -1332,9 +1823,10 @@ table {
1332
1823
  gap: var(--space-1);
1333
1824
  padding: 0.125rem var(--space-2);
1334
1825
  border-radius: var(--badge-radius, var(--radius-full));
1826
+ corner-shape: var(--corner-shape);
1335
1827
  background: var(--color-bg-muted);
1336
1828
  color: var(--color-fg);
1337
- font-family: var(--badge-font, var(--font-sans));
1829
+ font-family: var(--badge-font, var(--font-ui));
1338
1830
  font-size: var(--text-xs);
1339
1831
  font-weight: var(--weight-medium);
1340
1832
  line-height: 1.5;
@@ -1380,11 +1872,11 @@ table {
1380
1872
 
1381
1873
  /* === primitives/breadcrumb.css === */
1382
1874
  /* @ui:component breadcrumb */
1383
- /* @ui:tokens color-fg color-fg-muted color-fg-subtle color-primary-hover color-ring radius-sm space-2 text-xs text-sm text-base font-sans weight-medium duration-fast ease-default */
1875
+ /* @ui:tokens color-fg color-fg-muted color-fg-subtle color-primary-hover color-ring radius-sm space-2 text-xs text-sm text-base font-ui weight-medium duration-fast ease-default focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow link-decoration */
1384
1876
 
1385
1877
  /* ── Root ── */
1386
1878
  [data-ui="breadcrumb"] {
1387
- font-family: var(--breadcrumb-font, var(--font-sans));
1879
+ font-family: var(--breadcrumb-font, var(--font-ui));
1388
1880
  font-size: var(--breadcrumb-size, var(--text-sm));
1389
1881
  color: var(--color-fg-muted);
1390
1882
  }
@@ -1410,12 +1902,13 @@ table {
1410
1902
 
1411
1903
  [data-ui="breadcrumb"] [data-part="item"]:hover {
1412
1904
  color: var(--color-primary-hover);
1413
- text-decoration: underline;
1905
+ text-decoration-line: var(--link-decoration);
1414
1906
  }
1415
1907
 
1416
1908
  [data-ui="breadcrumb"] [data-part="item"]:focus-visible {
1417
- outline: 2px solid var(--color-ring);
1418
- outline-offset: 2px;
1909
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1910
+ outline-offset: var(--focus-ring-offset);
1911
+ box-shadow: var(--focus-shadow);
1419
1912
  }
1420
1913
 
1421
1914
  /* ── Separator (presentational) ── */
@@ -1455,7 +1948,7 @@ table {
1455
1948
 
1456
1949
  /* === primitives/button.css === */
1457
1950
  /* @ui:component button */
1458
- /* @ui:tokens color-primary color-primary-hover color-primary-fg color-secondary color-secondary-hover color-secondary-fg color-destructive color-destructive-hover color-destructive-fg color-bg color-bg-muted color-bg-subtle color-fg color-border color-ring radius-md space-2 space-3 space-4 space-6 font-sans text-xs text-sm text-base weight-medium duration-fast ease-default shadow-xs radius-full */
1951
+ /* @ui:tokens color-primary color-primary-hover color-primary-fg color-secondary color-secondary-hover color-secondary-fg color-destructive color-destructive-hover color-destructive-fg color-bg color-bg-muted color-bg-subtle color-fg color-border color-ring radius-md space-2 space-3 space-4 space-6 font-ui text-xs text-sm text-base weight-medium duration-fast ease-default shadow-xs radius-full border-width border-width-strong corner-shape focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow button-text-transform motion-hover-lift link-decoration disabled-opacity */
1459
1952
 
1460
1953
  /* ── Base ── */
1461
1954
  [data-ui="button"] {
@@ -1465,18 +1958,21 @@ table {
1465
1958
  gap: var(--space-2);
1466
1959
  height: var(--button-height-md, 40px);
1467
1960
  padding-inline: var(--space-4);
1468
- border: 1px solid var(--color-border);
1961
+ border: var(--border-width) solid var(--color-border);
1469
1962
  border-radius: var(--button-radius, var(--radius-md));
1963
+ corner-shape: var(--corner-shape);
1470
1964
  background: var(--color-bg);
1471
1965
  color: var(--color-fg);
1472
- font-family: var(--font-sans);
1966
+ font-family: var(--font-ui);
1473
1967
  font-size: var(--text-sm);
1474
1968
  font-weight: var(--weight-medium);
1969
+ text-transform: var(--button-text-transform);
1475
1970
  line-height: 1;
1476
1971
  cursor: pointer;
1477
1972
  transition: background var(--duration-fast) var(--ease-default),
1478
1973
  border-color var(--duration-fast) var(--ease-default),
1479
1974
  color var(--duration-fast) var(--ease-default),
1975
+ translate var(--duration-fast) var(--ease-default),
1480
1976
  box-shadow var(--duration-fast) var(--ease-default);
1481
1977
  user-select: none;
1482
1978
  white-space: nowrap;
@@ -1485,11 +1981,16 @@ table {
1485
1981
 
1486
1982
  [data-ui="button"]:hover {
1487
1983
  background: var(--color-bg-muted);
1984
+ /* The hover lift. `none` by default — the initial value of `translate` — so
1985
+ this rule computes what the button computed before the token existed; a
1986
+ theme with a springy personality sets `--motion-hover-lift: 0 -1px`. */
1987
+ translate: var(--motion-hover-lift);
1488
1988
  }
1489
1989
 
1490
1990
  [data-ui="button"]:focus-visible {
1491
- outline: 2px solid var(--color-ring);
1492
- outline-offset: 2px;
1991
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
1992
+ outline-offset: var(--focus-ring-offset);
1993
+ box-shadow: var(--focus-shadow);
1493
1994
  }
1494
1995
 
1495
1996
  /* ── Variants ── */
@@ -1545,7 +2046,7 @@ table {
1545
2046
  padding: 0;
1546
2047
  }
1547
2048
  [data-ui="button"][data-variant="link"]:hover {
1548
- text-decoration: underline;
2049
+ text-decoration-line: var(--link-decoration);
1549
2050
  }
1550
2051
 
1551
2052
  /* ── Sizes ── */
@@ -1564,7 +2065,7 @@ table {
1564
2065
  /* ── States ── */
1565
2066
  [data-ui="button"]:disabled,
1566
2067
  [data-ui="button"][data-state="disabled"] {
1567
- opacity: 0.5;
2068
+ opacity: var(--disabled-opacity);
1568
2069
  cursor: not-allowed;
1569
2070
  pointer-events: none;
1570
2071
  }
@@ -1579,7 +2080,7 @@ table {
1579
2080
  position: absolute;
1580
2081
  width: 1em;
1581
2082
  height: 1em;
1582
- border: 2px solid currentColor;
2083
+ border: var(--border-width-strong) solid currentColor;
1583
2084
  border-inline-end-color: transparent;
1584
2085
  border-radius: var(--radius-full);
1585
2086
  animation: faqir-spin 0.6s linear infinite;
@@ -1626,7 +2127,7 @@ table {
1626
2127
 
1627
2128
  /* === primitives/callout.css === */
1628
2129
  /* @ui:component callout */
1629
- /* @ui:tokens callout-radius callout-padding-y callout-padding-x callout-border-left-width callout-font-size callout-icon-size callout-fg color-fg color-fg-muted color-info color-info-subtle color-warning color-warning-subtle color-destructive color-destructive-subtle color-success color-success-subtle color-bg-muted color-border color-ring space-1 radius-sm font-sans weight-semibold */
2130
+ /* @ui:tokens callout-radius callout-padding-y callout-padding-x callout-border-left-width callout-font-size callout-icon-size callout-fg color-fg color-fg-muted color-info color-info-subtle color-warning color-warning-subtle color-destructive color-destructive-subtle color-success color-success-subtle color-bg-muted color-border color-ring space-1 radius-sm font-heading font-body weight-semibold focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
1630
2131
 
1631
2132
  /* ── Base ── */
1632
2133
  [data-ui="callout"] {
@@ -1635,7 +2136,7 @@ table {
1635
2136
  padding: var(--callout-padding-y) var(--callout-padding-x);
1636
2137
  border-radius: var(--callout-radius);
1637
2138
  border-inline-start: var(--callout-border-left-width) solid;
1638
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
2139
+ font-family: var(--doc-font, var(--font-body));
1639
2140
  font-size: var(--callout-font-size);
1640
2141
  line-height: var(--doc-line-height, 1.5);
1641
2142
  }
@@ -1666,6 +2167,7 @@ table {
1666
2167
  /* ── Title ── */
1667
2168
  [data-ui="callout"] [data-part="title"] {
1668
2169
  display: block;
2170
+ font-family: var(--font-heading);
1669
2171
  font-weight: var(--weight-semibold);
1670
2172
  margin-bottom: var(--doc-label-gap, var(--space-1, 0.25rem));
1671
2173
  }
@@ -1692,8 +2194,9 @@ table {
1692
2194
  }
1693
2195
 
1694
2196
  [data-ui="callout"] [data-part="dismiss"]:focus-visible {
1695
- outline: 2px solid var(--color-ring, var(--color-info));
1696
- outline-offset: 2px;
2197
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2198
+ outline-offset: var(--focus-ring-offset);
2199
+ box-shadow: var(--focus-shadow);
1697
2200
  opacity: 1;
1698
2201
  }
1699
2202
 
@@ -1779,17 +2282,36 @@ table {
1779
2282
 
1780
2283
  /* === primitives/card.css === */
1781
2284
  /* @ui:component card */
1782
- /* @ui:tokens color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border color-fg color-fg-muted radius-lg shadow-sm space-4 space-6 font-sans text-sm text-lg text-xl weight-semibold leading-tight */
2285
+ /* @ui:tokens color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border color-fg color-fg-muted radius-lg shadow-sm space-4 space-6 font-heading text-sm text-lg text-xl weight-semibold leading-tight border-width corner-shape card-border-width surface-backdrop texture-surface motion-hover-lift duration-fast ease-default */
1783
2286
 
1784
2287
  /* ── Base ── */
1785
2288
  [data-ui="card"] {
1786
2289
  display: flex;
1787
2290
  flex-direction: column;
1788
- border: 1px solid var(--card-border, var(--color-surface-1-border));
2291
+ border: var(--card-border-width) solid var(--card-border, var(--color-surface-1-border));
1789
2292
  border-radius: var(--card-radius, var(--radius-lg));
1790
- background: var(--card-bg, var(--color-surface-1));
2293
+ corner-shape: var(--corner-shape);
2294
+ /* One shorthand, two layers: the material on top, the fill beneath. The fill
2295
+ is the final layer, so `--card-bg` may be a colour OR a gradient — what 1.0
2296
+ projects set it to — and the texture (`none` by default) never clobbers it. */
2297
+ background: var(--texture-surface), var(--card-bg, var(--color-surface-1));
1791
2298
  box-shadow: var(--card-shadow, var(--shadow-sm));
1792
2299
  overflow: hidden;
2300
+ transition: translate var(--duration-fast) var(--ease-default);
2301
+ }
2302
+
2303
+ /* The hover lift, the same axis `button` reads. `none` by default (the initial
2304
+ value of `translate`), so a card sits exactly where it always sat until a
2305
+ theme says surfaces rise under the pointer. */
2306
+ [data-ui="card"]:hover {
2307
+ translate: var(--motion-hover-lift);
2308
+ }
2309
+
2310
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
2311
+ [data-ui="card"] {
2312
+ -webkit-backdrop-filter: var(--surface-backdrop);
2313
+ backdrop-filter: var(--surface-backdrop);
2314
+ }
1793
2315
  }
1794
2316
 
1795
2317
  /* ── Variants ── */
@@ -1798,7 +2320,7 @@ table {
1798
2320
  }
1799
2321
 
1800
2322
  [data-ui="card"][data-variant="filled"] {
1801
- background: var(--color-surface-2);
2323
+ background: var(--texture-surface), var(--color-surface-2);
1802
2324
  border-color: var(--color-surface-2-border);
1803
2325
  box-shadow: none;
1804
2326
  }
@@ -1813,7 +2335,7 @@ table {
1813
2335
  }
1814
2336
 
1815
2337
  [data-ui="card"] > [data-part="header"] > [data-part="title"] {
1816
- font-family: var(--font-sans);
2338
+ font-family: var(--font-heading);
1817
2339
  font-size: var(--text-lg);
1818
2340
  font-weight: var(--weight-semibold);
1819
2341
  line-height: var(--leading-tight);
@@ -1854,9 +2376,19 @@ table {
1854
2376
  padding-top: 0;
1855
2377
  }
1856
2378
 
2379
+ /* ── Motion ── */
2380
+ /* The hover lift is the only thing a card animates, and it is `none` until a
2381
+ theme states one — but the house rule is that a stylesheet which transitions
2382
+ carries its own opt-out, so a reader never has to check the token first. */
2383
+ @media (prefers-reduced-motion: reduce) {
2384
+ [data-ui="card"] {
2385
+ transition: none;
2386
+ }
2387
+ }
2388
+
1857
2389
  /* === primitives/checkbox.css === */
1858
2390
  /* @ui:component checkbox */
1859
- /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-sm space-1 space-2 duration-fast ease-default */
2391
+ /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring space-1 space-2 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow checkbox-radius checkbox-size disabled-opacity */
1860
2392
 
1861
2393
  /* -- Label wrapper -- */
1862
2394
  [data-ui="checkbox-label"] {
@@ -1868,7 +2400,7 @@ table {
1868
2400
 
1869
2401
  [data-ui="checkbox-label"]:has([data-ui="checkbox"]:disabled) {
1870
2402
  cursor: not-allowed;
1871
- opacity: 0.5;
2403
+ opacity: var(--disabled-opacity);
1872
2404
  }
1873
2405
 
1874
2406
  /* -- Base -- */
@@ -1880,8 +2412,8 @@ table {
1880
2412
  width: var(--checkbox-size, 18px);
1881
2413
  height: var(--checkbox-size, 18px);
1882
2414
  flex-shrink: 0;
1883
- border: 1px solid var(--color-border);
1884
- border-radius: var(--checkbox-radius, var(--radius-sm));
2415
+ border: var(--border-width) solid var(--color-border);
2416
+ border-radius: var(--checkbox-radius);
1885
2417
  background: var(--color-bg);
1886
2418
  cursor: pointer;
1887
2419
  transition: background var(--duration-fast) var(--ease-default),
@@ -1894,8 +2426,9 @@ table {
1894
2426
  }
1895
2427
 
1896
2428
  [data-ui="checkbox"]:focus-visible {
1897
- outline: 2px solid var(--color-ring);
1898
- outline-offset: 2px;
2429
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2430
+ outline-offset: var(--focus-ring-offset);
2431
+ box-shadow: var(--focus-shadow);
1899
2432
  }
1900
2433
 
1901
2434
  /* -- Checked -- */
@@ -1986,7 +2519,7 @@ table {
1986
2519
  The mask has to opt out of the substitution to stay readable. [W3-3] */
1987
2520
  @media (forced-colors: active) {
1988
2521
  [data-ui="checkbox"] {
1989
- border: 1px solid ButtonText;
2522
+ border: var(--border-width) solid ButtonText;
1990
2523
  }
1991
2524
 
1992
2525
  [data-ui="checkbox"]:checked,
@@ -2010,7 +2543,7 @@ table {
2010
2543
 
2011
2544
  /* === primitives/chip.css === */
2012
2545
  /* @ui:component chip */
2013
- /* @ui:tokens color-bg-muted color-fg color-fg-muted color-primary color-primary-subtle color-destructive color-destructive-subtle color-border color-ring radius-full space-1 space-2 space-3 font-sans text-xs text-sm weight-medium */
2546
+ /* @ui:tokens color-bg-muted color-fg color-fg-muted color-primary color-primary-subtle color-destructive color-destructive-subtle color-border color-ring radius-full space-1 space-2 space-3 font-ui text-xs text-sm weight-medium border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
2014
2547
 
2015
2548
  /* ── Base ── */
2016
2549
  [data-ui="chip"] {
@@ -2018,11 +2551,11 @@ table {
2018
2551
  align-items: center;
2019
2552
  gap: var(--space-1);
2020
2553
  padding: var(--space-1) var(--space-2);
2021
- border: 1px solid transparent;
2554
+ border: var(--border-width) solid transparent;
2022
2555
  border-radius: var(--chip-radius, var(--radius-full));
2023
2556
  background: var(--color-bg-muted);
2024
2557
  color: var(--color-fg);
2025
- font-family: var(--chip-font, var(--font-sans));
2558
+ font-family: var(--chip-font, var(--font-ui));
2026
2559
  font-size: var(--text-sm);
2027
2560
  font-weight: var(--weight-medium);
2028
2561
  line-height: 1.2;
@@ -2058,8 +2591,11 @@ table {
2058
2591
  }
2059
2592
 
2060
2593
  [data-ui="chip"] [data-part="dismiss"]:focus-visible {
2061
- outline: 2px solid var(--color-ring);
2062
- outline-offset: 1px;
2594
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2595
+ /* Half the default gap — the dismiss target is small, and the full ring
2596
+ would collide with the chip's own edge. */
2597
+ outline-offset: calc(var(--focus-ring-offset) / 2);
2598
+ box-shadow: var(--focus-shadow);
2063
2599
  }
2064
2600
 
2065
2601
  /* ── Variants ── */
@@ -2282,12 +2818,12 @@ table {
2282
2818
 
2283
2819
  /* === primitives/collapsible.css === */
2284
2820
  /* @ui:component collapsible */
2285
- /* @ui:tokens color-fg color-fg-muted color-bg-subtle color-border color-ring radius-md space-2 space-3 text-sm text-base font-sans weight-medium duration-fast duration-normal ease-default */
2821
+ /* @ui:tokens color-fg color-fg-muted color-bg-subtle color-border color-ring radius-md space-2 space-3 text-sm text-base font-ui weight-medium duration-fast duration-normal ease-default border-width border-width-strong focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow */
2286
2822
 
2287
2823
  /* ── Root — native <details>, so it opens/closes with zero JavaScript ── */
2288
2824
  [data-ui="collapsible"] {
2289
2825
  border-radius: var(--collapsible-radius, var(--radius-md));
2290
- font-family: var(--collapsible-font, var(--font-sans));
2826
+ font-family: var(--collapsible-font, var(--font-ui));
2291
2827
  color: var(--color-fg);
2292
2828
  }
2293
2829
 
@@ -2317,8 +2853,9 @@ table {
2317
2853
  }
2318
2854
 
2319
2855
  [data-ui="collapsible"] [data-part="trigger"]:focus-visible {
2320
- outline: 2px solid var(--color-ring);
2321
- outline-offset: 2px;
2856
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
2857
+ outline-offset: var(--focus-ring-offset);
2858
+ box-shadow: var(--focus-shadow);
2322
2859
  }
2323
2860
 
2324
2861
  /* Chevron indicator — rotates when open, CSS-only */
@@ -2327,8 +2864,8 @@ table {
2327
2864
  flex: none;
2328
2865
  width: 0.5em;
2329
2866
  height: 0.5em;
2330
- border-inline-end: 2px solid var(--color-fg-muted);
2331
- border-block-end: 2px solid var(--color-fg-muted);
2867
+ border-inline-end: var(--border-width-strong) solid var(--color-fg-muted);
2868
+ border-block-end: var(--border-width-strong) solid var(--color-fg-muted);
2332
2869
  transform: rotate(45deg);
2333
2870
  transition: transform var(--duration-normal) var(--ease-default);
2334
2871
  }
@@ -2347,7 +2884,7 @@ table {
2347
2884
 
2348
2885
  /* ── Bordered variant ── */
2349
2886
  [data-ui="collapsible"][data-variant="bordered"] {
2350
- border: 1px solid var(--color-border);
2887
+ border: var(--border-width) solid var(--color-border);
2351
2888
  }
2352
2889
 
2353
2890
  /* ── Open/close animation via ::details-content, where supported ── */
@@ -2480,13 +3017,13 @@ table {
2480
3017
 
2481
3018
  /* === primitives/description-list.css === */
2482
3019
  /* @ui:component description-list */
2483
- /* @ui:tokens color-fg color-fg-muted color-border doc-font doc-line-height space-1 space-2 space-3 space-4 space-6 text-xs text-sm text-base font-sans weight-semibold */
3020
+ /* @ui:tokens color-fg color-fg-muted color-border doc-font doc-line-height space-1 space-2 space-3 space-4 space-6 text-xs text-sm text-base font-body weight-semibold border-width */
2484
3021
 
2485
3022
  /* ── Base ── */
2486
3023
  [data-ui="description-list"] {
2487
3024
  margin: 0;
2488
3025
  padding: 0;
2489
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3026
+ font-family: var(--doc-font, var(--font-body));
2490
3027
  }
2491
3028
 
2492
3029
  /* ── Term ── */
@@ -2542,7 +3079,7 @@ table {
2542
3079
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"],
2543
3080
  [data-ui="description-list"][data-divided]:not([data-variant]) [data-part="details"] {
2544
3081
  padding-bottom: var(--space-4);
2545
- border-bottom: 1px solid var(--color-border);
3082
+ border-bottom: var(--border-width) solid var(--color-border);
2546
3083
  }
2547
3084
 
2548
3085
  [data-ui="description-list"][data-divided][data-variant="vertical"] [data-part="details"]:last-child,
@@ -2554,7 +3091,7 @@ table {
2554
3091
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="term"],
2555
3092
  [data-ui="description-list"][data-divided][data-variant="horizontal"] [data-part="details"] {
2556
3093
  padding-bottom: var(--space-3);
2557
- border-bottom: 1px solid var(--color-border);
3094
+ border-bottom: var(--border-width) solid var(--color-border);
2558
3095
  }
2559
3096
 
2560
3097
  /* ── Size: Small ── */
@@ -2592,7 +3129,7 @@ table {
2592
3129
 
2593
3130
  /* === primitives/empty-state.css === */
2594
3131
  /* @ui:component empty-state */
2595
- /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl */
3132
+ /* @ui:tokens color-fg-muted color-fg-subtle space-3 space-4 space-6 space-8 text-sm text-lg text-3xl font-heading */
2596
3133
 
2597
3134
  /* ── Base ── */
2598
3135
  [data-ui="empty-state"] {
@@ -2613,6 +3150,7 @@ table {
2613
3150
 
2614
3151
  /* ── Title ── */
2615
3152
  [data-ui="empty-state"] [data-part="title"] {
3153
+ font-family: var(--font-heading);
2616
3154
  font-size: var(--text-lg);
2617
3155
  font-weight: var(--weight-medium);
2618
3156
  color: var(--color-fg);
@@ -2660,7 +3198,7 @@ table {
2660
3198
 
2661
3199
  /* === primitives/field-group.css === */
2662
3200
  /* @ui:component field-group */
2663
- /* @ui:tokens field-label-size field-label-weight field-label-color field-description-size field-description-color field-error-size field-error-color field-required-color field-required-marker field-validating-color field-disabled-opacity color-destructive color-success space-1 space-2 space-3 space-4 text-xs text-sm font-sans */
3201
+ /* @ui:tokens field-label-size field-label-weight field-label-color field-description-size field-description-color field-error-size field-error-color field-required-color field-required-marker field-validating-color field-disabled-opacity color-destructive color-success space-1 space-2 space-3 space-4 text-xs text-sm font-body border-width */
2664
3202
 
2665
3203
  /* ── Base / spacing ownership ──
2666
3204
  A field-group owns only its tight, density-aware intra-field step: label →
@@ -2672,7 +3210,7 @@ table {
2672
3210
  display: flex;
2673
3211
  flex-direction: column;
2674
3212
  gap: var(--space-2);
2675
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3213
+ font-family: var(--doc-font, var(--font-body));
2676
3214
  }
2677
3215
 
2678
3216
  /* ── Label ── */
@@ -2742,7 +3280,7 @@ table {
2742
3280
  [data-ui="field-group"][data-state="invalid"] [data-ui="textarea"],
2743
3281
  [data-ui="field-group"][data-state="invalid"] [data-ui="select"] {
2744
3282
  border-color: var(--field-error-color);
2745
- box-shadow: 0 0 0 1px var(--field-error-color);
3283
+ box-shadow: 0 0 0 var(--border-width) var(--field-error-color);
2746
3284
  }
2747
3285
 
2748
3286
  /* ── State: Validating ──
@@ -2752,7 +3290,7 @@ table {
2752
3290
  [data-ui="field-group"][data-state="validating"] [data-ui="textarea"],
2753
3291
  [data-ui="field-group"][data-state="validating"] [data-ui="select"] {
2754
3292
  border-color: var(--field-validating-color);
2755
- box-shadow: 0 0 0 1px var(--field-validating-color);
3293
+ box-shadow: 0 0 0 var(--border-width) var(--field-validating-color);
2756
3294
  }
2757
3295
 
2758
3296
  /* ── State: Disabled ──
@@ -2771,8 +3309,8 @@ table {
2771
3309
  [data-ui="field-group"][data-state="valid"] [data-ui="input"],
2772
3310
  [data-ui="field-group"][data-state="valid"] [data-ui="textarea"],
2773
3311
  [data-ui="field-group"][data-state="valid"] [data-ui="select"] {
2774
- border-color: var(--color-success, oklch(0.62 0.19 145));
2775
- box-shadow: 0 0 0 1px var(--color-success, oklch(0.62 0.19 145));
3312
+ border-color: var(--color-success);
3313
+ box-shadow: 0 0 0 var(--border-width) var(--color-success);
2776
3314
  }
2777
3315
 
2778
3316
  /* ── Variant: Horizontal ── */
@@ -3077,7 +3615,7 @@ table {
3077
3615
 
3078
3616
  /* === primitives/image.css === */
3079
3617
  /* @ui:component image */
3080
- /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-sans */
3618
+ /* @ui:tokens image-radius image-border image-border-width image-caption-size image-caption-color color-bg-muted font-body */
3081
3619
 
3082
3620
  /* ── Base ── */
3083
3621
  [data-ui="image"] {
@@ -3101,7 +3639,7 @@ table {
3101
3639
  [data-ui="image"] [data-part="caption"] {
3102
3640
  display: block;
3103
3641
  margin-top: var(--space-2);
3104
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3642
+ font-family: var(--doc-font, var(--font-body));
3105
3643
  font-size: var(--image-caption-size);
3106
3644
  color: var(--image-caption-color);
3107
3645
  line-height: 1.4;
@@ -3198,7 +3736,7 @@ table {
3198
3736
 
3199
3737
  /* === primitives/input.css === */
3200
3738
  /* @ui:component input */
3201
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
3739
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width corner-shape focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
3202
3740
 
3203
3741
  /* ── Base ── */
3204
3742
  [data-ui="input"] {
@@ -3206,11 +3744,18 @@ table {
3206
3744
  width: 100%;
3207
3745
  height: var(--input-height, 40px);
3208
3746
  padding-inline: var(--space-3);
3209
- border: 1px solid var(--color-border);
3747
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
3748
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
3749
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
3750
+ is drawn. Identical to the shorthand at every other value of the token. */
3751
+ border-style: solid;
3752
+ border-color: var(--color-border);
3753
+ border-width: var(--input-border-width);
3210
3754
  border-radius: var(--input-radius, var(--radius-md));
3211
- background: var(--input-bg, var(--color-bg));
3755
+ corner-shape: var(--corner-shape);
3756
+ background: var(--input-fill);
3212
3757
  color: var(--color-fg);
3213
- font-family: var(--input-font, var(--font-sans));
3758
+ font-family: var(--input-font, var(--font-ui));
3214
3759
  font-size: var(--text-sm);
3215
3760
  line-height: 1;
3216
3761
  transition: border-color var(--duration-fast) var(--ease-default),
@@ -3226,8 +3771,11 @@ table {
3226
3771
  }
3227
3772
 
3228
3773
  [data-ui="input"]:focus {
3229
- outline: 2px solid var(--color-ring);
3230
- outline-offset: -1px;
3774
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
3775
+ /* The ring replaces the border rather than sitting outside it: inset by
3776
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
3777
+ outline-offset: calc(-1 * var(--input-border-width));
3778
+ box-shadow: var(--focus-shadow);
3231
3779
  border-color: transparent;
3232
3780
  }
3233
3781
 
@@ -3255,7 +3803,7 @@ table {
3255
3803
  }
3256
3804
 
3257
3805
  [data-ui="input"]:disabled {
3258
- opacity: 0.5;
3806
+ opacity: var(--disabled-opacity);
3259
3807
  cursor: not-allowed;
3260
3808
  }
3261
3809
 
@@ -3318,7 +3866,7 @@ table {
3318
3866
 
3319
3867
  /* === primitives/kbd.css === */
3320
3868
  /* @ui:component kbd */
3321
- /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs */
3869
+ /* @ui:tokens color-bg-subtle color-fg color-border radius-sm space-1h font-mono text-xs border-width border-width-strong */
3322
3870
 
3323
3871
  /* ── Base ── */
3324
3872
  [data-ui="kbd"] {
@@ -3328,8 +3876,8 @@ table {
3328
3876
  height: 20px;
3329
3877
  min-width: 20px;
3330
3878
  padding-inline: var(--space-1h);
3331
- border: 1px solid var(--color-border);
3332
- border-bottom-width: 2px;
3879
+ border: var(--border-width) solid var(--color-border);
3880
+ border-bottom-width: var(--border-width-strong);
3333
3881
  border-radius: var(--radius-sm);
3334
3882
  background: var(--color-bg-subtle);
3335
3883
  color: var(--color-fg);
@@ -3342,7 +3890,7 @@ table {
3342
3890
 
3343
3891
  /* === primitives/key-value.css === */
3344
3892
  /* @ui:component key-value */
3345
- /* @ui:tokens kv-label-color kv-label-weight kv-label-size kv-value-color kv-value-size kv-value-weight kv-gap kv-pair-gap kv-grid-gap text-xs text-sm text-base font-sans */
3893
+ /* @ui:tokens kv-label-color kv-label-weight kv-label-size kv-value-color kv-value-size kv-value-weight kv-gap kv-pair-gap kv-grid-gap text-xs text-sm text-base font-body */
3346
3894
 
3347
3895
  /* ── Base ── */
3348
3896
  [data-ui="key-value"] {
@@ -3351,7 +3899,7 @@ table {
3351
3899
  gap: var(--kv-pair-gap);
3352
3900
  margin: 0;
3353
3901
  padding: 0;
3354
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
3902
+ font-family: var(--doc-font, var(--font-body));
3355
3903
  }
3356
3904
 
3357
3905
  /* ── Label ── */
@@ -3481,12 +4029,12 @@ table {
3481
4029
 
3482
4030
  /* === primitives/label.css === */
3483
4031
  /* @ui:component label */
3484
- /* @ui:tokens color-fg color-fg-muted color-destructive font-sans text-xs text-sm text-base weight-medium */
4032
+ /* @ui:tokens color-fg color-fg-muted color-destructive font-ui text-xs text-sm text-base weight-medium disabled-opacity */
3485
4033
 
3486
4034
  /* ── Base ── */
3487
4035
  [data-ui="label"] {
3488
4036
  display: block;
3489
- font-family: var(--font-sans);
4037
+ font-family: var(--font-ui);
3490
4038
  font-size: var(--text-sm);
3491
4039
  font-weight: var(--weight-medium);
3492
4040
  color: var(--color-fg);
@@ -3519,21 +4067,21 @@ table {
3519
4067
 
3520
4068
  /* ── States ── */
3521
4069
  [data-ui="label"][data-state="disabled"] {
3522
- opacity: 0.5;
4070
+ opacity: var(--disabled-opacity);
3523
4071
  cursor: not-allowed;
3524
4072
  }
3525
4073
 
3526
4074
  /* === primitives/link.css === */
3527
4075
  /* @ui:component link */
3528
- /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 */
4076
+ /* @ui:tokens color-primary color-primary-hover color-primary-active color-fg color-fg-muted color-ring radius-sm space-1 focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow link-decoration link-thickness link-underline-offset */
3529
4077
 
3530
4078
  /* ── Base ── */
3531
4079
  [data-ui="link"] {
3532
4080
  color: var(--color-primary);
3533
4081
  font-family: inherit;
3534
- text-decoration: underline;
3535
- text-decoration-thickness: 1px;
3536
- text-underline-offset: 0.2em;
4082
+ text-decoration-line: var(--link-decoration);
4083
+ text-decoration-thickness: var(--link-thickness);
4084
+ text-underline-offset: var(--link-underline-offset);
3537
4085
  border-radius: var(--radius-sm);
3538
4086
  cursor: pointer;
3539
4087
  }
@@ -3547,8 +4095,9 @@ table {
3547
4095
  }
3548
4096
 
3549
4097
  [data-ui="link"]:focus-visible {
3550
- outline: 2px solid var(--color-ring);
3551
- outline-offset: 2px;
4098
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4099
+ outline-offset: var(--focus-ring-offset);
4100
+ box-shadow: var(--focus-shadow);
3552
4101
  }
3553
4102
 
3554
4103
  /* ── Variants ── */
@@ -3572,7 +4121,7 @@ table {
3572
4121
 
3573
4122
  /* === primitives/nav.css === */
3574
4123
  /* @ui:component nav */
3575
- /* @ui:tokens color-fg color-fg-muted color-primary color-primary-subtle color-bg-subtle color-border text-sm weight-medium radius-md space-1 space-2 space-3 space-4 duration-fast ease-default */
4124
+ /* @ui:tokens color-fg color-fg-muted color-primary color-primary-subtle color-bg-subtle color-border text-sm weight-medium radius-md space-1 space-2 space-3 space-4 duration-fast ease-default border-width border-width-strong */
3576
4125
 
3577
4126
  /* ── Base ── */
3578
4127
  [data-ui="nav"] {
@@ -3622,14 +4171,14 @@ table {
3622
4171
 
3623
4172
  /* ── Underline variant ── */
3624
4173
  [data-ui="nav"][data-variant="underline"] {
3625
- border-bottom: 1px solid var(--color-border);
4174
+ border-bottom: var(--border-width) solid var(--color-border);
3626
4175
  gap: 0;
3627
4176
  }
3628
4177
 
3629
4178
  [data-ui="nav"][data-variant="underline"] [data-part="link"] {
3630
4179
  border-radius: 0;
3631
4180
  padding: var(--space-2) var(--space-4);
3632
- border-bottom: 2px solid transparent;
4181
+ border-bottom: var(--border-width-strong) solid transparent;
3633
4182
  margin-bottom: -1px;
3634
4183
  }
3635
4184
 
@@ -3685,7 +4234,7 @@ table {
3685
4234
 
3686
4235
  /* === primitives/page-break.css === */
3687
4236
  /* @ui:component page-break */
3688
- /* @ui:tokens page-break-screen-color page-break-screen-style page-break-screen-label-color page-break-screen-label-size doc-font font-sans space-4 space-6 */
4237
+ /* @ui:tokens page-break-screen-color page-break-screen-style page-break-screen-label-color page-break-screen-label-size doc-font font-body space-4 space-6 border-width */
3689
4238
 
3690
4239
  /* ── Base (Screen) ── */
3691
4240
  [data-ui="page-break"] {
@@ -3700,12 +4249,12 @@ table {
3700
4249
  [data-ui="page-break"]::after {
3701
4250
  content: "";
3702
4251
  flex: 1;
3703
- border-top: 1px var(--page-break-screen-style) var(--page-break-screen-color);
4252
+ border-top: var(--border-width) var(--page-break-screen-style) var(--page-break-screen-color);
3704
4253
  }
3705
4254
 
3706
4255
  /* ── Label (Screen) ── */
3707
4256
  [data-ui="page-break"] {
3708
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4257
+ font-family: var(--doc-font, var(--font-body));
3709
4258
  font-size: var(--page-break-screen-label-size);
3710
4259
  color: var(--page-break-screen-label-color);
3711
4260
  letter-spacing: 0.05em;
@@ -3747,7 +4296,7 @@ table {
3747
4296
 
3748
4297
  /* === primitives/progress.css === */
3749
4298
  /* @ui:component progress */
3750
- /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default */
4299
+ /* @ui:tokens color-primary color-bg-muted color-success color-warning color-destructive radius-full radius-md space-1 duration-normal ease-default border-width */
3751
4300
 
3752
4301
  /* ── Base ── */
3753
4302
  [data-ui="progress"] {
@@ -3822,7 +4371,7 @@ table {
3822
4371
  substitution and paints `Highlight`; the track keeps a visible boundary. [W3-3] */
3823
4372
  @media (forced-colors: active) {
3824
4373
  [data-ui="progress"] [data-part="track"] {
3825
- border: 1px solid ButtonText;
4374
+ border: var(--border-width) solid ButtonText;
3826
4375
  }
3827
4376
 
3828
4377
  [data-ui="progress"] [data-part="fill"],
@@ -3836,7 +4385,7 @@ table {
3836
4385
 
3837
4386
  /* === primitives/radio.css === */
3838
4387
  /* @ui:component radio */
3839
- /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-full space-1 space-2 duration-fast ease-default */
4388
+ /* @ui:tokens color-bg color-fg color-primary color-primary-fg color-border color-border-strong color-ring radius-full space-1 space-2 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow disabled-opacity */
3840
4389
 
3841
4390
  /* -- Radio group -- */
3842
4391
  [data-ui="radio-group"] {
@@ -3858,7 +4407,7 @@ table {
3858
4407
 
3859
4408
  [data-ui="radio-label"]:has([data-ui="radio"]:disabled) {
3860
4409
  cursor: not-allowed;
3861
- opacity: 0.5;
4410
+ opacity: var(--disabled-opacity);
3862
4411
  }
3863
4412
 
3864
4413
  /* -- Base -- */
@@ -3870,7 +4419,7 @@ table {
3870
4419
  width: var(--radio-size, 18px);
3871
4420
  height: var(--radio-size, 18px);
3872
4421
  flex-shrink: 0;
3873
- border: 1px solid var(--color-border);
4422
+ border: var(--border-width) solid var(--color-border);
3874
4423
  border-radius: var(--radius-full);
3875
4424
  background: var(--color-bg);
3876
4425
  cursor: pointer;
@@ -3884,8 +4433,9 @@ table {
3884
4433
  }
3885
4434
 
3886
4435
  [data-ui="radio"]:focus-visible {
3887
- outline: 2px solid var(--color-ring);
3888
- outline-offset: 2px;
4436
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4437
+ outline-offset: var(--focus-ring-offset);
4438
+ box-shadow: var(--focus-shadow);
3889
4439
  }
3890
4440
 
3891
4441
  /* -- Checked -- */
@@ -3938,7 +4488,7 @@ table {
3938
4488
  inside a `--color-primary` circle, and the OS collapses both to one colour. [W3-3] */
3939
4489
  @media (forced-colors: active) {
3940
4490
  [data-ui="radio"] {
3941
- border: 1px solid ButtonText;
4491
+ border: var(--border-width) solid ButtonText;
3942
4492
  }
3943
4493
 
3944
4494
  [data-ui="radio"]:checked {
@@ -3958,7 +4508,7 @@ table {
3958
4508
 
3959
4509
  /* === primitives/select.css === */
3960
4510
  /* @ui:component select */
3961
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
4511
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
3962
4512
 
3963
4513
  /* -- Base -- */
3964
4514
  [data-ui="select"] {
@@ -3967,11 +4517,17 @@ table {
3967
4517
  height: var(--select-height, 40px);
3968
4518
  padding-inline: var(--space-3);
3969
4519
  padding-inline-end: var(--space-8, 2rem);
3970
- border: 1px solid var(--color-border);
4520
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
4521
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
4522
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
4523
+ is drawn. Identical to the shorthand at every other value of the token. */
4524
+ border-style: solid;
4525
+ border-color: var(--color-border);
4526
+ border-width: var(--input-border-width);
3971
4527
  border-radius: var(--select-radius, var(--radius-md));
3972
- background: var(--select-bg, var(--color-bg));
4528
+ background: var(--select-bg, var(--input-fill));
3973
4529
  color: var(--color-fg);
3974
- font-family: var(--select-font, var(--font-sans));
4530
+ font-family: var(--select-font, var(--font-ui));
3975
4531
  font-size: var(--text-sm);
3976
4532
  line-height: 1;
3977
4533
  cursor: pointer;
@@ -4001,8 +4557,11 @@ table {
4001
4557
  }
4002
4558
 
4003
4559
  [data-ui="select"]:focus {
4004
- outline: 2px solid var(--color-ring);
4005
- outline-offset: -1px;
4560
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
4561
+ /* The ring replaces the border rather than sitting outside it: inset by
4562
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
4563
+ outline-offset: calc(-1 * var(--input-border-width));
4564
+ box-shadow: var(--focus-shadow);
4006
4565
  border-color: transparent;
4007
4566
  }
4008
4567
 
@@ -4035,7 +4594,7 @@ table {
4035
4594
  }
4036
4595
 
4037
4596
  [data-ui="select"]:disabled {
4038
- opacity: 0.5;
4597
+ opacity: var(--disabled-opacity);
4039
4598
  cursor: not-allowed;
4040
4599
  }
4041
4600
 
@@ -4048,12 +4607,12 @@ table {
4048
4607
 
4049
4608
  /* === primitives/separator.css === */
4050
4609
  /* @ui:component separator */
4051
- /* @ui:tokens color-border space-4 text-xs color-fg-muted font-sans */
4610
+ /* @ui:tokens color-border space-4 text-xs color-fg-muted font-ui border-width-strong divider-width divider-style */
4052
4611
 
4053
4612
  /* ── Base (horizontal) ── */
4054
4613
  [data-ui="separator"] {
4055
4614
  border: none;
4056
- border-top: 1px solid var(--color-border);
4615
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4057
4616
  margin: 0;
4058
4617
  width: 100%;
4059
4618
  }
@@ -4061,7 +4620,7 @@ table {
4061
4620
  /* ── Vertical ── */
4062
4621
  [data-ui="separator"][data-variant="vertical"] {
4063
4622
  border-top: none;
4064
- border-inline-start: 1px solid var(--color-border);
4623
+ border-inline-start: var(--divider-width) var(--divider-style) var(--color-border);
4065
4624
  width: auto;
4066
4625
  height: 100%;
4067
4626
  align-self: stretch;
@@ -4079,11 +4638,11 @@ div[data-ui="separator"]::before,
4079
4638
  div[data-ui="separator"]::after {
4080
4639
  content: "";
4081
4640
  flex: 1;
4082
- border-top: 1px solid var(--color-border);
4641
+ border-top: var(--divider-width) var(--divider-style) var(--color-border);
4083
4642
  }
4084
4643
 
4085
4644
  [data-ui="separator"] [data-part="label"] {
4086
- font-family: var(--font-sans);
4645
+ font-family: var(--font-ui);
4087
4646
  font-size: var(--text-xs);
4088
4647
  color: var(--color-fg-muted);
4089
4648
  white-space: nowrap;
@@ -4121,17 +4680,17 @@ div[data-ui="separator"][data-style="dotted"]::after {
4121
4680
 
4122
4681
  /* ── Style: Thick ── */
4123
4682
  [data-ui="separator"][data-style="thick"] {
4124
- border-top-width: 2px;
4683
+ border-top-width: var(--border-width-strong);
4125
4684
  }
4126
4685
 
4127
4686
  [data-ui="separator"][data-style="thick"][data-variant="vertical"] {
4128
4687
  border-top-width: 0;
4129
- border-inline-start-width: 2px;
4688
+ border-inline-start-width: var(--border-width-strong);
4130
4689
  }
4131
4690
 
4132
4691
  div[data-ui="separator"][data-style="thick"]::before,
4133
4692
  div[data-ui="separator"][data-style="thick"]::after {
4134
- border-top-width: 2px;
4693
+ border-top-width: var(--border-width-strong);
4135
4694
  }
4136
4695
 
4137
4696
  /* ── Vertical Sizes ── */
@@ -4149,20 +4708,20 @@ div[data-ui="separator"][data-style="thick"]::after {
4149
4708
 
4150
4709
  /* === primitives/signature.css === */
4151
4710
  /* @ui:component signature */
4152
- /* @ui:tokens doc-signature-width doc-signature-gap doc-signature-line-color doc-signature-label-size doc-signature-label-color doc-font font-sans space-2 space-12 */
4711
+ /* @ui:tokens doc-signature-width doc-signature-gap doc-signature-line-color doc-signature-label-size doc-signature-label-color doc-font font-body space-2 space-12 border-width */
4153
4712
 
4154
4713
  /* ── Base ── */
4155
4714
  [data-ui="signature"] {
4156
4715
  display: flex;
4157
4716
  flex-direction: column;
4158
4717
  gap: var(--space-2);
4159
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
4718
+ font-family: var(--doc-font, var(--font-body));
4160
4719
  margin-top: var(--doc-signature-gap);
4161
4720
  }
4162
4721
 
4163
4722
  /* ── Line ── */
4164
4723
  [data-ui="signature"] [data-part="line"] {
4165
- border-top: 1px solid var(--doc-signature-line-color);
4724
+ border-top: var(--border-width) solid var(--doc-signature-line-color);
4166
4725
  min-height: 1px;
4167
4726
  }
4168
4727
 
@@ -4265,14 +4824,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4265
4824
 
4266
4825
  /* === primitives/spinner.css === */
4267
4826
  /* @ui:component spinner */
4268
- /* @ui:tokens color-border color-primary radius-full duration-normal ease-default */
4827
+ /* @ui:tokens color-border color-primary radius-full duration-normal ease-default border-width-strong border-width-lg */
4269
4828
 
4270
4829
  /* ── Base ── */
4271
4830
  [data-ui="spinner"] {
4272
4831
  display: inline-block;
4273
4832
  width: 24px;
4274
4833
  height: 24px;
4275
- border: 2px solid var(--color-border);
4834
+ border: var(--border-width-strong) solid var(--color-border);
4276
4835
  border-top-color: var(--color-primary);
4277
4836
  border-radius: var(--radius-full);
4278
4837
  animation: faqir-spin 0.75s linear infinite;
@@ -4288,13 +4847,13 @@ div[data-ui="separator"][data-style="thick"]::after {
4288
4847
  [data-ui="spinner"][data-size="lg"] {
4289
4848
  width: 32px;
4290
4849
  height: 32px;
4291
- border-width: 3px;
4850
+ border-width: var(--border-width-lg);
4292
4851
  }
4293
4852
 
4294
4853
  [data-ui="spinner"][data-size="xl"] {
4295
4854
  width: 48px;
4296
4855
  height: 48px;
4297
- border-width: 3px;
4856
+ border-width: var(--border-width-lg);
4298
4857
  }
4299
4858
 
4300
4859
  /* ── Motion ── */
@@ -4876,14 +5435,14 @@ div[data-ui="separator"][data-style="thick"]::after {
4876
5435
 
4877
5436
  /* === primitives/stat.css === */
4878
5437
  /* @ui:component stat */
4879
- /* @ui:tokens stat-value-size stat-value-weight stat-value-num-font stat-label-size stat-label-color stat-change-positive stat-change-negative color-fg color-fg-muted color-bg color-border space-1 space-2 space-4 radius-md shadow-sm font-sans text-xs text-sm text-lg text-3xl weight-semibold */
5438
+ /* @ui:tokens stat-value-size stat-value-weight stat-value-num-font stat-label-size stat-label-color stat-change-positive stat-change-negative color-fg color-fg-muted color-bg color-border space-1 space-2 space-4 radius-md shadow-sm font-heading font-body text-xs text-sm text-lg text-3xl weight-semibold border-width */
4880
5439
 
4881
5440
  /* ── Base ── */
4882
5441
  [data-ui="stat"] {
4883
5442
  display: flex;
4884
5443
  flex-direction: column;
4885
5444
  gap: var(--space-1);
4886
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
5445
+ font-family: var(--doc-font, var(--font-body));
4887
5446
  }
4888
5447
 
4889
5448
  /* ── Label ── */
@@ -4897,6 +5456,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4897
5456
 
4898
5457
  /* ── Value ── */
4899
5458
  [data-ui="stat"] [data-part="value"] {
5459
+ font-family: var(--font-heading);
4900
5460
  font-size: var(--stat-value-size);
4901
5461
  font-weight: var(--stat-value-weight);
4902
5462
  color: var(--color-fg);
@@ -4955,10 +5515,10 @@ div[data-ui="separator"][data-style="thick"]::after {
4955
5515
  /* ── Variant: Card ── */
4956
5516
  [data-ui="stat"][data-variant="card"] {
4957
5517
  padding: var(--space-4);
4958
- border: 1px solid var(--color-border);
5518
+ border: var(--border-width) solid var(--color-border);
4959
5519
  border-radius: var(--radius-md, 0.375rem);
4960
5520
  background: var(--color-bg);
4961
- box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.05));
5521
+ box-shadow: var(--shadow-sm);
4962
5522
  }
4963
5523
 
4964
5524
  /* ── Value + Change Inline ── */
@@ -4970,7 +5530,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4970
5530
  @media print {
4971
5531
  [data-ui="stat"][data-variant="card"] {
4972
5532
  box-shadow: none;
4973
- border: 1px solid var(--doc-print-border-color, var(--color-border, #ccc));
5533
+ border: var(--border-width) solid var(--doc-print-border-color, var(--color-border, #ccc));
4974
5534
  }
4975
5535
 
4976
5536
  [data-ui="stat"] {
@@ -4980,7 +5540,7 @@ div[data-ui="separator"][data-style="thick"]::after {
4980
5540
 
4981
5541
  /* === primitives/stepper.css === */
4982
5542
  /* @ui:component stepper */
4983
- /* @ui:tokens color-primary color-primary-fg color-bg-muted color-fg-muted color-success color-success-subtle color-border text-sm text-xs weight-medium radius-full space-2 space-3 space-1 */
5543
+ /* @ui:tokens color-primary color-primary-fg color-bg-muted color-fg-muted color-success color-success-subtle color-border text-sm text-xs weight-medium radius-full space-2 space-3 space-1 border-width-strong */
4984
5544
 
4985
5545
  /* ── Base ── */
4986
5546
  [data-ui="stepper"] {
@@ -5059,7 +5619,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5059
5619
  The tight phone metrics are the base; the roomier ones arrive at `sm`. */
5060
5620
  [data-ui="stepper"] [data-part="connector"] {
5061
5621
  flex: 1;
5062
- height: 2px;
5622
+ height: var(--border-width-strong);
5063
5623
  background: var(--color-border);
5064
5624
  margin: 0 var(--space-1);
5065
5625
  min-width: var(--space-2);
@@ -5127,18 +5687,20 @@ div[data-ui="separator"][data-style="thick"]::after {
5127
5687
 
5128
5688
  /* === primitives/surface.css === */
5129
5689
  /* @ui:component surface */
5130
- /* @ui:tokens color-bg color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border measure-content measure-narrow measure-prose measure-wide radius-lg shadow-sm shadow-md shadow-lg space-3 space-4 space-6 */
5690
+ /* @ui:tokens color-bg color-surface-1 color-surface-2 color-surface-1-border color-surface-2-border measure-content measure-narrow measure-prose measure-wide radius-lg shadow-sm shadow-md shadow-lg space-3 space-4 space-6 border-width corner-shape surface-backdrop texture-surface */
5131
5691
 
5132
5692
  /* ── Base ── */
5133
5693
  [data-ui="surface"] {
5134
- background: var(--color-surface-1);
5694
+ background-color: var(--color-surface-1);
5695
+ background-image: var(--texture-surface);
5135
5696
  border-radius: var(--radius-lg);
5136
- border: 1px solid var(--color-surface-1-border);
5697
+ corner-shape: var(--corner-shape);
5698
+ border: var(--border-width) solid var(--color-surface-1-border);
5137
5699
  }
5138
5700
 
5139
5701
  /* ── Elevation Variants ── */
5140
5702
  [data-ui="surface"][data-variant="flat"] {
5141
- background: var(--color-bg);
5703
+ background-color: var(--color-bg);
5142
5704
  border: none;
5143
5705
  box-shadow: none;
5144
5706
  }
@@ -5148,11 +5710,22 @@ div[data-ui="separator"][data-style="thick"]::after {
5148
5710
  }
5149
5711
 
5150
5712
  [data-ui="surface"][data-variant="overlay"] {
5151
- background: var(--color-surface-2);
5713
+ background-color: var(--color-surface-2);
5152
5714
  box-shadow: var(--shadow-lg);
5153
5715
  border-color: var(--color-surface-2-border);
5154
5716
  }
5155
5717
 
5718
+ /* An overlay is the one surface variant that floats over other content, so it
5719
+ is the one that can be frosted. Guarded exactly as themes/glass.css guards
5720
+ its own: a browser without backdrop-filter renders the solid surface above
5721
+ and never sees this rule. */
5722
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
5723
+ [data-ui="surface"][data-variant="overlay"] {
5724
+ -webkit-backdrop-filter: var(--surface-backdrop);
5725
+ backdrop-filter: var(--surface-backdrop);
5726
+ }
5727
+ }
5728
+
5156
5729
  /* ── Padding Sizes ── */
5157
5730
  [data-ui="surface"][data-size="sm"] {
5158
5731
  padding: var(--space-3);
@@ -5208,7 +5781,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5208
5781
 
5209
5782
  /* === primitives/switch.css === */
5210
5783
  /* @ui:component switch */
5211
- /* @ui:tokens color-bg-muted color-primary color-primary-fg color-border color-ring shadow-xs radius-full space-0h space-1 duration-fast ease-default */
5784
+ /* @ui:tokens color-bg-muted color-primary color-primary-fg color-border color-ring shadow-xs space-0h space-1 duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow switch-radius switch-width switch-height switch-thumb switch-travel switch-bg switch-thumb-shadow disabled-opacity */
5212
5785
 
5213
5786
  /* -- Label wrapper -- */
5214
5787
  [data-ui="switch-label"] {
@@ -5220,7 +5793,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5220
5793
 
5221
5794
  [data-ui="switch-label"]:has([data-ui="switch"]:disabled) {
5222
5795
  cursor: not-allowed;
5223
- opacity: 0.5;
5796
+ opacity: var(--disabled-opacity);
5224
5797
  }
5225
5798
 
5226
5799
  /* -- Base (track) -- */
@@ -5248,8 +5821,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5248
5821
  width: var(--switch-width, 44px);
5249
5822
  height: var(--switch-height, 24px);
5250
5823
  padding: var(--space-0h, 2px);
5251
- border: 1px solid var(--color-border);
5252
- border-radius: var(--radius-full);
5824
+ border: var(--border-width) solid var(--color-border);
5825
+ border-radius: var(--switch-radius);
5253
5826
  background: var(--switch-bg, var(--color-bg-muted));
5254
5827
  cursor: pointer;
5255
5828
  position: relative;
@@ -5259,8 +5832,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5259
5832
  }
5260
5833
 
5261
5834
  [data-ui="switch"]:focus-visible {
5262
- outline: 2px solid var(--color-ring);
5263
- outline-offset: 2px;
5835
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
5836
+ outline-offset: var(--focus-ring-offset);
5837
+ box-shadow: var(--focus-shadow);
5264
5838
  }
5265
5839
 
5266
5840
  /* -- Thumb (pseudo-element for <input>, child for custom markup) -- */
@@ -5269,7 +5843,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5269
5843
  display: block;
5270
5844
  width: var(--switch-thumb, 18px);
5271
5845
  height: var(--switch-thumb, 18px);
5272
- border-radius: var(--radius-full);
5846
+ border-radius: var(--switch-radius);
5273
5847
  background: var(--color-primary-fg);
5274
5848
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5275
5849
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5281,7 +5855,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5281
5855
  display: block;
5282
5856
  width: var(--switch-thumb, 18px);
5283
5857
  height: var(--switch-thumb, 18px);
5284
- border-radius: var(--radius-full);
5858
+ border-radius: var(--switch-radius);
5285
5859
  background: var(--color-primary-fg);
5286
5860
  box-shadow: var(--switch-thumb-shadow, var(--shadow-xs));
5287
5861
  transition: transform var(--duration-fast) var(--ease-default);
@@ -5363,7 +5937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5363
5937
  the track's border is always visible, and ON fills it with `Highlight`. [W3-3] */
5364
5938
  @media (forced-colors: active) {
5365
5939
  [data-ui="switch"] {
5366
- border: 1px solid ButtonText;
5940
+ border: var(--border-width) solid ButtonText;
5367
5941
  background: ButtonFace;
5368
5942
  }
5369
5943
 
@@ -5520,25 +6094,31 @@ div[data-ui="separator"][data-style="thick"]::after {
5520
6094
 
5521
6095
  /* === primitives/text.css === */
5522
6096
  /* @ui:component text */
5523
- /* @ui:tokens color-fg color-fg-muted color-primary text-xs text-sm text-base text-lg text-xl text-2xl text-3xl text-4xl weight-normal weight-medium weight-semibold weight-bold leading-tight leading-snug leading-normal leading-relaxed font-sans font-mono */
6097
+ /* @ui:tokens color-fg color-fg-muted color-primary text-xs text-sm text-base text-lg text-xl text-2xl text-3xl text-4xl weight-normal weight-medium weight-semibold weight-bold leading-tight leading-snug leading-normal leading-relaxed font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading font-mono */
5524
6098
 
5525
6099
  /* ── Heading ── */
5526
6100
  [data-ui="heading"] {
5527
- font-family: var(--font-sans);
5528
- font-weight: var(--weight-bold);
6101
+ font-family: var(--font-heading);
6102
+ font-weight: var(--heading-weight);
5529
6103
  color: var(--color-fg);
5530
- line-height: var(--leading-tight);
5531
- letter-spacing: -0.01em;
6104
+ line-height: var(--heading-leading);
6105
+ text-transform: var(--heading-transform);
6106
+ font-variant-caps: var(--heading-caps);
6107
+ /* The optical tightening a large heading needs, PLUS whatever tracking the
6108
+ theme's voice asks for on top of it — so a theme that wants wide-tracked
6109
+ headings sets --heading-tracking once and every size follows, instead of
6110
+ each size having to re-derive its own number. */
6111
+ letter-spacing: calc(-0.01em + var(--heading-tracking));
5532
6112
  }
5533
6113
 
5534
6114
  [data-ui="heading"][data-size="1"] {
5535
6115
  font-size: var(--text-4xl);
5536
- letter-spacing: -0.02em;
6116
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5537
6117
  }
5538
6118
 
5539
6119
  [data-ui="heading"][data-size="2"] {
5540
6120
  font-size: var(--text-3xl);
5541
- letter-spacing: -0.02em;
6121
+ letter-spacing: calc(-0.02em + var(--heading-tracking));
5542
6122
  }
5543
6123
 
5544
6124
  [data-ui="heading"][data-size="3"] {
@@ -5562,7 +6142,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5562
6142
 
5563
6143
  /* ── Text ── */
5564
6144
  [data-ui="text"] {
5565
- font-family: var(--font-sans);
6145
+ font-family: var(--font-body);
5566
6146
  color: var(--color-fg);
5567
6147
  }
5568
6148
 
@@ -5640,7 +6220,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5640
6220
 
5641
6221
  /* === primitives/textarea.css === */
5642
6222
  /* @ui:component textarea */
5643
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-sans text-xs text-sm text-base duration-fast ease-default */
6223
+ /* @ui:tokens color-fg color-fg-muted color-border color-border-strong color-ring color-destructive radius-md space-2 space-3 space-4 font-ui text-xs text-sm text-base duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-shadow input-border-width input-fill disabled-opacity */
5644
6224
 
5645
6225
  /* -- Base -- */
5646
6226
  [data-ui="textarea"] {
@@ -5648,11 +6228,17 @@ div[data-ui="separator"][data-style="thick"]::after {
5648
6228
  width: 100%;
5649
6229
  min-height: var(--textarea-min-height, 80px);
5650
6230
  padding: var(--space-2) var(--space-3);
5651
- border: 1px solid var(--color-border);
6231
+ /* Longhands, not the `border:` shorthand: the shorthand's width slot takes
6232
+ ONE value, and `controls.input: underline` (1.1A-10) states the silhouette
6233
+ as a four-value box — `0 0 var(--border-width) 0` — so only a bottom rule
6234
+ is drawn. Identical to the shorthand at every other value of the token. */
6235
+ border-style: solid;
6236
+ border-color: var(--color-border);
6237
+ border-width: var(--input-border-width);
5652
6238
  border-radius: var(--textarea-radius, var(--radius-md));
5653
- background: var(--textarea-bg, var(--color-bg));
6239
+ background: var(--textarea-bg, var(--input-fill));
5654
6240
  color: var(--color-fg);
5655
- font-family: var(--textarea-font, var(--font-sans));
6241
+ font-family: var(--textarea-font, var(--font-ui));
5656
6242
  font-size: var(--text-sm);
5657
6243
  line-height: 1.5;
5658
6244
  resize: vertical;
@@ -5669,8 +6255,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5669
6255
  }
5670
6256
 
5671
6257
  [data-ui="textarea"]:focus {
5672
- outline: 2px solid var(--color-ring);
5673
- outline-offset: -1px;
6258
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6259
+ /* The ring replaces the border rather than sitting outside it: inset by
6260
+ exactly the edge it covers, so a heavier shape theme stays aligned. */
6261
+ outline-offset: calc(-1 * var(--input-border-width));
6262
+ box-shadow: var(--focus-shadow);
5674
6263
  border-color: transparent;
5675
6264
  }
5676
6265
 
@@ -5698,7 +6287,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5698
6287
  }
5699
6288
 
5700
6289
  [data-ui="textarea"]:disabled {
5701
- opacity: 0.5;
6290
+ opacity: var(--disabled-opacity);
5702
6291
  cursor: not-allowed;
5703
6292
  resize: none;
5704
6293
  }
@@ -5712,7 +6301,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5712
6301
 
5713
6302
  /* === primitives/toggle.css === */
5714
6303
  /* @ui:component toggle */
5715
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 space-4 text-xs text-sm text-base font-sans weight-medium duration-fast ease-default */
6304
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 space-4 text-xs text-sm text-base font-ui weight-medium duration-fast ease-default border-width focus-ring-width focus-ring-offset focus-ring-style focus-ring-color focus-shadow disabled-opacity */
5716
6305
 
5717
6306
  /* ── Base (off / unpressed) ── */
5718
6307
  [data-ui="toggle"] {
@@ -5721,11 +6310,11 @@ div[data-ui="separator"][data-style="thick"]::after {
5721
6310
  justify-content: center;
5722
6311
  gap: var(--space-1h);
5723
6312
  padding: var(--toggle-pad-y, var(--space-1h)) var(--toggle-pad-x, var(--space-3));
5724
- border: 1px solid var(--color-border);
6313
+ border: var(--border-width) solid var(--color-border);
5725
6314
  border-radius: var(--toggle-radius, var(--radius-md));
5726
6315
  background: var(--color-bg);
5727
6316
  color: var(--color-fg-muted);
5728
- font-family: var(--toggle-font, var(--font-sans));
6317
+ font-family: var(--toggle-font, var(--font-ui));
5729
6318
  font-size: var(--text-sm);
5730
6319
  font-weight: var(--weight-medium);
5731
6320
  line-height: 1;
@@ -5742,8 +6331,9 @@ div[data-ui="separator"][data-style="thick"]::after {
5742
6331
  }
5743
6332
 
5744
6333
  [data-ui="toggle"]:focus-visible {
5745
- outline: 2px solid var(--color-ring);
5746
- outline-offset: 2px;
6334
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6335
+ outline-offset: var(--focus-ring-offset);
6336
+ box-shadow: var(--focus-shadow);
5747
6337
  }
5748
6338
 
5749
6339
  /* ── Pressed / on — styled entirely off aria-pressed, no JS ── */
@@ -5760,7 +6350,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5760
6350
 
5761
6351
  /* ── Disabled ── */
5762
6352
  [data-ui="toggle"]:disabled {
5763
- opacity: 0.5;
6353
+ opacity: var(--disabled-opacity);
5764
6354
  cursor: not-allowed;
5765
6355
  }
5766
6356
 
@@ -5784,7 +6374,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5784
6374
 
5785
6375
  /* === primitives/watermark.css === */
5786
6376
  /* @ui:component watermark */
5787
- /* @ui:tokens color-fg-muted doc-font font-sans text-xl text-2xl text-4xl weight-bold leading-tight space-8 space-20 z-raised */
6377
+ /* @ui:tokens color-fg-muted doc-font font-body text-xl text-2xl text-4xl weight-bold leading-tight space-8 space-20 z-raised */
5788
6378
 
5789
6379
  [data-ui="watermark"] {
5790
6380
  position: fixed;
@@ -5803,7 +6393,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5803
6393
 
5804
6394
  [data-ui="watermark"] > [data-part="mark"] {
5805
6395
  color: var(--color-fg-muted);
5806
- font-family: var(--doc-font, var(--font-sans));
6396
+ font-family: var(--doc-font, var(--font-body));
5807
6397
  font-size: var(--text-4xl);
5808
6398
  font-weight: var(--weight-bold);
5809
6399
  line-height: var(--leading-tight);
@@ -5861,7 +6451,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5861
6451
 
5862
6452
  /* === recipes/accordion.css === */
5863
6453
  /* @ui:component accordion */
5864
- /* @ui:tokens color-bg color-fg color-fg-muted color-border space-3 space-4 text-sm text-base weight-medium duration-normal ease-default radius-lg */
6454
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border space-3 space-4 text-sm text-base weight-medium duration-normal ease-default radius-lg font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
5865
6455
 
5866
6456
  /* ── Root ── */
5867
6457
  [data-ui="accordion"] {
@@ -5870,7 +6460,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5870
6460
 
5871
6461
  /* ── Item ── */
5872
6462
  [data-ui="accordion"] [data-part="item"] {
5873
- border-bottom: 1px solid var(--color-border);
6463
+ border-bottom: var(--border-width) solid var(--color-border);
5874
6464
  }
5875
6465
 
5876
6466
  [data-ui="accordion"] [data-part="item"]:last-child {
@@ -5887,7 +6477,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5887
6477
  border: none;
5888
6478
  background: transparent;
5889
6479
  color: var(--color-fg);
5890
- font-family: var(--font-sans, system-ui, sans-serif);
6480
+ font-family: var(--font-ui);
5891
6481
  font-size: var(--text-base);
5892
6482
  font-weight: var(--weight-medium);
5893
6483
  text-align: start;
@@ -5901,8 +6491,8 @@ div[data-ui="separator"][data-style="thick"]::after {
5901
6491
  }
5902
6492
 
5903
6493
  [data-ui="accordion"] [data-part="trigger"]:focus-visible {
5904
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
5905
- outline-offset: -2px;
6494
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6495
+ outline-offset: calc(-1 * var(--focus-ring-offset));
5906
6496
  border-radius: var(--radius-sm, 0.25rem);
5907
6497
  }
5908
6498
 
@@ -5934,13 +6524,13 @@ div[data-ui="separator"][data-style="thick"]::after {
5934
6524
 
5935
6525
  /* ── Bordered Variant ── */
5936
6526
  [data-ui="accordion"][data-bordered="true"] {
5937
- border: 1px solid var(--color-border);
6527
+ border: var(--border-width) solid var(--color-border);
5938
6528
  border-radius: var(--radius-lg);
5939
6529
  overflow: hidden;
5940
6530
  }
5941
6531
 
5942
6532
  [data-ui="accordion"][data-bordered="true"] [data-part="item"] {
5943
- border-bottom: 1px solid var(--color-border);
6533
+ border-bottom: var(--border-width) solid var(--color-border);
5944
6534
  }
5945
6535
 
5946
6536
  [data-ui="accordion"][data-bordered="true"] [data-part="item"]:last-child {
@@ -5957,7 +6547,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5957
6547
 
5958
6548
  /* === recipes/alert-dialog.css === */
5959
6549
  /* @ui:component alert-dialog */
5960
- /* @ui:tokens radius-xl shadow-xl space-2 space-3 space-6 color-bg color-fg color-border color-fg-muted color-destructive duration-normal ease-default ease-out z-overlay z-modal */
6550
+ /* @ui:tokens radius-xl shadow-xl space-2 space-3 space-6 color-bg color-fg color-border color-fg-muted color-destructive duration-normal ease-default ease-out z-overlay z-modal font-heading border-width */
5961
6551
 
5962
6552
  /* ── Root ── */
5963
6553
  [data-ui="alert-dialog"] {
@@ -5993,7 +6583,7 @@ div[data-ui="separator"][data-style="thick"]::after {
5993
6583
  max-height: 85vh;
5994
6584
  overflow-y: auto;
5995
6585
  background: var(--color-bg);
5996
- border: 1px solid var(--color-border);
6586
+ border: var(--border-width) solid var(--color-border);
5997
6587
  border-radius: var(--alert-dialog-radius, var(--radius-xl));
5998
6588
  box-shadow: var(--alert-dialog-shadow, var(--shadow-xl));
5999
6589
  opacity: 0;
@@ -6039,6 +6629,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6039
6629
  /* ── Title ── */
6040
6630
  [data-ui="alert-dialog"] [data-part="title"] {
6041
6631
  margin: 0;
6632
+ font-family: var(--font-heading);
6042
6633
  font-size: var(--text-lg, 1.125rem);
6043
6634
  font-weight: var(--weight-semibold, 600);
6044
6635
  color: var(--color-fg);
@@ -6078,7 +6669,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6078
6669
 
6079
6670
  /* === recipes/barcode.css === */
6080
6671
  /* @ui:component barcode */
6081
- /* @ui:tokens color-fg color-bg color-fg-muted doc-font doc-legal-color doc-legal-size font-mono font-sans space-2 space-12 space-16 space-20 */
6672
+ /* @ui:tokens color-fg color-bg color-fg-muted doc-font doc-legal-color doc-legal-size font-mono font-body space-2 space-12 space-16 space-20 */
6082
6673
 
6083
6674
  [data-ui="barcode"] {
6084
6675
  display: inline-flex;
@@ -6105,7 +6696,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6105
6696
 
6106
6697
  [data-ui="barcode"] > [data-part="caption"] {
6107
6698
  color: var(--doc-legal-color, var(--color-fg-muted));
6108
- font-family: var(--font-mono, var(--doc-font, var(--font-sans)));
6699
+ font-family: var(--font-mono, var(--doc-font, var(--font-body)));
6109
6700
  font-size: var(--doc-legal-size);
6110
6701
  line-height: var(--leading-normal);
6111
6702
  text-align: center;
@@ -6125,7 +6716,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6125
6716
 
6126
6717
  /* === recipes/calendar.css === */
6127
6718
  /* @ui:component calendar */
6128
- /* @ui:tokens color-bg color-fg color-fg-muted color-fg-subtle color-border color-primary color-primary-fg color-primary-subtle color-ring radius-md radius-full space-0 space-1 space-2 text-xs text-sm text-base weight-medium duration-fast ease-default */
6719
+ /* @ui:tokens color-bg color-fg color-fg-muted color-fg-subtle color-border color-primary color-primary-fg color-primary-subtle color-ring radius-md radius-full space-0 space-1 space-2 text-xs text-sm text-base weight-medium duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6129
6720
 
6130
6721
  /* ── Root ── */
6131
6722
  [data-ui="calendar"] {
@@ -6158,7 +6749,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6158
6749
  width: 28px;
6159
6750
  height: 28px;
6160
6751
  padding: 0;
6161
- border: 1px solid var(--color-border);
6752
+ border: var(--border-width) solid var(--color-border);
6162
6753
  border-radius: var(--radius-md);
6163
6754
  background: var(--color-bg);
6164
6755
  color: var(--color-fg);
@@ -6174,13 +6765,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6174
6765
 
6175
6766
  [data-ui="calendar"] [data-part="nav-prev"]:focus-visible,
6176
6767
  [data-ui="calendar"] [data-part="nav-next"]:focus-visible {
6177
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6178
- outline-offset: 2px;
6768
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6769
+ outline-offset: var(--focus-ring-offset);
6179
6770
  }
6180
6771
 
6181
6772
  [data-ui="calendar"] [data-part="nav-prev"]:disabled,
6182
6773
  [data-ui="calendar"] [data-part="nav-next"]:disabled {
6183
- opacity: 0.4;
6774
+ /* Dimmer than a disabled control — 0.4 at the 0.5 default — and it follows a
6775
+ theme's `--disabled-opacity` like every other disabled dim (1.1A-27). */
6776
+ opacity: calc(var(--disabled-opacity) * 0.8);
6184
6777
  cursor: not-allowed;
6185
6778
  }
6186
6779
 
@@ -6215,11 +6808,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6215
6808
  width: 36px;
6216
6809
  height: 36px;
6217
6810
  padding: 0;
6218
- border: 1px solid transparent;
6811
+ border: var(--border-width) solid transparent;
6219
6812
  border-radius: var(--radius-full);
6220
6813
  background: transparent;
6221
6814
  color: var(--color-fg);
6222
- font-family: var(--font-sans, system-ui, sans-serif);
6815
+ font-family: var(--font-ui);
6223
6816
  font-size: var(--text-sm);
6224
6817
  cursor: pointer;
6225
6818
  transition: background var(--duration-fast) var(--ease-default),
@@ -6232,8 +6825,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6232
6825
  }
6233
6826
 
6234
6827
  [data-ui="calendar"] [data-part="day"]:focus-visible {
6235
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6236
- outline-offset: 2px;
6828
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6829
+ outline-offset: var(--focus-ring-offset);
6237
6830
  }
6238
6831
 
6239
6832
  /* ── Today ── */
@@ -6268,7 +6861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6268
6861
  /* ── Disabled days (aria-disabled keeps them focusable; :disabled for hard-disabled) ── */
6269
6862
  [data-ui="calendar"] [data-part="day"][aria-disabled="true"],
6270
6863
  [data-ui="calendar"] [data-part="day"]:disabled {
6271
- opacity: 0.5;
6864
+ opacity: var(--disabled-opacity);
6272
6865
  cursor: not-allowed;
6273
6866
  text-decoration: line-through;
6274
6867
  }
@@ -6332,7 +6925,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6332
6925
 
6333
6926
  /* === recipes/carousel.css === */
6334
6927
  /* @ui:component carousel */
6335
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-ring radius-md radius-lg space-1 space-2 space-3 space-4 text-sm font-sans duration-fast ease-default */
6928
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-ring radius-md radius-lg space-1 space-2 space-3 space-4 text-sm font-ui duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6336
6929
 
6337
6930
  /* The sliding is CSS, not JavaScript: the viewport is a scroll-snap strip and
6338
6931
  every slide is a snap target. Everything below works with no controller
@@ -6346,7 +6939,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6346
6939
  inline-size: 100%;
6347
6940
  min-inline-size: 0;
6348
6941
  max-inline-size: 100%;
6349
- font-family: var(--carousel-font, var(--font-sans));
6942
+ font-family: var(--carousel-font, var(--font-ui));
6350
6943
  }
6351
6944
 
6352
6945
  /* ── Viewport: the scroll-snap strip ── */
@@ -6372,8 +6965,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6372
6965
  }
6373
6966
 
6374
6967
  [data-ui="carousel"] [data-part="viewport"]:focus-visible {
6375
- outline: 2px solid var(--color-ring);
6376
- outline-offset: 2px;
6968
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
6969
+ outline-offset: var(--focus-ring-offset);
6377
6970
  }
6378
6971
 
6379
6972
  /* ── Slide: one full-width snap target ── */
@@ -6381,7 +6974,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6381
6974
  flex: 0 0 var(--carousel-slide-size, 100%);
6382
6975
  min-inline-size: 0;
6383
6976
  padding: var(--space-4);
6384
- border: 1px solid var(--color-border);
6977
+ border: var(--border-width) solid var(--color-border);
6385
6978
  border-radius: var(--radius-lg);
6386
6979
  background: var(--color-bg);
6387
6980
  color: var(--color-fg);
@@ -6410,7 +7003,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6410
7003
  min-inline-size: 2rem;
6411
7004
  min-block-size: 2rem;
6412
7005
  padding: var(--space-1) var(--space-2);
6413
- border: 1px solid var(--color-border);
7006
+ border: var(--border-width) solid var(--color-border);
6414
7007
  border-radius: var(--radius-md);
6415
7008
  background: var(--color-bg);
6416
7009
  color: var(--color-fg);
@@ -6429,14 +7022,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6429
7022
  [data-ui="carousel"] [data-part="prev"]:focus-visible,
6430
7023
  [data-ui="carousel"] [data-part="next"]:focus-visible,
6431
7024
  [data-ui="carousel"] [data-part="dot"]:focus-visible {
6432
- outline: 2px solid var(--color-ring);
6433
- outline-offset: 2px;
7025
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7026
+ outline-offset: var(--focus-ring-offset);
6434
7027
  }
6435
7028
 
6436
7029
  /* Boundary contract "stop" — the controller disables the end button. */
6437
7030
  [data-ui="carousel"] [data-part="prev"]:disabled,
6438
7031
  [data-ui="carousel"] [data-part="next"]:disabled {
6439
- opacity: 0.4;
7032
+ /* 0.4 at the 0.5 default, and a theme's `--disabled-opacity` moves it (1.1A-27). */
7033
+ opacity: calc(var(--disabled-opacity) * 0.8);
6440
7034
  cursor: not-allowed;
6441
7035
  }
6442
7036
 
@@ -6445,7 +7039,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6445
7039
  inline-size: 0.625rem;
6446
7040
  block-size: 0.625rem;
6447
7041
  padding: 0;
6448
- border: 1px solid var(--color-border);
7042
+ border: var(--border-width) solid var(--color-border);
6449
7043
  border-radius: 50%;
6450
7044
  background: var(--color-bg-muted);
6451
7045
  cursor: pointer;
@@ -6481,7 +7075,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6481
7075
 
6482
7076
  /* === recipes/combobox.css === */
6483
7077
  /* @ui:component combobox */
6484
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 text-sm text-base z-dropdown duration-fast ease-default */
7078
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle radius-md radius-lg shadow-md space-1 space-2 space-3 text-sm text-base z-dropdown duration-fast ease-default font-ui border-width focus-ring-color focus-ring-width */
6485
7079
 
6486
7080
  /* ── Root ── */
6487
7081
  [data-ui="combobox"] {
@@ -6495,11 +7089,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6495
7089
  display: block;
6496
7090
  width: 100%;
6497
7091
  padding: var(--space-2) var(--space-3);
6498
- border: 1px solid var(--color-border);
7092
+ border: var(--border-width) solid var(--color-border);
6499
7093
  border-radius: var(--radius-md);
6500
7094
  background: var(--color-bg);
6501
7095
  color: var(--color-fg);
6502
- font-family: var(--font-sans, system-ui, sans-serif);
7096
+ font-family: var(--font-ui);
6503
7097
  font-size: var(--text-sm);
6504
7098
  line-height: 1.5;
6505
7099
  outline: none;
@@ -6512,8 +7106,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6512
7106
  }
6513
7107
 
6514
7108
  [data-ui="combobox"] [data-part="input"]:focus {
6515
- border-color: var(--color-ring, oklch(0.55 0.22 264));
6516
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
7109
+ border-color: var(--focus-ring-color);
7110
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
6517
7111
  }
6518
7112
 
6519
7113
  /* ── Listbox ── */
@@ -6525,7 +7119,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6525
7119
  z-index: var(--z-dropdown);
6526
7120
  margin-top: var(--space-1);
6527
7121
  padding: var(--space-1);
6528
- border: 1px solid var(--color-border);
7122
+ border: var(--border-width) solid var(--color-border);
6529
7123
  border-radius: var(--radius-lg);
6530
7124
  background: var(--color-bg);
6531
7125
  box-shadow: var(--shadow-md);
@@ -6610,7 +7204,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6610
7204
 
6611
7205
  /* === recipes/command-palette.css === */
6612
7206
  /* @ui:component command-palette */
6613
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-bg-muted shadow-xl radius-xl space-2 space-3 space-4 text-sm text-xs text-base weight-medium font-mono z-overlay z-modal duration-fast duration-normal ease-out */
7207
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-bg-muted shadow-xl radius-xl space-2 space-3 space-4 text-sm text-xs text-base weight-medium font-mono z-overlay z-modal duration-fast duration-normal ease-out font-ui border-width */
6614
7208
 
6615
7209
  /* ── Root ── */
6616
7210
  [data-ui="command-palette"] {
@@ -6643,7 +7237,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6643
7237
  display: flex;
6644
7238
  flex-direction: column;
6645
7239
  background: var(--color-bg);
6646
- border: 1px solid var(--color-border);
7240
+ border: var(--border-width) solid var(--color-border);
6647
7241
  border-radius: var(--radius-xl);
6648
7242
  box-shadow: var(--shadow-xl);
6649
7243
  overflow: hidden;
@@ -6675,7 +7269,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6675
7269
  display: flex;
6676
7270
  align-items: center;
6677
7271
  padding: var(--space-3) var(--space-4);
6678
- border-bottom: 1px solid var(--color-border);
7272
+ border-bottom: var(--border-width) solid var(--color-border);
6679
7273
  }
6680
7274
 
6681
7275
  /* ── Search Input ── */
@@ -6685,7 +7279,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6685
7279
  border: none;
6686
7280
  background: transparent;
6687
7281
  color: var(--color-fg);
6688
- font-family: var(--font-sans, system-ui, sans-serif);
7282
+ font-family: var(--font-ui);
6689
7283
  font-size: var(--text-base);
6690
7284
  outline: none;
6691
7285
  }
@@ -6769,7 +7363,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6769
7363
  align-items: center;
6770
7364
  gap: var(--space-1, 0.25rem);
6771
7365
  padding: var(--space-1, 0.25rem) var(--space-2);
6772
- border: 1px solid var(--color-border);
7366
+ border: var(--border-width) solid var(--color-border);
6773
7367
  border-radius: var(--radius-sm, 0.25rem);
6774
7368
  background: var(--color-bg-muted, oklch(0.96 0.004 260));
6775
7369
  color: var(--color-fg-muted);
@@ -6798,7 +7392,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6798
7392
 
6799
7393
  /* === recipes/context-menu.css === */
6800
7394
  /* @ui:component context-menu */
6801
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-sm weight-medium font-sans duration-fast ease-out z-dropdown */
7395
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-sm weight-medium font-ui duration-fast ease-out z-dropdown focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
6802
7396
 
6803
7397
  [data-ui="context-menu"] {
6804
7398
  position: relative;
@@ -6811,12 +7405,12 @@ div[data-ui="separator"][data-style="thick"]::after {
6811
7405
  border-radius: var(--radius-lg);
6812
7406
  background: var(--color-bg-muted);
6813
7407
  color: var(--color-fg);
6814
- font-family: var(--font-sans, system-ui, sans-serif);
7408
+ font-family: var(--font-ui);
6815
7409
  }
6816
7410
 
6817
7411
  [data-ui="context-menu"] [data-part="target"]:focus-visible {
6818
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6819
- outline-offset: var(--space-1);
7412
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7413
+ outline-offset: var(--focus-ring-offset);
6820
7414
  }
6821
7415
 
6822
7416
  [data-ui="context-menu"] [data-part="menu"] {
@@ -6848,7 +7442,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6848
7442
  border-radius: var(--radius-md);
6849
7443
  background: transparent;
6850
7444
  color: var(--color-fg);
6851
- font-family: var(--font-sans, system-ui, sans-serif);
7445
+ font-family: var(--font-ui);
6852
7446
  font-size: var(--text-sm);
6853
7447
  font-weight: var(--weight-medium);
6854
7448
  text-align: start;
@@ -6872,15 +7466,15 @@ div[data-ui="separator"][data-style="thick"]::after {
6872
7466
  focus additionally draws the ring, inset so it does not overlap the item
6873
7467
  above. [W3-3] */
6874
7468
  [data-ui="context-menu"] [data-part="item"]:focus-visible {
6875
- outline: calc(var(--space-px) * 2) solid var(--color-ring);
6876
- outline-offset: calc(var(--space-px) * -2);
7469
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7470
+ outline-offset: calc(-1 * var(--focus-ring-offset));
6877
7471
  }
6878
7472
 
6879
7473
  [data-ui="context-menu"] [data-part="item"]:disabled,
6880
7474
  [data-ui="context-menu"] [data-part="item"][aria-disabled="true"] {
6881
7475
  color: var(--color-fg-muted);
6882
7476
  cursor: not-allowed;
6883
- opacity: 0.5;
7477
+ opacity: var(--disabled-opacity);
6884
7478
  }
6885
7479
 
6886
7480
  [data-ui="context-menu"] [data-part="separator"] {
@@ -6899,7 +7493,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6899
7493
 
6900
7494
  /* === recipes/date-picker.css === */
6901
7495
  /* @ui:component date-picker */
6902
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-ring shadow-lg radius-md radius-lg space-1 space-2 space-3 space-4 text-xs text-sm z-dropdown duration-fast ease-default */
7496
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-ring shadow-lg radius-md radius-lg space-1 space-2 space-3 space-4 text-xs text-sm z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
6903
7497
  /* The month grid inside the popup is the `calendar` recipe — see calendar.css */
6904
7498
 
6905
7499
  /* ── Root ── */
@@ -6920,11 +7514,11 @@ div[data-ui="separator"][data-style="thick"]::after {
6920
7514
  width: 100%;
6921
7515
  padding: var(--space-2, 0.5rem) var(--space-3);
6922
7516
  padding-inline-end: var(--space-8, 2.5rem);
6923
- border: 1px solid var(--color-border);
7517
+ border: var(--border-width) solid var(--color-border);
6924
7518
  border-radius: var(--radius-md);
6925
7519
  background: var(--color-bg);
6926
7520
  color: var(--color-fg);
6927
- font-family: var(--font-sans, system-ui, sans-serif);
7521
+ font-family: var(--font-ui);
6928
7522
  font-size: var(--text-sm);
6929
7523
  line-height: 1.5;
6930
7524
  cursor: pointer;
@@ -6936,8 +7530,8 @@ div[data-ui="separator"][data-style="thick"]::after {
6936
7530
  }
6937
7531
 
6938
7532
  [data-ui="date-picker"] [data-part="input"]:focus-visible {
6939
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
6940
- outline-offset: 2px;
7533
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7534
+ outline-offset: var(--focus-ring-offset);
6941
7535
  border-color: var(--color-primary);
6942
7536
  }
6943
7537
 
@@ -6960,7 +7554,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6960
7554
  z-index: var(--z-dropdown);
6961
7555
  margin-top: var(--space-1);
6962
7556
  padding: var(--space-3);
6963
- border: 1px solid var(--color-border);
7557
+ border: var(--border-width) solid var(--color-border);
6964
7558
  border-radius: var(--radius-lg);
6965
7559
  background: var(--color-bg);
6966
7560
  box-shadow: var(--shadow-lg);
@@ -6999,7 +7593,7 @@ div[data-ui="separator"][data-style="thick"]::after {
6999
7593
 
7000
7594
  /* === recipes/dialog.css === */
7001
7595
  /* @ui:component dialog */
7002
- /* @ui:tokens radius-xl shadow-xl space-4 space-6 space-8 color-bg color-fg color-border color-fg-muted duration-normal duration-slow ease-default ease-out z-overlay z-modal */
7596
+ /* @ui:tokens radius-xl shadow-xl space-4 space-6 space-8 color-bg panel-bg color-fg color-border color-fg-muted duration-normal duration-slow ease-default ease-out z-overlay z-modal font-heading corner-shape border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
7003
7597
 
7004
7598
  /* ── Root ── */
7005
7599
  [data-ui="dialog"] {
@@ -7034,15 +7628,23 @@ div[data-ui="separator"][data-style="thick"]::after {
7034
7628
  width: 90%;
7035
7629
  max-height: 85vh;
7036
7630
  overflow-y: auto;
7037
- background: var(--color-bg);
7038
- border: 1px solid var(--color-border);
7631
+ background: var(--panel-bg);
7632
+ border: var(--border-width) solid var(--color-border);
7039
7633
  border-radius: var(--dialog-radius, var(--radius-xl));
7634
+ corner-shape: var(--corner-shape);
7040
7635
  box-shadow: var(--dialog-shadow, var(--shadow-xl));
7041
7636
  opacity: 0;
7042
7637
  transition: opacity var(--duration-normal) var(--ease-out),
7043
7638
  transform var(--duration-normal) var(--ease-out);
7044
7639
  }
7045
7640
 
7641
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7642
+ [data-ui="dialog"] [data-part="panel"] {
7643
+ -webkit-backdrop-filter: var(--surface-backdrop);
7644
+ backdrop-filter: var(--surface-backdrop);
7645
+ }
7646
+ }
7647
+
7046
7648
  [data-ui="dialog"][data-state="open"] [data-part="panel"] {
7047
7649
  opacity: 1;
7048
7650
  transform: translate(-50%, -50%) scale(1);
@@ -7091,6 +7693,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7091
7693
  /* ── Title ── */
7092
7694
  [data-ui="dialog"] [data-part="title"] {
7093
7695
  margin: 0;
7696
+ font-family: var(--font-heading);
7094
7697
  font-size: var(--text-lg, 1.125rem);
7095
7698
  font-weight: var(--weight-semibold, 600);
7096
7699
  color: var(--color-fg);
@@ -7125,8 +7728,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7125
7728
  }
7126
7729
 
7127
7730
  [data-ui="dialog"] [data-part="close"]:not([data-ui]):focus-visible {
7128
- outline: 2px solid var(--color-ring);
7129
- outline-offset: 2px;
7731
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7732
+ outline-offset: var(--focus-ring-offset);
7130
7733
  }
7131
7734
 
7132
7735
  /* ── Description ── */
@@ -7162,7 +7765,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7162
7765
 
7163
7766
  /* === recipes/drawer.css === */
7164
7767
  /* @ui:component drawer */
7165
- /* @ui:tokens color-bg color-fg color-border shadow-xl space-4 space-6 radius-none z-overlay z-modal duration-normal duration-slow ease-out ease-default */
7768
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-xl space-4 space-6 radius-none z-overlay z-modal duration-normal duration-slow ease-out ease-default font-heading border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
7166
7769
 
7167
7770
  /* ── Root ── */
7168
7771
  [data-ui="drawer"] {
@@ -7197,17 +7800,24 @@ div[data-ui="separator"][data-style="thick"]::after {
7197
7800
  flex-direction: column;
7198
7801
  width: var(--drawer-width, 400px);
7199
7802
  max-width: 100vw;
7200
- background: var(--color-bg);
7803
+ background: var(--panel-bg);
7201
7804
  border: none;
7202
7805
  box-shadow: var(--drawer-shadow, var(--shadow-xl));
7203
7806
  transition: transform var(--duration-slow) var(--ease-out);
7204
7807
  }
7205
7808
 
7809
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
7810
+ [data-ui="drawer"] [data-part="panel"] {
7811
+ -webkit-backdrop-filter: var(--surface-backdrop);
7812
+ backdrop-filter: var(--surface-backdrop);
7813
+ }
7814
+ }
7815
+
7206
7816
  /* ── Side Variants ── */
7207
7817
  [data-ui="drawer"] [data-part="panel"][data-variant="left"] {
7208
7818
  inset-inline-start: 0;
7209
7819
  inset-inline-end: auto;
7210
- border-inline-end: 1px solid var(--color-border);
7820
+ border-inline-end: var(--border-width) solid var(--color-border);
7211
7821
  border-radius: 0 var(--radius-none, 0) var(--radius-none, 0) 0;
7212
7822
  transform: translateX(-100%);
7213
7823
  }
@@ -7215,7 +7825,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7215
7825
  [data-ui="drawer"] [data-part="panel"][data-variant="right"] {
7216
7826
  inset-inline-end: 0;
7217
7827
  inset-inline-start: auto;
7218
- border-inline-start: 1px solid var(--color-border);
7828
+ border-inline-start: var(--border-width) solid var(--color-border);
7219
7829
  border-radius: var(--radius-none, 0) 0 0 var(--radius-none, 0);
7220
7830
  transform: translateX(100%);
7221
7831
  }
@@ -7269,6 +7879,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7269
7879
  /* ── Title ── */
7270
7880
  [data-ui="drawer"] [data-part="title"] {
7271
7881
  margin: 0;
7882
+ font-family: var(--font-heading);
7272
7883
  font-size: var(--text-lg, 1.125rem);
7273
7884
  font-weight: var(--weight-semibold, 600);
7274
7885
  color: var(--color-fg);
@@ -7303,8 +7914,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7303
7914
  }
7304
7915
 
7305
7916
  [data-ui="drawer"] [data-part="close"]:not([data-ui]):focus-visible {
7306
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7307
- outline-offset: 2px;
7917
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7918
+ outline-offset: var(--focus-ring-offset);
7308
7919
  }
7309
7920
 
7310
7921
  /* ── Body ── */
@@ -7323,7 +7934,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7323
7934
  gap: var(--space-3, 0.75rem);
7324
7935
  padding: var(--space-6);
7325
7936
  padding-top: var(--space-4);
7326
- border-top: 1px solid var(--color-border);
7937
+ border-top: var(--border-width) solid var(--color-border);
7327
7938
  flex-shrink: 0;
7328
7939
  }
7329
7940
 
@@ -7337,7 +7948,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7337
7948
 
7338
7949
  /* === recipes/dropdown.css === */
7339
7950
  /* @ui:component dropdown */
7340
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-primary space-1 space-2 space-3 space-4 radius-md radius-lg shadow-md text-sm weight-medium duration-fast ease-default ease-out z-dropdown */
7951
+ /* @ui:tokens color-bg panel-bg color-fg color-fg-muted color-border color-primary-subtle color-primary space-1 space-2 space-3 space-4 radius-md radius-lg shadow-md text-sm weight-medium duration-fast ease-default ease-out z-dropdown font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop disabled-opacity */
7341
7952
 
7342
7953
  /* ── Root ── */
7343
7954
  [data-ui="dropdown"] {
@@ -7351,11 +7962,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7351
7962
  align-items: center;
7352
7963
  gap: var(--space-2);
7353
7964
  padding: var(--space-2) var(--space-3);
7354
- border: 1px solid var(--color-border);
7965
+ border: var(--border-width) solid var(--color-border);
7355
7966
  border-radius: var(--radius-md);
7356
7967
  background: var(--color-bg);
7357
7968
  color: var(--color-fg);
7358
- font-family: var(--font-sans, system-ui, sans-serif);
7969
+ font-family: var(--font-ui);
7359
7970
  font-size: var(--text-sm);
7360
7971
  font-weight: var(--weight-medium);
7361
7972
  cursor: pointer;
@@ -7369,8 +7980,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7369
7980
  }
7370
7981
 
7371
7982
  [data-ui="dropdown"] [data-part="trigger"]:focus-visible {
7372
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7373
- outline-offset: 2px;
7983
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
7984
+ outline-offset: var(--focus-ring-offset);
7374
7985
  }
7375
7986
 
7376
7987
  /* ── Menu ── */
@@ -7382,9 +7993,9 @@ div[data-ui="separator"][data-style="thick"]::after {
7382
7993
  min-width: 180px;
7383
7994
  margin-top: var(--space-1);
7384
7995
  padding: var(--space-1);
7385
- border: 1px solid var(--color-border);
7996
+ border: var(--border-width) solid var(--color-border);
7386
7997
  border-radius: var(--radius-lg);
7387
- background: var(--color-bg);
7998
+ background: var(--panel-bg);
7388
7999
  box-shadow: var(--shadow-md);
7389
8000
  opacity: 0;
7390
8001
  transform: translateY(-4px);
@@ -7392,6 +8003,13 @@ div[data-ui="separator"][data-style="thick"]::after {
7392
8003
  transform var(--duration-fast) var(--ease-out);
7393
8004
  }
7394
8005
 
8006
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8007
+ [data-ui="dropdown"] [data-part="menu"] {
8008
+ -webkit-backdrop-filter: var(--surface-backdrop);
8009
+ backdrop-filter: var(--surface-backdrop);
8010
+ }
8011
+ }
8012
+
7395
8013
  [data-ui="dropdown"][data-state="open"] [data-part="menu"] {
7396
8014
  opacity: 1;
7397
8015
  transform: translateY(0);
@@ -7414,7 +8032,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7414
8032
  border-radius: var(--radius-md);
7415
8033
  background: transparent;
7416
8034
  color: var(--color-fg);
7417
- font-family: var(--font-sans, system-ui, sans-serif);
8035
+ font-family: var(--font-ui);
7418
8036
  font-size: var(--text-sm);
7419
8037
  text-align: start;
7420
8038
  cursor: pointer;
@@ -7436,12 +8054,12 @@ div[data-ui="separator"][data-style="thick"]::after {
7436
8054
  focus additionally draws the ring, inset so it does not overlap the item
7437
8055
  above. [W3-3] */
7438
8056
  [data-ui="dropdown"] [data-part="item"]:focus-visible {
7439
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7440
- outline-offset: -2px;
8057
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8058
+ outline-offset: calc(-1 * var(--focus-ring-offset));
7441
8059
  }
7442
8060
 
7443
8061
  [data-ui="dropdown"] [data-part="item"]:disabled {
7444
- opacity: 0.5;
8062
+ opacity: var(--disabled-opacity);
7445
8063
  cursor: not-allowed;
7446
8064
  pointer-events: none;
7447
8065
  }
@@ -7494,14 +8112,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7494
8112
 
7495
8113
  /* === recipes/file-upload.css === */
7496
8114
  /* @ui:component file-upload */
7497
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-px space-1 space-2 space-3 space-4 space-8 radius-md radius-lg text-xs text-sm text-base weight-semibold font-sans duration-fast ease-default */
8115
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-px space-1 space-2 space-3 space-4 space-8 radius-md radius-lg text-xs text-sm text-base weight-semibold font-ui duration-fast ease-default focus-ring-width focus-ring-style focus-ring-color focus-ring-offset border-width disabled-opacity */
7498
8116
 
7499
8117
  [data-ui="file-upload"] {
7500
8118
  display: grid;
7501
8119
  gap: var(--space-4);
7502
8120
  inline-size: 100%;
7503
8121
  color: var(--color-fg);
7504
- font-family: var(--font-sans);
8122
+ font-family: var(--font-ui);
7505
8123
  }
7506
8124
 
7507
8125
  [data-ui="file-upload"] [data-part="dropzone"] {
@@ -7536,14 +8154,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7536
8154
  }
7537
8155
 
7538
8156
  [data-ui="file-upload"]:has([data-part="input"]:focus-visible) [data-part="dropzone"] {
7539
- outline: var(--space-px) solid var(--color-ring);
7540
- outline-offset: var(--space-1);
8157
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8158
+ outline-offset: var(--focus-ring-offset);
7541
8159
  }
7542
8160
 
7543
8161
  [data-ui="file-upload"][data-state="dragging"] [data-part="dropzone"] {
7544
8162
  border-color: var(--color-primary);
7545
8163
  background: var(--color-primary-subtle);
7546
- box-shadow: 0 0 0 var(--space-px) var(--color-primary);
8164
+ box-shadow: 0 0 0 var(--border-width) var(--color-primary);
7547
8165
  }
7548
8166
 
7549
8167
  [data-ui="file-upload"] [data-part="prompt"] {
@@ -7617,8 +8235,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7617
8235
  }
7618
8236
 
7619
8237
  [data-ui="file-upload"] [data-part="remove"]:focus-visible {
7620
- outline: var(--space-px) solid var(--color-ring);
7621
- outline-offset: var(--space-1);
8238
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8239
+ outline-offset: var(--focus-ring-offset);
7622
8240
  }
7623
8241
 
7624
8242
  [data-ui="file-upload"] [data-part="empty"] {
@@ -7640,7 +8258,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7640
8258
  }
7641
8259
 
7642
8260
  [data-ui="file-upload"][data-disabled] {
7643
- opacity: 0.5;
8261
+ opacity: var(--disabled-opacity);
7644
8262
  }
7645
8263
 
7646
8264
  [data-ui="file-upload"][data-disabled] [data-part="dropzone"],
@@ -7656,7 +8274,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7656
8274
 
7657
8275
  /* === recipes/input-otp.css === */
7658
8276
  /* @ui:component input-otp */
7659
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-destructive radius-md space-2 space-3 text-base text-lg font-sans duration-fast ease-default */
8277
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-destructive radius-md space-2 space-3 text-base text-lg font-ui duration-fast ease-default border-width disabled-opacity */
7660
8278
 
7661
8279
  /* ── Root ── */
7662
8280
  [data-ui="input-otp"] {
@@ -7671,7 +8289,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7671
8289
  gutter. The transparent input is `inset: 0`, so it follows the box the
7672
8290
  segments settle into however many rows that takes. */
7673
8291
  max-inline-size: 100%;
7674
- font-family: var(--font-sans, system-ui, sans-serif);
8292
+ font-family: var(--font-ui);
7675
8293
  }
7676
8294
 
7677
8295
  /* ── Real input ──
@@ -7716,14 +8334,14 @@ div[data-ui="separator"][data-style="thick"]::after {
7716
8334
  justify-content: center;
7717
8335
  inline-size: var(--input-otp-segment-size);
7718
8336
  block-size: var(--input-otp-segment-size);
7719
- border: 1px solid var(--color-border);
8337
+ border: var(--border-width) solid var(--color-border);
7720
8338
  border-radius: var(--radius-md);
7721
8339
  background: var(--color-bg);
7722
8340
  color: var(--color-fg);
7723
8341
  font-size: var(--text-lg, 1.125rem);
7724
8342
  font-variant-numeric: tabular-nums;
7725
8343
  line-height: 1;
7726
- transition: border-color var(--duration-fast, 120ms) var(--ease-default, ease),
8344
+ transition: border-color var(--duration-fast) var(--ease-default),
7727
8345
  box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
7728
8346
  }
7729
8347
 
@@ -7735,7 +8353,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7735
8353
  /* Active (caret / selected) segment while focused */
7736
8354
  [data-ui="input-otp"] [data-part="segment"][data-active] {
7737
8355
  border-color: var(--color-ring);
7738
- box-shadow: 0 0 0 1px var(--color-ring);
8356
+ box-shadow: 0 0 0 var(--border-width) var(--color-ring);
7739
8357
  }
7740
8358
 
7741
8359
  /* Blinking caret in the next-to-fill empty slot */
@@ -7783,7 +8401,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7783
8401
 
7784
8402
  /* ── Disabled ── */
7785
8403
  [data-ui="input-otp"][data-disabled] {
7786
- opacity: 0.5;
8404
+ opacity: var(--disabled-opacity);
7787
8405
  cursor: not-allowed;
7788
8406
  }
7789
8407
  [data-ui="input-otp"][data-disabled] [data-part="input"] {
@@ -7807,7 +8425,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7807
8425
 
7808
8426
  /* === recipes/menubar.css === */
7809
8427
  /* @ui:component menubar */
7810
- /* @ui:tokens color-bg color-border color-fg color-fg-muted color-primary color-primary-subtle color-ring space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-xs text-sm text-base weight-medium duration-fast ease-out z-dropdown font-sans */
8428
+ /* @ui:tokens color-bg color-border color-fg color-fg-muted color-primary color-primary-subtle space-px space-1 space-2 space-3 space-4 space-20 radius-md radius-lg shadow-md text-xs text-sm text-base weight-medium duration-fast ease-out z-dropdown font-ui focus-ring-color focus-ring-width disabled-opacity */
7811
8429
 
7812
8430
  [data-ui="menubar"] {
7813
8431
  position: relative;
@@ -7825,7 +8443,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7825
8443
  border-radius: var(--radius-lg);
7826
8444
  background: var(--color-bg);
7827
8445
  color: var(--color-fg);
7828
- font-family: var(--font-sans);
8446
+ font-family: var(--font-ui);
7829
8447
  }
7830
8448
 
7831
8449
  [data-ui="menubar"] [data-part="group"] {
@@ -7867,7 +8485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7867
8485
 
7868
8486
  [data-ui="menubar"] [data-part="trigger"]:focus-visible,
7869
8487
  [data-ui="menubar"] [data-part="item"]:focus-visible {
7870
- box-shadow: 0 0 0 calc(var(--space-px) * 2) var(--color-ring);
8488
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
7871
8489
  }
7872
8490
 
7873
8491
  [data-ui="menubar"] [data-part="submenu"] {
@@ -7902,7 +8520,10 @@ div[data-ui="separator"][data-style="thick"]::after {
7902
8520
  [data-ui="menubar"] [role="menuitem"][aria-disabled="true"] {
7903
8521
  color: var(--color-fg-muted);
7904
8522
  cursor: not-allowed;
7905
- opacity: 0.6;
8523
+ /* 0.6 at the 0.5 default — lighter than a control, since the muted colour
8524
+ already carries half the signal — and a theme's `--disabled-opacity` moves
8525
+ it (1.1A-27). */
8526
+ opacity: calc(var(--disabled-opacity) * 1.2);
7906
8527
  }
7907
8528
 
7908
8529
  [data-ui="menubar"] [data-part="separator"] {
@@ -7934,7 +8555,7 @@ div[data-ui="separator"][data-style="thick"]::after {
7934
8555
 
7935
8556
  /* === recipes/pagination.css === */
7936
8557
  /* @ui:component pagination */
7937
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-primary color-primary-fg color-border radius-md space-1 space-2 space-3 text-xs text-sm text-base weight-medium duration-fast ease-default */
8558
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-primary color-primary-fg color-border radius-md space-1 space-2 space-3 text-xs text-sm text-base weight-medium duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
7938
8559
 
7939
8560
  /* ── Root ── */
7940
8561
  [data-ui="pagination"] {
@@ -7970,11 +8591,11 @@ div[data-ui="separator"][data-style="thick"]::after {
7970
8591
  min-width: 36px;
7971
8592
  height: 36px;
7972
8593
  padding: 0 var(--space-2);
7973
- border: 1px solid var(--color-border);
8594
+ border: var(--border-width) solid var(--color-border);
7974
8595
  border-radius: var(--radius-md);
7975
8596
  background: var(--color-bg);
7976
8597
  color: var(--color-fg);
7977
- font-family: var(--font-sans, system-ui, sans-serif);
8598
+ font-family: var(--font-ui);
7978
8599
  font-size: var(--text-sm);
7979
8600
  font-weight: var(--weight-medium);
7980
8601
  cursor: pointer;
@@ -7995,8 +8616,8 @@ div[data-ui="separator"][data-style="thick"]::after {
7995
8616
  [data-ui="pagination"] [data-part="page"]:focus-visible,
7996
8617
  [data-ui="pagination"] [data-part="prev"]:focus-visible,
7997
8618
  [data-ui="pagination"] [data-part="next"]:focus-visible {
7998
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
7999
- outline-offset: 2px;
8619
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8620
+ outline-offset: var(--focus-ring-offset);
8000
8621
  }
8001
8622
 
8002
8623
  /* ── Active page ── */
@@ -8020,7 +8641,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8020
8641
  /* ── Disabled ── */
8021
8642
  [data-ui="pagination"] [data-part="prev"]:disabled,
8022
8643
  [data-ui="pagination"] [data-part="next"]:disabled {
8023
- opacity: 0.5;
8644
+ opacity: var(--disabled-opacity);
8024
8645
  cursor: not-allowed;
8025
8646
  pointer-events: none;
8026
8647
  }
@@ -8090,7 +8711,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8090
8711
 
8091
8712
  /* === recipes/popover.css === */
8092
8713
  /* @ui:component popover */
8093
- /* @ui:tokens color-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default */
8714
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-md radius-lg space-3 space-4 z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
8094
8715
 
8095
8716
  /* ── Root ── */
8096
8717
  [data-ui="popover"] {
@@ -8104,11 +8725,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8104
8725
  align-items: center;
8105
8726
  gap: var(--space-2, 0.5rem);
8106
8727
  padding: var(--space-2, 0.5rem) var(--space-3);
8107
- border: 1px solid var(--color-border);
8728
+ border: var(--border-width) solid var(--color-border);
8108
8729
  border-radius: var(--radius-md, 0.375rem);
8109
8730
  background: var(--color-bg);
8110
8731
  color: var(--color-fg);
8111
- font-family: var(--font-sans, system-ui, sans-serif);
8732
+ font-family: var(--font-ui);
8112
8733
  font-size: var(--text-sm, 0.875rem);
8113
8734
  font-weight: var(--weight-medium, 500);
8114
8735
  cursor: pointer;
@@ -8122,8 +8743,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8122
8743
  }
8123
8744
 
8124
8745
  [data-ui="popover"] [data-part="trigger"]:focus-visible {
8125
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8126
- outline-offset: 2px;
8746
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8747
+ outline-offset: var(--focus-ring-offset);
8127
8748
  }
8128
8749
 
8129
8750
  /* ── Content ── */
@@ -8132,9 +8753,9 @@ div[data-ui="separator"][data-style="thick"]::after {
8132
8753
  z-index: var(--z-dropdown);
8133
8754
  min-width: 200px;
8134
8755
  padding: var(--space-4);
8135
- border: 1px solid var(--color-border);
8756
+ border: var(--border-width) solid var(--color-border);
8136
8757
  border-radius: var(--radius-lg);
8137
- background: var(--color-bg);
8758
+ background: var(--panel-bg);
8138
8759
  color: var(--color-fg);
8139
8760
  box-shadow: var(--shadow-md);
8140
8761
  opacity: 0;
@@ -8143,6 +8764,13 @@ div[data-ui="separator"][data-style="thick"]::after {
8143
8764
  transform var(--duration-fast) var(--ease-default);
8144
8765
  }
8145
8766
 
8767
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
8768
+ [data-ui="popover"] [data-part="content"] {
8769
+ -webkit-backdrop-filter: var(--surface-backdrop);
8770
+ backdrop-filter: var(--surface-backdrop);
8771
+ }
8772
+ }
8773
+
8146
8774
  [data-ui="popover"][data-state="open"] [data-part="content"] {
8147
8775
  opacity: 1;
8148
8776
  transform: scale(1);
@@ -8230,8 +8858,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8230
8858
  position: absolute;
8231
8859
  width: 8px;
8232
8860
  height: 8px;
8233
- background: var(--color-bg);
8234
- border: 1px solid var(--color-border);
8861
+ background: var(--panel-bg);
8862
+ border: var(--border-width) solid var(--color-border);
8235
8863
  transform: rotate(45deg);
8236
8864
  }
8237
8865
 
@@ -8332,8 +8960,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8332
8960
  }
8333
8961
 
8334
8962
  [data-ui="popover"] [data-part="close"]:focus-visible {
8335
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8336
- outline-offset: 2px;
8963
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
8964
+ outline-offset: var(--focus-ring-offset);
8337
8965
  }
8338
8966
 
8339
8967
  /* ── Motion ── */
@@ -8346,7 +8974,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8346
8974
 
8347
8975
  /* === recipes/qr-code.css === */
8348
8976
  /* @ui:component qr-code */
8349
- /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-sans space-2 */
8977
+ /* @ui:tokens color-fg color-bg doc-legal-color doc-legal-size doc-font font-body space-2 */
8350
8978
 
8351
8979
  /* ── Base ── */
8352
8980
  [data-ui="qr-code"] {
@@ -8364,7 +8992,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8364
8992
 
8365
8993
  /* ── Caption ── */
8366
8994
  [data-ui="qr-code"] [data-part="caption"] {
8367
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
8995
+ font-family: var(--doc-font, var(--font-body));
8368
8996
  font-size: var(--doc-legal-size, var(--text-xs));
8369
8997
  color: var(--doc-legal-color, var(--color-fg-muted));
8370
8998
  text-align: center;
@@ -8405,7 +9033,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8405
9033
 
8406
9034
  /* === recipes/select-custom.css === */
8407
9035
  /* @ui:component select-custom */
8408
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 space-4 text-sm text-xs z-dropdown duration-fast ease-default */
9036
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-2 space-3 space-4 text-sm text-xs z-dropdown duration-fast ease-default font-ui border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
8409
9037
 
8410
9038
  /* ── Root ── */
8411
9039
  [data-ui="select-custom"] {
@@ -8422,11 +9050,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8422
9050
  width: 100%;
8423
9051
  min-width: 180px;
8424
9052
  padding: var(--space-2) var(--space-3);
8425
- border: 1px solid var(--color-border);
9053
+ border: var(--border-width) solid var(--color-border);
8426
9054
  border-radius: var(--radius-md);
8427
9055
  background: var(--color-bg);
8428
9056
  color: var(--color-fg);
8429
- font-family: var(--font-sans, system-ui, sans-serif);
9057
+ font-family: var(--font-ui);
8430
9058
  font-size: var(--text-sm);
8431
9059
  cursor: pointer;
8432
9060
  white-space: nowrap;
@@ -8439,8 +9067,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8439
9067
  }
8440
9068
 
8441
9069
  [data-ui="select-custom"] [data-part="trigger"]:focus-visible {
8442
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8443
- outline-offset: 2px;
9070
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9071
+ outline-offset: var(--focus-ring-offset);
8444
9072
  }
8445
9073
 
8446
9074
  /* ── Value ── */
@@ -8476,7 +9104,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8476
9104
  z-index: var(--z-dropdown);
8477
9105
  margin-top: var(--space-1);
8478
9106
  padding: var(--space-1);
8479
- border: 1px solid var(--color-border);
9107
+ border: var(--border-width) solid var(--color-border);
8480
9108
  border-radius: var(--radius-lg);
8481
9109
  background: var(--color-bg);
8482
9110
  box-shadow: var(--shadow-md);
@@ -8500,11 +9128,11 @@ div[data-ui="separator"][data-style="thick"]::after {
8500
9128
  padding: var(--space-2) var(--space-3);
8501
9129
  margin-bottom: var(--space-1);
8502
9130
  border: none;
8503
- border-bottom: 1px solid var(--color-border);
9131
+ border-bottom: var(--border-width) solid var(--color-border);
8504
9132
  border-radius: 0;
8505
9133
  background: transparent;
8506
9134
  color: var(--color-fg);
8507
- font-family: var(--font-sans, system-ui, sans-serif);
9135
+ font-family: var(--font-ui);
8508
9136
  font-size: var(--text-sm);
8509
9137
  outline: none;
8510
9138
  }
@@ -8598,7 +9226,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8598
9226
 
8599
9227
  /* === recipes/sheet.css === */
8600
9228
  /* @ui:component sheet */
8601
- /* @ui:tokens color-bg color-fg color-border shadow-xl radius-xl space-4 space-6 z-overlay z-modal duration-normal duration-slow ease-out */
9229
+ /* @ui:tokens color-bg panel-bg color-fg color-border shadow-xl radius-xl space-4 space-6 z-overlay z-modal duration-normal duration-slow ease-out font-heading border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
8602
9230
 
8603
9231
  /* ── Root ── */
8604
9232
  [data-ui="sheet"] {
@@ -8629,11 +9257,18 @@ div[data-ui="separator"][data-style="thick"]::after {
8629
9257
  z-index: var(--z-modal);
8630
9258
  display: flex;
8631
9259
  flex-direction: column;
8632
- background: var(--color-bg);
9260
+ background: var(--panel-bg);
8633
9261
  box-shadow: var(--shadow-xl);
8634
9262
  transition: transform var(--duration-slow) var(--ease-out);
8635
9263
  }
8636
9264
 
9265
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
9266
+ [data-ui="sheet"] [data-part="panel"] {
9267
+ -webkit-backdrop-filter: var(--surface-backdrop);
9268
+ backdrop-filter: var(--surface-backdrop);
9269
+ }
9270
+ }
9271
+
8637
9272
  /* ── Side: Bottom ── */
8638
9273
  [data-ui="sheet"] [data-part="panel"][data-variant="bottom"] {
8639
9274
  bottom: 0;
@@ -8661,7 +9296,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8661
9296
  bottom: 0;
8662
9297
  max-width: 100vw;
8663
9298
  border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
8664
- border-inline-end: 1px solid var(--color-border);
9299
+ border-inline-end: var(--border-width) solid var(--color-border);
8665
9300
  transform: translateX(-100%);
8666
9301
  }
8667
9302
 
@@ -8672,7 +9307,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8672
9307
  bottom: 0;
8673
9308
  max-width: 100vw;
8674
9309
  border-radius: var(--radius-xl) 0 0 var(--radius-xl);
8675
- border-inline-start: 1px solid var(--color-border);
9310
+ border-inline-start: var(--border-width) solid var(--color-border);
8676
9311
  transform: translateX(100%);
8677
9312
  }
8678
9313
 
@@ -8749,6 +9384,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8749
9384
  /* ── Title ── */
8750
9385
  [data-ui="sheet"] [data-part="title"] {
8751
9386
  margin: 0;
9387
+ font-family: var(--font-heading);
8752
9388
  font-size: var(--text-lg, 1.125rem);
8753
9389
  font-weight: var(--weight-semibold, 600);
8754
9390
  color: var(--color-fg);
@@ -8783,8 +9419,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8783
9419
  }
8784
9420
 
8785
9421
  [data-ui="sheet"] [data-part="close"]:not([data-ui]):focus-visible {
8786
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8787
- outline-offset: 2px;
9422
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9423
+ outline-offset: var(--focus-ring-offset);
8788
9424
  }
8789
9425
 
8790
9426
  /* ── Body ── */
@@ -8805,7 +9441,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8805
9441
 
8806
9442
  /* === recipes/sidebar.css === */
8807
9443
  /* @ui:component sidebar */
8808
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-bg-muted color-ring shadow-xl space-1 space-2 space-3 space-4 radius-md radius-lg z-overlay z-modal text-sm text-lg weight-medium weight-semibold duration-normal duration-slow ease-out ease-default */
9444
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-bg-muted color-ring shadow-xl space-1 space-2 space-3 space-4 radius-md radius-lg z-overlay z-modal text-sm text-lg weight-medium weight-semibold duration-normal duration-slow ease-out ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
8809
9445
 
8810
9446
  /* ── Root ──
8811
9447
  The root owns the layout column from `md` up; the panel is the visual surface.
@@ -8849,7 +9485,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8849
9485
  flex-direction: column;
8850
9486
  gap: var(--space-2);
8851
9487
  background: var(--sidebar-bg);
8852
- border-inline-end: 1px solid var(--color-border);
9488
+ border-inline-end: var(--border-width) solid var(--color-border);
8853
9489
  border-start-end-radius: var(--radius-lg, 0.5rem);
8854
9490
  border-end-end-radius: var(--radius-lg, 0.5rem);
8855
9491
  box-shadow: var(--shadow-xl);
@@ -8930,8 +9566,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8930
9566
  }
8931
9567
 
8932
9568
  [data-ui="sidebar"] [data-part="trigger"]:focus-visible {
8933
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8934
- outline-offset: 2px;
9569
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9570
+ outline-offset: var(--focus-ring-offset);
8935
9571
  }
8936
9572
 
8937
9573
  /* ── Navigation ── */
@@ -8967,8 +9603,8 @@ div[data-ui="separator"][data-style="thick"]::after {
8967
9603
  }
8968
9604
 
8969
9605
  [data-ui="sidebar"] [data-part="item"]:focus-visible {
8970
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
8971
- outline-offset: -2px;
9606
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9607
+ outline-offset: calc(-1 * var(--focus-ring-offset));
8972
9608
  }
8973
9609
 
8974
9610
  [data-ui="sidebar"] [data-part="item"][aria-current="page"] {
@@ -8995,7 +9631,7 @@ div[data-ui="separator"][data-style="thick"]::after {
8995
9631
  [data-ui="sidebar"] [data-part="footer"] {
8996
9632
  flex-shrink: 0;
8997
9633
  padding: var(--space-3) var(--space-4);
8998
- border-block-start: 1px solid var(--color-border);
9634
+ border-block-start: var(--border-width) solid var(--color-border);
8999
9635
  }
9000
9636
 
9001
9637
  /* ── Rail (icons only) ── */
@@ -9088,7 +9724,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9088
9724
 
9089
9725
  /* === recipes/slider.css === */
9090
9726
  /* @ui:component slider */
9091
- /* @ui:tokens color-bg color-fg-muted color-border color-primary color-primary-subtle color-ring color-bg-muted space-2 space-3 space-4 radius-full text-sm text-base shadow-sm duration-fast ease-default */
9727
+ /* @ui:tokens color-bg color-fg-muted color-border color-primary color-primary-subtle color-ring color-bg-muted space-2 space-3 space-4 radius-full text-sm text-base shadow-sm duration-fast ease-default font-ui border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
9092
9728
 
9093
9729
  /* ── Root ── */
9094
9730
  [data-ui="slider"] {
@@ -9138,28 +9774,28 @@ div[data-ui="separator"][data-style="thick"]::after {
9138
9774
  value in both LTR and RTL (translateX is physical, so -50% always recentres). */
9139
9775
  transform: translate(-50%, -50%);
9140
9776
  background: var(--color-bg, white);
9141
- border: 2px solid var(--color-primary);
9777
+ border: var(--border-width-strong) solid var(--color-primary);
9142
9778
  border-radius: var(--radius-full, 9999px);
9143
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1));
9779
+ box-shadow: var(--shadow-sm);
9144
9780
  cursor: grab;
9145
9781
  touch-action: none;
9146
- transition: box-shadow var(--duration-fast, 120ms) var(--ease-default, ease);
9782
+ transition: box-shadow var(--duration-fast) var(--ease-default);
9147
9783
  }
9148
9784
 
9149
9785
  [data-ui="slider"] [data-part="thumb"]:hover {
9150
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9151
- 0 0 0 4px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9786
+ box-shadow: var(--shadow-sm),
9787
+ 0 0 0 4px var(--color-primary-subtle);
9152
9788
  }
9153
9789
 
9154
9790
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
9155
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9156
- outline-offset: 2px;
9791
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9792
+ outline-offset: var(--focus-ring-offset);
9157
9793
  }
9158
9794
 
9159
9795
  [data-ui="slider"] [data-part="thumb"][data-state="dragging"] {
9160
9796
  cursor: grabbing;
9161
- box-shadow: var(--shadow-sm, 0 1px 3px oklch(0 0 0 / 0.1)),
9162
- 0 0 0 5px var(--color-primary-subtle, oklch(0.95 0.03 264 / 0.6));
9797
+ box-shadow: var(--shadow-sm),
9798
+ 0 0 0 5px var(--color-primary-subtle);
9163
9799
  }
9164
9800
 
9165
9801
  /* ── Value output ── */
@@ -9167,7 +9803,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9167
9803
  flex: 0 0 auto;
9168
9804
  min-inline-size: 3ch;
9169
9805
  color: var(--color-fg-muted);
9170
- font-family: var(--font-sans, system-ui, sans-serif);
9806
+ font-family: var(--font-ui);
9171
9807
  font-size: var(--text-sm);
9172
9808
  font-variant-numeric: tabular-nums;
9173
9809
  text-align: end;
@@ -9186,7 +9822,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9186
9822
 
9187
9823
  /* ── Disabled ── */
9188
9824
  [data-ui="slider"][data-disabled] {
9189
- opacity: 0.5;
9825
+ opacity: var(--disabled-opacity);
9190
9826
  cursor: not-allowed;
9191
9827
  pointer-events: none;
9192
9828
  }
@@ -9204,7 +9840,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9204
9840
  the substitution so the control still reads as "this much, up to here". [W3-3] */
9205
9841
  @media (forced-colors: active) {
9206
9842
  [data-ui="slider"] [data-part="track"] {
9207
- border: 1px solid ButtonText;
9843
+ border: var(--border-width) solid ButtonText;
9208
9844
  }
9209
9845
 
9210
9846
  [data-ui="slider"] [data-part="range"] {
@@ -9215,7 +9851,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9215
9851
  [data-ui="slider"] [data-part="thumb"] {
9216
9852
  forced-color-adjust: none;
9217
9853
  background: ButtonText;
9218
- border: 1px solid ButtonFace;
9854
+ border: var(--border-width) solid ButtonFace;
9219
9855
  }
9220
9856
 
9221
9857
  [data-ui="slider"] [data-part="thumb"]:focus-visible {
@@ -9225,7 +9861,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9225
9861
 
9226
9862
  /* === recipes/table.css === */
9227
9863
  /* @ui:component table */
9228
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-fg-subtle color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-0h space-1 space-2 space-3 space-4 space-5 space-8 text-xs text-sm weight-semibold weight-bold radius-sm radius-md radius-full duration-fast ease-default doc-table-footer-bg doc-table-footer-weight doc-print-border-color */
9864
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-fg-subtle color-border color-border-strong color-primary color-primary-subtle color-ring color-destructive color-destructive-subtle space-0h space-1 space-2 space-3 space-4 space-5 space-8 text-xs text-sm weight-semibold weight-bold radius-sm radius-md radius-full duration-fast ease-default doc-table-footer-bg doc-table-footer-weight doc-print-border-color font-body border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset stripe-bg */
9229
9865
 
9230
9866
  /* ── Root ── */
9231
9867
  [data-ui="table"] {
@@ -9251,7 +9887,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9251
9887
  width: 100%;
9252
9888
  border-collapse: separate;
9253
9889
  border-spacing: 0;
9254
- font-family: var(--font-sans, system-ui, sans-serif);
9890
+ font-family: var(--font-body);
9255
9891
  }
9256
9892
 
9257
9893
  /* Once any column is resized the layout freezes so widths are exact. */
@@ -9273,7 +9909,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9273
9909
  font-weight: var(--weight-semibold);
9274
9910
  color: var(--color-fg-muted);
9275
9911
  background: var(--color-bg);
9276
- border-bottom: 2px solid var(--color-border);
9912
+ border-bottom: var(--border-width-strong) solid var(--color-border);
9277
9913
  white-space: nowrap;
9278
9914
  user-select: none;
9279
9915
  }
@@ -9331,8 +9967,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9331
9967
  /* Keyboard focus on cells (sortable headers + navigable grids). */
9332
9968
  [data-ui="table"] [data-part="th"]:focus-visible,
9333
9969
  [data-ui="table"] [data-part="td"]:focus-visible {
9334
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9335
- outline-offset: -2px;
9970
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
9971
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9336
9972
  }
9337
9973
 
9338
9974
  /* ── Data Cell ── */
@@ -9340,7 +9976,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9340
9976
  padding: var(--space-3) var(--space-4);
9341
9977
  font-size: var(--text-sm);
9342
9978
  color: var(--color-fg);
9343
- border-bottom: 1px solid var(--color-border);
9979
+ border-bottom: var(--border-width) solid var(--color-border);
9344
9980
  background: var(--color-bg);
9345
9981
  transition: background var(--duration-fast) var(--ease-default);
9346
9982
  }
@@ -9369,31 +10005,31 @@ div[data-ui="separator"][data-style="thick"]::after {
9369
10005
  Static fallback via nth-child; once the controller stamps data-stripe on the
9370
10006
  visible rows (so hidden rows never break the pattern), the stamped rules win. */
9371
10007
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]) [data-part="td"] {
9372
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10008
+ background: var(--stripe-bg);
9373
10009
  }
9374
10010
 
9375
10011
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"]:not([data-stripe]):nth-child(even):not([data-selected]):hover [data-part="td"] {
9376
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10012
+ background: var(--stripe-bg);
9377
10013
  }
9378
10014
 
9379
10015
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]) [data-part="td"] {
9380
- background: var(--color-bg-subtle, oklch(0.97 0.004 260));
10016
+ background: var(--stripe-bg);
9381
10017
  }
9382
10018
 
9383
10019
  [data-ui="table"][data-variant="striped"] [data-part="tbody"] [data-part="tr"][data-stripe="even"]:not([data-selected]):hover [data-part="td"] {
9384
- background: var(--color-bg-subtle, oklch(0.95 0.006 260));
10020
+ background: var(--stripe-bg);
9385
10021
  }
9386
10022
 
9387
10023
  /* ── Bordered Variant ── */
9388
10024
  [data-ui="table"][data-variant="bordered"] [data-part="table"] {
9389
- border: 1px solid var(--color-border);
10025
+ border: var(--border-width) solid var(--color-border);
9390
10026
  border-radius: var(--radius-md, 0.375rem);
9391
10027
  overflow: hidden;
9392
10028
  }
9393
10029
 
9394
10030
  [data-ui="table"][data-variant="bordered"] [data-part="th"],
9395
10031
  [data-ui="table"][data-variant="bordered"] [data-part="td"] {
9396
- border: 1px solid var(--color-border);
10032
+ border: var(--border-width) solid var(--color-border);
9397
10033
  }
9398
10034
 
9399
10035
  /* ── Size: Small ── */
@@ -9421,7 +10057,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9421
10057
  /* ── Footer ── */
9422
10058
  [data-ui="table"] [data-part="tfoot"] [data-part="td"] {
9423
10059
  font-weight: var(--doc-table-footer-weight, var(--weight-semibold));
9424
- border-top: 2px solid var(--color-border);
10060
+ border-top: var(--border-width-strong) solid var(--color-border);
9425
10061
  border-bottom: none;
9426
10062
  background: var(--doc-table-footer-bg, var(--color-bg-subtle, oklch(0.97 0.004 260)));
9427
10063
  }
@@ -9547,7 +10183,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9547
10183
  [data-ui="table"] [data-part="filter-row"] [data-part="th"] {
9548
10184
  padding: var(--space-1) var(--space-2);
9549
10185
  background: var(--color-bg);
9550
- border-bottom: 1px solid var(--color-border);
10186
+ border-bottom: var(--border-width) solid var(--color-border);
9551
10187
  }
9552
10188
 
9553
10189
  [data-ui="table"] [data-part="filter-input"],
@@ -9559,14 +10195,14 @@ div[data-ui="separator"][data-style="thick"]::after {
9559
10195
  font-size: var(--text-xs);
9560
10196
  color: var(--color-fg);
9561
10197
  background: var(--color-bg);
9562
- border: 1px solid var(--color-border);
10198
+ border: var(--border-width) solid var(--color-border);
9563
10199
  border-radius: var(--radius-sm);
9564
10200
  }
9565
10201
 
9566
10202
  [data-ui="table"] [data-part="filter-input"]:focus,
9567
10203
  [data-ui="table"] [data-part="filter"]:focus {
9568
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9569
- outline-offset: -1px;
10204
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10205
+ outline-offset: calc(-1 * var(--border-width));
9570
10206
  border-color: var(--color-primary);
9571
10207
  }
9572
10208
 
@@ -9587,7 +10223,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9587
10223
  text-align: inherit;
9588
10224
  color: var(--color-fg);
9589
10225
  background: var(--color-bg);
9590
- border: 1px solid var(--color-primary);
10226
+ border: var(--border-width) solid var(--color-primary);
9591
10227
  border-radius: var(--radius-sm);
9592
10228
  outline: none;
9593
10229
  }
@@ -9640,11 +10276,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9640
10276
  }
9641
10277
 
9642
10278
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="before"] [data-part="td"] {
9643
- border-block-start: 2px solid var(--color-primary);
10279
+ border-block-start: var(--border-width-strong) solid var(--color-primary);
9644
10280
  }
9645
10281
 
9646
10282
  [data-ui="table"] [data-part="tr"][data-drop-target][data-drop-pos="after"] [data-part="td"] {
9647
- border-block-end: 2px solid var(--color-primary);
10283
+ border-block-end: var(--border-width-strong) solid var(--color-primary);
9648
10284
  }
9649
10285
 
9650
10286
  [data-ui="table"] [data-part="th"][data-dragging] {
@@ -9652,11 +10288,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9652
10288
  }
9653
10289
 
9654
10290
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="before"] {
9655
- border-inline-start: 2px solid var(--color-primary);
10291
+ border-inline-start: var(--border-width-strong) solid var(--color-primary);
9656
10292
  }
9657
10293
 
9658
10294
  [data-ui="table"] [data-part="th"][data-drop-target][data-drop-pos="after"] {
9659
- border-inline-end: 2px solid var(--color-primary);
10295
+ border-inline-end: var(--border-width-strong) solid var(--color-primary);
9660
10296
  }
9661
10297
 
9662
10298
  /* ── Column Resize Handles (injected by the controller) ── */
@@ -9729,11 +10365,11 @@ div[data-ui="separator"][data-style="thick"]::after {
9729
10365
  }
9730
10366
 
9731
10367
  [data-ui="table"] [data-pin="start"][data-pin-edge] {
9732
- border-inline-end: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10368
+ border-inline-end: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9733
10369
  }
9734
10370
 
9735
10371
  [data-ui="table"] [data-pin="end"][data-pin-edge] {
9736
- border-inline-start: 1px solid var(--color-border-strong, oklch(0.85 0.006 260));
10372
+ border-inline-start: var(--border-width) solid var(--color-border-strong, oklch(0.85 0.006 260));
9737
10373
  }
9738
10374
 
9739
10375
  /* ── Column Visibility ── */
@@ -9805,7 +10441,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9805
10441
  [data-ui="table"][data-stacked] [data-part="tfoot"] [data-part="tr"] {
9806
10442
  display: block;
9807
10443
  margin-block-end: var(--space-3);
9808
- border: 1px solid var(--color-border);
10444
+ border: var(--border-width) solid var(--color-border);
9809
10445
  border-radius: var(--radius-md);
9810
10446
  background: var(--color-bg);
9811
10447
  overflow: hidden;
@@ -9819,7 +10455,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9819
10455
  gap: var(--space-4);
9820
10456
  text-align: end;
9821
10457
  border-bottom: none;
9822
- border-block-end: 1px solid var(--color-border);
10458
+ border-block-end: var(--border-width) solid var(--color-border);
9823
10459
  }
9824
10460
 
9825
10461
  [data-ui="table"][data-stacked] [data-part="tr"] [data-part="td"]:last-child,
@@ -9916,7 +10552,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9916
10552
 
9917
10553
  /* === recipes/tabs.css === */
9918
10554
  /* @ui:component tabs */
9919
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle space-1 space-2 space-3 space-4 radius-md radius-lg text-sm text-base weight-medium duration-fast ease-default */
10555
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle space-1 space-2 space-3 space-4 radius-md radius-lg text-sm text-base weight-medium duration-fast ease-default font-ui border-width border-width-strong focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
9920
10556
 
9921
10557
  /* ── Root ── */
9922
10558
  [data-ui="tabs"] {
@@ -9945,7 +10581,7 @@ div[data-ui="separator"][data-style="thick"]::after {
9945
10581
  border: none;
9946
10582
  background: transparent;
9947
10583
  color: var(--color-fg-muted);
9948
- font-family: var(--font-sans, system-ui, sans-serif);
10584
+ font-family: var(--font-ui);
9949
10585
  font-size: var(--text-sm);
9950
10586
  font-weight: var(--weight-medium);
9951
10587
  cursor: pointer;
@@ -9960,8 +10596,8 @@ div[data-ui="separator"][data-style="thick"]::after {
9960
10596
  }
9961
10597
 
9962
10598
  [data-ui="tabs"] [data-part="trigger"]:focus-visible {
9963
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
9964
- outline-offset: -2px;
10599
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10600
+ outline-offset: calc(-1 * var(--focus-ring-offset));
9965
10601
  border-radius: var(--radius-md);
9966
10602
  }
9967
10603
 
@@ -9971,12 +10607,12 @@ div[data-ui="separator"][data-style="thick"]::after {
9971
10607
 
9972
10608
  /* ── Underline Variant ── */
9973
10609
  [data-ui="tabs"][data-variant="underline"] [data-part="list"] {
9974
- border-bottom: 1px solid var(--color-border);
10610
+ border-bottom: var(--border-width) solid var(--color-border);
9975
10611
  gap: 0;
9976
10612
  }
9977
10613
 
9978
10614
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"] {
9979
- border-bottom: 2px solid transparent;
10615
+ border-bottom: var(--border-width-strong) solid transparent;
9980
10616
  margin-bottom: -1px;
9981
10617
  border-radius: 0;
9982
10618
  }
@@ -10008,17 +10644,17 @@ div[data-ui="separator"][data-style="thick"]::after {
10008
10644
  [data-ui="tabs"][data-variant="pill"] [data-part="trigger"][aria-selected="true"] {
10009
10645
  background: var(--color-bg);
10010
10646
  color: var(--color-fg);
10011
- box-shadow: var(--shadow-xs, 0 1px 2px oklch(0 0 0 / 0.04));
10647
+ box-shadow: var(--shadow-xs);
10012
10648
  }
10013
10649
 
10014
10650
  /* ── Enclosed Variant ── */
10015
10651
  [data-ui="tabs"][data-variant="enclosed"] [data-part="list"] {
10016
- border-bottom: 1px solid var(--color-border);
10652
+ border-bottom: var(--border-width) solid var(--color-border);
10017
10653
  gap: 0;
10018
10654
  }
10019
10655
 
10020
10656
  [data-ui="tabs"][data-variant="enclosed"] [data-part="trigger"] {
10021
- border: 1px solid transparent;
10657
+ border: var(--border-width) solid transparent;
10022
10658
  border-bottom: none;
10023
10659
  border-radius: var(--radius-md) var(--radius-md) 0 0;
10024
10660
  margin-bottom: -1px;
@@ -10063,8 +10699,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10063
10699
  @media (forced-colors: active) {
10064
10700
  [data-ui="tabs"] [data-part="trigger"][aria-selected="true"] {
10065
10701
  /* An outline the OS preserves, on every variant. */
10066
- outline: 2px solid Highlight;
10067
- outline-offset: -2px;
10702
+ outline: var(--border-width-strong) solid Highlight;
10703
+ outline-offset: calc(-1 * var(--border-width-strong));
10068
10704
  }
10069
10705
 
10070
10706
  [data-ui="tabs"][data-variant="underline"] [data-part="trigger"][aria-selected="true"] {
@@ -10079,7 +10715,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10079
10715
 
10080
10716
  /* === recipes/tag-input.css === */
10081
10717
  /* @ui:component tag-input */
10082
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle color-ring radius-md radius-lg shadow-md space-1 space-1h space-2 space-3 text-sm z-dropdown duration-fast ease-default font-sans */
10718
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary-subtle radius-md radius-lg shadow-md space-1 space-1h space-2 space-3 text-sm z-dropdown duration-fast ease-default font-ui border-width focus-ring-color focus-ring-width */
10083
10719
 
10084
10720
  /* NOTE: the tags themselves are `data-ui="chip"` elements — their styling comes
10085
10721
  entirely from chip.css. This file styles only the field wrapper, the tag row,
@@ -10100,7 +10736,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10100
10736
  gap: var(--space-1h);
10101
10737
  width: 100%;
10102
10738
  padding: var(--space-1h) var(--space-2);
10103
- border: 1px solid var(--color-border);
10739
+ border: var(--border-width) solid var(--color-border);
10104
10740
  border-radius: var(--radius-md);
10105
10741
  background: var(--color-bg);
10106
10742
  list-style: none;
@@ -10109,8 +10745,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10109
10745
  }
10110
10746
 
10111
10747
  [data-ui="tag-input"] [data-part="taglist"]:focus-within {
10112
- border-color: var(--color-ring, oklch(0.55 0.22 264));
10113
- box-shadow: 0 0 0 2px var(--color-ring, oklch(0.55 0.22 264));
10748
+ border-color: var(--focus-ring-color);
10749
+ box-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring-color);
10114
10750
  }
10115
10751
 
10116
10752
  /* ── Text input: borderless, grows to fill the remaining row space ── */
@@ -10121,7 +10757,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10121
10757
  border: none;
10122
10758
  background: transparent;
10123
10759
  color: var(--color-fg);
10124
- font-family: var(--font-sans, system-ui, sans-serif);
10760
+ font-family: var(--font-ui);
10125
10761
  font-size: var(--text-sm);
10126
10762
  line-height: 1.5;
10127
10763
  outline: none;
@@ -10140,7 +10776,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10140
10776
  z-index: var(--z-dropdown);
10141
10777
  margin-top: var(--space-1);
10142
10778
  padding: var(--space-1);
10143
- border: 1px solid var(--color-border);
10779
+ border: var(--border-width) solid var(--color-border);
10144
10780
  border-radius: var(--radius-lg);
10145
10781
  background: var(--color-bg);
10146
10782
  box-shadow: var(--shadow-md);
@@ -10187,7 +10823,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10187
10823
 
10188
10824
  /* === recipes/toast.css === */
10189
10825
  /* @ui:component toast */
10190
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-success color-destructive color-warning shadow-lg radius-lg space-2 space-3 space-4 text-sm weight-medium z-toast duration-normal duration-slow ease-out */
10826
+ /* @ui:tokens color-bg panel-bg color-fg color-fg-muted color-border color-success color-destructive color-warning shadow-lg radius-lg space-2 space-3 space-4 text-sm weight-medium z-toast duration-normal duration-slow ease-out font-ui border-width border-width-lg focus-ring-width focus-ring-style focus-ring-color focus-ring-offset surface-backdrop */
10191
10827
 
10192
10828
  /* ── Container ── */
10193
10829
  [data-ui="toast"][data-part="container"] {
@@ -10236,8 +10872,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10236
10872
  max-width: 380px;
10237
10873
  width: max-content;
10238
10874
  padding: var(--space-3) var(--space-4);
10239
- background: var(--color-bg);
10240
- border: 1px solid var(--color-border);
10875
+ background: var(--panel-bg);
10876
+ border: var(--border-width) solid var(--color-border);
10241
10877
  border-radius: var(--radius-lg);
10242
10878
  box-shadow: var(--shadow-lg);
10243
10879
  pointer-events: auto;
@@ -10247,6 +10883,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10247
10883
  transform var(--duration-normal) var(--ease-out);
10248
10884
  }
10249
10885
 
10886
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
10887
+ [data-ui="toast"] [data-part="toast"] {
10888
+ -webkit-backdrop-filter: var(--surface-backdrop);
10889
+ backdrop-filter: var(--surface-backdrop);
10890
+ }
10891
+ }
10892
+
10250
10893
  /* ── State: Entering ── */
10251
10894
  [data-ui="toast"][data-variant="top-right"] [data-part="toast"][data-state="entering"],
10252
10895
  [data-ui="toast"][data-variant="top-left"] [data-part="toast"][data-state="entering"] {
@@ -10286,7 +10929,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10286
10929
 
10287
10930
  /* ── Tone Variants ── */
10288
10931
  [data-ui="toast"] [data-part="toast"][data-variant="success"] {
10289
- border-inline-start: 3px solid var(--color-success, oklch(0.55 0.18 145));
10932
+ border-inline-start: var(--border-width-lg) solid var(--color-success, oklch(0.55 0.18 145));
10290
10933
  }
10291
10934
 
10292
10935
  [data-ui="toast"] [data-part="toast"][data-variant="success"] [data-part="icon"] {
@@ -10294,7 +10937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10294
10937
  }
10295
10938
 
10296
10939
  [data-ui="toast"] [data-part="toast"][data-variant="error"] {
10297
- border-inline-start: 3px solid var(--color-destructive, oklch(0.55 0.22 25));
10940
+ border-inline-start: var(--border-width-lg) solid var(--color-destructive, oklch(0.55 0.22 25));
10298
10941
  }
10299
10942
 
10300
10943
  [data-ui="toast"] [data-part="toast"][data-variant="error"] [data-part="icon"] {
@@ -10302,7 +10945,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10302
10945
  }
10303
10946
 
10304
10947
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] {
10305
- border-inline-start: 3px solid var(--color-warning, oklch(0.7 0.18 85));
10948
+ border-inline-start: var(--border-width-lg) solid var(--color-warning, oklch(0.7 0.18 85));
10306
10949
  }
10307
10950
 
10308
10951
  [data-ui="toast"] [data-part="toast"][data-variant="warning"] [data-part="icon"] {
@@ -10324,7 +10967,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10324
10967
  /* ── Message ── */
10325
10968
  [data-ui="toast"] [data-part="message"] {
10326
10969
  flex: 1;
10327
- font-family: var(--font-sans, system-ui, sans-serif);
10970
+ font-family: var(--font-ui);
10328
10971
  font-size: var(--text-sm);
10329
10972
  font-weight: var(--weight-medium);
10330
10973
  color: var(--color-fg);
@@ -10335,11 +10978,11 @@ div[data-ui="separator"][data-style="thick"]::after {
10335
10978
  [data-ui="toast"] [data-part="action"] {
10336
10979
  flex-shrink: 0;
10337
10980
  padding: var(--space-1, 0.25rem) var(--space-2);
10338
- border: 1px solid var(--color-border);
10981
+ border: var(--border-width) solid var(--color-border);
10339
10982
  border-radius: var(--radius-md, 0.375rem);
10340
10983
  background: transparent;
10341
10984
  color: var(--color-fg);
10342
- font-family: var(--font-sans, system-ui, sans-serif);
10985
+ font-family: var(--font-ui);
10343
10986
  font-size: var(--text-xs, 0.75rem);
10344
10987
  font-weight: var(--weight-medium);
10345
10988
  cursor: pointer;
@@ -10352,8 +10995,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10352
10995
  }
10353
10996
 
10354
10997
  [data-ui="toast"] [data-part="action"]:focus-visible {
10355
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10356
- outline-offset: 2px;
10998
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
10999
+ outline-offset: var(--focus-ring-offset);
10357
11000
  }
10358
11001
 
10359
11002
  /* ── Close Button ── */
@@ -10379,8 +11022,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10379
11022
  }
10380
11023
 
10381
11024
  [data-ui="toast"] [data-part="close"]:focus-visible {
10382
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
10383
- outline-offset: 2px;
11025
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11026
+ outline-offset: var(--focus-ring-offset);
10384
11027
  }
10385
11028
 
10386
11029
  /* ── Motion ── */
@@ -10393,14 +11036,14 @@ div[data-ui="separator"][data-style="thick"]::after {
10393
11036
 
10394
11037
  /* === recipes/toggle-group.css === */
10395
11038
  /* @ui:component toggle-group */
10396
- /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 text-sm font-sans weight-medium duration-fast ease-default */
11039
+ /* @ui:tokens color-bg color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-subtle color-ring radius-md space-1 space-1h space-2 space-3 text-sm font-ui weight-medium duration-fast ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset disabled-opacity */
10397
11040
 
10398
11041
  /* ── Root: a segmented row of toggle buttons ── */
10399
11042
  [data-ui="toggle-group"] {
10400
11043
  display: inline-flex;
10401
11044
  gap: var(--space-1);
10402
11045
  padding: var(--space-1);
10403
- border: 1px solid var(--color-border);
11046
+ border: var(--border-width) solid var(--color-border);
10404
11047
  border-radius: var(--radius-md);
10405
11048
  background: var(--color-bg);
10406
11049
  }
@@ -10415,7 +11058,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10415
11058
  border-radius: var(--radius-md);
10416
11059
  background: transparent;
10417
11060
  color: var(--color-fg-muted);
10418
- font-family: var(--toggle-group-font, var(--font-sans));
11061
+ font-family: var(--toggle-group-font, var(--font-ui));
10419
11062
  font-size: var(--text-sm);
10420
11063
  font-weight: var(--weight-medium);
10421
11064
  line-height: 1;
@@ -10456,13 +11099,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10456
11099
 
10457
11100
  /* ── Keyboard focus ring on the item (focus lives on the hidden control) ── */
10458
11101
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:focus-visible) {
10459
- outline: 2px solid var(--color-ring);
10460
- outline-offset: 2px;
11102
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11103
+ outline-offset: var(--focus-ring-offset);
10461
11104
  }
10462
11105
 
10463
11106
  /* ── Disabled control ── */
10464
11107
  [data-ui="toggle-group"] [data-part="item"]:has([data-part="control"]:disabled) {
10465
- opacity: 0.5;
11108
+ opacity: var(--disabled-opacity);
10466
11109
  cursor: not-allowed;
10467
11110
  }
10468
11111
 
@@ -10475,7 +11118,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10475
11118
 
10476
11119
  /* === recipes/tooltip.css === */
10477
11120
  /* @ui:component tooltip */
10478
- /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default */
11121
+ /* @ui:tokens color-bg color-fg radius-md space-1h space-2 text-xs z-dropdown duration-fast ease-default font-ui surface-backdrop */
10479
11122
 
10480
11123
  /* ── Root ── */
10481
11124
  [data-ui="tooltip"] {
@@ -10496,7 +11139,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10496
11139
  color: var(--color-bg);
10497
11140
  border-radius: var(--radius-md);
10498
11141
  padding: var(--space-1h, 0.375rem) var(--space-2);
10499
- font-family: var(--font-sans, system-ui, sans-serif);
11142
+ font-family: var(--font-ui);
10500
11143
  font-size: var(--text-xs, 0.75rem);
10501
11144
  line-height: 1.4;
10502
11145
  white-space: nowrap;
@@ -10507,6 +11150,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10507
11150
  transform var(--duration-fast) var(--ease-default);
10508
11151
  }
10509
11152
 
11153
+ @supports ((-webkit-backdrop-filter: blur(1rem)) or (backdrop-filter: blur(1rem))) {
11154
+ [data-ui="tooltip"] [data-part="content"] {
11155
+ -webkit-backdrop-filter: var(--surface-backdrop);
11156
+ backdrop-filter: var(--surface-backdrop);
11157
+ }
11158
+ }
11159
+
10510
11160
  /* Default position (top) when no variant is specified */
10511
11161
  [data-ui="tooltip"]:not([data-variant]) [data-part="content"] {
10512
11162
  bottom: 100%;
@@ -10622,7 +11272,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10622
11272
 
10623
11273
  /* === recipes/tree-view.css === */
10624
11274
  /* @ui:component tree-view */
10625
- /* @ui:tokens color-bg-muted color-fg color-fg-muted color-fg-subtle color-primary color-primary-subtle color-ring space-px space-1 space-2 space-5 radius-md text-sm font-sans weight-medium duration-fast ease-default */
11275
+ /* @ui:tokens color-bg-muted color-fg color-fg-muted color-fg-subtle color-primary color-primary-subtle color-ring space-px space-1 space-2 space-5 radius-md text-sm font-ui weight-medium duration-fast ease-default focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
10626
11276
 
10627
11277
  [data-ui="tree-view"],
10628
11278
  [data-ui="tree-view"] [data-part="group"] {
@@ -10635,7 +11285,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10635
11285
  inline-size: 100%;
10636
11286
  padding: var(--space-1);
10637
11287
  color: var(--color-fg);
10638
- font-family: var(--font-sans);
11288
+ font-family: var(--font-ui);
10639
11289
  font-size: var(--text-sm);
10640
11290
  }
10641
11291
 
@@ -10663,8 +11313,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10663
11313
  }
10664
11314
 
10665
11315
  [data-ui="tree-view"] [data-part="item"]:focus-visible > [data-part="label"] {
10666
- outline: var(--space-px) solid var(--color-ring);
10667
- outline-offset: var(--space-px);
11316
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11317
+ outline-offset: var(--focus-ring-offset);
10668
11318
  }
10669
11319
 
10670
11320
  [data-ui="tree-view"] [data-part="item"][aria-selected="true"] > [data-part="label"] {
@@ -10703,7 +11353,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10703
11353
 
10704
11354
  /* === patterns/auth-form.css === */
10705
11355
  /* @ui:component auth-form */
10706
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-primary-hover color-primary-fg color-destructive color-destructive-subtle color-success color-success-subtle radius-lg radius-xl shadow-sm shadow-md space-1 space-2 space-3 space-4 space-5 space-6 space-8 font-sans text-xs text-sm text-base text-lg text-xl text-2xl weight-medium weight-semibold weight-bold leading-tight leading-normal duration-fast duration-normal ease-default */
11356
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-border-strong color-ring color-primary color-primary-hover color-primary-fg color-destructive color-destructive-subtle color-success color-success-subtle radius-lg radius-xl shadow-sm shadow-md space-1 space-2 space-3 space-4 space-5 space-6 space-8 font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading text-xs text-sm text-base text-lg text-xl text-2xl weight-medium weight-semibold weight-bold leading-tight leading-normal duration-fast duration-normal ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset link-decoration */
10707
11357
 
10708
11358
  /* ── Root Container ── */
10709
11359
  [data-ui="auth-form"] {
@@ -10711,7 +11361,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10711
11361
  align-items: center;
10712
11362
  justify-content: center;
10713
11363
  width: 100%;
10714
- font-family: var(--font-sans);
11364
+ font-family: var(--font-body);
10715
11365
  }
10716
11366
 
10717
11367
  /* Mobile-first (task 0.8-09): on a phone the card IS the page — edge to edge,
@@ -10743,9 +11393,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10743
11393
 
10744
11394
  [data-ui="auth-form"] [data-part="title"] {
10745
11395
  margin: 0;
11396
+ font-family: var(--font-heading);
10746
11397
  font-size: var(--text-xl);
10747
- font-weight: var(--weight-bold);
10748
- line-height: var(--leading-tight);
11398
+ font-weight: var(--heading-weight);
11399
+ letter-spacing: var(--heading-tracking);
11400
+ text-transform: var(--heading-transform);
11401
+ font-variant-caps: var(--heading-caps);
11402
+ line-height: var(--heading-leading);
10749
11403
  color: var(--color-fg);
10750
11404
  }
10751
11405
 
@@ -10762,7 +11416,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10762
11416
  margin: var(--space-4) var(--space-6) 0;
10763
11417
  padding: var(--space-3);
10764
11418
  background: var(--color-destructive-subtle);
10765
- border: 1px solid var(--color-destructive);
11419
+ border: var(--border-width) solid var(--color-destructive);
10766
11420
  border-radius: var(--radius-lg);
10767
11421
  color: var(--color-destructive);
10768
11422
  font-size: var(--text-sm);
@@ -10840,13 +11494,13 @@ div[data-ui="separator"][data-style="thick"]::after {
10840
11494
  }
10841
11495
 
10842
11496
  [data-ui="auth-form"] [data-part="footer"] a:hover {
10843
- text-decoration: underline;
11497
+ text-decoration-line: var(--link-decoration);
10844
11498
  color: var(--color-primary-hover);
10845
11499
  }
10846
11500
 
10847
11501
  [data-ui="auth-form"] [data-part="footer"] a:focus-visible {
10848
- outline: 2px solid var(--color-ring);
10849
- outline-offset: 2px;
11502
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
11503
+ outline-offset: var(--focus-ring-offset);
10850
11504
  border-radius: var(--radius-sm, 0.25rem);
10851
11505
  }
10852
11506
 
@@ -10974,8 +11628,8 @@ div[data-ui="separator"][data-style="thick"]::after {
10974
11628
  max-width: var(--auth-form-max-width, 400px);
10975
11629
  border-radius: var(--card-radius, var(--radius-lg));
10976
11630
  box-shadow: var(--card-shadow, var(--shadow-sm));
10977
- border-inline-start: 1px solid var(--card-border, var(--color-border));
10978
- border-inline-end: 1px solid var(--card-border, var(--color-border));
11631
+ border-inline-start: var(--border-width) solid var(--card-border, var(--color-border));
11632
+ border-inline-end: var(--border-width) solid var(--card-border, var(--color-border));
10979
11633
  }
10980
11634
  }
10981
11635
 
@@ -10990,7 +11644,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10990
11644
 
10991
11645
  /* === patterns/crud-table.css === */
10992
11646
  /* @ui:component crud-table */
10993
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg color-destructive color-destructive-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-sans text-sm text-base text-lg weight-medium weight-semibold duration-fast duration-normal ease-default */
11647
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg color-destructive color-destructive-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-body text-sm text-base text-lg weight-medium weight-semibold duration-fast duration-normal ease-default border-width */
10994
11648
 
10995
11649
  /* ── Root ── */
10996
11650
  [data-ui="crud-table"] {
@@ -10998,7 +11652,7 @@ div[data-ui="separator"][data-style="thick"]::after {
10998
11652
  flex-direction: column;
10999
11653
  gap: var(--space-4);
11000
11654
  width: 100%;
11001
- font-family: var(--font-sans, system-ui, sans-serif);
11655
+ font-family: var(--font-body);
11002
11656
  }
11003
11657
 
11004
11658
  /* ── Toolbar ── */
@@ -11056,7 +11710,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11056
11710
  gap: var(--space-3);
11057
11711
  padding: var(--space-3) var(--space-4);
11058
11712
  background: var(--color-bg-subtle);
11059
- border: 1px solid var(--color-border);
11713
+ border: var(--border-width) solid var(--color-border);
11060
11714
  border-radius: var(--radius-md);
11061
11715
  }
11062
11716
 
@@ -11071,7 +11725,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11071
11725
  [data-ui="crud-table"] [data-part="table-wrapper"] {
11072
11726
  width: 100%;
11073
11727
  overflow-x: auto;
11074
- border: 1px solid var(--color-border);
11728
+ border: var(--border-width) solid var(--color-border);
11075
11729
  border-radius: var(--radius-lg);
11076
11730
  background: var(--color-bg);
11077
11731
  }
@@ -11101,7 +11755,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11101
11755
  padding: var(--space-8) var(--space-4);
11102
11756
  text-align: center;
11103
11757
  min-height: 240px;
11104
- border: 1px dashed var(--color-border);
11758
+ border: var(--border-width) dashed var(--color-border);
11105
11759
  border-radius: var(--radius-lg);
11106
11760
  background: var(--color-bg);
11107
11761
  }
@@ -11214,7 +11868,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11214
11868
 
11215
11869
  /* === patterns/dashboard-shell.css === */
11216
11870
  /* @ui:component dashboard-shell */
11217
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-primary-fg space-2 space-3 space-4 space-5 space-6 space-8 space-12 space-16 radius-md radius-lg shadow-sm shadow-md font-sans text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-normal duration-slow ease-default ease-out z-sticky */
11871
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-border-strong color-primary color-primary-subtle color-primary-fg space-2 space-3 space-4 space-5 space-6 space-8 space-12 space-16 radius-md radius-lg shadow-sm shadow-md font-body font-ui text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-normal duration-slow ease-default ease-out z-sticky border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
11218
11872
 
11219
11873
  /* ── Shell Grid Layout ──
11220
11874
  Mobile-first (task 0.8-09): the base is the PHONE shell — one column, header
@@ -11239,7 +11893,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11239
11893
  "footer";
11240
11894
  min-height: 100vh;
11241
11895
  background: var(--color-bg);
11242
- font-family: var(--font-sans);
11896
+ font-family: var(--font-body);
11243
11897
  color: var(--color-fg);
11244
11898
  }
11245
11899
 
@@ -11263,7 +11917,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11263
11917
  gap: var(--space-2);
11264
11918
  padding: var(--space-4);
11265
11919
  background: var(--color-bg-subtle);
11266
- border-inline-end: 1px solid var(--color-border);
11920
+ border-inline-end: var(--border-width) solid var(--color-border);
11267
11921
  overflow-y: auto;
11268
11922
  position: fixed;
11269
11923
  top: 0;
@@ -11283,7 +11937,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11283
11937
 
11284
11938
  [data-ui="dashboard-shell"][data-variant="right"] > [data-part="sidebar"] {
11285
11939
  border-inline-end: none;
11286
- border-inline-start: 1px solid var(--color-border);
11940
+ border-inline-start: var(--border-width) solid var(--color-border);
11287
11941
  inset-inline-start: auto;
11288
11942
  inset-inline-end: 0;
11289
11943
  transform: translateX(100%);
@@ -11358,7 +12012,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11358
12012
  gap: var(--space-3);
11359
12013
  padding: var(--space-2) var(--space-3);
11360
12014
  border-radius: var(--radius-md);
11361
- font-family: var(--font-sans);
12015
+ font-family: var(--font-ui);
11362
12016
  font-size: var(--text-sm);
11363
12017
  font-weight: var(--weight-medium);
11364
12018
  line-height: var(--leading-normal);
@@ -11377,8 +12031,8 @@ div[data-ui="separator"][data-style="thick"]::after {
11377
12031
  }
11378
12032
 
11379
12033
  [data-ui="dashboard-shell"] > [data-part="sidebar"] [data-part="nav-item"]:focus-visible {
11380
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
11381
- outline-offset: -2px;
12034
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
12035
+ outline-offset: calc(-1 * var(--focus-ring-offset));
11382
12036
  }
11383
12037
 
11384
12038
  /* ── Nav Item Active ── */
@@ -11425,7 +12079,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11425
12079
  gap: var(--space-2);
11426
12080
  padding: 0 var(--space-3);
11427
12081
  background: var(--color-bg);
11428
- border-bottom: 1px solid var(--color-border);
12082
+ border-bottom: var(--border-width) solid var(--color-border);
11429
12083
  position: sticky;
11430
12084
  top: 0;
11431
12085
  z-index: var(--z-sticky);
@@ -11506,7 +12160,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11506
12160
  align-items: center;
11507
12161
  gap: var(--space-3);
11508
12162
  padding: var(--space-4) var(--space-6);
11509
- border-top: 1px solid var(--color-border);
12163
+ border-top: var(--border-width) solid var(--color-border);
11510
12164
  font-size: var(--text-xs);
11511
12165
  color: var(--color-fg-muted);
11512
12166
  }
@@ -11589,7 +12243,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11589
12243
 
11590
12244
  /* === patterns/document.css === */
11591
12245
  /* @ui:component document */
11592
- /* @ui:tokens doc-max-width doc-font doc-font-size doc-line-height doc-heading-font doc-heading-weight doc-heading-size doc-subheading-size doc-legal-size doc-legal-color doc-section-gap doc-component-gap doc-running-header-height doc-running-footer-height doc-running-gap doc-bg doc-fg doc-print-border-color doc-table-header-bg doc-table-header-fg doc-table-header-weight doc-table-border doc-table-cell-pad-y doc-table-cell-pad-x doc-table-font-size doc-table-num-font doc-table-footer-bg doc-table-footer-weight doc-table-stripe-bg page-format page-orientation page-margin page-margin-top page-margin-bottom page-margin-left page-margin-right color-bg color-fg color-fg-muted color-border space-4 space-6 space-8 space-12 shadow-lg radius-md font-serif z-raised */
12246
+ /* @ui:tokens doc-max-width doc-font doc-font-size doc-line-height doc-heading-font doc-heading-weight doc-heading-size doc-subheading-size doc-legal-size doc-legal-color doc-section-gap doc-component-gap doc-running-header-height doc-running-footer-height doc-running-gap doc-bg doc-fg doc-print-border-color doc-table-header-bg doc-table-header-fg doc-table-header-weight doc-table-border doc-table-cell-pad-y doc-table-cell-pad-x doc-table-font-size doc-table-num-font doc-table-footer-bg doc-table-footer-weight doc-table-stripe-bg page-format page-orientation page-margin page-margin-top page-margin-bottom page-margin-left page-margin-right color-bg color-fg color-fg-muted color-border space-4 space-6 space-8 space-12 shadow-lg radius-md font-body weight-bold z-raised border-width texture-page */
11593
12247
 
11594
12248
  /* ── Page Rules ── */
11595
12249
  @page {
@@ -11629,14 +12283,17 @@ div[data-ui="separator"][data-style="thick"]::after {
11629
12283
  max-width: var(--doc-max-width);
11630
12284
  margin: var(--space-4) auto;
11631
12285
  padding: var(--space-6) var(--space-4);
11632
- background: var(--color-bg, #fff);
12286
+ background-color: var(--color-bg, #fff);
12287
+ background-image: var(--texture-page);
11633
12288
  color: var(--color-fg);
11634
- font-family: var(--doc-font, var(--font-sans, system-ui, sans-serif));
12289
+ font-family: var(--doc-font, var(--font-body));
11635
12290
  font-size: var(--doc-font-size);
11636
12291
  line-height: var(--doc-line-height);
11637
- box-shadow: var(--shadow-lg,
11638
- 0 10px 15px -3px rgba(0, 0, 0, 0.1),
11639
- 0 4px 6px -4px rgba(0, 0, 0, 0.1));
12292
+ /* The fallback here used to spell out two rgba() layers, which is a shadow
12293
+ colour no theme could reach. --shadow-lg is always defined by the token
12294
+ layer, and it now carries --shadow-color, so the fallback is gone rather
12295
+ than re-tokenised. */
12296
+ box-shadow: var(--shadow-lg);
11640
12297
  border-radius: 0;
11641
12298
  position: relative;
11642
12299
  }
@@ -11652,7 +12309,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11652
12309
  [data-ui="document"] > [data-part="header"] {
11653
12310
  margin-block-end: var(--doc-section-gap);
11654
12311
  padding-block-end: var(--doc-component-gap);
11655
- border-block-end: 1px solid var(--color-border);
12312
+ border-block-end: var(--border-width) solid var(--color-border);
11656
12313
  }
11657
12314
 
11658
12315
  /* ── Body ── */
@@ -11662,13 +12319,25 @@ div[data-ui="separator"][data-style="thick"]::after {
11662
12319
  gap: var(--doc-section-gap);
11663
12320
  }
11664
12321
 
12322
+ /* ── Headings ──
12323
+ The document's own heading face and weight (1.1A-21): a print theme sets
12324
+ --doc-heading-font / --doc-heading-weight to give its titles a voice apart
12325
+ from the body copy (document-serif's Times titles over Georgia text). Both
12326
+ default to the page's heading role in tokens/document.css, and each falls
12327
+ back to what a heading rendered before the tokens had a reader. A heading
12328
+ that carries its own data-weight keeps it — that is the author asking. */
12329
+ [data-ui="document"] :is(h1, h2, h3, h4, h5, h6) {
12330
+ font-family: var(--doc-heading-font, var(--font-body));
12331
+ font-weight: var(--doc-heading-weight, var(--weight-bold));
12332
+ }
12333
+
11665
12334
  /* ── Running footer ──
11666
12335
  footer remains a non-breaking selector alias for pre-1.1.0 documents. */
11667
12336
  [data-ui="document"] > [data-part="doc-footer"],
11668
12337
  [data-ui="document"] > [data-part="footer"] {
11669
12338
  margin-block-start: var(--doc-section-gap);
11670
12339
  padding-block-start: var(--doc-component-gap);
11671
- border-block-start: 1px solid var(--color-border);
12340
+ border-block-start: var(--border-width) solid var(--color-border);
11672
12341
  font-size: var(--doc-legal-size);
11673
12342
  color: var(--doc-legal-color);
11674
12343
  }
@@ -11706,7 +12375,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11706
12375
 
11707
12376
  /* ── Variant: Report ── */
11708
12377
  [data-ui="document"][data-variant="report"] {
11709
- font-family: var(--font-serif, Georgia, "Times New Roman", serif);
12378
+ /* A report is serif-set by definition. It re-points the document's own font
12379
+ ROLE rather than its `font-family`, so every doc primitive nested inside it
12380
+ (key-value, callout, signature — all of which read --doc-font) follows the
12381
+ report into serif instead of staying sans inside a serif page. `report` is
12382
+ the author asking for serif; a theme that wants its own document face
12383
+ declares --doc-font at :root, which this variant deliberately outranks. */
12384
+ --doc-font: Georgia, 'Times New Roman', serif;
11710
12385
  line-height: 1.6;
11711
12386
  }
11712
12387
 
@@ -11801,7 +12476,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11801
12476
  z-index: var(--z-raised);
11802
12477
  margin-block-end: 0;
11803
12478
  padding-block-end: var(--doc-running-gap);
11804
- border-block-end: 1px solid var(--doc-print-border-color);
12479
+ border-block-end: var(--border-width) solid var(--doc-print-border-color);
11805
12480
  background: var(--doc-bg);
11806
12481
  transform: translateZ(0);
11807
12482
  }
@@ -11817,7 +12492,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11817
12492
  z-index: var(--z-raised);
11818
12493
  margin-block-start: 0;
11819
12494
  padding-block-start: var(--doc-running-gap);
11820
- border-block-start: 1px solid var(--doc-print-border-color);
12495
+ border-block-start: var(--border-width) solid var(--doc-print-border-color);
11821
12496
  background: var(--doc-bg);
11822
12497
  transform: translateZ(0);
11823
12498
  }
@@ -11846,7 +12521,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11846
12521
 
11847
12522
  /* === patterns/empty-state.css === */
11848
12523
  /* @ui:component empty-state */
11849
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary radius-lg shadow-sm space-2 space-3 space-4 space-6 space-8 space-10 font-sans text-sm text-base text-lg text-xl text-2xl weight-semibold leading-tight leading-normal duration-normal ease-default */
12524
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary radius-lg shadow-sm space-2 space-3 space-4 space-6 space-8 space-10 font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-xl text-2xl weight-semibold leading-tight leading-normal duration-normal ease-default */
11850
12525
 
11851
12526
  /* ── Root ── */
11852
12527
  [data-ui="empty-state"] {
@@ -11857,7 +12532,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11857
12532
  text-align: center;
11858
12533
  padding: var(--space-8) var(--space-6);
11859
12534
  gap: var(--space-3);
11860
- font-family: var(--font-sans, system-ui, sans-serif);
12535
+ font-family: var(--font-body);
11861
12536
  }
11862
12537
 
11863
12538
  /* ── Icon ── */
@@ -11880,10 +12555,13 @@ div[data-ui="separator"][data-style="thick"]::after {
11880
12555
 
11881
12556
  /* ── Title ── */
11882
12557
  [data-ui="empty-state"] [data-part="title"] {
11883
- font-family: var(--font-sans, system-ui, sans-serif);
12558
+ font-family: var(--font-heading);
11884
12559
  font-size: var(--text-lg);
11885
12560
  font-weight: var(--weight-semibold);
11886
- line-height: var(--leading-tight);
12561
+ letter-spacing: var(--heading-tracking);
12562
+ text-transform: var(--heading-transform);
12563
+ font-variant-caps: var(--heading-caps);
12564
+ line-height: var(--heading-leading);
11887
12565
  color: var(--color-fg);
11888
12566
  margin: 0;
11889
12567
  }
@@ -11981,7 +12659,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11981
12659
 
11982
12660
  /* === patterns/feature-grid.css === */
11983
12661
  /* @ui:component feature-grid */
11984
- /* @ui:tokens color-bg color-fg color-fg-muted color-primary color-primary-subtle space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-base text-lg text-xl text-3xl font-sans weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-md radius-lg */
12662
+ /* @ui:tokens color-bg color-fg color-fg-muted color-primary color-primary-subtle space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-base text-lg text-xl text-3xl font-body weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-md radius-lg */
11985
12663
 
11986
12664
  /* ── Root ──
11987
12665
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -11991,7 +12669,7 @@ div[data-ui="separator"][data-style="thick"]::after {
11991
12669
  gap: var(--space-4);
11992
12670
  padding-block: var(--space-12);
11993
12671
  padding-inline: var(--space-4);
11994
- font-family: var(--font-sans, system-ui, sans-serif);
12672
+ font-family: var(--font-body);
11995
12673
  color: var(--color-fg);
11996
12674
  background: var(--color-bg);
11997
12675
  }
@@ -12133,7 +12811,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12133
12811
  max-inline-size: var(--measure-narrow);
12134
12812
  margin-inline: auto;
12135
12813
  padding-block: var(--space-8);
12136
- font-family: var(--font-sans);
12814
+ font-family: var(--font-body);
12137
12815
  }
12138
12816
 
12139
12817
  :where(form[l-data]:not([data-ui]) > h1) {
@@ -12153,7 +12831,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12153
12831
 
12154
12832
  /* === patterns/hero.css === */
12155
12833
  /* @ui:component hero */
12156
- /* @ui:tokens color-bg color-fg color-fg-muted space-3 space-4 space-6 space-8 space-12 space-16 space-20 text-sm text-base text-lg text-xl text-3xl text-4xl font-sans weight-bold weight-normal leading-tight leading-relaxed radius-lg */
12834
+ /* @ui:tokens color-bg color-fg color-fg-muted space-3 space-4 space-6 space-8 space-12 space-16 space-20 text-sm text-base text-lg text-xl text-3xl text-4xl font-heading font-body heading-weight heading-tracking heading-transform heading-caps heading-leading weight-bold weight-normal leading-tight leading-relaxed radius-lg texture-surface */
12157
12835
 
12158
12836
  /* ── Root ──
12159
12837
  A one-column grid by default; the layout variants only change how that grid
@@ -12167,9 +12845,10 @@ div[data-ui="separator"][data-style="thick"]::after {
12167
12845
  gap: var(--space-4);
12168
12846
  padding-block: var(--space-12);
12169
12847
  padding-inline: var(--space-4);
12170
- font-family: var(--font-sans, system-ui, sans-serif);
12848
+ font-family: var(--font-body);
12171
12849
  color: var(--color-fg);
12172
- background: var(--color-bg);
12850
+ background-color: var(--color-bg);
12851
+ background-image: var(--texture-surface);
12173
12852
  }
12174
12853
 
12175
12854
  /* ── Eyebrow ── */
@@ -12181,9 +12860,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12181
12860
  /* ── Headline ── */
12182
12861
  [data-ui="hero"] [data-part="headline"] {
12183
12862
  margin: 0;
12863
+ font-family: var(--font-heading);
12184
12864
  font-size: var(--text-3xl);
12185
- font-weight: var(--weight-bold);
12186
- line-height: var(--leading-tight);
12865
+ font-weight: var(--heading-weight);
12866
+ letter-spacing: var(--heading-tracking);
12867
+ text-transform: var(--heading-transform);
12868
+ font-variant-caps: var(--heading-caps);
12869
+ line-height: var(--heading-leading);
12187
12870
  color: var(--color-fg);
12188
12871
  text-wrap: balance;
12189
12872
  }
@@ -12302,7 +12985,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12302
12985
 
12303
12986
  /* === patterns/inbox.css === */
12304
12987
  /* @ui:component inbox */
12305
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-destructive color-primary color-primary-subtle color-ring space-1 space-2 space-3 space-4 space-6 space-px font-sans text-xs text-sm text-base text-xl weight-medium weight-semibold leading-tight leading-normal leading-relaxed radius-md radius-lg */
12988
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-destructive color-primary color-primary-subtle color-ring space-1 space-2 space-3 space-4 space-6 space-px font-body text-xs text-sm text-base text-xl weight-medium weight-semibold leading-tight leading-normal leading-relaxed radius-md radius-lg focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
12306
12989
 
12307
12990
  /* ── Root ──
12308
12991
  ONE pane, because that is what a phone has room for. Each pane's `data-state`
@@ -12322,7 +13005,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12322
13005
  overflow: hidden;
12323
13006
  border: var(--space-px, 1px) solid var(--color-border);
12324
13007
  border-radius: var(--radius-lg);
12325
- font-family: var(--font-sans, system-ui, sans-serif);
13008
+ font-family: var(--font-body);
12326
13009
  color: var(--color-fg);
12327
13010
  background: var(--color-bg);
12328
13011
  }
@@ -12414,8 +13097,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12414
13097
  }
12415
13098
 
12416
13099
  [data-ui="inbox"] [data-part="item"]:focus-visible {
12417
- outline: 2px solid var(--color-ring);
12418
- outline-offset: 2px;
13100
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13101
+ outline-offset: var(--focus-ring-offset);
12419
13102
  }
12420
13103
 
12421
13104
  [data-ui="inbox"] [data-part="item"][data-state="selected"] {
@@ -12574,7 +13257,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12574
13257
 
12575
13258
  /* === patterns/pricing.css === */
12576
13259
  /* @ui:component pricing */
12577
- /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-sm text-base text-lg text-3xl font-sans weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-lg shadow-md */
13260
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border color-primary color-primary-subtle color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-16 text-sm text-base text-lg text-3xl font-heading font-body heading-tracking heading-transform heading-caps heading-leading weight-semibold weight-bold leading-tight leading-normal leading-relaxed radius-lg shadow-md border-width-strong */
12578
13261
 
12579
13262
  /* ── Root ──
12580
13263
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -12584,7 +13267,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12584
13267
  gap: var(--space-4);
12585
13268
  padding-block: var(--space-12);
12586
13269
  padding-inline: var(--space-4);
12587
- font-family: var(--font-sans, system-ui, sans-serif);
13270
+ font-family: var(--font-body);
12588
13271
  color: var(--color-fg);
12589
13272
  background: var(--color-bg);
12590
13273
  }
@@ -12634,9 +13317,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12634
13317
 
12635
13318
  [data-ui="pricing"] [data-part="tier"] [data-part="title"] {
12636
13319
  margin: 0;
13320
+ font-family: var(--font-heading);
12637
13321
  font-size: var(--text-lg);
12638
13322
  font-weight: var(--weight-semibold);
12639
- line-height: var(--leading-tight);
13323
+ letter-spacing: var(--heading-tracking);
13324
+ text-transform: var(--heading-transform);
13325
+ font-variant-caps: var(--heading-caps);
13326
+ line-height: var(--heading-leading);
12640
13327
  }
12641
13328
 
12642
13329
  [data-ui="pricing"] [data-part="tier"] [data-part="header"] [data-part="description"] {
@@ -12697,7 +13384,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12697
13384
  [data-ui="pricing"] [data-part="tier"][data-state="featured"] {
12698
13385
  border-color: var(--color-primary);
12699
13386
  box-shadow: var(--shadow-md);
12700
- outline: var(--space-px, 1px) solid var(--color-primary);
13387
+ outline: var(--border-width-strong) solid var(--color-primary);
12701
13388
  }
12702
13389
 
12703
13390
  /* ── Footnote ── */
@@ -12742,14 +13429,14 @@ div[data-ui="separator"][data-style="thick"]::after {
12742
13429
 
12743
13430
  /* === patterns/search-results.css === */
12744
13431
  /* @ui:component search-results */
12745
- /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-sans text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default */
13432
+ /* @ui:tokens color-bg color-bg-subtle color-bg-muted color-fg color-fg-muted color-border color-primary color-primary-fg radius-md radius-lg shadow-sm space-1 space-2 space-3 space-4 space-6 space-8 font-body text-xs text-sm text-base text-lg weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default border-width focus-ring-width focus-ring-style focus-ring-color focus-ring-offset */
12746
13433
 
12747
13434
  /* ── Root ── */
12748
13435
  [data-ui="search-results"] {
12749
13436
  display: flex;
12750
13437
  flex-direction: column;
12751
13438
  gap: var(--space-4);
12752
- font-family: var(--font-sans, system-ui, sans-serif);
13439
+ font-family: var(--font-body);
12753
13440
  }
12754
13441
 
12755
13442
  /* ── Search Input ── */
@@ -12777,7 +13464,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12777
13464
  justify-content: space-between;
12778
13465
  gap: var(--space-4);
12779
13466
  padding-bottom: var(--space-2);
12780
- border-bottom: 1px solid var(--color-border);
13467
+ border-bottom: var(--border-width) solid var(--color-border);
12781
13468
  }
12782
13469
 
12783
13470
  [data-ui="search-results"] [data-part="results-count"] {
@@ -12812,7 +13499,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12812
13499
  flex-direction: column;
12813
13500
  gap: var(--space-2);
12814
13501
  padding: var(--space-4);
12815
- border: 1px solid var(--color-border);
13502
+ border: var(--border-width) solid var(--color-border);
12816
13503
  border-radius: var(--radius-md);
12817
13504
  background: var(--color-bg);
12818
13505
  transition: background var(--duration-fast) var(--ease-default),
@@ -12871,7 +13558,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12871
13558
  display: flex;
12872
13559
  justify-content: center;
12873
13560
  padding-top: var(--space-4);
12874
- border-top: 1px solid var(--color-border);
13561
+ border-top: var(--border-width) solid var(--color-border);
12875
13562
  }
12876
13563
 
12877
13564
  /* ── Loading ── */
@@ -12911,7 +13598,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12911
13598
 
12912
13599
  /* ── Error State ── */
12913
13600
  [data-ui="search-results"][data-state="error"] [data-part="results-list"] {
12914
- border: 1px solid var(--color-border);
13601
+ border: var(--border-width) solid var(--color-border);
12915
13602
  border-radius: var(--radius-md);
12916
13603
  padding: var(--space-6);
12917
13604
  text-align: center;
@@ -12920,8 +13607,8 @@ div[data-ui="separator"][data-style="thick"]::after {
12920
13607
 
12921
13608
  /* ── Focus management ── */
12922
13609
  [data-ui="search-results"] [data-part="result-item"]:focus-visible {
12923
- outline: 2px solid var(--color-ring, oklch(0.55 0.22 264));
12924
- outline-offset: 2px;
13610
+ outline: var(--focus-ring-width) var(--focus-ring-style) var(--focus-ring-color);
13611
+ outline-offset: var(--focus-ring-offset);
12925
13612
  }
12926
13613
 
12927
13614
  /* ── Motion ── */
@@ -12937,7 +13624,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12937
13624
 
12938
13625
  /* === patterns/settings-page.css === */
12939
13626
  /* @ui:component settings-page */
12940
- /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-48 radius-md radius-lg shadow-sm shadow-md font-sans text-sm text-base text-lg text-xl weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default z-sticky */
13627
+ /* @ui:tokens color-bg color-bg-subtle color-fg color-fg-muted color-border color-primary color-primary-fg space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 space-48 radius-md radius-lg shadow-sm shadow-md font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-xl weight-medium weight-semibold leading-tight leading-normal duration-fast duration-normal ease-default z-sticky border-width border-width-strong */
12941
13628
 
12942
13629
  /* ── Root ── */
12943
13630
  [data-ui="settings-page"] {
@@ -12947,7 +13634,7 @@ div[data-ui="separator"][data-style="thick"]::after {
12947
13634
  width: 100%;
12948
13635
  max-width: 768px;
12949
13636
  margin-inline: auto;
12950
- font-family: var(--font-sans, system-ui, sans-serif);
13637
+ font-family: var(--font-body);
12951
13638
  color: var(--color-fg);
12952
13639
  }
12953
13640
 
@@ -12961,9 +13648,13 @@ div[data-ui="separator"][data-style="thick"]::after {
12961
13648
  /* ── Title ── */
12962
13649
  [data-ui="settings-page"] [data-part="title"] {
12963
13650
  margin: 0;
13651
+ font-family: var(--font-heading);
12964
13652
  font-size: var(--text-xl, 1.25rem);
12965
13653
  font-weight: var(--weight-semibold, 600);
12966
- line-height: var(--leading-tight);
13654
+ letter-spacing: var(--heading-tracking);
13655
+ text-transform: var(--heading-transform);
13656
+ font-variant-caps: var(--heading-caps);
13657
+ line-height: var(--heading-leading);
12967
13658
  color: var(--color-fg);
12968
13659
  }
12969
13660
 
@@ -13027,7 +13718,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13027
13718
  gap: var(--space-3, 0.75rem);
13028
13719
  padding: var(--space-4);
13029
13720
  background: var(--color-bg);
13030
- border-top: 1px solid var(--color-border);
13721
+ border-top: var(--border-width) solid var(--color-border);
13031
13722
  border-radius: var(--radius-lg);
13032
13723
  box-shadow: var(--shadow-md);
13033
13724
  position: sticky;
@@ -13091,7 +13782,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13091
13782
  flex-direction: row;
13092
13783
  flex-wrap: wrap;
13093
13784
  border-inline-end: none;
13094
- border-bottom: 1px solid var(--color-border);
13785
+ border-bottom: var(--border-width) solid var(--color-border);
13095
13786
  padding-inline-end: 0;
13096
13787
  position: static;
13097
13788
  }
@@ -13110,7 +13801,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13110
13801
  [data-ui="settings-page"][data-variant="horizontal"] [data-ui="tabs"] [data-part="list"] {
13111
13802
  flex-direction: column;
13112
13803
  border-bottom: none;
13113
- border-inline-end: 1px solid var(--color-border);
13804
+ border-inline-end: var(--border-width) solid var(--color-border);
13114
13805
  padding-inline-end: var(--space-4);
13115
13806
  position: sticky;
13116
13807
  top: var(--space-4);
@@ -13128,7 +13819,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13128
13819
  justify-content: flex-start;
13129
13820
  text-align: start;
13130
13821
  border-bottom: none;
13131
- border-inline-start: 2px solid transparent;
13822
+ border-inline-start: var(--border-width-strong) solid transparent;
13132
13823
  margin-bottom: 0;
13133
13824
  margin-inline-end: -1px;
13134
13825
  padding: var(--space-2) var(--space-3);
@@ -13162,7 +13853,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13162
13853
 
13163
13854
  /* === patterns/site-footer.css === */
13164
13855
  /* @ui:component site-footer */
13165
- /* @ui:tokens color-bg-subtle color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 text-sm text-base text-lg font-sans weight-semibold weight-bold leading-normal */
13856
+ /* @ui:tokens color-bg-subtle color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-10 space-12 text-sm text-base text-lg font-body weight-semibold weight-bold leading-normal border-width */
13166
13857
 
13167
13858
  /* ── Root ──
13168
13859
  Mobile-first (task 0.8-09): everything outside the two `@media` blocks at the
@@ -13172,11 +13863,11 @@ div[data-ui="separator"][data-style="thick"]::after {
13172
13863
  gap: var(--space-8);
13173
13864
  padding-block: var(--space-10);
13174
13865
  padding-inline: var(--space-4);
13175
- font-family: var(--font-sans, system-ui, sans-serif);
13866
+ font-family: var(--font-body);
13176
13867
  font-size: var(--text-sm);
13177
13868
  color: var(--color-fg-muted);
13178
13869
  background: var(--color-bg-subtle);
13179
- border-block-start: 1px solid var(--color-border);
13870
+ border-block-start: var(--border-width) solid var(--color-border);
13180
13871
  }
13181
13872
 
13182
13873
  /* ── Brand ── */
@@ -13308,7 +13999,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13308
13999
 
13309
14000
  /* === patterns/stats-dashboard.css === */
13310
14001
  /* @ui:component stats-dashboard */
13311
- /* @ui:tokens color-bg color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-12 space-px font-sans text-sm text-base text-lg text-3xl weight-semibold weight-bold leading-tight leading-normal leading-relaxed */
14002
+ /* @ui:tokens color-bg color-fg color-fg-muted color-border space-1 space-2 space-3 space-4 space-6 space-8 space-12 space-px font-heading font-body heading-tracking heading-transform heading-caps heading-leading text-sm text-base text-lg text-3xl weight-semibold weight-bold leading-tight leading-normal leading-relaxed */
13312
14003
 
13313
14004
  /* ── Root ──
13314
14005
  A reporting page: title block, KPI row, then the panel region. The KPI row
@@ -13321,7 +14012,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13321
14012
  gap: var(--space-3);
13322
14013
  padding-block: var(--space-8);
13323
14014
  padding-inline: var(--space-4);
13324
- font-family: var(--font-sans, system-ui, sans-serif);
14015
+ font-family: var(--font-body);
13325
14016
  color: var(--color-fg);
13326
14017
  background: var(--color-bg);
13327
14018
  }
@@ -13395,9 +14086,13 @@ div[data-ui="separator"][data-style="thick"]::after {
13395
14086
 
13396
14087
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="title"] {
13397
14088
  margin: 0;
14089
+ font-family: var(--font-heading);
13398
14090
  font-size: var(--text-lg);
13399
14091
  font-weight: var(--weight-semibold);
13400
- line-height: var(--leading-tight);
14092
+ letter-spacing: var(--heading-tracking);
14093
+ text-transform: var(--heading-transform);
14094
+ font-variant-caps: var(--heading-caps);
14095
+ line-height: var(--heading-leading);
13401
14096
  }
13402
14097
 
13403
14098
  [data-ui="stats-dashboard"] [data-part="report"] [data-part="header"] [data-part="description"] {
@@ -13488,7 +14183,7 @@ div[data-ui="separator"][data-style="thick"]::after {
13488
14183
  gap: var(--space-6);
13489
14184
  max-inline-size: var(--measure-narrow);
13490
14185
  margin-inline: auto;
13491
- font-family: var(--font-sans);
14186
+ font-family: var(--font-body);
13492
14187
  }
13493
14188
 
13494
14189
  [data-ui="wizard"] [data-part="heading"] {