@mkbabb/glass-ui 3.8.0 → 3.9.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 (164) 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/{NumberFieldContent-CLNVR1iY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  8. package/dist/{SelectScrollDownButton-C7TRe-ep.js → SelectScrollDownButton-T32cVFeM.js} +3 -3
  9. package/dist/{SelectSeparator-L8pPEn4L.js → SelectSeparator-C4Ql0gzV.js} +1 -1
  10. package/dist/{TabsList-qyHZ2lKY.js → TabsList-B8CVOQPC.js} +2 -2
  11. package/dist/{Toaster-CabYEEF_.js → Toaster-1rYWrmAm.js} +1 -1
  12. package/dist/{ToggleGroupItem-CkXUcBlt.js → ToggleGroupItem-Cev4pOVK.js} +4 -4
  13. package/dist/animated-digit.js +1 -1
  14. package/dist/api/index.d.ts +1 -1
  15. package/dist/api.js +1 -1
  16. package/dist/aurora.js +10 -10
  17. package/dist/{badge-DHQrc_GQ.js → badge-BvwvT50i.js} +4 -4
  18. package/dist/badge.js +1 -1
  19. package/dist/{button-CAywcrhO.js → button-DN39cGqL.js} +13 -12
  20. package/dist/button.js +1 -1
  21. package/dist/card.js +1 -1
  22. package/dist/carousel.js +1 -1
  23. package/dist/color.js +1 -1
  24. package/dist/command.js +1 -1
  25. package/dist/{compile-BBTRjvQS.js → compile-DAjIoEy2.js} +1 -1
  26. package/dist/components/custom/configurator/ConfiguratorLayer.vue.d.ts +1 -1
  27. package/dist/components/custom/dock/DockSeparator.vue.d.ts +3 -0
  28. package/dist/components/custom/dock/GlassDock.vue.d.ts +45 -63
  29. package/dist/components/custom/dock/composables/dockContext.d.ts +7 -0
  30. package/dist/components/custom/dock/index.d.ts +2 -1
  31. package/dist/components/custom/goo-blob/composables/useBlobMood.d.ts +19 -5
  32. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +92 -0
  33. package/dist/components/custom/tabs/composables/useTabIndicator.d.ts +49 -0
  34. package/dist/components/custom/tabs/index.d.ts +2 -5
  35. package/dist/components/ui/button/index.d.ts +1 -1
  36. package/dist/components/ui/card/Card.vue.d.ts +5 -3
  37. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  38. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  39. package/dist/components/ui/carousel/GlassCarouselPager.vue.d.ts +3 -4
  40. package/dist/components/ui/slider/index.d.ts +14 -7
  41. package/dist/components/ui/tabs/TabsList.vue.d.ts +1 -1
  42. package/dist/composables/context/createContext.d.ts +1 -1
  43. package/dist/configurator.js +1 -1
  44. package/dist/confirm-dialog.js +1 -1
  45. package/dist/constellation.js +1 -1
  46. package/dist/context-menu.js +1 -1
  47. package/dist/controls.js +1 -1
  48. package/dist/dark.js +1 -1
  49. package/dist/data-table.js +1 -1
  50. package/dist/deck-progress.js +1 -1
  51. package/dist/dialog.js +1 -1
  52. package/dist/dock.js +256 -243
  53. package/dist/{dropdown-menu-B_4bWyyG.js → dropdown-menu-D77jX6Df.js} +3 -3
  54. package/dist/dropdown-menu.js +1 -1
  55. package/dist/expandable-container.js +1 -1
  56. package/dist/forms.js +5 -5
  57. package/dist/fourier-field.js +3 -3
  58. package/dist/glass-ui.css +1 -1
  59. package/dist/glass-ui.js +101 -104
  60. package/dist/goo-blob.js +36 -32
  61. package/dist/hover-popover.js +1 -1
  62. package/dist/icon-tooltip.js +1 -1
  63. package/dist/index.d.ts +0 -2
  64. package/dist/keyboard.js +1 -1
  65. package/dist/labeled-field.js +4 -4
  66. package/dist/{menuItemVariants-DKM85SNE.js → menuItemVariants-CCoBNkU5.js} +1 -1
  67. package/dist/motion-core.js +4 -4
  68. package/dist/motion.js +2 -2
  69. package/dist/number-field.js +1 -1
  70. package/dist/pulse.js +1 -1
  71. package/dist/reactive.js +1 -1
  72. package/dist/scrolling-text.js +1 -1
  73. package/dist/search.js +4 -4
  74. package/dist/select.js +2 -2
  75. package/dist/{slider-D9puf-Ko.js → slider-DC2mwuoe.js} +1 -1
  76. package/dist/slider.js +1 -1
  77. package/dist/sortable-list.js +1 -1
  78. package/dist/status-dot.js +17 -16
  79. package/dist/styles/animations.css +6 -2
  80. package/dist/styles/components.css +1 -1
  81. package/dist/styles/dock/density.css +230 -0
  82. package/dist/styles/dock/layer-group.css +263 -0
  83. package/dist/styles/dock/layers.css +355 -0
  84. package/dist/styles/dock/morph.css +244 -0
  85. package/dist/styles/dock/overflow.css +201 -0
  86. package/dist/styles/dock/shell.css +457 -0
  87. package/dist/styles/dock-controls.css +166 -32
  88. package/dist/styles/dock.css +42 -1349
  89. package/dist/styles/glass.css +396 -75
  90. package/dist/styles/index.css +12 -11
  91. package/dist/styles/theme.css +51 -0
  92. package/dist/styles/tokens.css +501 -55
  93. package/dist/styles/utilities.css +89 -39
  94. package/dist/tabs.js +182 -151
  95. package/dist/timeline.js +1 -1
  96. package/dist/toast.js +1 -1
  97. package/dist/toggle-group.js +1 -1
  98. package/dist/{useAnimatedNumber-C_3wZLx4.js → useAnimatedNumber-C5I3wWd8.js} +1 -1
  99. package/dist/{useConfiguratorState-CMff4GzH.js → useConfiguratorState-DxAqksK6.js} +21 -10
  100. package/dist/watercolor-dot.js +1 -1
  101. package/package.json +32 -33
  102. package/src/styles/animations.css +6 -2
  103. package/src/styles/dock/density.css +230 -0
  104. package/src/styles/dock/layer-group.css +263 -0
  105. package/src/styles/dock/layers.css +355 -0
  106. package/src/styles/dock/morph.css +244 -0
  107. package/src/styles/dock/overflow.css +201 -0
  108. package/src/styles/dock/shell.css +457 -0
  109. package/src/styles/dock-controls.css +166 -32
  110. package/src/styles/dock.css +42 -1349
  111. package/src/styles/glass.css +396 -75
  112. package/src/styles/index.css +12 -11
  113. package/src/styles/theme.css +51 -0
  114. package/src/styles/tokens.css +501 -55
  115. package/src/styles/utilities.css +89 -39
  116. package/dist/DiscoGlyph-CG0F410s.js +0 -132
  117. package/dist/GlyphFace-DRjDkB0s.js +0 -51
  118. package/dist/UnderlineTabs-Uxn-R3MT.js +0 -39
  119. package/dist/components/custom/aurora/constants/shaders/painterly.wgsl.d.ts +0 -7
  120. package/dist/components/custom/aurora/constants/shaders/wake.wgsl.d.ts +0 -4
  121. package/dist/components/custom/disco-glyph/DiscoGlyph.vue.d.ts +0 -58
  122. package/dist/components/custom/disco-glyph/index.d.ts +0 -1
  123. package/dist/components/custom/glass-carousel/GlassCarousel.vue.d.ts +0 -36
  124. package/dist/components/custom/glass-carousel/GlassCarouselItem.vue.d.ts +0 -28
  125. package/dist/components/custom/glass-carousel/index.d.ts +0 -4
  126. package/dist/components/custom/glass-carousel/useGlassCarousel.d.ts +0 -30
  127. package/dist/components/custom/glyph-face/GlyphFace.vue.d.ts +0 -64
  128. package/dist/components/custom/glyph-face/index.d.ts +0 -2
  129. package/dist/components/custom/glyph-face/keys.d.ts +0 -9
  130. package/dist/components/custom/responsive-tabs/ResponsiveTabs.vue.d.ts +0 -73
  131. package/dist/components/custom/responsive-tabs/index.d.ts +0 -2
  132. package/dist/components/custom/tabs/BouncyTabs.vue.d.ts +0 -27
  133. package/dist/components/custom/tabs/BouncyToggle.vue.d.ts +0 -60
  134. package/dist/components/custom/tabs/UnderlineTabs.vue.d.ts +0 -20
  135. package/dist/components/custom/tabs/composables/useBouncySlider.d.ts +0 -39
  136. package/dist/disco-glyph.d.ts +0 -1
  137. package/dist/disco-glyph.js +0 -2
  138. package/dist/glass-carousel.d.ts +0 -1
  139. package/dist/glass-carousel.js +0 -219
  140. package/dist/glyph-face.d.ts +0 -1
  141. package/dist/glyph-face.js +0 -3
  142. package/dist/keys-BsYjEFOW.js +0 -9
  143. package/dist/responsive-tabs.d.ts +0 -1
  144. package/dist/responsive-tabs.js +0 -95
  145. package/dist/styles/disco-glyph.css +0 -26
  146. package/dist/styles/glyph-face.css +0 -92
  147. package/src/styles/disco-glyph.css +0 -26
  148. package/src/styles/glyph-face.css +0 -92
  149. /package/dist/{DeckProgress-AVgbIULY.js → DeckProgress-Dmk4_AKN.js} +0 -0
  150. /package/dist/{HoverPopover-D56O6Ylp.js → HoverPopover-2LOIW34a.js} +0 -0
  151. /package/dist/{IconTooltip-D2T5nYOM.js → IconTooltip-yefK7cJc.js} +0 -0
  152. /package/dist/{Input-DVG_J0ne.js → Input-DWQQIOC4.js} +0 -0
  153. /package/dist/{ScrollingText-CVyqxvfv.js → ScrollingText-BPP84wKo.js} +0 -0
  154. /package/dist/{color-DMLTunJK.js → color-8jBjWiJ6.js} +0 -0
  155. /package/dist/{constants-BPOqYJAm.js → constants-CS75AWHG.js} +0 -0
  156. /package/dist/{presets-D1XPuTj-.js → presets-BKVyQfbt.js} +0 -0
  157. /package/dist/{prng-COGhh02-.js → prng-wHuHlNHE.js} +0 -0
  158. /package/dist/{useGlobalDark-D3EBWzXK.js → useGlobalDark-yhL4Wp-s.js} +0 -0
  159. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Cc-H9ees.js} +0 -0
  160. /package/dist/{useInterval-CcLfq2WU.js → useInterval-Dsmqwi03.js} +0 -0
  161. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-Be3w_Rwk.js} +0 -0
  162. /package/dist/{useScrollProgress-C9ysDic5.js → useScrollProgress-CAH8Ofwt.js} +0 -0
  163. /package/dist/{useSortable-MGAbCGVJ.js → useSortable-C8ReQ50P.js} +0 -0
  164. /package/dist/{useTextHighlight-9nMW23Qb.js → useTextHighlight-DON84L8w.js} +0 -0
