@mkbabb/glass-ui 3.8.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +1 -6
  2. package/dist/{CardAction-q2qHCJFG.js → CardAction-DuArVky-.js} +4 -4
  3. package/dist/{CommandShortcut-SzWRhROC.js → CommandShortcut-CefCj5mt.js} +7 -7
  4. package/dist/{ContextMenuSubContent-Do977Cbf.js → ContextMenuSubContent-Bhg4f5jX.js} +3 -3
  5. package/dist/{DataTable-CvlWXz65.js → DataTable-CUHMukiQ.js} +1 -1
  6. package/dist/{DialogContent-DjZWT3lK.js → DialogContent-BRkT1cjP.js} +1 -1
  7. package/dist/{MetricBadge-lTc002u2.js → MetricBadge-BZVWIxNy.js} +6 -4
  8. package/dist/{Notification-BxK8LZMw.js → Notification-DLMhblXR.js} +2 -2
  9. package/dist/{NumberFieldContent-CLNVR1iY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  10. package/dist/{SelectScrollDownButton-C7TRe-ep.js → SelectScrollDownButton-T32cVFeM.js} +3 -3
  11. package/dist/{SelectSeparator-L8pPEn4L.js → SelectSeparator-C4Ql0gzV.js} +1 -1
  12. package/dist/{Switch-LDKLmmgx.js → Switch-Ch-k3Rv-.js} +1 -1
  13. package/dist/{TabsList-qyHZ2lKY.js → TabsList-B8CVOQPC.js} +2 -2
  14. package/dist/{Toaster-CabYEEF_.js → Toaster-1rYWrmAm.js} +1 -1
  15. package/dist/{ToggleGroupItem-CkXUcBlt.js → ToggleGroupItem-Cev4pOVK.js} +4 -4
  16. package/dist/animated-digit.js +1 -1
  17. package/dist/api/index.d.ts +2 -1
  18. package/dist/api.js +1 -1
  19. package/dist/aurora.js +236 -545
  20. package/dist/{badge-DHQrc_GQ.js → badge-CaoFJzRb.js} +5 -5
  21. package/dist/badge.js +1 -1
  22. package/dist/{button-CAywcrhO.js → button-DN39cGqL.js} +13 -12
  23. package/dist/button.js +1 -1
  24. package/dist/card.js +1 -1
  25. package/dist/carousel.js +1 -1
  26. package/dist/color.js +1 -1
  27. package/dist/command.js +1 -1
  28. package/dist/{compile-BBTRjvQS.js → compile-BOXjLUxu.js} +24 -24
  29. package/dist/components/custom/aurora/composables/atoms.d.ts +21 -4
  30. package/dist/components/custom/aurora/composables/runtime.d.ts +0 -9
  31. package/dist/components/custom/aurora/composables/uniformBridge.d.ts +0 -11
  32. package/dist/components/custom/aurora/constants/renderMode.d.ts +0 -32
  33. package/dist/components/custom/aurora/constants/shaders/brush.glsl.d.ts +1 -1
  34. package/dist/components/custom/aurora/constants/shaders/mediums.glsl.d.ts +2 -2
  35. package/dist/components/custom/aurora/constants/shaders/tonemap.glsl.d.ts +1 -1
  36. package/dist/components/custom/aurora/index.d.ts +1 -1
  37. package/dist/components/custom/configurator/ConfiguratorLayer.vue.d.ts +1 -1
  38. package/dist/components/custom/constellation/Constellation.vue.d.ts +73 -1
  39. package/dist/components/custom/constellation/constellationField.d.ts +255 -3
  40. package/dist/components/custom/constellation/index.d.ts +2 -2
  41. package/dist/components/custom/dock/DockSeparator.vue.d.ts +3 -0
  42. package/dist/components/custom/dock/DockTabButton.vue.d.ts +4 -3
  43. package/dist/components/custom/dock/GlassDock.vue.d.ts +45 -63
  44. package/dist/components/custom/dock/composables/dockContext.d.ts +7 -0
  45. package/dist/components/custom/dock/index.d.ts +2 -1
  46. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +29 -0
  47. package/dist/components/custom/fourier-field/FourierField.vue.d.ts +6 -0
  48. package/dist/components/custom/fourier-field/index.d.ts +25 -1
  49. package/dist/components/custom/fourier-field/math.d.ts +3 -8
  50. package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +8 -10
  51. package/dist/components/custom/goo-blob/composables/useBlobMood.d.ts +19 -5
  52. package/dist/components/custom/goo-blob/composables/useMetaballRenderer.d.ts +6 -14
  53. package/dist/components/custom/goo-blob/index.d.ts +1 -1
  54. package/dist/components/custom/goo-blob/types.d.ts +59 -25
  55. package/dist/components/custom/handmark/HandMark.vue.d.ts +29 -0
  56. package/dist/components/custom/handmark/brush.d.ts +219 -0
  57. package/dist/components/custom/handmark/freehand.d.ts +69 -0
  58. package/dist/components/custom/handmark/geometry.d.ts +32 -0
  59. package/dist/components/custom/handmark/index.d.ts +21 -0
  60. package/dist/components/custom/handmark/ink.d.ts +11 -0
  61. package/dist/components/custom/handmark/texture.d.ts +39 -0
  62. package/dist/components/custom/handmark/types.d.ts +53 -0
  63. package/dist/components/custom/handmark/useHandMark.d.ts +66 -0
  64. package/dist/components/custom/metric-badge/MetricBadge.vue.d.ts +8 -0
  65. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +92 -0
  66. package/dist/components/custom/tabs/composables/useTabIndicator.d.ts +49 -0
  67. package/dist/components/custom/tabs/index.d.ts +2 -5
  68. package/dist/components/ui/button/index.d.ts +1 -1
  69. package/dist/components/ui/card/Card.vue.d.ts +5 -3
  70. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  71. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  72. package/dist/components/ui/carousel/GlassCarouselPager.vue.d.ts +3 -4
  73. package/dist/components/ui/slider/index.d.ts +22 -11
  74. package/dist/components/ui/tabs/TabsList.vue.d.ts +1 -1
  75. package/dist/composables/color/index.d.ts +12 -7
  76. package/dist/composables/context/createContext.d.ts +1 -1
  77. package/dist/composables/glass/webgl/shaders/procedural-color.glsl.d.ts +1 -6
  78. package/dist/composables/motion/core/index.d.ts +1 -0
  79. package/dist/composables/motion/useRouteTransition.d.ts +42 -0
  80. package/dist/configurator.js +1 -1
  81. package/dist/confirm-dialog.js +1 -1
  82. package/dist/constellation.js +212 -72
  83. package/dist/context-menu.js +1 -1
  84. package/dist/controls.js +1 -1
  85. package/dist/dark.js +1 -1
  86. package/dist/data-table.js +1 -1
  87. package/dist/deck-progress.js +1 -1
  88. package/dist/dialog.js +1 -1
  89. package/dist/dock.js +257 -243
  90. package/dist/{dropdown-menu-B_4bWyyG.js → dropdown-menu-D77jX6Df.js} +3 -3
  91. package/dist/dropdown-menu.js +1 -1
  92. package/dist/expandable-container.js +61 -38
  93. package/dist/forms.js +5 -5
  94. package/dist/fourier-field.js +89 -97
  95. package/dist/fourier-math.d.ts +1 -0
  96. package/dist/fourier-math.js +2 -0
  97. package/dist/glass-panel.js +1 -1
  98. package/dist/glass-ui.css +1 -1
  99. package/dist/glass-ui.js +107 -109
  100. package/dist/goo-blob.js +316 -297
  101. package/dist/handmark.d.ts +1 -0
  102. package/dist/handmark.js +609 -0
  103. package/dist/hover-popover.js +1 -1
  104. package/dist/icon-tooltip.js +1 -1
  105. package/dist/index.d.ts +1 -2
  106. package/dist/keyboard.js +1 -1
  107. package/dist/labeled-field.js +5 -5
  108. package/dist/math-DTpRVC0e.js +27 -0
  109. package/dist/{menuItemVariants-DKM85SNE.js → menuItemVariants-CCoBNkU5.js} +1 -1
  110. package/dist/metric-badge.js +1 -1
  111. package/dist/metric-stack.js +1 -1
  112. package/dist/motion-core.js +70 -69
  113. package/dist/motion.js +2 -2
  114. package/dist/notification.js +1 -1
  115. package/dist/number-field.js +1 -1
  116. package/dist/pulse.js +1 -1
  117. package/dist/reactive.js +1 -1
  118. package/dist/scrolling-text.js +1 -1
  119. package/dist/search.js +4 -4
  120. package/dist/select.js +2 -2
  121. package/dist/{slider-D9puf-Ko.js → slider-CyzcxBoh.js} +6 -6
  122. package/dist/slider.js +1 -1
  123. package/dist/sortable-list.js +1 -1
  124. package/dist/status-dot.js +17 -16
  125. package/dist/styles/animations.css +80 -20
  126. package/dist/styles/cards.css +2 -2
  127. package/dist/styles/components.css +1 -1
  128. package/dist/styles/dock/density.css +230 -0
  129. package/dist/styles/dock/layer-group.css +275 -0
  130. package/dist/styles/dock/layers.css +355 -0
  131. package/dist/styles/dock/morph.css +244 -0
  132. package/dist/styles/dock/overflow.css +201 -0
  133. package/dist/styles/dock/shell.css +457 -0
  134. package/dist/styles/dock-controls.css +205 -55
  135. package/dist/styles/dock.css +42 -1349
  136. package/dist/styles/drawer.css +12 -4
  137. package/dist/styles/glass.css +535 -78
  138. package/dist/styles/index.css +12 -11
  139. package/dist/styles/paper.css +68 -2
  140. package/dist/styles/theme.css +58 -0
  141. package/dist/styles/tokens.css +601 -69
  142. package/dist/styles/transitions.css +20 -2
  143. package/dist/styles/utilities.css +218 -78
  144. package/dist/styles/view-transition.css +51 -0
  145. package/dist/switch.js +1 -1
  146. package/dist/tabs.js +182 -151
  147. package/dist/timeline.js +1 -1
  148. package/dist/toast.js +1 -1
  149. package/dist/toggle-group.js +1 -1
  150. package/dist/{useAnimatedNumber-C_3wZLx4.js → useAnimatedNumber-Bcpy5Etf.js} +1 -1
  151. package/dist/{useConfiguratorState-CMff4GzH.js → useConfiguratorState-DxAqksK6.js} +21 -10
  152. package/dist/{useGlassRenderer-5I0YkI4t.js → useGlassRenderer-D7YGOYiM.js} +1 -1
  153. package/dist/useViewTransition-DaN5Zrox.js +21 -0
  154. package/dist/vReveal-zUIQk-rJ.js +53 -0
  155. package/dist/watercolor-dot.js +1 -1
  156. package/package.json +80 -39
  157. package/src/styles/animations.css +80 -20
  158. package/src/styles/cards.css +2 -2
  159. package/src/styles/dock/density.css +230 -0
  160. package/src/styles/dock/layer-group.css +275 -0
  161. package/src/styles/dock/layers.css +355 -0
  162. package/src/styles/dock/morph.css +244 -0
  163. package/src/styles/dock/overflow.css +201 -0
  164. package/src/styles/dock/shell.css +457 -0
  165. package/src/styles/dock-controls.css +205 -55
  166. package/src/styles/dock.css +42 -1349
  167. package/src/styles/drawer.css +12 -4
  168. package/src/styles/glass.css +535 -78
  169. package/src/styles/index.css +12 -11
  170. package/src/styles/paper.css +68 -2
  171. package/src/styles/theme.css +58 -0
  172. package/src/styles/tokens.css +601 -69
  173. package/src/styles/transitions.css +20 -2
  174. package/src/styles/utilities.css +218 -78
  175. package/src/styles/view-transition.css +51 -0
  176. package/dist/DiscoGlyph-CG0F410s.js +0 -132
  177. package/dist/GlyphFace-DRjDkB0s.js +0 -51
  178. package/dist/UnderlineTabs-Uxn-R3MT.js +0 -39
  179. package/dist/components/custom/aurora/composables/gpuRuntime.d.ts +0 -16
  180. package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +0 -7
  181. package/dist/components/custom/aurora/constants/shaders/painterly.wgsl.d.ts +0 -7
  182. package/dist/components/custom/aurora/constants/shaders/wake.wgsl.d.ts +0 -4
  183. package/dist/components/custom/disco-glyph/DiscoGlyph.vue.d.ts +0 -58
  184. package/dist/components/custom/disco-glyph/index.d.ts +0 -1
  185. package/dist/components/custom/glass-carousel/GlassCarousel.vue.d.ts +0 -36
  186. package/dist/components/custom/glass-carousel/GlassCarouselItem.vue.d.ts +0 -28
  187. package/dist/components/custom/glass-carousel/index.d.ts +0 -4
  188. package/dist/components/custom/glass-carousel/useGlassCarousel.d.ts +0 -30
  189. package/dist/components/custom/glyph-face/GlyphFace.vue.d.ts +0 -64
  190. package/dist/components/custom/glyph-face/index.d.ts +0 -2
  191. package/dist/components/custom/glyph-face/keys.d.ts +0 -9
  192. package/dist/components/custom/responsive-tabs/ResponsiveTabs.vue.d.ts +0 -73
  193. package/dist/components/custom/responsive-tabs/index.d.ts +0 -2
  194. package/dist/components/custom/tabs/BouncyTabs.vue.d.ts +0 -27
  195. package/dist/components/custom/tabs/BouncyToggle.vue.d.ts +0 -60
  196. package/dist/components/custom/tabs/UnderlineTabs.vue.d.ts +0 -20
  197. package/dist/components/custom/tabs/composables/useBouncySlider.d.ts +0 -39
  198. package/dist/composables/glass/createGPUCanvas.d.ts +0 -40
  199. package/dist/disco-glyph.d.ts +0 -1
  200. package/dist/disco-glyph.js +0 -2
  201. package/dist/glass-carousel.d.ts +0 -1
  202. package/dist/glass-carousel.js +0 -219
  203. package/dist/glyph-face.d.ts +0 -1
  204. package/dist/glyph-face.js +0 -3
  205. package/dist/keys-BsYjEFOW.js +0 -9
  206. package/dist/responsive-tabs.d.ts +0 -1
  207. package/dist/responsive-tabs.js +0 -95
  208. package/dist/styles/disco-glyph.css +0 -26
  209. package/dist/styles/glyph-face.css +0 -92
  210. package/dist/vReveal-CqaCz_mC.js +0 -44
  211. package/src/styles/disco-glyph.css +0 -26
  212. package/src/styles/glyph-face.css +0 -92
  213. /package/dist/{DeckProgress-AVgbIULY.js → DeckProgress-Dmk4_AKN.js} +0 -0
  214. /package/dist/{HoverPopover-D56O6Ylp.js → HoverPopover-2LOIW34a.js} +0 -0
  215. /package/dist/{IconTooltip-D2T5nYOM.js → IconTooltip-Cus0fvK0.js} +0 -0
  216. /package/dist/{Input-DVG_J0ne.js → Input-xuDwALQR.js} +0 -0
  217. /package/dist/{ScrollingText-CVyqxvfv.js → ScrollingText-BPP84wKo.js} +0 -0
  218. /package/dist/{color-DMLTunJK.js → color-C5ls_QF7.js} +0 -0
  219. /package/dist/{constants-BPOqYJAm.js → constants-yKeKnE84.js} +0 -0
  220. /package/dist/{presets-D1XPuTj-.js → presets-Dkdv55Gt.js} +0 -0
  221. /package/dist/{prng-COGhh02-.js → prng-D27-B3tK.js} +0 -0
  222. /package/dist/{useGlobalDark-D3EBWzXK.js → useGlobalDark-d6waty-X.js} +0 -0
  223. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Cck5Uxk8.js} +0 -0
  224. /package/dist/{useInterval-CcLfq2WU.js → useInterval-Dsmqwi03.js} +0 -0
  225. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-CyIYrndH.js} +0 -0
  226. /package/dist/{useScrollProgress-C9ysDic5.js → useScrollProgress-CffFGLa5.js} +0 -0
  227. /package/dist/{useSortable-MGAbCGVJ.js → useSortable-C8ReQ50P.js} +0 -0
  228. /package/dist/{useTextHighlight-9nMW23Qb.js → useTextHighlight-CWEi25hf.js} +0 -0
