@mkbabb/glass-ui 3.0.0 → 3.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 (184) hide show
  1. package/dist/{CardFooter-Yi0xtLLd.js → CardFooter-CSGcJkqa.js} +1 -1
  2. package/dist/{CommandShortcut-BNDzfFnB.js → CommandShortcut-DWT19a2Y.js} +3 -3
  3. package/dist/{ContextMenuSubContent-DLEyeqbh.js → ContextMenuSubContent-gAFxJ-qi.js} +4 -4
  4. package/dist/{DataTable-Ce00dbHD.js → DataTable-R8-Zidms.js} +3 -3
  5. package/dist/{DialogContent-DSo7PKlU.js → DialogContent-2fALDSvc.js} +3 -3
  6. package/dist/{DialogFooter-D5KY6sCX.js → DialogFooter-ClrNEOVU.js} +2 -2
  7. package/dist/{DiscoGlyph-wRA02zAJ.js → DiscoGlyph-C3JfMnRV.js} +1 -1
  8. package/dist/{GlyphFace-BnPMUZ16.js → GlyphFace-BRS8vUb7.js} +1 -1
  9. package/dist/HoverPopover-CWFCfLx3.js +96 -0
  10. package/dist/{IconTooltip-GIeWdo64.js → IconTooltip-BkaA7tZ2.js} +1 -1
  11. package/dist/{Input-CBvqW8kZ.js → Input-DDpFn568.js} +3 -5
  12. package/dist/Label-DJty89bp.js +36 -0
  13. package/dist/{MetricBadge-DRBB18Xq.js → MetricBadge-DmAihkXd.js} +1 -1
  14. package/dist/{Notification-D97JO0fK.js → Notification-OqIpADml.js} +3 -3
  15. package/dist/NumberFieldContent-DTH9gb_N.js +141 -0
  16. package/dist/{PopoverContent-BCH4eYs8.js → PopoverContent-EiklFrna.js} +1 -1
  17. package/dist/{Progress-CCH-2UBR.js → Progress-FApA9fm_.js} +1 -1
  18. package/dist/{ScrollingText-7P8skg5W.js → ScrollingText-BFd0i2zJ.js} +2 -2
  19. package/dist/{SelectScrollDownButton-BwTexKeY.js → SelectScrollDownButton-Dth8-wXQ.js} +4 -4
  20. package/dist/{Toaster-CY8gJu9E.js → Toaster-Bjlunvq4.js} +1 -1
  21. package/dist/UnderlineTabs-DAWMLmJG.js +37 -0
  22. package/dist/animated-digit.js +2 -2
  23. package/dist/api/index.d.ts +2 -0
  24. package/dist/api.js +1 -1
  25. package/dist/aurora.js +3 -3
  26. package/dist/badge.js +1 -1
  27. package/dist/{button-BlOW34DT.js → button-C0aHmBbt.js} +2 -0
  28. package/dist/button.js +1 -1
  29. package/dist/card.js +1 -1
  30. package/dist/carousel.js +5 -5
  31. package/dist/{check-Nuw7H9Yh.js → check-dwgetki8.js} +1 -1
  32. package/dist/{chevron-down-Du2b9vY_.js → chevron-down-DILQA1t6.js} +1 -1
  33. package/dist/{chevron-right-CtDxpE3w.js → chevron-right-fS7fal2t.js} +1 -1
  34. package/dist/{chevron-up-CenYokvI.js → chevron-up-BtYjYQOS.js} +1 -1
  35. package/dist/collapsible.js +1 -1
  36. package/dist/command.js +1 -1
  37. package/dist/components/custom/dialog-native/GlassDialogNative.vue.d.ts +57 -0
  38. package/dist/components/custom/dialog-native/index.d.ts +1 -0
  39. package/dist/components/custom/dock/composables/useLayerTransition.d.ts +20 -10
  40. package/dist/components/custom/hover-popover/HoverPopover.vue.d.ts +26 -4
  41. package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +16 -2
  42. package/dist/components/custom/labeled-field/LabeledInput.vue.d.ts +17 -1
  43. package/dist/components/custom/labeled-field/LabeledSelect.vue.d.ts +2 -0
  44. package/dist/components/custom/labeled-field/LabeledSlider.vue.d.ts +2 -0
  45. package/dist/components/custom/labeled-field/LabeledSwitch.vue.d.ts +2 -0
  46. package/dist/components/ui/input/Input.vue.d.ts +10 -7
  47. package/dist/components/ui/label/Label.vue.d.ts +8 -0
  48. package/dist/components/ui/textarea/Textarea.vue.d.ts +45 -8
  49. package/dist/composables/dom/index.d.ts +1 -0
  50. package/dist/composables/dom/useUserInvalidAria.d.ts +32 -0
  51. package/dist/composables/motion/core/index.d.ts +2 -0
  52. package/dist/composables/motion/supportsCssTimeline.d.ts +8 -0
  53. package/dist/composables/motion/useRAFLoop.d.ts +7 -0
  54. package/dist/composables/motion/useScrollProgress.d.ts +6 -2
  55. package/dist/composables/motion/useStaggerReveal.d.ts +6 -0
  56. package/dist/composables/motion/useViewTransition.d.ts +31 -0
  57. package/dist/composables/motion/useYieldToMain.d.ts +29 -0
  58. package/dist/configurator.js +1 -1
  59. package/dist/confirm-dialog.js +3 -3
  60. package/dist/context-menu.js +2 -2
  61. package/dist/controls.js +2 -2
  62. package/dist/{createLucideIcon-rHu18UQW.js → createLucideIcon-Bn9a1b70.js} +2 -2
  63. package/dist/dark.js +1 -1
  64. package/dist/data-table.js +1 -1
  65. package/dist/dialog.js +2 -2
  66. package/dist/disco-glyph.js +1 -1
  67. package/dist/dock.js +215 -196
  68. package/dist/dom.js +5 -4
  69. package/dist/{dropdown-menu-gHSkffW7.js → dropdown-menu-BvRUamNs.js} +4 -4
  70. package/dist/dropdown-menu.js +1 -1
  71. package/dist/expandable-container.js +4 -4
  72. package/dist/forms.d.ts +1 -0
  73. package/dist/forms.js +47 -42
  74. package/dist/glass-carousel.js +1 -1
  75. package/dist/glass-panel.js +2 -2
  76. package/dist/glass-ui.css +1 -1
  77. package/dist/glass-ui.js +156 -275
  78. package/dist/glyph-face.js +2 -2
  79. package/dist/header-ribbon.js +1 -1
  80. package/dist/hover-card.js +1 -1
  81. package/dist/hover-popover.js +1 -1
  82. package/dist/icon-tooltip.js +1 -1
  83. package/dist/index.d.ts +1 -0
  84. package/dist/instrument-chassis.js +1 -1
  85. package/dist/instrument-rail.js +1 -1
  86. package/dist/keyboard.js +1 -1
  87. package/dist/label.js +1 -1
  88. package/dist/labeled-field.js +96 -57
  89. package/dist/metric-badge.js +1 -1
  90. package/dist/metric-stack.js +1 -1
  91. package/dist/{minimize-2-C_oyKVwZ.js → minimize-2-LsCJ_eNt.js} +1 -1
  92. package/dist/motion-core.js +135 -98
  93. package/dist/motion.js +3 -3
  94. package/dist/notification.js +1 -1
  95. package/dist/number-field.d.ts +1 -0
  96. package/dist/number-field.js +2 -0
  97. package/dist/paper-backdrop.js +1 -1
  98. package/dist/popover.js +1 -1
  99. package/dist/progress.js +1 -1
  100. package/dist/pulse.js +1 -1
  101. package/dist/reactive.js +2 -2
  102. package/dist/responsive-tabs.js +3 -3
  103. package/dist/scrolling-text.js +1 -1
  104. package/dist/{search-7XEx_6hq.js → search-DBAiUABx.js} +1 -1
  105. package/dist/search.js +7 -7
  106. package/dist/select.js +3 -3
  107. package/dist/separator.js +1 -1
  108. package/dist/{sheet-BsBdO5jq.js → sheet-CukNDezz.js} +53 -53
  109. package/dist/sheet.js +1 -1
  110. package/dist/{slider-BQaLYFLh.js → slider-DJvHkTRe.js} +3 -3
  111. package/dist/slider.js +1 -1
  112. package/dist/sortable-list.js +2 -2
  113. package/dist/styles/animations.css +77 -0
  114. package/dist/styles/cards.css +6 -2
  115. package/dist/styles/dock.css +37 -14
  116. package/dist/styles/glass.css +89 -6
  117. package/dist/styles/index.css +10 -1
  118. package/dist/styles/scroll-driven.css +72 -0
  119. package/dist/styles/theme.css +3 -0
  120. package/dist/styles/tokens.css +237 -24
  121. package/dist/styles/typography.css +21 -0
  122. package/dist/styles/utilities.css +176 -23
  123. package/dist/styles/view-transition.css +62 -0
  124. package/dist/switch.d.ts +1 -0
  125. package/dist/switch.js +2 -0
  126. package/dist/tabs.js +40 -36
  127. package/dist/timeline.js +2 -2
  128. package/dist/toast.js +1 -1
  129. package/dist/toggle-group.js +1 -1
  130. package/dist/tooltip.js +1 -1
  131. package/dist/typewriter.js +1 -1
  132. package/dist/{useAnimatedNumber-2l13GibX.js → useAnimatedNumber-DKQYVB7s.js} +1 -1
  133. package/dist/{useConfiguratorState-BpZi8QJu.js → useConfiguratorState-CtRBE0m_.js} +8 -6
  134. package/dist/{useIdleReady-DlzJicQH.js → useIdleReady-Cmkhm03v.js} +1 -1
  135. package/dist/{useTouchGate-BhhEMlwJ.js → useTouchGate-D9Zvrzyc.js} +1 -1
  136. package/dist/useUserInvalidAria-DVu1eTXG.js +29 -0
  137. package/dist/useViewTransition-DYIK6Gzb.js +16 -0
  138. package/dist/utils/index.d.ts +1 -0
  139. package/dist/utils/moveBefore.d.ts +15 -0
  140. package/dist/{x-Cb3NE2Ne.js → x-q7pJa83X.js} +1 -1
  141. package/package.json +19 -4
  142. package/src/styles/animations.css +77 -0
  143. package/src/styles/cards.css +6 -2
  144. package/src/styles/dock.css +37 -14
  145. package/src/styles/glass.css +89 -6
  146. package/src/styles/index.css +10 -1
  147. package/src/styles/scroll-driven.css +72 -0
  148. package/src/styles/theme.css +3 -0
  149. package/src/styles/tokens.css +237 -24
  150. package/src/styles/typography.css +21 -0
  151. package/src/styles/utilities.css +176 -23
  152. package/src/styles/view-transition.css +62 -0
  153. package/dist/HoverPopover-Btv4RQfv.js +0 -80
  154. package/dist/Label-C8QMJSsf.js +0 -32
  155. package/dist/UnderlineTabs-BtrUcXn-.js +0 -64
  156. /package/dist/{CollapsibleContent-DHRuXE3P.js → CollapsibleContent-CVMOcYlV.js} +0 -0
  157. /package/dist/{ContextMenuContent-CvXfU5qz.js → ContextMenuContent-otjFIu8v.js} +0 -0
  158. /package/dist/{HoverCardContent-4nN5-5bz.js → HoverCardContent-DaGrgJBO.js} +0 -0
  159. /package/dist/{InstrumentChassis-DOaVYyWq.js → InstrumentChassis-CnHTMxds.js} +0 -0
  160. /package/dist/{InstrumentRail-jHDqXj70.js → InstrumentRail-C6dEbi8E.js} +0 -0
  161. /package/dist/{ModalOverlay-DKLVY-cj.js → ModalOverlay-iWiAgbYH.js} +0 -0
  162. /package/dist/{PaperBackdrop-Bc2drCqJ.js → PaperBackdrop-CeZ-w0R0.js} +0 -0
  163. /package/dist/{SelectGroup-O69GTQ77.js → SelectGroup-DdR4tdDY.js} +0 -0
  164. /package/dist/{SelectSeparator-GTHxKO0a.js → SelectSeparator-CXm_hlqA.js} +0 -0
  165. /package/dist/{Separator-_NCypg_C.js → Separator-D8AUMhxY.js} +0 -0
  166. /package/dist/{Switch-CL0uxu8F.js → Switch-Cr1t_F_U.js} +0 -0
  167. /package/dist/{ToggleGroupItem-BYG_8M9M.js → ToggleGroupItem-OesUouE7.js} +0 -0
  168. /package/dist/{TooltipProvider-C5QLSPto.js → TooltipProvider-DE78vbEP.js} +0 -0
  169. /package/dist/{_plugin-vue_export-helper-n-_DRHWS.js → _plugin-vue_export-helper-Dq1MygBL.js} +0 -0
  170. /package/dist/{badge-BbxVKZfw.js → badge-x46my_Fo.js} +0 -0
  171. /package/dist/{constants-D-8FN28s.js → constants-DwBwnG8N.js} +0 -0
  172. /package/dist/{dockContext-BDGSrwsV.js → dockContext-D5NZCWJs.js} +0 -0
  173. /package/dist/{keys-DVkcUktU.js → keys-CaTQS-vx.js} +0 -0
  174. /package/dist/{menuItemVariants-B2nDL7zH.js → menuItemVariants-BsbGNq9C.js} +0 -0
  175. /package/dist/{presets-BMzCDrmR.js → presets-a-D93K1S.js} +0 -0
  176. /package/dist/{useGlassRenderer-DMDdMH55.js → useGlassRenderer-Ds-nmrGz.js} +0 -0
  177. /package/dist/{useGlobalDark-PMiP5Jku.js → useGlobalDark-B0WvLJE3.js} +0 -0
  178. /package/dist/{useIntersectionPause-CXYfYg_C.js → useIntersectionPause-IY2CwPQb.js} +0 -0
  179. /package/dist/{useInterval-COlTCeVa.js → useInterval-DVgGUf_y.js} +0 -0
  180. /package/dist/{useKeyboardShortcuts-CPO4AhLx.js → useKeyboardShortcuts-Dpw_RUcB.js} +0 -0
  181. /package/dist/{useResizeObserver-F4aRR4Cj.js → useResizeObserver-Cg9npuM3.js} +0 -0
  182. /package/dist/{useSortable-Ck0rBJ4g.js → useSortable-Cq2Y1JLO.js} +0 -0
  183. /package/dist/{useSpringMount-BTRBNzXP.js → useSpringMount-Cfk1XK1R.js} +0 -0
  184. /package/dist/{useTimer-lp5NlH4w.js → useTimer-NAaj9zNq.js} +0 -0