@@ -59,7 +59,10 @@
59
59
  .glass-overlay,
60
60
  .glass-card,
61
61
  .glass-specular-track,
62
- .dock-icon-button {
62
+ .dock-icon-button,
63
+ .dock-tab-button,
64
+ .dock-select-trigger,
65
+ .dock-dropdown-trigger {
63
66
  position: relative;
64
67
  }
65
68
 
@@ -85,7 +88,10 @@
85
88
  .glass-overlay::before,
86
89
  .glass-card::before,
87
90
  .glass-specular-track::before,
88
- .dock-icon-button::before {
91
+ .dock-icon-button::before,
92
+ .dock-tab-button::before,
93
+ .dock-select-trigger::before,
94
+ .dock-dropdown-trigger::before {
89
95
  content: "";
90
96
  position: absolute;
91
97
  inset: 0;
@@ -106,32 +112,40 @@
106
112
  longer defeated by a floor. Hover/active lift it through the same
107
113
  cohort (the interaction-light state machine below). */
108
114
  --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
115
+ /* AX.W52 D19 — a thin, BOUNDED, pointer-anchored EDGE gleam (not the prior
116
+ full-plate central disc that washed small tiles muddy). The geometry is an
117
+ EXPLICIT-radius circle bounded by `--glass-specular-size` (36% of the
118
+ plate) whose falloff reaches `/0` well INSIDE the plate (70%) — a tracked
119
+ catch-light reading the surface near the lit edge, NEVER a whole-surface
120
+ wash. The core is genuinely WARM-CREAM (L < 100% so the warm hue survives;
121
+ the prior `hsl(40 30% 100%)` blew out to white). The `--specular-intensity`
122
+ multiplier drives the layer `opacity`, NOT a per-stop alpha (a
115
123
  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. */
124
+ Chromium — the cross-engine-safe path); the per-stop alphas are literals so
125
+ even the lifted hover/active states read as a lens, not a flash. */
118
126
  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%
127
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
128
+ hsl(40 35% 92% / 0.5) 0%,
129
+ hsl(40 35% 92% / 0) 70%,
130
+ transparent 100%
123
131
  );
124
132
  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. */
133
+ /* Clip the gleam to ITS OWN radius (not the whole plate) so it stays a
134
+ bounded glint. `mask-image` Baseline 2023-12-07; a non-supporting engine
135
+ ignores it and the `inset: 0` + radius-inherit + the in-paint falloff
136
+ already bound the gleam to the surface. */
128
137
  mask-image: radial-gradient(
129
- circle at var(--specular-x, 50%) var(--specular-y, 50%),
138
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
130
139
  black 0%,
131
- black 55%,
132
- transparent 75%
140
+ black 60%,
141
+ transparent 100%
133
142
  );
134
- mix-blend-mode: screen;
143
+ /* AX.W52 D19 — `plus-lighter` (additive but HDR-clamped, Safari 16.4+) over
144
+ the prior `screen` (a non-linear lightener that lifted the whole tile
145
+ toward white — the muddy-card defect). A non-supporting engine degrades to
146
+ a plain low-alpha warm overlay (the gleam composes normally — no blend, no
147
+ blowout), the no-workaround floor; NOT a `screen` fallback. */
148
+ mix-blend-mode: plus-lighter;
135
149
  /* Smooth the position + intensity between pointer samples (the typed
136
150
  @property regs make the percentage stops interpolable). */
137
151
  transition:
@@ -148,9 +162,12 @@
148
162
  .dark .glass-overlay::before,
149
163
  .dark .glass-card::before,
150
164
  .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-
165
+ .dark .dock-icon-button::before,
166
+ .dark .dock-tab-button::before,
167
+ .dark .dock-select-trigger::before,
168
+ .dark .dock-dropdown-trigger::before {
169
+ /* Softer over the deep canvas — `plus-lighter` still lifts on dark, so the
170
+ `.dark` cohort runs a lower hover/active rung (tokens.css §specular-
154
171
  intensity `.dark` arm); the rest rung is already 0 so the dark arm only
155
172
  softens hover/active via the cohort. The rest rung re-reads the (dark)
156
173
  token here so a dark `:root` override resolves. */
@@ -169,8 +186,11 @@
169
186
  .glass-overlay:hover::before,
170
187
  .glass-card:hover::before,
171
188
  .glass-specular-track:hover::before,
172
- .dock-icon-button:hover::before {
173
- --specular-intensity: var(--glass-specular-intensity-hover, 0.22);
189
+ .dock-icon-button:hover::before,
190
+ .dock-tab-button:hover::before,
191
+ .dock-select-trigger:hover::before,
192
+ .dock-dropdown-trigger:hover::before {
193
+ --specular-intensity: var(--glass-specular-intensity-hover, 0.1);
174
194
  }
175
195
  .glass-material:active::before,
176
196
  .glass-wash:active::before,
@@ -180,8 +200,26 @@
180
200
  .glass-overlay:active::before,
181
201
  .glass-card:active::before,
182
202
  .glass-specular-track:active::before,
183
- .dock-icon-button:active::before {
184
- --specular-intensity: var(--glass-specular-intensity-active, 0.32);
203
+ .dock-icon-button:active::before,
204
+ .dock-tab-button:active::before,
205
+ .dock-select-trigger:active::before,
206
+ .dock-dropdown-trigger:active::before {
207
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
208
+ }
209
+
210
+ /* AX.W45-TUNE C5 — the SELECTED dock control reads as the keyframes-dock glass
211
+ register: a glass-tier active fill (`--dock-control-active-bg` → the floating
212
+ plate, tokens.css) WITH the specular gleam waking over it, not a flat ink
213
+ stamp. The CSS `:active` pseudo above only fires on press-down; a SELECTED tile
214
+ (`.is-active` / `[aria-pressed]` / `[aria-expanded]` / `[aria-current]`) holds
215
+ the gleam lit so the selected element reads as a lit glass tier the substrate
216
+ shows through (the model the user named, `pass-3:13`). Family-scoped addition
217
+ on the dock-control `::before`, line-disjoint from the shared recipe above. */
218
+ .dock-icon-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
219
+ .dock-tab-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
220
+ .dock-select-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
221
+ .dock-dropdown-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before {
222
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
185
223
  }
186
224
 
187
225
  /* ── Five-tier surface ladder (v0.8.0; visual only, no geometry) ──
@@ -273,6 +311,76 @@
273
311
  box-shadow: var(--glass-material-rim), var(--glass-shadow-overlay);
274
312
  }
275
313
 
314
+ /* ── Adaptive legibility: the bright-backdrop bucket (AX.W55 — the iOS-26/27
315
+ "locally darken the glass over light content" move; G2) ──────────────────
316
+ When a consumer sets `--glass-backdrop: light` on any ancestor (a near-white
317
+ card surface, a pale aurora bleed, a bright data grid), the `@container
318
+ style()` read engages here and LIFTS the tint toward ink: `--glass-tint-
319
+ strength` climbs from the `0%` rest default to the bounded AA floor
320
+ (`--glass-tint-strength-aa`, ≤24% — translucent floor preserved) and `--glass-
321
+ tint-source` re-points from `var(--card)` to the warm-ink `--glass-tint-ink`.
322
+ Both are INHERITING custom properties the rungs' `background:` composite
323
+ already reads, so re-pointing them on the material group re-resolves the
324
+ EXISTING `color-mix(in oklab, <rung bg>, …)` toward ink — ZERO new compositing
325
+ seam, the literal darken-over-light recipe. The `.glass-*::before` specular
326
+ `plus-lighter` gleam (W52) is untouched (it composes ON the darkened plate;
327
+ the darkening is the orthogonal oklab-tint axis). No `@supports` wrapper:
328
+ style queries introduce no new `container-type` value (every element is a
329
+ style container by default), so an engine without style-query support parses
330
+ the unknown at-rule as invalid, drops the block, and keeps the zero-delta
331
+ glass (the graceful degradation — the surface is today's-glass, the pre-W55
332
+ state; see utilities.css §density for the same precedent). */
333
+ @container style(--glass-backdrop: light) {
334
+ .glass-material,
335
+ .glass-wash,
336
+ .glass-quiet,
337
+ .glass-resting,
338
+ .glass-floating,
339
+ .glass-overlay,
340
+ .glass-card {
341
+ --glass-tint-source: var(--glass-tint-ink);
342
+ --glass-tint-strength: var(--glass-tint-strength-aa);
343
+ }
344
+ }
345
+
346
+ /* AX.W55 — the `contrast-color()` foreground-ink flip (Chrome 147+/Safari 26+).
347
+ A PROGRESSIVE-ENHANCEMENT layer, NEVER the load-bearing floor (Open-Q #5
348
+ ratified): the declarative bucket above already carries AA on ALL engines (it
349
+ darkens the translucent plate so dark text clears ~11:1 over white at the 18%
350
+ floor — the live π readback ratifies). On a supporting engine `contrast-color()`
351
+ REFINES the foreground-ink pick natively, anchored on the LIGHT BACKDROP signal
352
+ (`--card`, the warm-white surface base the bright bucket implies) — NOT on the
353
+ ink. `contrast-color(var(--card))` over the light backdrop resolves to the
354
+ maximally-legible DARK ink (anchoring on the dark ink instead would invert to
355
+ white, illegible on the still-light translucent plate). The bucket is the floor;
356
+ this is the native refinement. Scoped to the bright bucket. */
357
+ @supports (color: contrast-color(white)) {
358
+ @container style(--glass-backdrop: light) {
359
+ .glass-material,
360
+ .glass-wash,
361
+ .glass-quiet,
362
+ .glass-resting,
363
+ .glass-floating,
364
+ .glass-overlay,
365
+ .glass-card {
366
+ color: contrast-color(var(--card));
367
+ }
368
+ }
369
+ }
370
+
371
+ /* ── The opaque escape (AX.W54) ───────────────────
372
+ The level-0 endpoint of the SAME glass machinery — a solid `--card` plate
373
+ (the opacity seam → 1) with `blur(0)` (the blur seam → 0), routed through
374
+ the ONE `--glass-level` knob. NOT a parallel solid `background:` recipe:
375
+ a `.glass-*` surface that ALSO carries `.glass-opaque` keeps its glass edge,
376
+ rim, and under-shadow (a solid plate with a glass edge, not a bare div), and
377
+ the @supports fallback + the a11y brackets compose coherently. This is the
378
+ explicit opt-out from the MAXIMAL glass default (dense data, forced-colors,
379
+ a consumer that wants a flat surface). */
380
+ .glass-opaque {
381
+ --glass-level: 0;
382
+ }
383
+
276
384
  /* ── Content-aware under-shadow modifier (AV.W15 M4) ──────────────
277
385
  Apple raises the under-shadow over text (so the glass reads as
278
386
  lifting OFF the text) and drops it over solid light. The modifier
@@ -405,11 +513,17 @@
405
513
  background: var(--glass-bg-wash);
406
514
  backdrop-filter: var(--glass-blur-wash);
407
515
  color: var(--muted-foreground);
516
+ /* AX.W52 §6 doctrine — the surface legs ride the bezier `--ease-standard`;
517
+ the `scale` leg is reconciled onto `--spring-smooth` (was `--spring-snappy`)
518
+ so the icon-button hover settles on the SAME ONE register as `.btn-pill` /
519
+ `.tap-squish` / `btn-interactive` (the gate asserts one scale register
520
+ across all four). The press still reads crisp — `--spring-smooth` ζ=0.86
521
+ settles fast without a visible bounce. */
408
522
  transition:
409
523
  background var(--duration-fast) var(--ease-standard),
410
524
  border-color var(--duration-fast) var(--ease-standard),
411
525
  color var(--duration-fast) var(--ease-standard),
412
- scale var(--duration-normal) var(--spring-snappy);
526
+ scale var(--duration-normal) var(--spring-smooth);
413
527
  }
414
528
 
415
529
  .glass-btn:hover:not(:disabled) {
@@ -445,17 +559,40 @@
445
559
  .btn-pill {
446
560
  @apply inline-flex items-center justify-center cursor-pointer font-medium border-none;
447
561
 
448
- gap: 0.375rem;
562
+ /* AX.W52 §6 identity base — `scale: 1` at rest so the hover/press scale
563
+ below animates the `scale` longhand (not `transform`) coherently and
564
+ does not flicker the stacking context into being (AQ.W3 §W3.2). */
565
+ scale: 1;
566
+ /* AX.W51 D18 — the pill GEOMETRY rides the ONE `--ui-scale` comfort axis.
567
+ gap / padding scale by the master scalar; the font reads the
568
+ `--control-text` register (`calc(--type-small * --ui-scale)`, the same
569
+ `text-sm` register the Button CVA paints), so a bare `.btn-pill` consumer
570
+ and a `<Button>` agree on the control font, and ONE `--ui-scale` override
571
+ grows the pill's height (via padding) + gap + font in lockstep. Desktop
572
+ default is the identity (scale 1 → the prior proportion). */
573
+ gap: calc(0.375rem * var(--ui-scale));
449
574
  border-radius: var(--radius-pill);
450
- padding: 0.5rem 1rem;
451
- font-size: 1rem;
575
+ padding: calc(0.5rem * var(--ui-scale)) calc(1rem * var(--ui-scale));
576
+ font-size: var(--control-text);
577
+ /* AX.W52 — the ONE coherent button transition (RED witness 5/6). The
578
+ SURFACE legs (bg/border/box-shadow/color/opacity) ride the bezier
579
+ `--ease-standard` (a colour cross-fade reads as a wobble on a spring);
580
+ the TRANSFORM leg (`scale`) rides `--spring-smooth` (the sub-perceptual
581
+ settle), so the hover lift + the surface cross-fade read as ONE glide.
582
+ The DEAD `transform` leg is retired — the variants animate the `scale`
583
+ longhand. CRITICAL: `.tap-squish` (composed alongside on the button
584
+ base, utilities.css) ALSO lists this full coherent set, so neither
585
+ class's `transition` shorthand can clobber the other down to a
586
+ scale-only animation — the cascade bug that left every button
587
+ transitioning ONLY `scale` (the live-readback RED, RED witness 5). The
588
+ doctrine: surface-props→bezier, transform→spring (tokens.css §2). */
452
589
  transition:
453
590
  background-color var(--duration-fast) var(--ease-standard),
454
591
  border-color var(--duration-fast) var(--ease-standard),
455
592
  box-shadow var(--duration-fast) var(--ease-standard),
456
593
  color var(--duration-fast) var(--ease-standard),
457
594
  opacity var(--duration-fast) var(--ease-standard),
458
- transform var(--duration-fast) var(--ease-standard);
595
+ scale var(--duration-fast) var(--spring-smooth);
459
596
  }
460
597
 
461
598
  .btn-pill > * {
@@ -469,23 +606,52 @@
469
606
  pointer-events: none;
470
607
  }
471
608
 
609
+ /* ── Glass-button backdrop ─────────────────────────────────────────────
610
+ AX.W52 — the `glass`/`glass-wash` Button variants compose `.glass-wash`,
611
+ which resolves `--glass-blur-wash` = `blur(1px)` — a sub-perceptual
612
+ diffusion authored for a small detail TILE, not a button the user reads
613
+ as "glass" (the live readback found the glass variants at a negligible
614
+ 1px). A hero control wants a real glass blur. `.btn-glass` re-points the
615
+ backdrop at `--glass-blur-btn` (the `quiet`-tier 10px radius + the gentle
616
+ `saturate(1.05) brightness(1.02)` light-concentration), so the glass
617
+ button variants actually read as liquid glass while the wash TILE tier
618
+ keeps its 1px untouched. Declares the UNPREFIXED `backdrop-filter` ONLY —
619
+ Lightning CSS emits the `-webkit-` companion per the single-source
620
+ authorship discipline above (hand-authoring both forms makes Lightning
621
+ dedup-and-keep-prefixed, which modern Chromium then drops). */
622
+ .btn-glass {
623
+ backdrop-filter: var(--glass-blur-btn);
624
+ }
625
+
472
626
  /* ── Pill input ───────────────────────────────── */
473
627
  .input-pill {
474
628
  @apply flex w-full;
475
629
 
476
- height: 2.5rem;
630
+ /* AX.W51 D18 — the input pill rides the ONE `--ui-scale` comfort axis: the
631
+ height reads the `--control-h-md` cohort (`max(calc(2.5rem * --ui-scale),
632
+ --control-floor)`, the h-10 register with the WCAG-44px coarse clamp), the
633
+ font reads `--control-text`, the inline padding scales — so ONE override
634
+ grows the field's height + padding + font in lockstep. Desktop default is
635
+ the identity. */
636
+ height: var(--control-h-md);
477
637
  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);
638
+ /* AW.W13 — the resting field edge reads as an enclosed control at rest
639
+ (~15%α — ~2× the prior 8% glass-wash floor that vanished on cream). The
640
+ `:focus-visible` accent ring + the `:user-invalid`/`[aria-invalid]`
641
+ destructive ring below still win by order + specificity.
642
+ AX.W54 — moved off the srgb `--surface-tint-15` fork onto the glass
643
+ border seam (`--glass-border-floating`, the matching 15%α rung) so the
644
+ pill is ONE glass model with the rest of the ladder, not a divergent
645
+ tint axis. */
646
+ border: 1.5px solid var(--glass-border-floating);
485
647
  background: var(--glass-bg-quiet);
486
- backdrop-filter: var(--glass-blur-wash);
487
- padding: 0 1rem;
488
- font-size: 1rem;
648
+ /* AX.W54 — the pill reads as REAL glass: the quiet-tier 10px blur (the
649
+ same `--glass-blur-quiet` its `--glass-bg-quiet` background pairs with),
650
+ not the sub-perceptual `blur(1px)` wash it carried — and the
651
+ `--glass-level` knob now clarifies it in lockstep with every surface. */
652
+ backdrop-filter: var(--glass-blur-quiet);
653
+ padding: 0 calc(1rem * var(--ui-scale));
654
+ font-size: var(--control-text);
489
655
  color: var(--foreground);
490
656
  transition:
491
657
  background-color var(--duration-fast) var(--ease-standard),
@@ -664,50 +830,205 @@
664
830
  }
665
831
  }
666
832
 
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;
833
+ /* ── AX.W56 — the rounded-vs-squircle POLICY (re-homes AW.W23's squircle) ─────
834
+ Cards, glass buttons, and pills stay ROUND. The earlier AW.W23 block applied
835
+ `corner-shape: squircle` to `.glass-card`/`.glass-btn`/`.btn-pill`, which
836
+ inverted the design intent — the superellipse is imperceptible at a 16px card
837
+ radius or a stadium pill, so the squircle on those surfaces was visual cost
838
+ without read. The squircle is RE-HOMED onto the one surface where it reads: the
839
+ big-dock card shell (`dock.css` → `var(--corner-shape-bigdock)` under
840
+ `@supports (corner-shape: superellipse(2))`). This is a clean break — no alias,
841
+ no `--corner-shape-card` decl here (it resolves `round`, the default, so a
842
+ `corner-shape` rule would be a no-op). The `--corner-shape-*` token axis lives
843
+ in `theme.css`; a consumer who WANTS a squircle card opts in by re-pointing
844
+ `--corner-shape-card` at `superellipse(var(--corner-k-squircle))`. Do NOT
845
+ re-add a squircle rule to the card/button/pill surfaces — they are round by
846
+ policy. */
847
+
848
+ /* ── AX.W56(R1) — squircle coupling onto the overlay-band glass surfaces ───────
849
+ W54 makes GLASS the default for the Dialog + Sheet content surfaces; W56 couples
850
+ the SQUIRCLE onto them too. Both ride `.glass-floating` at the large
851
+ `--radius-dialog` (16px) modal radius where the superellipse READS — the same
852
+ iOS-26 idiom the big-dock card shell carries. The compound selectors scope the
853
+ shape to the dialog/sheet content ONLY (the `.rounded-dialog` class the
854
+ DialogContent surface composes, the `.sheet-animate` class the SheetContent
855
+ surface composes via `sheetVariants`) so it never leaks onto a bare
856
+ `.glass-floating` panel. Mirrors the big-dock idiom EXACTLY: an `@supports`-
857
+ gated ENHANCEMENT (Chrome 139+, no FF/Safari 2026) over the `border-radius`
858
+ round CONTRACT — the squircle is the better tier, NOT a degraded fallback. The
859
+ shape is the tokenized `var(--corner-shape-{dialog,sheet})` (theme.css) so it is
860
+ as overridable as the radius; a consumer dials either back to round by
861
+ re-pointing the alias. The `@supports` condition tests the LITERAL
862
+ `superellipse(2)` (a `var()` is not evaluable in an `@supports` query) — the same
863
+ Chrome-139 feature the token resolves to. */
864
+ @layer components {
865
+ @supports (corner-shape: superellipse(2)) {
866
+ .glass-floating.rounded-dialog {
867
+ corner-shape: var(--corner-shape-dialog);
868
+ }
869
+ .glass-floating.sheet-animate {
870
+ corner-shape: var(--corner-shape-sheet);
680
871
  }
681
872
  }
682
873
  }
683
874
 
684
- /* ── Accessibility: reduced transparency ────────── */
875
+ /* ── Accessibility: reduced transparency ──────────
876
+ AX.W54 — the gestalt collapse: ONE `--glass-level: 0` replaces the ten per-rung
877
+ opacity+blur clobbers. The level-0 path resolves solid `--card` + `blur(0)`
878
+ through the SAME machinery (the opacity seam → 1, the blur seam → 0), so every
879
+ glass surface — current and future — flattens with no per-rung enumeration. The
880
+ grain + highlight kills stay (they sit off the level axis). */
685
881
  @media (prefers-reduced-transparency: reduce) {
686
882
  :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;
883
+ --glass-level: 0;
698
884
  --glass-grain-opacity: 0;
699
885
  --glass-highlight: 0 0 0 0 transparent;
700
886
  }
701
887
  }
702
888
 
703
- /* ── Accessibility: high contrast ───────────────── */
889
+ /* ── Accessibility: high contrast ─────────────────
890
+ AX.W54 — a single bounded `--glass-level: 0.3` (mostly-solid, not fully flat)
891
+ replaces the five per-rung opacity clobbers: every rung firms up toward solid
892
+ for AA while keeping a hint of the glass register. ONE knob, every rung.
893
+
894
+ AX.W55 — the Clear↔Tinted user-escape (Apple's iOS-26.2 analog) COORDINATES the
895
+ two axes here: the OPACITY axis rides W54's `--glass-level` (firm up toward solid)
896
+ AND the TINT axis biases toward ink — `--glass-tint-source` → the warm-ink +
897
+ `--glass-tint-strength` → the AA floor, the same darken the automatic bright
898
+ bucket applies, now reached by the explicit "more contrast" user request. The two
899
+ axes stay DISTINCT (level = opacity+blur, tint = darken) but share the bracket so
900
+ a high-contrast user gets BOTH a firmer plate and the ink-tint legibility lift —
901
+ one coordinated escape, not two parallel forks. */
704
902
  @media (prefers-contrast: more) {
705
903
  :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;
904
+ --glass-level: 0.3;
905
+ --glass-tint-source: var(--glass-tint-ink);
906
+ --glass-tint-strength: var(--glass-tint-strength-aa);
907
+ }
908
+ }
909
+
910
+ /* ── Accessibility: forced-colors (Windows High Contrast) glass-language skin ──
911
+ AX.W36 — when the OS forces a palette (Windows High Contrast), the platform
912
+ strips the whole decorative glass register: `backdrop-filter` is dropped, the
913
+ `--glass-*` inset/box-shadow rungs vanish, and every meaning-bearing chroma
914
+ flattens to one system color. A `.glass-floating` Dialog over a `.glass-resting`
915
+ Card would read as two borderless transparent rectangles with no edge, and a
916
+ green-vs-red StatusDot would resolve to one indistinguishable dot. This skin
917
+ restores the STRUCTURE the glass chrome encoded — it does NOT pin glass-ui's
918
+ brand colours (no `forced-color-adjust: none`); the chrome is decorative and
919
+ YIELDS to the user's forced palette (css forced-colors guidance). Only the
920
+ standard WHC system keywords are used (`Canvas`/`CanvasText`/`Highlight`) — no
921
+ glass-ui token leaks into the WHC arm.
922
+
923
+ COORDINATES WITH W54 — the same `--glass-level: 0` opaque escape the reduced-
924
+ transparency / high-contrast brackets ride. Setting the ONE clarity knob to 0
925
+ collapses the `--glass-bg-*` opacity recipe to solid `--card` + `blur(0)` through
926
+ the SAME machinery (no parallel solid recipe), so the platform sees opaque plates
927
+ it maps to `Canvas`. The grain + highlight kills match the reduce bracket (they
928
+ sit off the level axis). The W55 tint axis is moot under WHC (the user's palette
929
+ supersedes the ink-darken) but harmless — the opaque plate is system-painted. */
930
+ @media (forced-colors: active) {
931
+ :root {
932
+ --glass-level: 0;
933
+ --glass-grain-opacity: 0;
934
+ --glass-highlight: 0 0 0 0 transparent;
935
+ }
936
+
937
+ /* Every glass-material ladder rung relied on `backdrop-filter` + an inset
938
+ `box-shadow` rim for its silhouette — both gone under WHC. Restore a real
939
+ `border` keyed to the system text colour so each tier pane reads as a boxed
940
+ region. The selector group MIRRORS the ladder definition above (one source,
941
+ not a hand-rolled re-list) so a future rung added to the material group
942
+ inherits the WHC edge for free — and a `.glass-material` div that became one
943
+ via the GlassPanel retire gets the edge with no per-component arm. */
944
+ .glass-material,
945
+ .glass-wash,
946
+ .glass-quiet,
947
+ .glass-resting,
948
+ .glass-floating,
949
+ .glass-overlay,
950
+ .glass-card {
951
+ border: 1px solid CanvasText;
952
+ }
953
+
954
+ /* The floating + overlay rungs (Dialog / Sheet / Popover / DropdownMenu /
955
+ HoverCard compose them) get the canonical `Canvas` fill so the modal reads as
956
+ a DISTINCT boxed region OVER the page, not a transparent overlap — the
957
+ hierarchy survives. The `CanvasText` edge above already draws the box; this
958
+ opaque fill separates the floating layer from the content beneath it. */
959
+ .glass-floating,
960
+ .glass-overlay {
961
+ background: Canvas;
962
+ }
963
+
964
+ /* The decorative specular catch-light (`::before`) + grain overlay (`::after`)
965
+ paint nothing meaningful once chroma collapses — yield them entirely (the
966
+ same decorative-chrome cede the `--glass-level: 0` opaque escape performs on
967
+ the body). They are NOT part of the structure the skin restores. */
968
+ .glass-material::before,
969
+ .glass-wash::before,
970
+ .glass-quiet::before,
971
+ .glass-resting::before,
972
+ .glass-floating::before,
973
+ .glass-overlay::before,
974
+ .glass-card::before,
975
+ .glass-wash::after,
976
+ .glass-quiet::after,
977
+ .glass-resting::after,
978
+ .glass-floating::after,
979
+ .glass-overlay::after {
980
+ display: none;
981
+ }
982
+
983
+ /* Meaning-bearing hue identity → a bordered glyph that keeps ok/warn/error
984
+ distinguishable by a WHC-HONORED system color, NOT a glass-ui hue (which WHC
985
+ strips to one fill). StatusDot reflects its variant onto `data-status`
986
+ (StatusDot.vue) and the inner dot carries `.status-dot__dot`; the
987
+ `role="img"` + `aria-label` accessible name already ships, so this is the
988
+ VISUAL differentiation only. A bare bordered dot + the per-status fill triplet
989
+ below means a sighted WHC user can still tell the row apart.
990
+
991
+ `!important` IS load-bearing here: StatusDot paints the dot fill via an INLINE
992
+ `:style="dotStyle"` (`background-color`, specificity 1,0,0,0), which outranks
993
+ any stylesheet selector AND which forced-colors then `forced-color-adjust:
994
+ auto`-remaps to a single Canvas-white — collapsing the row to one indistinct
995
+ dot. The WHC arm must override that inline fill, and inline can only be beaten
996
+ by `!important`; this is the documented forced-colors degradation path (the
997
+ arm only activates under WHC). The component keeps its inline hue in normal
998
+ mode untouched. */
999
+ .status-dot__dot {
1000
+ border: 1px solid CanvasText;
1001
+ /* The bordered ring alone separates a dot from its surround; the per-status
1002
+ fill below adds the WHC-honored distinction. */
1003
+ }
1004
+ /* The inner painted fill (`.status-dot__fill`, `h-full w-full`) + the pulse ring
1005
+ carry the SAME inline glass-ui hue StatusDot paints — under WHC they cover the
1006
+ outer `.status-dot__dot` glyph with a `forced-color-adjust`-remapped Canvas
1007
+ fill (the row collapses to one white dot even with the outer system color set).
1008
+ Yield them so the outer bordered + system-color glyph is the sole visible dot. */
1009
+ .status-dot__fill,
1010
+ .status-dot__pulse {
1011
+ display: none;
1012
+ }
1013
+ /* The ok/warn/error/idle distinction rides the standard WHC keyword palette:
1014
+ active (ok) → Highlight (the affirmative system accent)
1015
+ paused (warn) → Mark (the marked/attention system color)
1016
+ error → CanvasText (a solid filled dot — the strongest weight)
1017
+ idle/custom → Canvas (a hollow dot — only the CanvasText ring reads)
1018
+ Each stays distinguishable by the system color the user's palette assigns,
1019
+ never glass-ui chroma. The `!important` beats the component's inline fill. */
1020
+ .status-dot__dot[data-status="active"] {
1021
+ background: Highlight !important;
1022
+ }
1023
+ .status-dot__dot[data-status="paused"] {
1024
+ background: Mark !important;
1025
+ }
1026
+ .status-dot__dot[data-status="error"] {
1027
+ background: CanvasText !important;
1028
+ }
1029
+ .status-dot__dot[data-status="idle"],
1030
+ .status-dot__dot[data-status="custom"] {
1031
+ background: Canvas !important;
711
1032
  }
712
1033
  }