@@ -46,8 +46,15 @@
46
46
 
47
47
  The `.glass-dock` SHELL is OUT of this group BY DESIGN — it hand-rolls a
48
48
  parallel surface (its own `--glass-*-dock` family + a local rim + an
49
- instrument-strip `::before`) the dock arm owns; the dock's catch-light
50
- lives on its CONTROL (`.dock-icon-button`, listed below), not the shell.
49
+ instrument-strip `::before`) the dock arm owns. The COHESION CONSEQUENCE is
50
+ DELIBERATE: the dock shell carries NO shared edge-gleam / moving-specular
51
+ `::before` (its only `::before` is the `variant-instrument-strip` engraved
52
+ bezel, dock/shell.css — a different effect). The dock's catch-light lives on
53
+ its CONTROLS (`.dock-icon-button` et al., listed below + in the opt-in
54
+ transition block), which ARE in the material group — NOT on the shell plate.
55
+ Adding a shell gleam would re-introduce glass-on-glass over the controls, so
56
+ the shell-without-gleam is a NAMED EXEMPTION, gated as `dock-shell-exempt` in
57
+ proof:glass-cohesion (the only exemption beside the legibility allowlist).
51
58
 
52
59
  The selector GROUP is the single source. Adding a surface to the band
53
60
  material is one comma-entry here, not a new opt-in class string. */