@@ -63,7 +63,14 @@
63
63
  * pop, dialog-scale, dropdown, tab-fade).
64
64
  * 10. animations.css — @keyframes for components consumed via
65
65
  * `animation:` properties in (9) and component
66
- * <style> blocks.
66
+ * <style> blocks. Includes the §TOP-LAYER
67
+ * `@starting-style` entry/exit grammar (AQ.W5).
68
+ * 10a. scroll-driven.css — native scroll-driven recipes (.scroll-progress
69
+ * + [data-scroll-reveal]); the `@supports`-gated
70
+ * primary over the JS-composable fallback (AQ.W5).
71
+ * 10b. view-transition.css — the `.gl-list-item` View-Transitions group
72
+ * recipe + `--vt-*` axes (AQ.W5; the
73
+ * `useViewTransition` substrate's CSS half).
67
74
  * 11. utilities.css — focus-ring, btn-audacious + btn-interactive
68
75
  * (press cluster; K W6 + Q.W3 Lane E),
69
76
  * rainbow-vivid + rainbow-pastel. Consumes earlier
@@ -95,6 +102,8 @@
95
102
  @import "./floating-panel.css";
96
103
  @import "./transitions.css";
97
104
  @import "./animations.css";
105
+ @import "./scroll-driven.css";
106
+ @import "./view-transition.css";
98
107
  @import "./utilities.css";
99
108
  @import "./instrument-chassis.css";
100
109
  @import "./instrument-rail.css";
@@ -0,0 +1,72 @@
1
+ /*
2
+ * scroll-driven.css — native scroll-driven CSS animations (AQ.W5 §Design 1).
3
+ *
4
+ * Cascade rung after animations.css. Two token-first recipe families that move
5
+ * the scroll-progress + stagger-reveal work OFF the main thread (the consumer
6
+ * INP lever): the browser runs them on the compositor instead of a rAF/IO
7
+ * listener loop in JS.
8
+ *
9
+ * .scroll-progress — a 0..1 scaleX bar driven by a `scroll()` timeline.
10
+ * The `useScrollProgress` composable replacement.
11
+ * [data-scroll-reveal] — fade + lift on entry, one `view()` timeline PER
12
+ * child (the stagger is implicit — no setTimeout
13
+ * cascade). The `useStaggerReveal` composable
14
+ * replacement.
15
+ *
16
+ * DUAL-PATH with a SINGLE writer (no double-run): when the engine supports
17
+ * `animation-timeline`, the CSS here owns the visual axis and the composables
18
+ * gate their listener/observer machinery OFF (so CSS and JS never both write
19
+ * the same target). When the engine does NOT support it, this block is skipped
20
+ * by `@supports` and the composable is the sole writer. See the gate at the top
21
+ * of `useScrollProgress.ts` / `useStaggerReveal.ts`.
22
+ *
23
+ * Baseline: `scroll-driven-animations` = Newly Available → adopt CSS as
24
+ * primary, keep the composable as the ≤ 20-LOC feature-detected fallback.
25
+ *
26
+ * Reduced-motion is the OUTER gate: the whole `@supports` block sits under
27
+ * `prefers-reduced-motion: no-preference`, so under PRM no scroll animation
28
+ * attaches at all and content renders in its terminal state (the `from`
29
+ * keyframe is never applied because the animation never binds).
30
+ */
31
+
32
+ /* ── Scroll progress (scroll() timeline) — drives a 0..1 scaleX bar.
33
+ * Consumers add `.scroll-progress` on a position:fixed/absolute element; the
34
+ * scroller is the nearest ancestor block scroller (`root` by default; override
35
+ * via `--scroll-progress-scroller`). */
36
+ @media (prefers-reduced-motion: no-preference) {
37
+ @supports (animation-timeline: scroll()) {
38
+ @keyframes gl-scroll-grow {
39
+ from { transform: scaleX(0); }
40
+ to { transform: scaleX(1); }
41
+ }
42
+ .scroll-progress {
43
+ transform-origin: 0 50%;
44
+ animation: gl-scroll-grow auto linear;
45
+ animation-timeline: scroll(var(--scroll-progress-scroller, root) block);
46
+ }
47
+ }
48
+ }
49
+
50
+ /* ── View-driven entry (view() timeline) — the useStaggerReveal replacement.
51
+ * Each child of a `[data-scroll-reveal]` scroller fades + lifts on entry. The
52
+ * stagger is implicit in the per-element view-timeline (each child owns its
53
+ * own timeline), so NO setTimeout cascade is needed. Horizontal scrollers add
54
+ * `.scroll-reveal--inline` for a `view(inline)` axis. */
55
+ @media (prefers-reduced-motion: no-preference) {
56
+ @supports ((animation-timeline: view()) and (animation-range: entry)) {
57
+ @keyframes gl-reveal-in {
58
+ from {
59
+ opacity: 0;
60
+ transform: translateY(var(--scroll-reveal-rise, 6px));
61
+ }
62
+ }
63
+ [data-scroll-reveal] > * {
64
+ animation: gl-reveal-in auto linear both;
65
+ animation-timeline: view(block);
66
+ animation-range: entry 0% entry var(--scroll-reveal-range-end, 60%);
67
+ }
68
+ [data-scroll-reveal].scroll-reveal--inline > * {
69
+ animation-timeline: view(inline);
70
+ }
71
+ }
72
+ }
@@ -55,6 +55,9 @@
55
55
  Colors — core
56
56
  ═══════════════════════════════════════════════ */
57
57
  --color-border: var(--border);
58
+ /* AQ.W2 §3d — the whisper-alpha border hairline rung (border-border-soft /
59
+ bg-border-soft utilities). Auto-dark via --border. */
60
+ --color-border-soft: var(--border-soft);
58
61
  --color-input: var(--input);
59
62
  --color-ring: var(--ring);
60
63
  --color-background: var(--background);
@@ -11,6 +11,27 @@
11
11
  */
12
12
 
13
13
  :root {
14
+ /* ═══════════════════════════════════════════════
15
+ §-1 COLOR-SCHEME (AQ.W2 §1)
16
+
17
+ Lets native UI (scrollbars, spinbuttons, form-control chrome, the
18
+ default focus ring) honor the OS preference when the consumer has
19
+ NOT pinned a `.dark` class. glass-ui's dark mode is class-driven
20
+ (`.dark`, theme.css `@variant dark`), so `.dark` overrides to a hard
21
+ `dark` regardless of OS — but absent the class, native chrome should
22
+ still track `prefers-color-scheme`. `light dark` (not `only light`)
23
+ on `:root` delivers that; `.dark` hard-pins `dark`.
24
+
25
+ Baseline Widely Available → adopt natively, no `@supports` guard
26
+ (older engines ignore the property and keep default-light chrome).
27
+ `accent-color` (AQ.W2 §4) is the companion native-control brand;
28
+ both are inherited built-in <color>/keyword properties re-specified
29
+ inside `.dark`. The `--accent-color` token is defined in the §5
30
+ color block below (custom properties resolve order-independently).
31
+ ═══════════════════════════════════════════════ */
32
+ color-scheme: light dark;
33
+ accent-color: var(--accent-color);
34
+
14
35
  /* ═══════════════════════════════════════════════
15
36
  §0 THEME BRIDGE FALLBACKS
16
37
 
@@ -353,6 +374,34 @@
353
374
  --shadow: hsl(24 10% 10%);
354
375
  --shadow-color: var(--foreground);
355
376
 
377
+ /* AQ.W2 §4 — native-control accent. `accent-color` is an inherited
378
+ built-in <color>, so per the §2b resolve-late discipline it reads a
379
+ dedicated UNREGISTERED token set per-mode (NOT light-dark()) and is
380
+ re-specified inside `.dark` — otherwise the accent freezes to the
381
+ light shade at the cascade root. Light: muted-black checkmarks /
382
+ sliders on warm cream. Dark arm (`.dark`) reads `--ring` (mid-tone),
383
+ not the near-white dark `--primary`, so a checkbox's white checkmark
384
+ keeps contrast headroom (accent-color.md §5). */
385
+ --accent-color: var(--primary);
386
+
387
+ /* Border hairline at whisper alpha — the canonical rung for
388
+ section-spine / panel-edge hairlines a consumer wants to read as an
389
+ iOS-26 whisper rather than a hard rule. Consumers compose this named
390
+ rung instead of hand-mixing `color-mix(... var(--border) ...)`
391
+ per-site (token-first). 45% is the canonical whisper. Auto-dark via
392
+ `--border` (which is `var(--neutral-4)`, light-dark()-resolved). */
393
+ --border-soft: color-mix(in srgb, var(--border) 45%, transparent);
394
+
395
+ /* AQ.W3 §W3.4 — tokenized scrollbar thumb + track. Minted in the color
396
+ block so the `scrollbar-color` / `::-webkit-scrollbar-thumb` rungs read a
397
+ single source. Auto-dark via `--muted-foreground` (light-dark()-resolved,
398
+ AQ.W2) — the OS scrollbar chrome also honors `color-scheme: dark`, so the
399
+ custom thumb tracks the dark surface without an explicit dark mirror. The
400
+ thumb α (25%) matches the prior inline `.scrollbar-thin` value byte-for-
401
+ byte; `transparent` track keeps the scroll-pane glass reading through. */
402
+ --scrollbar-thumb: color-mix(in srgb, var(--muted-foreground) 25%, transparent);
403
+ --scrollbar-track: transparent;
404
+
356
405
  /* Foreground-tint rungs — canonical handles for the 36+ raw
357
406
  `color-mix(in srgb, var(--foreground) N%, transparent)` sites surveyed
358
407
  in R5 axis-1. Each rung's α is named in its key (4 → 4%, 22 → 22%).
@@ -874,6 +923,15 @@
874
923
  WCAG 2.5.5 floor on touch devices. */
875
924
  --dock-touch-target: 2.75rem; /* 44px */
876
925
 
926
+ /* AQ.W3 §7 — canonical WCAG 2.5.5 (44px) touch-target floor for the
927
+ NON-dock coarse-pointer surfaces (`Button size="icon"`,
928
+ ExpandableContainer triggers, ResponsiveTabs mobile trigger). One
929
+ named rung the `@media (pointer: coarse)` block in utilities.css reads,
930
+ retiring the per-consumer one-liner `min-h-[44px]` patches. Equals
931
+ `--dock-touch-target` numerically; kept as a distinct token so the
932
+ dock floor and the general floor can be retuned independently. */
933
+ --touch-target: 2.75rem; /* 44px */
934
+
877
935
  /* MetricBadge — stacked variant geometry. The 2-row stacked layout
878
936
  (label / value+unit) wants a taller floor than the inline pill so the
879
937
  label has breathing room above the baseline pair. T.W2.T2 +
@@ -1136,14 +1194,184 @@
1136
1194
  --table-cell-py: calc(1rem * var(--table-density));
1137
1195
  --table-head-h: calc(3rem * var(--table-density));
1138
1196
  --table-head-px: calc(1rem * var(--table-density));
1197
+
1198
+ /* ═══════════════════════════════════════════════
1199
+ §20 PLATFORM MOTION (AQ.W5)
1200
+
1201
+ The native-platform motion substrate axes. Three families, each read
1202
+ by a `@supports`-gated CSS recipe in `scroll-driven.css`,
1203
+ `animations.css` (§TOP-LAYER), and `view-transition.css` — every visual
1204
+ knob a token so a consumer retunes without editing library source.
1205
+
1206
+ SCROLL-DRIVEN (scroll-driven.css). Values mirror the JS-fallback
1207
+ composable defaults (`useScrollProgress` / `useStaggerReveal`) so the
1208
+ native CSS path and the fallback path read identically — no visual seam
1209
+ at the `@supports` boundary.
1210
+
1211
+ TOP-LAYER (animations.css §TOP-LAYER). The `@starting-style` entry/exit
1212
+ grammar for native `<dialog>` / `[popover]` glass surfaces. Backdrop dim
1213
+ uses the `hsl(var(--background) / α)` channel form — the legitimate
1214
+ single-token alpha case (AQ.W2's color-mix migration is orthogonal).
1215
+
1216
+ VIEW-TRANSITION (view-transition.css). The shared `.gl-list-item` group
1217
+ recipe + the `--vt-*` axes the `useViewTransition` substrate consumers
1218
+ (dock layer swap, muster J's verdict re-rank) tune their swap against.
1219
+ ═══════════════════════════════════════════════ */
1220
+ --scroll-progress-scroller: root;
1221
+ --scroll-reveal-rise: 6px;
1222
+ --scroll-reveal-range-end: 60%;
1223
+
1224
+ --top-layer-enter-scale: 0.96;
1225
+ --top-layer-backdrop-blur: 8px;
1226
+ --top-layer-backdrop-dim: 0.5;
1227
+
1228
+ --vt-duration: var(--duration-normal);
1229
+ --vt-ease: var(--ease-apple-spring);
1230
+ --vt-rise: 8px;
1231
+ }
1232
+
1233
+ /* ═══════════════════════════════════════════════
1234
+ §-1b LIGHT-DARK() COLOR ARCHITECTURE (AQ.W2 §2)
1235
+
1236
+ Every PAIRED color token (a token whose `:root` and `.dark` values are
1237
+ BOTH a <color> and differ) folds onto one `light-dark(light, dark)`
1238
+ declaration, keyed off the element's `color-scheme` (§-1). This is the
1239
+ single-source-of-truth collapse of the `.dark` mirror AND the dynamism
1240
+ win: an unregistered custom property holding a `light-dark()` expression
1241
+ re-resolves under a descendant `color-scheme` override (a `.dark`
1242
+ code-block embedded in a light page, or vice-versa).
1243
+
1244
+ DISCIPLINE (§2b — BINDING): these tokens MUST stay UNREGISTERED (no
1245
+ `@property … syntax:"<color>"`). A registered <color> would resolve ONCE
1246
+ at the declaring element and inherit the RESOLVED color, freezing the
1247
+ descendant re-resolution. glass-ui's only `@property` registrations (§18)
1248
+ are non-color (percentage/length), so the discipline holds — W2 adds NO
1249
+ color `@property`.
1250
+
1251
+ The semantic `var()`-aliases (`--background`, `--muted`, `--border`,
1252
+ `--secondary`, `--accent`, `--card-foreground`, …) do NOT appear here:
1253
+ they point at the SAME source name in both modes and auto-track once the
1254
+ `--neutral-*` ladder + `--foreground` resolve via `light-dark()`. Their
1255
+ redundant `.dark` re-declarations DELETE below.
1256
+
1257
+ FALLBACK (§2c): this whole block is `@supports`-gated, so an engine
1258
+ WITHOUT `light-dark()` skips it and the retained `.dark` class block (the
1259
+ SOLE fallback floor) drives dark exactly as at HEAD. `light-dark()` is the
1260
+ enhancement OVER the class — not a parallel alias. Baseline Newly
1261
+ Available; the fallback floor is the pre-existing class block (net-zero
1262
+ new fallback LOC).
1263
+ ═══════════════════════════════════════════════ */
1264
+ @supports (color: light-dark(white, black)) {
1265
+ :root {
1266
+ /* Neutral ladder — the source the var()-aliases track */
1267
+ --neutral-0: light-dark(hsl(48 12% 98%), hsl(24 8% 6%));
1268
+ --neutral-1: light-dark(hsl(48 10% 95%), hsl(24 6% 11%));
1269
+ --neutral-2: light-dark(hsl(48 9% 90%), hsl(24 5% 16%));
1270
+ --neutral-3: light-dark(hsl(48 8% 82%), hsl(24 5% 22%));
1271
+ --neutral-4: light-dark(hsl(48 7% 70%), hsl(24 5% 34%));
1272
+ --neutral-5: light-dark(hsl(48 6% 40%), hsl(48 5% 62%));
1273
+ --neutral-6: light-dark(hsl(48 7% 30%), hsl(48 6% 72%));
1274
+
1275
+ /* Core surfaces + ink */
1276
+ --foreground: light-dark(hsl(24 10% 10%), hsl(48 10% 90%));
1277
+ --card: light-dark(var(--neutral-0), hsl(24 8% 10%));
1278
+ --popover: light-dark(var(--neutral-0), hsl(24 8% 10%));
1279
+ --surface-public-data-panel: light-dark(hsl(44 16% 96%), hsl(36 9% 12%));
1280
+
1281
+ --primary: light-dark(hsl(24 10% 10%), hsl(48 10% 90%));
1282
+ --primary-foreground: light-dark(var(--neutral-0), hsl(24 10% 10%));
1283
+ --destructive: light-dark(hsl(0 72% 50%), hsl(0 62.8% 30.6%));
1284
+ --destructive-foreground: light-dark(var(--neutral-0), hsl(48 10% 90%));
1285
+ --ring: light-dark(hsl(24 10% 10%), hsl(48 10% 70%));
1286
+ --shadow: light-dark(hsl(24 10% 10%), hsl(0 0% 5%));
1287
+
1288
+ /* §4 native-control accent — the per-mode arms (dark reads the
1289
+ mid-tone ring for checkmark-glyph contrast headroom, NOT the
1290
+ near-white dark primary). Joins the light-dark() collapse; still
1291
+ re-specified as `accent-color` inside `.dark` per §2b. */
1292
+ --accent-color: light-dark(var(--primary), var(--ring));
1293
+
1294
+ /* Section palette — jewel tones brightened ~20% L for dark */
1295
+ --section-color-0: light-dark(hsl(334 63% 47%), hsl(334 72% 70%));
1296
+ --section-color-1: light-dark(hsl(272 44% 47%), hsl(272 54% 73%));
1297
+ --section-color-2: light-dark(hsl(224 58% 46%), hsl(224 67% 72%));
1298
+ --section-color-3: light-dark(hsl(194 62% 36%), hsl(194 61% 64%));
1299
+ --section-color-4: light-dark(hsl(163 46% 35%), hsl(163 50% 60%));
1300
+ --section-color-5: light-dark(hsl(35 70% 42%), hsl(37 73% 67%));
1301
+ --section-color-6: light-dark(hsl(6 72% 49%), hsl(6 77% 66%));
1302
+ --section-color-7: light-dark(hsl(286 46% 47%), hsl(286 58% 72%));
1303
+ --section-color-8: light-dark(hsl(342 62% 44%), hsl(342 71% 69%));
1304
+ --section-color-9: light-dark(hsl(205 20% 38%), hsl(205 24% 70%));
1305
+ --section-color-10: light-dark(hsl(86 38% 36%), hsl(86 44% 63%));
1306
+ --section-color-11: light-dark(hsl(187 58% 39%), hsl(187 63% 65%));
1307
+ --section-color-12: light-dark(hsl(256 44% 52%), hsl(256 60% 74%));
1308
+
1309
+ --accent-pink: light-dark(hsl(330 65% 55%), hsl(335 55% 65%));
1310
+ --section-heading: light-dark(hsl(328 60% 46%), hsl(330 55% 68%));
1311
+ --accent-red: light-dark(hsl(0 72% 50%), hsl(0 68% 62%));
1312
+
1313
+ /* Viz basis (amber/green stay var()-aliases → auto-track) */
1314
+ --viz-fourier: light-dark(hsl(6 72% 49%), hsl(6 77% 66%));
1315
+ --viz-chebyshev: light-dark(hsl(224 58% 46%), hsl(224 67% 72%));
1316
+ --viz-legendre: light-dark(hsl(286 46% 47%), hsl(286 58% 72%));
1317
+
1318
+ /* WCAG companion chart labels */
1319
+ --chart-ping-label: light-dark(oklch(0.40 0.18 230), oklch(0.85 0.12 230));
1320
+ --chart-download-label: light-dark(oklch(0.40 0.20 22), oklch(0.85 0.14 22));
1321
+ --chart-upload-label: light-dark(oklch(0.40 0.16 55), oklch(0.85 0.12 55));
1322
+ --chart-jitter-label: light-dark(oklch(0.40 0.20 305), oklch(0.85 0.14 305));
1323
+
1324
+ /* Semantic UI accents */
1325
+ --tier-featured: light-dark(hsl(45 100% 50%), hsl(45 100% 60%));
1326
+ --tier-saved: light-dark(hsl(210 100% 60%), hsl(210 100% 70%));
1327
+ --like: light-dark(hsl(0 80% 60%), hsl(0 80% 68%));
1328
+ --success: light-dark(hsl(142 71% 45%), hsl(142 71% 58%));
1329
+ --warning: light-dark(hsl(38 92% 50%), hsl(38 92% 60%));
1330
+ --info: light-dark(hsl(217 91% 60%), hsl(217 91% 70%));
1331
+ --delete: light-dark(hsl(0 70% 55%), hsl(0 70% 62%));
1332
+
1333
+ /* Semantic foregrounds (warning-foreground is identical both modes
1334
+ → stays a single light-mode declaration, no light-dark() needed) */
1335
+ --success-foreground: light-dark(var(--neutral-0), hsl(48 10% 96%));
1336
+ --info-foreground: light-dark(var(--neutral-0), hsl(48 10% 96%));
1337
+
1338
+ /* Cartoon-shadow color primitives (§2d — plain colors, convert) */
1339
+ --shadow-cartoon-color: light-dark(rgb(0 0 0 / 0.12), rgb(255 255 255 / 0.07));
1340
+ --shadow-cartoon-color-soft: light-dark(rgb(0 0 0 / 0.06), rgb(255 255 255 / 0.03));
1341
+
1342
+ /* Gold family */
1343
+ --gold: light-dark(hsl(43 74% 49%), hsl(43 74% 55%));
1344
+ --gold-light: light-dark(hsl(51 100% 50%), hsl(51 100% 55%));
1345
+ --gold-dark: light-dark(hsl(34 87% 38%), hsl(34 87% 45%));
1346
+ }
1139
1347
  }
1140
1348
 
1141
1349
  /* ═══════════════════════════════════════════════
1142
1350
  DARK MODE — warm dark, section palette brightened ~20% L
1351
+
1352
+ FALLBACK FLOOR (AQ.W2 §2c): this class block is the SOLE non-light-dark()
1353
+ dark path. On a `light-dark()`-supporting engine with `.dark` present,
1354
+ `.dark { color-scheme: dark }` (§1) makes every §-1b token resolve to its
1355
+ dark arm and these explicit dark values agree with it (kept as the floor
1356
+ for non-supporting engines). The pure `var()`-alias re-declarations
1357
+ (`--muted`/`--secondary`/`--accent`/`--border`/`--input`/… and the
1358
+ `--background`/`*-foreground` aliases) are DELETED — they auto-track the
1359
+ `--neutral-*` ladder + `--foreground` resolved above; only EXPLICIT-color
1360
+ dark values (and the non-color overrides §2d) stay.
1143
1361
  ═══════════════════════════════════════════════ */
1144
1362
  .dark {
1363
+ /* §1 — hard-pin native chrome to dark regardless of OS preference. §4 —
1364
+ re-specify the inherited `accent-color` so it re-resolves to the dark
1365
+ arm (§2b: an inherited built-in <color> set at `:root` would freeze to
1366
+ the light shade without this re-specification). */
1367
+ color-scheme: dark;
1368
+ accent-color: var(--accent-color);
1369
+
1145
1370
  /* Neutral scale mirrors light-mode pattern: step UP from the background's
1146
- low L toward foreground. Same perceptual deltas as light. */
1371
+ low L toward foreground. Same perceptual deltas as light. FALLBACK
1372
+ FLOOR — kept verbatim for non-light-dark() engines (§2c); on a
1373
+ supporting engine `color-scheme: dark` (above) drives the §-1b
1374
+ light-dark() arms and these agree. */
1147
1375
  --neutral-0: hsl(24 8% 6%); /* L 6 — page surface (dark) */
1148
1376
  --neutral-1: hsl(24 6% 11%); /* L 11 — soft field */
1149
1377
  --neutral-2: hsl(24 5% 16%); /* L 16 — chip / tab-inactive */
@@ -1157,31 +1385,20 @@
1157
1385
  (cf. neutral-5's 7.39:1). */
1158
1386
  --neutral-6: hsl(48 6% 72%); /* L 72 — strong-muted text (secondary register) */
1159
1387
 
1160
- --background: var(--neutral-0);
1388
+ /* --background / --card-foreground / --popover-foreground / --muted /
1389
+ --muted-foreground{,-strong} / --secondary{,-foreground} /
1390
+ --accent{,-foreground} / --border / --input are pure var()-aliases —
1391
+ DELETED here (AQ.W2 §2a): they auto-track the --neutral-* ladder +
1392
+ --foreground above. Re-declaring them would be redundant. */
1161
1393
  --foreground: hsl(48 10% 90%);
1162
1394
  --card: hsl(24 8% 10%);
1163
- --card-foreground: var(--foreground);
1164
1395
  --popover: hsl(24 8% 10%);
1165
- --popover-foreground: var(--foreground);
1166
1396
 
1167
1397
  /* R0G-5 (AO.W4) — dark mirror of the warm-neutral public-data panel.
1168
1398
  --card's dark hsl(24 8% 10%) nudged one warmth step toward amber
1169
1399
  (24→36) + +1 sat + +2 L so the dark dashboard panel lifts off the page. */
1170
1400
  --surface-public-data-panel: hsl(36 9% 12%);
1171
1401
 
1172
- --muted: var(--neutral-1);
1173
- --muted-foreground: var(--neutral-5);
1174
- /* W7-α' (AK-FD1) — strong-muted secondary text. Auto-tracks the dark
1175
- neutral-6 rung above; by-colour, not alpha. */
1176
- --muted-foreground-strong: var(--neutral-6);
1177
- --secondary: var(--neutral-2);
1178
- --secondary-foreground: var(--foreground);
1179
- --accent: var(--neutral-3);
1180
- --accent-foreground: var(--foreground);
1181
-
1182
- --border: var(--neutral-4);
1183
- --input: var(--neutral-4);
1184
-
1185
1402
  --primary: hsl(48 10% 90%);
1186
1403
  --primary-foreground: hsl(24 10% 10%);
1187
1404
  --destructive: hsl(0 62.8% 30.6%);
@@ -1211,8 +1428,9 @@
1211
1428
  --viz-fourier: hsl(6 77% 66%);
1212
1429
  --viz-chebyshev: hsl(224 67% 72%);
1213
1430
  --viz-legendre: hsl(286 58% 72%);
1214
- --viz-amber: var(--section-color-5);
1215
- --viz-green: var(--section-color-4);
1431
+ /* --viz-amber / --viz-green / --meter-track-stroke are pure var()-aliases
1432
+ (--section-color-5/-4 / --foreground) — DELETED (§2a); they auto-track
1433
+ their sources, which convert via §-1b. */
1216
1434
 
1217
1435
  /* O.W6 Lane D — WCAG companion labels lift to L≈0.85 against the
1218
1436
  deep dark canvas; same two-token discipline as light mode (canvas
@@ -1222,11 +1440,6 @@
1222
1440
  --chart-upload-label: oklch(0.85 0.12 55);
1223
1441
  --chart-jitter-label: oklch(0.85 0.14 305);
1224
1442
 
1225
- /* O.W6 Lane D — Meter track stroke dark companion. Mirrors `:root`
1226
- (was speedtest's consumer-side `var(--background)` — bg-on-bg
1227
- invisible at dark mode; F1.V-02 closure). */
1228
- --meter-track-stroke: var(--foreground);
1229
-
1230
1443
  --tier-featured: hsl(45 100% 60%);
1231
1444
  --tier-saved: hsl(210 100% 70%);
1232
1445
  --like: hsl(0 80% 68%);
@@ -157,6 +157,9 @@ body {
157
157
  font-optical-sizing: auto;
158
158
  font-variation-settings: var(--font-display-variation-settings);
159
159
  font-weight: var(--font-display-weight);
160
+ /* AQ.W3 §W3.3 — balance multi-line display headlines. Text-only (no box) so
161
+ balance is safe; degrades to unbalanced wrapping with zero break. */
162
+ text-wrap: balance;
160
163
  }
161
164
 
162
165
  /* `.text-hero` — the poster-type hero register. Ceiling pegs to
@@ -177,7 +180,11 @@ body {
177
180
  font-variation-settings: var(--font-display-variation-settings);
178
181
  display: inline-block;
179
182
  max-inline-size: 100%;
183
+ /* AQ.W3 §W3.3 — `text-wrap: nowrap` (modern) sits AFTER `white-space:
184
+ nowrap` (legacy fallback) so supporting engines honor the modern form and
185
+ older ones fall through to `white-space`. Forgiving parse, no `@supports`. */
180
186
  white-space: nowrap;
187
+ text-wrap: nowrap;
181
188
  }
182
189
 
183
190
  @utility text-display-hero {
@@ -188,6 +195,7 @@ body {
188
195
  font-optical-sizing: auto;
189
196
  font-variation-settings: var(--font-display-variation-settings);
190
197
  font-weight: var(--font-display-weight);
198
+ text-wrap: balance; /* AQ.W3 §W3.3 */
191
199
  }
192
200
 
193
201
  @utility text-display-mega {
@@ -198,6 +206,7 @@ body {
198
206
  font-optical-sizing: auto;
199
207
  font-variation-settings: var(--font-display-variation-settings);
200
208
  font-weight: var(--font-display-weight);
209
+ text-wrap: balance; /* AQ.W3 §W3.3 */
201
210
  }
202
211
 
203
212
  @utility text-display-5 {
@@ -208,6 +217,7 @@ body {
208
217
  font-optical-sizing: auto;
209
218
  font-variation-settings: var(--font-display-variation-settings);
210
219
  font-weight: var(--font-display-weight);
220
+ text-wrap: balance; /* AQ.W3 §W3.3 */
211
221
  }
212
222
 
213
223
  @utility text-display-4 {
@@ -218,6 +228,7 @@ body {
218
228
  font-optical-sizing: auto;
219
229
  font-variation-settings: var(--font-display-variation-settings);
220
230
  font-weight: var(--font-display-weight);
231
+ text-wrap: balance; /* AQ.W3 §W3.3 */
221
232
  }
222
233
 
223
234
  @utility text-display-3 {
@@ -228,6 +239,7 @@ body {
228
239
  font-optical-sizing: auto;
229
240
  font-variation-settings: var(--font-display-variation-settings);
230
241
  font-weight: var(--font-display-weight);
242
+ text-wrap: balance; /* AQ.W3 §W3.3 */
231
243
  }
232
244
 
233
245
  @utility text-display-2 {
@@ -238,6 +250,7 @@ body {
238
250
  font-optical-sizing: auto;
239
251
  font-variation-settings: var(--font-display-variation-settings);
240
252
  font-weight: var(--font-display-weight);
253
+ text-wrap: balance; /* AQ.W3 §W3.3 */
241
254
  }
242
255
 
243
256
  @utility text-display {
@@ -248,6 +261,7 @@ body {
248
261
  font-optical-sizing: auto;
249
262
  font-variation-settings: var(--font-display-variation-settings);
250
263
  font-weight: var(--font-display-weight);
264
+ text-wrap: balance; /* AQ.W3 §W3.3 */
251
265
  }
252
266
 
253
267
  /* ═══════════════════════════════════════════════
@@ -259,6 +273,7 @@ body {
259
273
  line-height: var(--type-leading-heading);
260
274
  letter-spacing: var(--type-tracking-tight);
261
275
  font-weight: 700;
276
+ text-wrap: balance; /* AQ.W3 §W3.3 */
262
277
  }
263
278
 
264
279
  @utility text-heading {
@@ -266,6 +281,7 @@ body {
266
281
  font-size: var(--type-heading);
267
282
  line-height: var(--type-leading-heading);
268
283
  font-weight: 700;
284
+ text-wrap: balance; /* AQ.W3 §W3.3 */
269
285
  }
270
286
 
271
287
  @utility text-subheading {
@@ -273,6 +289,7 @@ body {
273
289
  font-size: var(--type-subheading);
274
290
  line-height: var(--type-leading-body);
275
291
  font-weight: 600;
292
+ text-wrap: balance; /* AQ.W3 §W3.3 */
276
293
  }
277
294
 
278
295
  /* Canonical dock control label register — text labels INSIDE
@@ -295,6 +312,9 @@ body {
295
312
  font-size: var(--type-prose);
296
313
  line-height: var(--type-leading-prose);
297
314
  font-weight: 400;
315
+ /* AQ.W3 §W3.3 — `pretty` fixes orphans/rivers in prose. Prose registers
316
+ only (not every text class); degrades to default wrapping, zero break. */
317
+ text-wrap: pretty;
298
318
  }
299
319
 
300
320
  @utility text-body {
@@ -302,6 +322,7 @@ body {
302
322
  font-size: var(--type-body);
303
323
  line-height: var(--type-leading-body);
304
324
  font-weight: 400;
325
+ text-wrap: pretty; /* AQ.W3 §W3.3 */
305
326
  }
306
327
 
307
328
  @utility text-small {