713
1034
 
@@ -60,10 +60,15 @@
60
60
  * over the glass tiers.
61
61
  * 5. paper.css — paper underpaint + grain overlay utilities.
62
62
  * Pairs with (4) for paper-on-glass compositions.
63
- * 6. dock.css — dock shell / density / grain / layer-crossfade
64
- * contract + the shared cross-control four-state
65
- * comma-groups. Component utility layer; consumes
66
- * (1) + (3).
63
+ * 6. dock.css — the dock CORE: the `@property --dock-morph-t`
64
+ * registration, the shared cross-control four-state
65
+ * comma-groups, and the `@import`s of the cohesive
66
+ * `dock/*.css` partials (shell · morph · density ·
67
+ * layers · layer-group · overflow — AX.W06 carved
68
+ * the 1762-line god-module into single-axis partials,
69
+ * each < 500 lines, all in the SAME @layer components
70
+ * so the cascade is isomorphic). Component utility
71
+ * layer; consumes (1) + (3).
67
72
  * 6b. dock-controls.css — the five dock CONTROL families carved out of
68
73
  * dock.css (AU.W8b.3): .dock-icon-button,
69
74
  * .dark-mode-toggle-button, .dock-tab-button + tiers,
@@ -99,13 +104,11 @@
99
104
  * binding + bezel hairlines + sibling divider