@@ -59,7 +66,10 @@
59
66
  .glass-overlay,
60
67
  .glass-card,
61
68
  .glass-specular-track,
62
- .dock-icon-button {
69
+ .dock-icon-button,
70
+ .dock-tab-button,
71
+ .dock-select-trigger,
72
+ .dock-dropdown-trigger {
63
73
  position: relative;
64
74
  }
65
75
 
@@ -85,7 +95,10 @@
85
95
  .glass-overlay::before,
86
96
  .glass-card::before,
87
97
  .glass-specular-track::before,
88
- .dock-icon-button::before {
98
+ .dock-icon-button::before,
99
+ .dock-tab-button::before,
100
+ .dock-select-trigger::before,
101
+ .dock-dropdown-trigger::before {
89
102
  content: "";
90
103
  position: absolute;
91
104
  inset: 0;
@@ -106,32 +119,71 @@
106
119
  longer defeated by a floor. Hover/active lift it through the same
107
120
  cohort (the interaction-light state machine below). */
108
121
  --specular-intensity: var(--glass-specular-intensity-rest, 0);
109
- /* The travelling catch-light — a genuinely WARM-CREAM, low-alpha circular
110
- glow centred on the tracked pointer position (L < 100% so the warm hue
111
- survives — the prior `hsl(40 30% 100%)` was PURE WHITE at L=100%, which
112
- saturated the 30% away and blew out under the screen blend; the
113
- warm-cream the comment claimed never painted). The `--specular-intensity`
114
- multiplier drives the layer `opacity`, not a per-stop alpha (a
122
+ /* AX.W52 D19 — a thin, BOUNDED, pointer-anchored EDGE gleam (not the prior
123
+ full-plate central disc that washed small tiles muddy). The geometry is an
124
+ EXPLICIT-radius circle bounded by `--glass-specular-size` (36% of the
125
+ plate) whose falloff reaches `/0` well INSIDE the plate (70%) — a tracked
126
+ catch-light reading the surface near the lit edge, NEVER a whole-surface
127
+ wash. The core is genuinely WARM-CREAM (L < 100% so the warm hue survives;
128
+ the prior `hsl(40 30% 100%)` blew out to white). The `--specular-intensity`
129
+ multiplier drives the layer `opacity`, NOT a per-stop alpha (a
115
130
  registered-`@property` var() nested in an hsl() alpha computes to 0 in
116
- Chromium); the per-stop alphas here keep the core soft so even the lifted
117
- hover/active states read as a lens, not a flash. */
131
+ Chromium — the cross-engine-safe path); the per-stop alphas are literals so
132
+ even the lifted hover/active states read as a lens, not a flash. */
118
133
  background: radial-gradient(
119
- circle at var(--specular-x, 50%) var(--specular-y, 50%),
120
- hsl(40 30% 96% / 0.22) 0%,
121
- hsl(40 30% 96% / 0.08) 22%,
122
- transparent 55%
134
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
135
+ hsl(40 35% 92% / 0.5) 0%,
136
+ hsl(40 35% 92% / 0) 70%,
137
+ transparent 100%
123
138
  );
124
139
  opacity: var(--specular-intensity, 0);
125
- /* Clip the glow to the plate so it rides the surface. `mask-image`
126
- Baseline 2023-12-07; a non-supporting engine ignores it and the
127
- `inset: 0` + radius-inherit already bound the glow. */
140
+ /* Clip the gleam to ITS OWN radius (not the whole plate) so it stays a
141
+ bounded glint. `mask-image` Baseline 2023-12-07; a non-supporting engine
142
+ ignores it and the `inset: 0` + radius-inherit + the in-paint falloff
143
+ already bound the gleam to the surface. */
128
144
  mask-image: radial-gradient(
129
- circle at var(--specular-x, 50%) var(--specular-y, 50%),
145
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
130
146
  black 0%,
131
- black 55%,
132
- transparent 75%
147
+ black 60%,
148
+ transparent 100%
133
149
  );
134
- mix-blend-mode: screen;
150
+ /* AX.W52 D19 — `plus-lighter` (additive but HDR-clamped, Safari 16.4+) over
151
+ the prior `screen` (a non-linear lightener that lifted the whole tile
152
+ toward white — the muddy-card defect). A non-supporting engine degrades to
153
+ a plain low-alpha warm overlay (the gleam composes normally — no blend, no
154
+ blowout), the no-workaround floor; NOT a `screen` fallback. */
155
+ mix-blend-mode: plus-lighter;
156
+ /* The moving-specular TRANSITION is NOT declared here. An idle/unwired
157
+ `::before` is STATIC (no interpolation track), so a bare glass rung / an
158
+ un-armed Card / a glass Button at rest attaches ZERO animation tracks (the
159
+ keyframes.js runtime counts 0 idle tracks, not 19). The transition rides
160
+ ONLY the WIRED + interactive surfaces — the opt-in scoped block below. */
161
+ }
162
+
163
+ /* AY.W-GLASS — the moving-specular transition is OPT-IN (the Card wire-or-omit
164
+ pattern, generalized). It attaches ONLY to a WIRED surface
165
+ (`.glass-specular-track` — Card emits it conditionally, the dock controls + the
166
+ Slider thumb compose it) OR to any glass surface under `:hover`/`:active` (the
167
+ pointer is present, so the interpolation is legitimately live). An idle/unwired
168
+ `.glass-floating` / `.glass-wash` / bare-rung `::before` carries NO transition
169
+ and thus NO keyframes.js track. The §6 register is PRESERVED (still
170
+ `--ease-standard` on the position-tracked + surface-opacity legs — H-motion §6
171
+ "position-tracked → --ease-standard"; only the SELECTOR scope changes). The dock
172
+ controls keep the always-on transition (they are interactive controls; their rest
173
+ intensity is 0 so they paint nothing at rest, but a control legitimately carries
174
+ the transition). */
175
+ .glass-specular-track::before,
176
+ .glass-material:hover::before, .glass-material:active::before,
177
+ .glass-wash:hover::before, .glass-wash:active::before,
178
+ .glass-quiet:hover::before, .glass-quiet:active::before,
179
+ .glass-resting:hover::before, .glass-resting:active::before,
180
+ .glass-floating:hover::before, .glass-floating:active::before,
181
+ .glass-overlay:hover::before, .glass-overlay:active::before,
182
+ .glass-card:hover::before, .glass-card:active::before,
183
+ .dock-icon-button::before,
184
+ .dock-tab-button::before,
185
+ .dock-select-trigger::before,
186
+ .dock-dropdown-trigger::before {
135
187
  /* Smooth the position + intensity between pointer samples (the typed
136
188
  @property regs make the percentage stops interpolable). */
137
189
  transition:
@@ -148,9 +200,12 @@
148
200
  .dark .glass-overlay::before,
149
201
  .dark .glass-card::before,
150
202
  .dark .glass-specular-track::before,
151
- .dark .dock-icon-button::before {
152
- /* Softer over the deep canvas — the screen blend lifts harder on dark.
153
- The `.dark` magnitude lives in the token cohort (tokens.css §specular-
203
+ .dark .dock-icon-button::before,
204
+ .dark .dock-tab-button::before,
205
+ .dark .dock-select-trigger::before,
206
+ .dark .dock-dropdown-trigger::before {
207
+ /* Softer over the deep canvas — `plus-lighter` still lifts on dark, so the
208
+ `.dark` cohort runs a lower hover/active rung (tokens.css §specular-
154
209
  intensity `.dark` arm); the rest rung is already 0 so the dark arm only
155
210
  softens hover/active via the cohort. The rest rung re-reads the (dark)
156
211
  token here so a dark `:root` override resolves. */
@@ -169,8 +224,11 @@
169
224
  .glass-overlay:hover::before,
170
225
  .glass-card:hover::before,
171
226
  .glass-specular-track:hover::before,
172
- .dock-icon-button:hover::before {
173
- --specular-intensity: var(--glass-specular-intensity-hover, 0.22);
227
+ .dock-icon-button:hover::before,
228
+ .dock-tab-button:hover::before,
229
+ .dock-select-trigger:hover::before,
230
+ .dock-dropdown-trigger:hover::before {
231
+ --specular-intensity: var(--glass-specular-intensity-hover, 0.1);
174
232
  }
175
233
  .glass-material:active::before,
176
234
  .glass-wash:active::before,
@@ -180,8 +238,117 @@
180
238
  .glass-overlay:active::before,
181
239
  .glass-card:active::before,
182
240
  .glass-specular-track:active::before,
183
- .dock-icon-button:active::before {
184
- --specular-intensity: var(--glass-specular-intensity-active, 0.32);
241
+ .dock-icon-button:active::before,
242
+ .dock-tab-button:active::before,
243
+ .dock-select-trigger:active::before,
244
+ .dock-dropdown-trigger:active::before {
245
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
246
+ }
247
+
248
+ /* AX.W45-TUNE C5 — the SELECTED dock control reads as the keyframes-dock glass
249
+ register: a glass-tier active fill (`--dock-control-active-bg` → the floating
250
+ plate, tokens.css) WITH the specular gleam waking over it, not a flat ink
251
+ stamp. The CSS `:active` pseudo above only fires on press-down; a SELECTED tile
252
+ (`.is-active` / `[aria-pressed]` / `[aria-expanded]` / `[aria-current]`) holds
253
+ the gleam lit so the selected element reads as a lit glass tier the substrate
254
+ shows through (the model the user named, `pass-3:13`). Family-scoped addition
255
+ on the dock-control `::before`, line-disjoint from the shared recipe above. */
256
+ .dock-icon-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
257
+ .dock-tab-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
258
+ .dock-select-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
259
+ .dock-dropdown-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before {
260
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
261
+ }
262
+
263
+ /* ── LIQUID by tier — the moving-specular hover catch-light is the
264
+ FLOATING / OVERLAY tier's PROPERTY, not a per-surface wire (D6.c M10) ──────
265
+ The shared `:hover::before` rule above already lifts `--specular-intensity`
266
+ to the hover rung on EVERY material surface, so the catch-light wakes on
267
+ hover library-wide. What this block promotes is the FLOATING / OVERLAY
268
+ tier's identity: a navigation/overlay-band surface (a Dialog, a Sheet, a
269
+ Popover, the dock crest's `.glass-floating`) reads as LIQUID OUT OF THE BOX
270
+ — the catch-light is a tier guarantee, documented here so a consumer reaches
271
+ for `variant="floating"` and inherits the lens without a `useSpecularTracking`
272
+ wire. The pointer-anchored TRACKING still rides `useSpecularTracking` (a
273
+ host can sharpen the lens to the cursor); un-wired, the catch-light sits at
274
+ the centred `50%` fallback and breathes on hover — felt, not garish.
275
+
276
+ The magnitude rides the SAME `--glass-specular-intensity-hover` cohort the
277
+ aurora-calibrated π-ledger judges (tokens.css §specular-intensity), so the
278
+ liquid tier never out-shouts a number — it is the SAME gleam, named as a
279
+ tier default. The OPT-OUT survives: `.glass-no-liquid` on a floating/overlay
280
+ surface pins the rest rung (a flat tier for dense data, the deft escape). */
281
+ .glass-floating:not(.glass-no-liquid),
282
+ .glass-overlay:not(.glass-no-liquid) {
283
+ --glass-liquid: 1; /* the tier carries the liquid identity (informational marker) */
284
+ }
285
+ .glass-floating.glass-no-liquid:hover::before,
286
+ .glass-overlay.glass-no-liquid:hover::before,
287
+ .glass-floating.glass-no-liquid:active::before,
288
+ .glass-overlay.glass-no-liquid:active::before {
289
+ /* The deft escape — a dense-data floating surface that wants a FLAT tier
290
+ pins the catch-light at the clean rest rung even on hover/active. */
291
+ --specular-intensity: var(--glass-specular-intensity-rest, 0);
292
+ }
293
+ @media (prefers-reduced-motion: reduce) {
294
+ /* PRM fence — the liquid tier degrades to the static centred gleam. The
295
+ `useSpecularTracking` write is already PRM-gated (it skips the pointer
296
+ write under reduce); this pins the CSS half (`--specular-x/y: 50%`
297
+ centred) AND kills the position-track `transition` so an un-wired liquid
298
+ tile does NOT animate a travelling catch-light on hover under PRM. The
299
+ gleam may still LIFT on hover (a discrete opacity step, no interpolation
300
+ track) — the correct PRM degrade: no MOTION, the surface still responds.
301
+ This mirrors the shared moving-specular PRM bracket (one static-pin
302
+ convention across the specular cohort). */
303
+ .glass-floating::before,
304
+ .glass-overlay::before {
305
+ --specular-x: 50%;
306
+ --specular-y: 50%;
307
+ transition: none;
308
+ }
309
+ }
310
+
311
+ /* ── The GILT EDGE — `.glass-gilt`, the gilt-tooled glass modifier (D6.c M3/M12) ──
312
+ A fine book's cover is gold-tooled at the EDGE — never a gold fill. The
313
+ modifier composes on ANY tier (the tier is the FROST; the gilt is the
314
+ hairline gold catch on its rim) so a featured card OR the dock crest wears
315
+ the same recipe over its own backdrop. Two box-shadow layers ride INSIDE
316
+ the tier (they do not perturb the tier's own elevation stack — they are
317
+ additive inset rings):
318
+ (1) a 1px inset ring on `--gold-rim` — the tooled gold edge (D6.b lands
319
+ `--gold-rim` = `--gold` at ~40%α over the surface; referenced by name,
320
+ so the gilt resolves the moment the token cohort is minted), and
321
+ (2) a 0.5px gold top-catch highlight — the bevel light reading off the
322
+ upper edge, `--gold-light` at low α so it is a catch, not a band.
323
+ The surface still reads as cream-glass; the gold is the bevel light, the
324
+ SCARCE flourish (the consumption budget — at most one gilt surface per
325
+ route — is the atlas's D7 rule, not enforced here). */
326
+ .glass-gilt {
327
+ box-shadow:
328
+ inset 0 0 0 1px var(--gold-rim, color-mix(in oklab, var(--gold) 40%, transparent)),
329
+ inset 0 0.5px 0 0 color-mix(in oklab, var(--gold-light) 35%, transparent),
330
+ var(--glass-material-rim),
331
+ var(--glass-shadow-floating);
332
+ }
333
+
334
+ /* The liquid-metal CATCH-LIGHT (D6.c M12) — `.glass-gilt` overrides the
335
+ moving-specular `::before` sweep COLOR from warm-cream to GOLD, so the light
336
+ travelling across the gilt edge is golden the way gold leaf catches a warm
337
+ highlight. This is the single richest moment in the platform — gold + liquid
338
+ + specular — and therefore the most scarce (ONE surface ever, the title-page
339
+ flourish; the budget lives in D7). The geometry (bounded circle, the
340
+ `--glass-specular-size` falloff, the `plus-lighter` blend, the mask) is
341
+ INHERITED verbatim from the shared `::before`; only the gradient color stops
342
+ shift to the warm-gold mix. The intensity still rides the `--specular-intensity`
343
+ opacity multiplier (0 at rest), so a resting gilt surface paints NO gold sweep
344
+ — it wakes on hover like every liquid tier. */
345
+ .glass-gilt::before {
346
+ background: radial-gradient(
347
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
348
+ color-mix(in oklab, var(--gold-light) 60%, hsl(40 35% 92%)) 0%,
349
+ hsl(40 35% 92% / 0) 70%,
350
+ transparent 100%
351
+ );
185
352
  }
186
353
 
187
354
  /* ── Five-tier surface ladder (v0.8.0; visual only, no geometry) ──
@@ -273,6 +440,76 @@
273
440
  box-shadow: var(--glass-material-rim), var(--glass-shadow-overlay);
274
441
  }
275
442
 
443
+ /* ── Adaptive legibility: the bright-backdrop bucket (AX.W55 — the iOS-26/27
444
+ "locally darken the glass over light content" move; G2) ──────────────────
445
+ When a consumer sets `--glass-backdrop: light` on any ancestor (a near-white
446
+ card surface, a pale aurora bleed, a bright data grid), the `@container
447
+ style()` read engages here and LIFTS the tint toward ink: `--glass-tint-
448
+ strength` climbs from the `0%` rest default to the bounded AA floor
449
+ (`--glass-tint-strength-aa`, ≤24% — translucent floor preserved) and `--glass-
450
+ tint-source` re-points from `var(--card)` to the warm-ink `--glass-tint-ink`.
451
+ Both are INHERITING custom properties the rungs' `background:` composite
452
+ already reads, so re-pointing them on the material group re-resolves the
453
+ EXISTING `color-mix(in oklab, <rung bg>, …)` toward ink — ZERO new compositing
454
+ seam, the literal darken-over-light recipe. The `.glass-*::before` specular
455
+ `plus-lighter` gleam (W52) is untouched (it composes ON the darkened plate;
456
+ the darkening is the orthogonal oklab-tint axis). No `@supports` wrapper:
457
+ style queries introduce no new `container-type` value (every element is a
458
+ style container by default), so an engine without style-query support parses
459
+ the unknown at-rule as invalid, drops the block, and keeps the zero-delta
460
+ glass (the graceful degradation — the surface is today's-glass, the pre-W55
461
+ state; see utilities.css §density for the same precedent). */
462
+ @container style(--glass-backdrop: light) {
463
+ .glass-material,
464
+ .glass-wash,
465
+ .glass-quiet,
466
+ .glass-resting,
467
+ .glass-floating,
468
+ .glass-overlay,
469
+ .glass-card {
470
+ --glass-tint-source: var(--glass-tint-ink);
471
+ --glass-tint-strength: var(--glass-tint-strength-aa);
472
+ }
473
+ }
474
+
475
+ /* AX.W55 — the `contrast-color()` foreground-ink flip (Chrome 147+/Safari 26+).
476
+ A PROGRESSIVE-ENHANCEMENT layer, NEVER the load-bearing floor (Open-Q #5
477
+ ratified): the declarative bucket above already carries AA on ALL engines (it
478
+ darkens the translucent plate so dark text clears ~11:1 over white at the 18%
479
+ floor — the live π readback ratifies). On a supporting engine `contrast-color()`
480
+ REFINES the foreground-ink pick natively, anchored on the LIGHT BACKDROP signal
481
+ (`--card`, the warm-white surface base the bright bucket implies) — NOT on the
482
+ ink. `contrast-color(var(--card))` over the light backdrop resolves to the
483
+ maximally-legible DARK ink (anchoring on the dark ink instead would invert to
484
+ white, illegible on the still-light translucent plate). The bucket is the floor;
485
+ this is the native refinement. Scoped to the bright bucket. */
486
+ @supports (color: contrast-color(white)) {
487
+ @container style(--glass-backdrop: light) {
488
+ .glass-material,
489
+ .glass-wash,
490
+ .glass-quiet,
491
+ .glass-resting,
492
+ .glass-floating,
493
+ .glass-overlay,
494
+ .glass-card {
495
+ color: contrast-color(var(--card));
496
+ }
497
+ }
498
+ }
499
+
500
+ /* ── The opaque escape (AX.W54) ───────────────────
501
+ The level-0 endpoint of the SAME glass machinery — a solid `--card` plate
502
+ (the opacity seam → 1) with `blur(0)` (the blur seam → 0), routed through
503
+ the ONE `--glass-level` knob. NOT a parallel solid `background:` recipe:
504
+ a `.glass-*` surface that ALSO carries `.glass-opaque` keeps its glass edge,
505
+ rim, and under-shadow (a solid plate with a glass edge, not a bare div), and
506
+ the @supports fallback + the a11y brackets compose coherently. This is the
507
+ explicit opt-out from the MAXIMAL glass default (dense data, forced-colors,
508
+ a consumer that wants a flat surface). */
509
+ .glass-opaque {
510
+ --glass-level: 0;
511
+ }
512
+
276
513
  /* ── Content-aware under-shadow modifier (AV.W15 M4) ──────────────
277
514
  Apple raises the under-shadow over text (so the glass reads as
278
515
  lifting OFF the text) and drops it over solid light. The modifier
@@ -322,7 +559,10 @@
322
559
  background: var(--paper-clean-texture);
323
560
  background-repeat: repeat;
324
561
  background-size: var(--paper-texture-size);
325
- opacity: var(--glass-grain-opacity);
562
+ /* D6.c M5 — the grain rung lifted off the dead 0.025 floor to a felt-but-
563
+ deft 0.038 (the page rung; the kitsch ceiling is ~0.05). The canonical
564
+ token still wins; this is the felt floor a no-override mount inherits. */
565
+ opacity: var(--glass-grain-opacity, 0.038);
326
566
  pointer-events: none;
327
567
  mix-blend-mode: overlay;
328
568
  }
@@ -405,11 +645,17 @@
405
645
  background: var(--glass-bg-wash);
406
646
  backdrop-filter: var(--glass-blur-wash);
407
647
  color: var(--muted-foreground);
648
+ /* AX.W52 §6 doctrine — the surface legs ride the bezier `--ease-standard`;
649
+ the `scale` leg is reconciled onto `--spring-smooth` (was `--spring-snappy`)
650
+ so the icon-button hover settles on the SAME ONE register as `.btn-pill` /
651
+ `.tap-squish` / `btn-interactive` (the gate asserts one scale register
652
+ across all four). The press still reads crisp — `--spring-smooth` ζ=0.86
653
+ settles fast without a visible bounce. */
408
654
  transition:
409
655
  background var(--duration-fast) var(--ease-standard),
410
656
  border-color var(--duration-fast) var(--ease-standard),
411
657
  color var(--duration-fast) var(--ease-standard),
412
- scale var(--duration-normal) var(--spring-snappy);
658
+ scale var(--duration-normal) var(--spring-smooth);
413
659
  }
414
660
 
415
661
  .glass-btn:hover:not(:disabled) {
@@ -445,17 +691,40 @@
445
691
  .btn-pill {
446
692
  @apply inline-flex items-center justify-center cursor-pointer font-medium border-none;
447
693
 
448
- gap: 0.375rem;
694
+ /* AX.W52 §6 identity base — `scale: 1` at rest so the hover/press scale
695
+ below animates the `scale` longhand (not `transform`) coherently and
696
+ does not flicker the stacking context into being (AQ.W3 §W3.2). */
697
+ scale: 1;
698
+ /* AX.W51 D18 — the pill GEOMETRY rides the ONE `--ui-scale` comfort axis.
699
+ gap / padding scale by the master scalar; the font reads the
700
+ `--control-text` register (`calc(--type-small * --ui-scale)`, the same
701
+ `text-sm` register the Button CVA paints), so a bare `.btn-pill` consumer
702
+ and a `<Button>` agree on the control font, and ONE `--ui-scale` override
703
+ grows the pill's height (via padding) + gap + font in lockstep. Desktop
704
+ default is the identity (scale 1 → the prior proportion). */
705
+ gap: calc(0.375rem * var(--ui-scale));
449
706
  border-radius: var(--radius-pill);
450
- padding: 0.5rem 1rem;
451
- font-size: 1rem;
707
+ padding: calc(0.5rem * var(--ui-scale)) calc(1rem * var(--ui-scale));
708
+ font-size: var(--control-text);
709
+ /* AX.W52 — the ONE coherent button transition (RED witness 5/6). The
710
+ SURFACE legs (bg/border/box-shadow/color/opacity) ride the bezier
711
+ `--ease-standard` (a colour cross-fade reads as a wobble on a spring);
712
+ the TRANSFORM leg (`scale`) rides `--spring-smooth` (the sub-perceptual
713
+ settle), so the hover lift + the surface cross-fade read as ONE glide.
714
+ The DEAD `transform` leg is retired — the variants animate the `scale`
715
+ longhand. CRITICAL: `.tap-squish` (composed alongside on the button
716
+ base, utilities.css) ALSO lists this full coherent set, so neither
717
+ class's `transition` shorthand can clobber the other down to a
718
+ scale-only animation — the cascade bug that left every button
719
+ transitioning ONLY `scale` (the live-readback RED, RED witness 5). The
720
+ doctrine: surface-props→bezier, transform→spring (tokens.css §2). */
452
721
  transition:
453
722
  background-color var(--duration-fast) var(--ease-standard),
454
723
  border-color var(--duration-fast) var(--ease-standard),
455
724
  box-shadow var(--duration-fast) var(--ease-standard),
456
725
  color var(--duration-fast) var(--ease-standard),
457
726
  opacity var(--duration-fast) var(--ease-standard),
458
- transform var(--duration-fast) var(--ease-standard);
727
+ scale var(--duration-fast) var(--spring-smooth);
459
728
  }
460
729
 
461
730
  .btn-pill > * {
@@ -469,23 +738,52 @@
469
738
  pointer-events: none;
470
739
  }
471
740
 
741
+ /* ── Glass-button backdrop ─────────────────────────────────────────────
742
+ AX.W52 — the `glass`/`glass-wash` Button variants compose `.glass-wash`,
743
+ which resolves `--glass-blur-wash` = `blur(1px)` — a sub-perceptual
744
+ diffusion authored for a small detail TILE, not a button the user reads
745
+ as "glass" (the live readback found the glass variants at a negligible
746
+ 1px). A hero control wants a real glass blur. `.btn-glass` re-points the
747
+ backdrop at `--glass-blur-btn` (the `quiet`-tier 10px radius + the gentle
748
+ `saturate(1.05) brightness(1.02)` light-concentration), so the glass
749
+ button variants actually read as liquid glass while the wash TILE tier
750
+ keeps its 1px untouched. Declares the UNPREFIXED `backdrop-filter` ONLY —
751
+ Lightning CSS emits the `-webkit-` companion per the single-source
752
+ authorship discipline above (hand-authoring both forms makes Lightning
753
+ dedup-and-keep-prefixed, which modern Chromium then drops). */
754
+ .btn-glass {
755
+ backdrop-filter: var(--glass-blur-btn);
756
+ }
757
+
472
758
  /* ── Pill input ───────────────────────────────── */
473
759
  .input-pill {
474
760
  @apply flex w-full;
475
761
 
476
- height: 2.5rem;
762
+ /* AX.W51 D18 — the input pill rides the ONE `--ui-scale` comfort axis: the
763
+ height reads the `--control-h-md` cohort (`max(calc(2.5rem * --ui-scale),
764
+ --control-floor)`, the h-10 register with the WCAG-44px coarse clamp), the
765
+ font reads `--control-text`, the inline padding scales — so ONE override
766
+ grows the field's height + padding + font in lockstep. Desktop default is
767
+ the identity. */
768
+ height: var(--control-h-md);
477
769
  border-radius: var(--radius-pill);
478
- /* AW.W13 — the resting field edge reads as an enclosed control at rest.
479
- Was `--glass-border-wash` (~8%α), which nearly vanished on cream; the
480
- lift to `--surface-tint-15` (15%α — ~2× the prior floor) makes the
481
- edge legible without going loud. The `:focus-visible` accent ring +
482
- the `:user-invalid`/`[aria-invalid]` destructive ring below still win
483
- by order + specificity, so this only raises the resting alpha. */
484
- border: 1.5px solid var(--surface-tint-15);
770
+ /* AW.W13 — the resting field edge reads as an enclosed control at rest
771
+ (~15%α — ~2× the prior 8% glass-wash floor that vanished on cream). The
772
+ `:focus-visible` accent ring + the `:user-invalid`/`[aria-invalid]`
773
+ destructive ring below still win by order + specificity.
774
+ AX.W54 — moved off the srgb `--surface-tint-15` fork onto the glass
775
+ border seam (`--glass-border-floating`, the matching 15%α rung) so the
776
+ pill is ONE glass model with the rest of the ladder, not a divergent
777
+ tint axis. */
778
+ border: 1.5px solid var(--glass-border-floating);
485
779
  background: var(--glass-bg-quiet);
486
- backdrop-filter: var(--glass-blur-wash);
487
- padding: 0 1rem;
488
- font-size: 1rem;
780
+ /* AX.W54 — the pill reads as REAL glass: the quiet-tier 10px blur (the
781
+ same `--glass-blur-quiet` its `--glass-bg-quiet` background pairs with),
782
+ not the sub-perceptual `blur(1px)` wash it carried — and the
783
+ `--glass-level` knob now clarifies it in lockstep with every surface. */
784
+ backdrop-filter: var(--glass-blur-quiet);
785
+ padding: 0 calc(1rem * var(--ui-scale));
786
+ font-size: var(--control-text);
489
787
  color: var(--foreground);
490
788
  transition:
491
789
  background-color var(--duration-fast) var(--ease-standard),
@@ -664,50 +962,209 @@
664
962
  }
665
963
  }
666
964
 
667
- /* ── AW.W23 — corner-shape: squircle PE (Chrome 139+) ───────────────────────
668
- The literal iOS-26 superellipse corner geometry that `backdrop-filter`,
669
- borders, and shadows follow. `@supports (corner-shape: squircle)`-gated over
670
- the un-gated `border-radius` round, which stays the fallback at zero cost on
671
- every other engine (Safari/Firefox). The `corner-shape` decl sits ONLY inside
672
- the `@supports` block — a leak onto the un-gated base would break the round
673
- fallback on a partial-support engine. */
674
- @supports (corner-shape: squircle) {
675
- @layer components {
676
- .glass-card,
677
- .glass-btn,
678
- .btn-pill {
679
- corner-shape: squircle;
965
+ /* ── AX.W56 — the rounded-vs-squircle POLICY (re-homes AW.W23's squircle) ─────
966
+ Cards, glass buttons, and pills stay ROUND. The earlier AW.W23 block applied
967
+ `corner-shape: squircle` to `.glass-card`/`.glass-btn`/`.btn-pill`, which
968
+ inverted the design intent — the superellipse is imperceptible at a 16px card
969
+ radius or a stadium pill, so the squircle on those surfaces was visual cost
970
+ without read. The squircle is RE-HOMED onto the one surface where it reads: the
971
+ big-dock card shell (`dock.css` → `var(--corner-shape-bigdock)` under
972
+ `@supports (corner-shape: superellipse(2))`). This is a clean break — no alias,
973
+ no `--corner-shape-card` decl here (it resolves `round`, the default, so a
974
+ `corner-shape` rule would be a no-op). The `--corner-shape-*` token axis lives
975
+ in `theme.css`; a consumer who WANTS a squircle card opts in by re-pointing
976
+ `--corner-shape-card` at `superellipse(var(--corner-k-squircle))`. Do NOT
977
+ re-add a squircle rule to the card/button/pill surfaces — they are round by
978
+ policy. */
979
+
980
+ /* ── AX.W56(R1) — squircle coupling onto the overlay-band glass surfaces ───────
981
+ W54 makes GLASS the default for the Dialog + Sheet content surfaces; W56 couples
982
+ the SQUIRCLE onto them too. Both ride `.glass-floating` at the large
983
+ `--radius-dialog` (16px) modal radius where the superellipse READS — the same
984
+ iOS-26 idiom the big-dock card shell carries. The compound selectors scope the
985
+ shape to the dialog/sheet content ONLY (the `.rounded-dialog` class the
986
+ DialogContent surface composes, the `.sheet-animate` class the SheetContent
987
+ surface composes via `sheetVariants`) so it never leaks onto a bare
988
+ `.glass-floating` panel. Mirrors the big-dock idiom EXACTLY: an `@supports`-
989
+ gated ENHANCEMENT (Chrome 139+, no FF/Safari 2026) over the `border-radius`
990
+ round CONTRACT — the squircle is the better tier, NOT a degraded fallback. The
991
+ shape is the tokenized `var(--corner-shape-{dialog,sheet})` (theme.css) so it is
992
+ as overridable as the radius; a consumer dials either back to round by
993
+ re-pointing the alias. The `@supports` condition tests the LITERAL
994
+ `superellipse(2)` (a `var()` is not evaluable in an `@supports` query) — the same
995
+ Chrome-139 feature the token resolves to. */
996
+ @layer components {
997
+ @supports (corner-shape: superellipse(2)) {
998
+ .glass-floating.rounded-dialog {
999
+ corner-shape: var(--corner-shape-dialog);
1000
+ }
1001
+ .glass-floating.sheet-animate {
1002
+ corner-shape: var(--corner-shape-sheet);
680
1003
  }
681
1004
  }
682
1005
  }
683
1006
 
684
- /* ── Accessibility: reduced transparency ────────── */
1007
+ /* ── Accessibility: reduced transparency ──────────
1008
+ AX.W54 — the gestalt collapse: ONE `--glass-level: 0` replaces the ten per-rung
1009
+ opacity+blur clobbers. The level-0 path resolves solid `--card` + `blur(0)`
1010
+ through the SAME machinery (the opacity seam → 1, the blur seam → 0), so every
1011
+ glass surface — current and future — flattens with no per-rung enumeration. The
1012
+ grain + highlight kills stay (they sit off the level axis). */
685
1013
  @media (prefers-reduced-transparency: reduce) {
686
1014
  :root {
687
- --glass-opacity-wash: 1;
688
- --glass-opacity-quiet: 1;
689
- --glass-opacity-resting: 1;
690
- --glass-opacity-floating: 1;
691
- --glass-opacity-overlay: 1;
692
- --glass-blur-wash: none;
693
- --glass-blur-quiet: none;
694
- --glass-blur-resting: none;
695
- --glass-blur-floating: none;
696
- --glass-blur-overlay: none;
697
- --glass-blur-dock: none;
1015
+ --glass-level: 0;
698
1016
  --glass-grain-opacity: 0;
699
1017
  --glass-highlight: 0 0 0 0 transparent;
700
1018
  }
701
1019
  }
702
1020
 
703
- /* ── Accessibility: high contrast ───────────────── */
1021
+ /* ── Accessibility: high contrast ─────────────────
1022
+ AX.W54 — a single bounded `--glass-level: 0.3` (mostly-solid, not fully flat)
1023
+ replaces the five per-rung opacity clobbers: every rung firms up toward solid
1024
+ for AA while keeping a hint of the glass register. ONE knob, every rung.
1025
+
1026
+ AX.W55 — the Clear↔Tinted user-escape (Apple's iOS-26.2 analog) COORDINATES the
1027
+ two axes here: the OPACITY axis rides W54's `--glass-level` (firm up toward solid)
1028
+ AND the TINT axis biases toward ink — `--glass-tint-source` → the warm-ink +
1029
+ `--glass-tint-strength` → the AA floor, the same darken the automatic bright
1030
+ bucket applies, now reached by the explicit "more contrast" user request. The two
1031
+ axes stay DISTINCT (level = opacity+blur, tint = darken) but share the bracket so
1032
+ a high-contrast user gets BOTH a firmer plate and the ink-tint legibility lift —
1033
+ one coordinated escape, not two parallel forks. */
704
1034
  @media (prefers-contrast: more) {
705
1035
  :root {
706
- --glass-opacity-wash: 0.85;
707
- --glass-opacity-quiet: 0.90;
708
- --glass-opacity-resting: 0.94;
709
- --glass-opacity-floating: 0.98;
710
- --glass-opacity-overlay: 1;
1036
+ --glass-level: 0.3;
1037
+ --glass-tint-source: var(--glass-tint-ink);
1038
+ --glass-tint-strength: var(--glass-tint-strength-aa);
1039
+ }
1040
+ }
1041
+
1042
+ /* ── Accessibility: forced-colors (Windows High Contrast) glass-language skin ──
1043
+ AX.W36 — when the OS forces a palette (Windows High Contrast), the platform
1044
+ strips the whole decorative glass register: `backdrop-filter` is dropped, the
1045
+ `--glass-*` inset/box-shadow rungs vanish, and every meaning-bearing chroma
1046
+ flattens to one system color. A `.glass-floating` Dialog over a `.glass-resting`
1047
+ Card would read as two borderless transparent rectangles with no edge, and a
1048
+ green-vs-red StatusDot would resolve to one indistinguishable dot. This skin
1049
+ restores the STRUCTURE the glass chrome encoded — it does NOT pin glass-ui's
1050
+ brand colours (no `forced-color-adjust: none`); the chrome is decorative and
1051
+ YIELDS to the user's forced palette (css forced-colors guidance). Only the
1052
+ standard WHC system keywords are used (`Canvas`/`CanvasText`/`Highlight`) — no
1053
+ glass-ui token leaks into the WHC arm.
1054
+
1055
+ COORDINATES WITH W54 — the same `--glass-level: 0` opaque escape the reduced-
1056
+ transparency / high-contrast brackets ride. Setting the ONE clarity knob to 0
1057
+ collapses the `--glass-bg-*` opacity recipe to solid `--card` + `blur(0)` through
1058
+ the SAME machinery (no parallel solid recipe), so the platform sees opaque plates
1059
+ it maps to `Canvas`. The grain + highlight kills match the reduce bracket (they
1060
+ sit off the level axis). The W55 tint axis is moot under WHC (the user's palette
1061
+ supersedes the ink-darken) but harmless — the opaque plate is system-painted. */
1062
+ @media (forced-colors: active) {
1063
+ :root {
1064
+ --glass-level: 0;
1065
+ --glass-grain-opacity: 0;
1066
+ --glass-highlight: 0 0 0 0 transparent;
1067
+ }
1068
+
1069
+ /* Every glass-material ladder rung relied on `backdrop-filter` + an inset
1070
+ `box-shadow` rim for its silhouette — both gone under WHC. Restore a real
1071
+ `border` keyed to the system text colour so each tier pane reads as a boxed
1072
+ region. The selector group MIRRORS the ladder definition above (one source,
1073
+ not a hand-rolled re-list) so a future rung added to the material group
1074
+ inherits the WHC edge for free — and a `.glass-material` div that became one
1075
+ via the GlassPanel retire gets the edge with no per-component arm. */
1076
+ .glass-material,
1077
+ .glass-wash,
1078
+ .glass-quiet,
1079
+ .glass-resting,
1080
+ .glass-floating,
1081
+ .glass-overlay,
1082
+ .glass-card,
1083
+ .glass-drawer {
1084
+ border: 1px solid CanvasText;
1085
+ }
1086
+
1087
+ /* The floating + overlay rungs (Dialog / Sheet / Popover / DropdownMenu /
1088
+ HoverCard compose them) + the Drawer (the overlay-band sheet, drawer.css)
1089
+ get the canonical `Canvas` fill so the modal reads as a DISTINCT boxed
1090
+ region OVER the page, not a transparent overlap — the hierarchy survives.
1091
+ The `CanvasText` edge above already draws the box; this opaque fill
1092
+ separates the floating layer from the content beneath it. */
1093
+ .glass-floating,
1094
+ .glass-overlay,
1095
+ .glass-drawer {
1096
+ background: Canvas;
1097
+ }
1098
+
1099
+ /* The decorative specular catch-light (`::before`) + grain overlay (`::after`)
1100
+ paint nothing meaningful once chroma collapses — yield them entirely (the
1101
+ same decorative-chrome cede the `--glass-level: 0` opaque escape performs on
1102
+ the body). They are NOT part of the structure the skin restores. */
1103
+ .glass-material::before,
1104
+ .glass-wash::before,
1105
+ .glass-quiet::before,
1106
+ .glass-resting::before,
1107
+ .glass-floating::before,
1108
+ .glass-overlay::before,
1109
+ .glass-card::before,
1110
+ .glass-drawer::before,
1111
+ .glass-wash::after,
1112
+ .glass-quiet::after,
1113
+ .glass-resting::after,
1114
+ .glass-floating::after,
1115
+ .glass-overlay::after {
1116
+ display: none;
1117
+ }
1118
+
1119
+ /* Meaning-bearing hue identity → a bordered glyph that keeps ok/warn/error
1120
+ distinguishable by a WHC-HONORED system color, NOT a glass-ui hue (which WHC
1121
+ strips to one fill). StatusDot reflects its variant onto `data-status`
1122
+ (StatusDot.vue) and the inner dot carries `.status-dot__dot`; the
1123
+ `role="img"` + `aria-label` accessible name already ships, so this is the
1124
+ VISUAL differentiation only. A bare bordered dot + the per-status fill triplet
1125
+ below means a sighted WHC user can still tell the row apart.
1126
+
1127
+ `!important` IS load-bearing here: StatusDot paints the dot fill via an INLINE
1128
+ `:style="dotStyle"` (`background-color`, specificity 1,0,0,0), which outranks
1129
+ any stylesheet selector AND which forced-colors then `forced-color-adjust:
1130
+ auto`-remaps to a single Canvas-white — collapsing the row to one indistinct
1131
+ dot. The WHC arm must override that inline fill, and inline can only be beaten
1132
+ by `!important`; this is the documented forced-colors degradation path (the
1133
+ arm only activates under WHC). The component keeps its inline hue in normal
1134
+ mode untouched. */
1135
+ .status-dot__dot {
1136
+ border: 1px solid CanvasText;
1137
+ /* The bordered ring alone separates a dot from its surround; the per-status
1138
+ fill below adds the WHC-honored distinction. */
1139
+ }
1140
+ /* The inner painted fill (`.status-dot__fill`, `h-full w-full`) + the pulse ring
1141
+ carry the SAME inline glass-ui hue StatusDot paints — under WHC they cover the
1142
+ outer `.status-dot__dot` glyph with a `forced-color-adjust`-remapped Canvas
1143
+ fill (the row collapses to one white dot even with the outer system color set).
1144
+ Yield them so the outer bordered + system-color glyph is the sole visible dot. */
1145
+ .status-dot__fill,
1146
+ .status-dot__pulse {
1147
+ display: none;
1148
+ }
1149
+ /* The ok/warn/error/idle distinction rides the standard WHC keyword palette:
1150
+ active (ok) → Highlight (the affirmative system accent)
1151
+ paused (warn) → Mark (the marked/attention system color)
1152
+ error → CanvasText (a solid filled dot — the strongest weight)
1153
+ idle/custom → Canvas (a hollow dot — only the CanvasText ring reads)
1154
+ Each stays distinguishable by the system color the user's palette assigns,
1155
+ never glass-ui chroma. The `!important` beats the component's inline fill. */
1156
+ .status-dot__dot[data-status="active"] {
1157
+ background: Highlight !important;
1158
+ }
1159
+ .status-dot__dot[data-status="paused"] {
1160
+ background: Mark !important;
1161
+ }
1162
+ .status-dot__dot[data-status="error"] {
1163
+ background: CanvasText !important;
1164
+ }
1165
+ .status-dot__dot[data-status="idle"],
1166
+ .status-dot__dot[data-status="custom"] {
1167
+ background: Canvas !important;
711
1168
  }
712
1169
  }
713
1170