100
105
  * rule). Composes alongside instrument-chassis;
101
106
  * shares the bezel-line twin-pixel idiom.
102
- * 14. glyph-face.css — P-tranche component CSS (cap + backplate).
103
- * 15. disco-glyph.css — P-tranche component CSS (layered fills).
104
- * 16. hover-popover.css — V.W3 popover-animation grammar.
105
- * 17. drawer.css — AN.W3 detented bottom-sheet grammar (glass
107
+ * 14. hover-popover.css — V.W3 popover-animation grammar.
108
+ * 15. drawer.css — AN.W3 detented bottom-sheet grammar (glass
106
109
  * sheet surface + peek handle + snap-stop rules).
107
110
  *
108
- * Per-package component CSS lives at (12)-(17) (loaded after utilities so
111
+ * Per-package component CSS lives at (12)-(15) (loaded after utilities so
109
112
  * component-local recipes can override). New per-package CSS files append
110
113
  * to that tail.
111
114
  */
@@ -127,8 +130,6 @@
127
130
  @import "./utilities.css";
128
131
  @import "./instrument-chassis.css";
129
132
  @import "./instrument-rail.css";
130
- @import "./glyph-face.css";
131
- @import "./disco-glyph.css";
132
133
  @import "./hover-popover.css";
133
134
  @import "./drawer.css";
134
135