@mkbabb/glass-ui 3.10.0 → 3.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/dist/{CardAction-DuArVky-.js → CardAction-DrAcAV4d.js} +2 -2
  2. package/dist/{CommandShortcut-CefCj5mt.js → CommandShortcut-mV2e1aG6.js} +2 -2
  3. package/dist/{DataTable-CUHMukiQ.js → DataTable-C3E6jZ5B.js} +2 -2
  4. package/dist/{DialogContent-BRkT1cjP.js → DialogContent-BxaaafFi.js} +1 -1
  5. package/dist/{HoverPopover-2LOIW34a.js → HoverPopover-CDA_SaCe.js} +1 -1
  6. package/dist/{MetricBadge-BZVWIxNy.js → MetricBadge-idgrkqoP.js} +5 -7
  7. package/dist/{Notification-DLMhblXR.js → Notification-Cu0nN17_.js} +1 -1
  8. package/dist/{NumberFieldContent-BbLOh8RU.js → NumberFieldContent-CHEWghnY.js} +2 -2
  9. package/dist/{PopoverContent-BId6ggf_.js → PopoverContent-DpUvdYY-.js} +1 -1
  10. package/dist/{Progress-iEuD9pxG.js → Progress-BW-StFw2.js} +1 -1
  11. package/dist/{ScrollingText-BPP84wKo.js → ScrollingText-DruYCni_.js} +1 -1
  12. package/dist/{SelectScrollDownButton-T32cVFeM.js → SelectScrollDownButton-pirzjm--.js} +3 -3
  13. package/dist/{Switch-Ch-k3Rv-.js → Switch-DeAqg6pi.js} +1 -1
  14. package/dist/{TabsList-B8CVOQPC.js → TabsList-BAVzOZpg.js} +2 -2
  15. package/dist/{Toaster-1rYWrmAm.js → Toaster-CvuuW_y9.js} +49 -46
  16. package/dist/{ToggleGroupItem-Cev4pOVK.js → ToggleGroupItem-DtD37b4G.js} +4 -4
  17. package/dist/animated-digit.js +2 -2
  18. package/dist/api/index.d.ts +3 -4
  19. package/dist/api.js +1 -1
  20. package/dist/aurora.js +66 -66
  21. package/dist/{badge-CaoFJzRb.js → badge-NdCQMvvB.js} +1 -1
  22. package/dist/badge.js +1 -1
  23. package/dist/{button-DN39cGqL.js → button-DyiWFAOE.js} +12 -12
  24. package/dist/button.js +1 -1
  25. package/dist/canvas.js +2 -2
  26. package/dist/card.js +1 -1
  27. package/dist/carousel.js +5 -5
  28. package/dist/collapsible.js +1 -1
  29. package/dist/{color-C5ls_QF7.js → color-B65wWyQz.js} +9 -7
  30. package/dist/color.js +1 -1
  31. package/dist/command.js +1 -1
  32. package/dist/components/custom/aurora/constants/shaders/mediums.glsl.d.ts +1 -1
  33. package/dist/components/custom/aurora/constants/shaders/vangogh-medium.glsl.d.ts +1 -0
  34. package/dist/components/custom/constellation/Constellation.vue.d.ts +12 -0
  35. package/dist/components/custom/constellation/composables/createConstellationField.d.ts +35 -0
  36. package/dist/components/custom/constellation/composables/useConstellationPointer.d.ts +35 -0
  37. package/dist/components/custom/constellation/constants.d.ts +36 -0
  38. package/dist/components/custom/constellation/constellationDraw.d.ts +18 -0
  39. package/dist/components/custom/constellation/constellationField.d.ts +10 -151
  40. package/dist/components/custom/constellation/constellationInteraction.d.ts +102 -0
  41. package/dist/components/custom/constellation/index.d.ts +3 -1
  42. package/dist/components/custom/controls/DarkModeToggle.vue.d.ts +11 -0
  43. package/dist/components/custom/dock/DockTabButton.vue.d.ts +3 -4
  44. package/dist/components/custom/dock/GlassDock.vue.d.ts +2 -110
  45. package/dist/components/custom/dock/composables/dockMorphContext.d.ts +36 -0
  46. package/dist/components/custom/dock/composables/useDockMorphWindow.d.ts +15 -0
  47. package/dist/components/custom/dock/composables/useDockShellProps.d.ts +131 -0
  48. package/dist/components/custom/dock/composables/useLayerTransition.d.ts +44 -0
  49. package/dist/components/custom/dock/constants.d.ts +23 -0
  50. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +0 -29
  51. package/dist/components/custom/fourier-field/index.d.ts +1 -1
  52. package/dist/components/custom/fourier-field/math.d.ts +17 -0
  53. package/dist/components/custom/fourier-field/presets.d.ts +54 -0
  54. package/dist/components/custom/goo-blob/composables/buildMetaballProgram.d.ts +18 -0
  55. package/dist/components/custom/goo-blob/composables/uploadBlobUniforms.d.ts +41 -0
  56. package/dist/components/custom/goo-blob/composables/useBlobPointer.d.ts +4 -3
  57. package/dist/components/custom/goo-blob/composables/useMetaballRenderer.d.ts +11 -8
  58. package/dist/components/custom/goo-blob/constants.d.ts +52 -0
  59. package/dist/components/custom/goo-blob/shaders/metaball-uniforms.glsl.d.ts +1 -0
  60. package/dist/components/custom/instrument-chassis/InstrumentChassis.vue.d.ts +2 -2
  61. package/dist/components/custom/metric-badge/MetricBadge.vue.d.ts +0 -8
  62. package/dist/components/custom/tabs/constants.d.ts +12 -0
  63. package/dist/components/custom/underline/GlassUnderline.vue.d.ts +84 -0
  64. package/dist/components/custom/underline/index.d.ts +2 -0
  65. package/dist/components/custom/underline/types.d.ts +56 -0
  66. package/dist/components/ui/drawer/Drawer.vue.d.ts +1 -0
  67. package/dist/components/ui/dropdown-menu/DropdownMenuSubContent.vue.d.ts +2 -2
  68. package/dist/components/ui/slider/index.d.ts +22 -19
  69. package/dist/components/ui/toast/use-toast.d.ts +2 -2
  70. package/dist/composables/color/index.d.ts +12 -0
  71. package/dist/composables/glass/useSpecularTracking.d.ts +12 -3
  72. package/dist/composables/motion/core/index.d.ts +0 -1
  73. package/dist/composables/motion/curves.d.ts +48 -0
  74. package/dist/composables/motion/index.d.ts +2 -0
  75. package/dist/composables/motion/springPresets.d.ts +33 -0
  76. package/dist/composables/motion/suite.d.ts +2 -0
  77. package/dist/composables/motion/useSpringMount.d.ts +1 -1
  78. package/dist/configurator.js +1 -1
  79. package/dist/confirm-dialog.js +2 -2
  80. package/dist/constellation.js +260 -225
  81. package/dist/controls.js +48 -14
  82. package/dist/dark.js +1 -1
  83. package/dist/data-table.js +1 -1
  84. package/dist/dialog.js +2 -2
  85. package/dist/dock.js +339 -327
  86. package/dist/dockContext-bho8B1A4.js +17 -0
  87. package/dist/{dropdown-menu-D77jX6Df.js → dropdown-menu-DVnQcA0E.js} +7 -4
  88. package/dist/dropdown-menu.js +1 -1
  89. package/dist/expandable-container.js +38 -61
  90. package/dist/forms.js +2 -2
  91. package/dist/fourier-field.js +137 -102
  92. package/dist/fourier-math.js +2 -2
  93. package/dist/glass-ui.css +1 -1
  94. package/dist/glass-ui.js +287 -209
  95. package/dist/goo-blob.js +243 -212
  96. package/dist/hover-popover.js +1 -1
  97. package/dist/icon-tooltip.js +1 -1
  98. package/dist/index.d.ts +0 -3
  99. package/dist/keyboard.js +1 -1
  100. package/dist/labeled-field.js +5 -5
  101. package/dist/{math-DTpRVC0e.js → math-BUU9hHID.js} +18 -2
  102. package/dist/metric-badge.js +1 -1
  103. package/dist/metric-stack.js +1 -1
  104. package/dist/motion-core.js +69 -70
  105. package/dist/motion-curves.d.ts +1 -0
  106. package/dist/motion-curves.js +130 -0
  107. package/dist/motion.js +38 -37
  108. package/dist/notification.js +1 -1
  109. package/dist/number-field.js +1 -1
  110. package/dist/popover.js +1 -1
  111. package/dist/progress.js +1 -1
  112. package/dist/pulse.js +1 -1
  113. package/dist/reactive.js +1 -1
  114. package/dist/scrolling-text.js +1 -1
  115. package/dist/search.js +6 -6
  116. package/dist/select.js +1 -1
  117. package/dist/{sheet-VZEtNFvO.js → sheet-ChSXcJpU.js} +1 -1
  118. package/dist/sheet.js +1 -1
  119. package/dist/{slider-CyzcxBoh.js → slider-sfl8gFDD.js} +4 -4
  120. package/dist/slider.js +1 -1
  121. package/dist/sortable-list.js +2 -2
  122. package/dist/springPresets-aRSm-4_k.js +40 -0
  123. package/dist/stacked-icons.js +6 -6
  124. package/dist/styles/animations.css +18 -74
  125. package/dist/styles/components.css +1 -1
  126. package/dist/styles/dock/layer-group.css +22 -0
  127. package/dist/styles/dock/layers.css +11 -1
  128. package/dist/styles/dock/morph.css +95 -19
  129. package/dist/styles/dock/shell.css +12 -0
  130. package/dist/styles/dock-controls.css +28 -31
  131. package/dist/styles/drawer.css +2 -0
  132. package/dist/styles/floating-panel.css +2 -0
  133. package/dist/styles/glass/a11y-fallback.css +245 -0
  134. package/dist/styles/glass/ladder.css +304 -0
  135. package/dist/styles/glass/material.css +238 -0
  136. package/dist/styles/glass/progress-rail.css +78 -0
  137. package/dist/styles/glass/squircle.css +66 -0
  138. package/dist/styles/glass/surfaces.css +306 -0
  139. package/dist/styles/glass-refract.css +2 -0
  140. package/dist/styles/glass.css +31 -1188
  141. package/dist/styles/hover-popover.css +2 -0
  142. package/dist/styles/index.css +24 -6
  143. package/dist/styles/instrument-chassis.css +4 -0
  144. package/dist/styles/paper.css +2 -68
  145. package/dist/styles/theme.css +13 -20
  146. package/dist/styles/tokens/color-radius.css +250 -0
  147. package/dist/styles/tokens/dark-arm.css +194 -0
  148. package/dist/styles/tokens/glass.css +413 -0
  149. package/dist/styles/tokens/light-dark.css +158 -0
  150. package/dist/styles/tokens/offsets-sizing.css +406 -0
  151. package/dist/styles/tokens/property-regs.css +169 -0
  152. package/dist/styles/tokens/scale-paper.css +361 -0
  153. package/dist/styles/tokens/scheme-motion.css +334 -0
  154. package/dist/styles/tokens/shadow.css +132 -0
  155. package/dist/styles/tokens.css +22 -2355
  156. package/dist/styles/typography.css +18 -6
  157. package/dist/styles/utilities/a11y-overrides.css +140 -0
  158. package/dist/styles/utilities/animate.css +26 -0
  159. package/dist/styles/utilities/base.css +365 -0
  160. package/dist/styles/utilities/btn.css +399 -0
  161. package/dist/styles/utilities/components.css +317 -0
  162. package/dist/styles/utilities.css +19 -1260
  163. package/dist/styles/view-transition.css +0 -51
  164. package/dist/switch.js +1 -1
  165. package/dist/tabs.js +98 -98
  166. package/dist/timeline.js +2 -2
  167. package/dist/toast.js +1 -1
  168. package/dist/toggle-group.js +1 -1
  169. package/dist/typewriter.js +1 -1
  170. package/dist/underline.d.ts +1 -0
  171. package/dist/underline.js +85 -0
  172. package/dist/{useAnimatedNumber-Bcpy5Etf.js → useAnimatedNumber-DfVgP4te.js} +1 -1
  173. package/dist/{useConfiguratorState-DxAqksK6.js → useConfiguratorState-BdQXh9ie.js} +1 -1
  174. package/dist/useSpecularTracking-DFK_fhpG.js +32 -0
  175. package/dist/useSpringMount-DXUzxBjV.js +108 -0
  176. package/dist/vReveal-CqaCz_mC.js +44 -0
  177. package/dist/watercolor-dot.js +2 -2
  178. package/package.json +34 -52
  179. package/src/styles/animations.css +18 -74
  180. package/src/styles/dock/layer-group.css +22 -0
  181. package/src/styles/dock/layers.css +11 -1
  182. package/src/styles/dock/morph.css +95 -19
  183. package/src/styles/dock/shell.css +12 -0
  184. package/src/styles/dock-controls.css +28 -31
  185. package/src/styles/glass/a11y-fallback.css +245 -0
  186. package/src/styles/glass/ladder.css +304 -0
  187. package/src/styles/glass/material.css +238 -0
  188. package/src/styles/glass/progress-rail.css +78 -0
  189. package/src/styles/glass/squircle.css +66 -0
  190. package/src/styles/glass/surfaces.css +306 -0
  191. package/src/styles/glass.css +31 -1188
  192. package/src/styles/index.css +24 -6
  193. package/src/styles/paper.css +2 -68
  194. package/src/styles/theme.css +13 -20
  195. package/src/styles/tokens/color-radius.css +250 -0
  196. package/src/styles/tokens/dark-arm.css +194 -0
  197. package/src/styles/tokens/glass.css +413 -0
  198. package/src/styles/tokens/light-dark.css +158 -0
  199. package/src/styles/tokens/offsets-sizing.css +406 -0
  200. package/src/styles/tokens/property-regs.css +169 -0
  201. package/src/styles/tokens/scale-paper.css +361 -0
  202. package/src/styles/tokens/scheme-motion.css +334 -0
  203. package/src/styles/tokens/shadow.css +132 -0
  204. package/src/styles/tokens.css +22 -2355
  205. package/src/styles/typography.css +18 -6
  206. package/src/styles/utilities/a11y-overrides.css +140 -0
  207. package/src/styles/utilities/animate.css +26 -0
  208. package/src/styles/utilities/base.css +365 -0
  209. package/src/styles/utilities/btn.css +399 -0
  210. package/src/styles/utilities/components.css +317 -0
  211. package/src/styles/utilities.css +19 -1260
  212. package/src/styles/view-transition.css +0 -51
  213. package/dist/DeckProgress-Dmk4_AKN.js +0 -23
  214. package/dist/InstrumentRail-CUJ05YVG.js +0 -44
  215. package/dist/components/custom/deck-progress/DeckProgress.vue.d.ts +0 -27
  216. package/dist/components/custom/deck-progress/index.d.ts +0 -2
  217. package/dist/components/custom/dialog-native/GlassDialogNative.vue.d.ts +0 -57
  218. package/dist/components/custom/dialog-native/index.d.ts +0 -1
  219. package/dist/components/custom/glass-panel/GlassPanel.vue.d.ts +0 -41
  220. package/dist/components/custom/glass-panel/index.d.ts +0 -2
  221. package/dist/components/custom/handmark/HandMark.vue.d.ts +0 -29
  222. package/dist/components/custom/handmark/brush.d.ts +0 -219
  223. package/dist/components/custom/handmark/freehand.d.ts +0 -69
  224. package/dist/components/custom/handmark/geometry.d.ts +0 -32
  225. package/dist/components/custom/handmark/index.d.ts +0 -21
  226. package/dist/components/custom/handmark/ink.d.ts +0 -11
  227. package/dist/components/custom/handmark/texture.d.ts +0 -39
  228. package/dist/components/custom/handmark/types.d.ts +0 -53
  229. package/dist/components/custom/handmark/useHandMark.d.ts +0 -66
  230. package/dist/components/custom/header-ribbon/HeaderRibbon.vue.d.ts +0 -31
  231. package/dist/components/custom/header-ribbon/index.d.ts +0 -2
  232. package/dist/components/custom/header-ribbon/types.d.ts +0 -7
  233. package/dist/components/custom/instrument-rail/InstrumentRail.vue.d.ts +0 -91
  234. package/dist/components/custom/instrument-rail/index.d.ts +0 -2
  235. package/dist/composables/motion/useRouteTransition.d.ts +0 -42
  236. package/dist/deck-progress.d.ts +0 -1
  237. package/dist/deck-progress.js +0 -2
  238. package/dist/dockContext-BKeIMmNk.js +0 -9
  239. package/dist/glass-panel.d.ts +0 -1
  240. package/dist/glass-panel.js +0 -44
  241. package/dist/handmark.d.ts +0 -1
  242. package/dist/handmark.js +0 -609
  243. package/dist/header-ribbon.d.ts +0 -1
  244. package/dist/header-ribbon.js +0 -63
  245. package/dist/instrument-rail.d.ts +0 -1
  246. package/dist/instrument-rail.js +0 -2
  247. package/dist/useGlassRenderer-D7YGOYiM.js +0 -69
  248. package/dist/useSpecularTracking-BVRZsRHA.js +0 -26
  249. package/dist/useSpringMount-BJSHcLl3.js +0 -113
  250. package/dist/useViewTransition-DaN5Zrox.js +0 -21
  251. package/dist/vReveal-zUIQk-rJ.js +0 -53
  252. /package/dist/{CollapsibleContent-CP9qF1v4.js → CollapsibleContent-Drow5WkV.js} +0 -0
  253. /package/dist/{DialogFooter-Gprw8H_A.js → DialogFooter-DufLHi0y.js} +0 -0
  254. /package/dist/{IconTooltip-Cus0fvK0.js → IconTooltip-BrQ5p181.js} +0 -0
  255. /package/dist/{Input-xuDwALQR.js → Input-B-F818RU.js} +0 -0
  256. /package/dist/{_plugin-vue_export-helper-ok8pgSl5.js → _plugin-vue_export-helper-DWghtRt7.js} +0 -0
  257. /package/dist/{compile-BOXjLUxu.js → compile-Ce_V55zi.js} +0 -0
  258. /package/dist/{constants-yKeKnE84.js → constants-C8NMonuo.js} +0 -0
  259. /package/dist/{presets-Dkdv55Gt.js → presets-1OhFpaIC.js} +0 -0
  260. /package/dist/{prng-D27-B3tK.js → prng-CjVgzjQT.js} +0 -0
  261. /package/dist/{resolveCanvasColor-BBiYfp8g.js → resolveCanvasColor-CRvVzOvP.js} +0 -0
  262. /package/dist/{useCanvas2D-ClrQuZtp.js → useCanvas2D-CSeH8h16.js} +0 -0
  263. /package/dist/{useGlobalDark-d6waty-X.js → useGlobalDark-D7R9OypB.js} +0 -0
  264. /package/dist/{useIntersectionPause-Cck5Uxk8.js → useIntersectionPause-DAdVPVp4.js} +0 -0
  265. /package/dist/{useInterval-Dsmqwi03.js → useInterval-D3USn0yc.js} +0 -0
  266. /package/dist/{useKeyboardShortcuts-CyIYrndH.js → useKeyboardShortcuts-i8tHd5WO.js} +0 -0
  267. /package/dist/{useScrollProgress-CffFGLa5.js → useScrollProgress-CcgmgMQt.js} +0 -0
  268. /package/dist/{useSortable-C8ReQ50P.js → useSortable-DnyGXKKY.js} +0 -0
  269. /package/dist/{useTextHighlight-CWEi25hf.js → useTextHighlight-B3b10W6r.js} +0 -0
@@ -0,0 +1,304 @@
1
+ /* glass/ladder.css
2
+ The five-tier .glass-{wash,quiet,resting,floating,overlay} surface ladder + the W55 adaptive-legibility @container style(--glass-backdrop: light) bucket (co-located with its rung) + the .glass-opaque escape + the content-aware under-shadow.
3
+ Carved from the glass.css cascade root; @import-ed by glass.css in cascade
4
+ order, each in its own @layer components (isomorphic to the monolith).
5
+ See docs/precepts/design-idioms.md §cohesion-aware partials. */
6
+ @layer components {
7
+ /* ── Five-tier surface ladder (v0.8.0; visual only, no geometry) ──
8
+ Tier semantics, alpha-monotonic per R3-spec §A:
9
+ wash ~0.30α + light blur (was `subtle`)
10
+ quiet ~0.50α + medium blur (the missing rung)
11
+ resting ~0.65α + canonical blur (was `default`; the speedtest plate)
12
+ floating ~0.80α + heavier blur (was `elevated`)
13
+ overlay ~0.95α + heaviest blur (NEW; modal-over-modal) */
14
+
15
+ /* The five-rung surface ladder declares the unprefixed
16
+ `backdrop-filter` only IN SOURCE. Authoring both forms manually here
17
+ caused Lightning CSS in Tailwind v4 to dedup-and-keep-prefixed,
18
+ which modern Chromium then dropped from the CSSOM (the prefixed
19
+ alias is parser-rejected post-Chrome 113). AY.W-A11Y-PERF O-2a — the
20
+ build now OWNS the prefix: `vite.style-assets.ts publishStyleAssets()`
21
+ injects the `-webkit-backdrop-filter:` pair into the SHIPPED
22
+ `dist/styles/*.css` as a LAST pass (the source stays unprefixed, so
23
+ the Lightning dedup never sees both forms; the build emits the pair
24
+ after the cascade is assembled). This GUARANTEES the prefix reaches
25
+ dist/ regardless of the consumer's autoprefixer/browserslist — a
26
+ Safari ≤17 engine (webkit-form-only) paints the blur instead of
27
+ silently dropping the unprefixed rule. Verified by
28
+ `proof:webkit-backdrop` (count-parity over the shipped dist). */
29
+ /* AW.W23 — every rung's background composes the adaptive-tint recipe
30
+ (`color-mix(in oklab, <rung bg>, var(--glass-tint-source) var(--glass-tint-
31
+ strength))`). With the default `--glass-tint-strength: 0%` the mix is a
32
+ no-op = byte-identical to the un-tinted rung; a consumer biases the surface
33
+ toward a sampled backdrop hue by setting `--glass-tint-source` + a
34
+ strength ≤30%. oklab is the mwg-preferred tint space (NEVER an
35
+ `oklch(from …)` lightness-shift — browsers don't gamut-map yet). */
36
+ .glass-wash {
37
+ position: relative;
38
+ background: color-mix(in oklab, var(--glass-bg-wash), var(--glass-tint-source) var(--glass-tint-strength));
39
+ backdrop-filter: var(--glass-blur-wash);
40
+ border: 1px solid var(--glass-border-wash);
41
+ box-shadow: var(--glass-material-rim), var(--glass-shadow-wash);
42
+ }
43
+
44
+ /* AL-W10 SLIM under-shadow wiring (tokens.css §AL-W10 SLIM —
45
+ UNDER-SHADOW recipe rungs). Each tier composes its canonical
46
+ iOS Liquid Glass under-shadow (a 0.5px dark hairline along the
47
+ bottom edge reading as glass thickness) as a NON-INSET layer
48
+ PREPENDED to the existing `--glass-shadow-*` recipe — the under-
49
+ shadow lays the floor; the existing shadow stack lays the lift.
50
+ quiet → `--glass-under-shadow-quiet` (0 2px 8px -1px α0.04)
51
+ resting → `--glass-under-shadow-default` (0 4px 16px -2px α0.08)
52
+ floating→ `--glass-under-shadow-vivid` (0 8px 32px -4px α0.12)
53
+ `.glass-wash` is sub-perceptual; `.glass-overlay` is modal-heavy
54
+ — neither composes an under-shadow rung (Y4/Y6/Y7 SLIM retention).
55
+ Spine tier wires its own rung at instrument-chassis.css. */
56
+ .glass-quiet {
57
+ position: relative;
58
+ background: color-mix(in oklab, var(--glass-bg-quiet), var(--glass-tint-source) var(--glass-tint-strength));
59
+ backdrop-filter: var(--glass-blur-quiet);
60
+ border: 1px solid var(--glass-border-quiet);
61
+ box-shadow:
62
+ var(--glass-material-rim),
63
+ var(--glass-under-shadow-quiet),
64
+ var(--glass-shadow-quiet);
65
+ }
66
+
67
+ .glass-resting {
68
+ position: relative;
69
+ background: color-mix(in oklab, var(--glass-bg-resting), var(--glass-tint-source) var(--glass-tint-strength));
70
+ backdrop-filter: var(--glass-blur-resting);
71
+ border: 1px solid var(--glass-border-resting);
72
+ box-shadow:
73
+ var(--glass-material-rim),
74
+ var(--glass-under-shadow-default),
75
+ var(--glass-shadow-resting);
76
+ }
77
+
78
+ /* AV.W15 M3 / AW.W22 — the floating tier carries the full-perimeter rim (the
79
+ catch-light that "defines the silhouette", WWDC25 sess. 219). The rim now
80
+ comes from the unified `--glass-material-rim` (= `--glass-edge-light`) so
81
+ it shares ONE source with the rest of the ladder; it rides INSIDE the
82
+ box-shadow stack so it composes with the under-shadow floor + the lift. */
83
+ .glass-floating {
84
+ /* AY.W-A11Y-PERF O-1 — engage the W55 bright-backdrop bucket BY DEFAULT on
85
+ the overlay band: a floating surface floats over WHATEVER the consumer
86
+ painted (frequently a light/near-white app surface — the canonical G2
87
+ case), so the library opts its own overlay-band glass in at its own root
88
+ via the SELF-CONTAINER reach below (`.glass-floating { --glass-backdrop }`
89
+ + `:where(.glass-floating) > * `-less: the rung re-points its OWN tint
90
+ through the companion self-rule, not only the ancestor @container). `dark`
91
+ (the :root default at tokens.css) stays the explicit per-surface override a
92
+ dark-substrate consumer dials in on an ancestor. */
93
+ --glass-backdrop: light;
94
+ position: relative;
95
+ background: color-mix(in oklab, var(--glass-bg-floating), var(--glass-tint-source) var(--glass-tint-strength));
96
+ backdrop-filter: var(--glass-blur-floating);
97
+ border: 1px solid var(--glass-border-floating);
98
+ box-shadow:
99
+ var(--glass-material-rim),
100
+ var(--glass-under-shadow-vivid),
101
+ var(--glass-shadow-floating);
102
+ }
103
+
104
+ .glass-overlay {
105
+ /* AY.W-A11Y-PERF O-1 — the overlay band engages the W55 bucket by default
106
+ (see .glass-floating). */
107
+ --glass-backdrop: light;
108
+ position: relative;
109
+ background: color-mix(in oklab, var(--glass-bg-overlay), var(--glass-tint-source) var(--glass-tint-strength));
110
+ backdrop-filter: var(--glass-blur-overlay);
111
+ border: 1px solid var(--glass-border-overlay);
112
+ box-shadow: var(--glass-material-rim), var(--glass-shadow-overlay);
113
+ }
114
+
115
+ /* ── Adaptive legibility: the bright-backdrop bucket (AX.W55 — the iOS-26/27
116
+ "locally darken the glass over light content" move; G2) ──────────────────
117
+ When a consumer sets `--glass-backdrop: light` on any ancestor (a near-white
118
+ card surface, a pale aurora bleed, a bright data grid), the `@container
119
+ style()` read engages here and LIFTS the tint toward ink: `--glass-tint-
120
+ strength` climbs from the `0%` rest default to the bounded AA floor
121
+ (`--glass-tint-strength-aa`, ≤24% — translucent floor preserved) and `--glass-
122
+ tint-source` re-points from `var(--card)` to the warm-ink `--glass-tint-ink`.
123
+ Both are INHERITING custom properties the rungs' `background:` composite
124
+ already reads, so re-pointing them on the material group re-resolves the
125
+ EXISTING `color-mix(in oklab, <rung bg>, …)` toward ink — ZERO new compositing
126
+ seam, the literal darken-over-light recipe. The `.glass-*::before` specular
127
+ `plus-lighter` gleam (W52) is untouched (it composes ON the darkened plate;
128
+ the darkening is the orthogonal oklab-tint axis). No `@supports` wrapper:
129
+ style queries introduce no new `container-type` value (every element is a
130
+ style container by default), so an engine without style-query support parses
131
+ the unknown at-rule as invalid, drops the block, and keeps the zero-delta
132
+ glass (the graceful degradation — the surface is today's-glass, the pre-W55
133
+ state; see utilities.css §density for the same precedent). */
134
+ @container style(--glass-backdrop: light) {
135
+ .glass-material,
136
+ .glass-wash,
137
+ .glass-quiet,
138
+ .glass-resting,
139
+ .glass-floating,
140
+ .glass-overlay,
141
+ .glass-card {
142
+ --glass-tint-source: var(--glass-tint-ink);
143
+ --glass-tint-strength: var(--glass-tint-strength-aa);
144
+ }
145
+ }
146
+
147
+ /* AY.W-A11Y-PERF O-1 — SELF-ENGAGE the overlay band by default. The
148
+ `@container style()` rule above queries an ANCESTOR (CSS style queries never
149
+ self-match — verified on Chrome 148), so the `.glass-floating { --glass-backdrop:
150
+ light }` default we set on the rung would NOT darken the rung's OWN surface, only
151
+ its descendants. AND the `:root` library default is `--glass-backdrop: dark`
152
+ (tokens.css), so a `@container style(--glass-backdrop: dark)` revert would ALWAYS
153
+ fire (every element has the dark :root as an ancestor) — it cannot distinguish an
154
+ explicit consumer `dark` from the default. So the overlay band self-engages
155
+ UNCONDITIONALLY as the library default: a floating/overlay surface floats over
156
+ WHATEVER the consumer painted (frequently a light/near-white app surface — the
157
+ canonical G2 case the user reported), so darkening the translucent plate toward
158
+ the warm-ink is the correct default. This re-points the tint tokens DIRECTLY on
159
+ the overlay-band surfaces (`.glass-floating` / `.glass-overlay` — the Dialog/
160
+ Sheet/Popover/DropdownMenu/HoverCard/Command/Tooltip/Toast/Select-content band),
161
+ engaging the SAME oklab tint axis (zero new compositing seam). Over a DARK page
162
+ the darken is sub-perceptual (warm-ink over an already-dark plate is a small
163
+ shift); a dark-substrate consumer who wants the pristine plate sets
164
+ `--glass-tint-strength: 0%` on the overlay band or uses `.glass-opaque`. SCOPED
165
+ to the overlay band ONLY — NOT `.glass-card`/`.glass-resting`/`.glass-dock`, so
166
+ the W55 default-path byte-identity canary (which tests those KINDS with a bare
167
+ no-ancestor div) stays GREEN; and the in-srgb `--surface-tint-*` family is never
168
+ touched (this edits only the in-oklab glass tint axis). */
169
+ :where(.glass-floating, .glass-overlay) {
170
+ --glass-tint-source: var(--glass-tint-ink);
171
+ --glass-tint-strength: var(--glass-tint-strength-aa);
172
+ }
173
+
174
+ /* AX.W55 — the `contrast-color()` foreground-ink flip (Chrome 147+/Safari 26+).
175
+ A PROGRESSIVE-ENHANCEMENT layer, NEVER the load-bearing floor (Open-Q #5
176
+ ratified): the declarative bucket above already carries AA on ALL engines (it
177
+ darkens the translucent plate so dark text clears ~11:1 over white at the 18%
178
+ floor — the live π readback ratifies). On a supporting engine `contrast-color()`
179
+ REFINES the foreground-ink pick natively, anchored on the LIGHT BACKDROP signal
180
+ (`--card`, the warm-white surface base the bright bucket implies) — NOT on the
181
+ ink. `contrast-color(var(--card))` over the light backdrop resolves to the
182
+ maximally-legible DARK ink (anchoring on the dark ink instead would invert to
183
+ white, illegible on the still-light translucent plate). The bucket is the floor;
184
+ this is the native refinement. Scoped to the bright bucket. */
185
+ @supports (color: contrast-color(white)) {
186
+ @container style(--glass-backdrop: light) {
187
+ .glass-material,
188
+ .glass-wash,
189
+ .glass-quiet,
190
+ .glass-resting,
191
+ .glass-floating,
192
+ .glass-overlay,
193
+ .glass-card {
194
+ color: contrast-color(var(--card));
195
+ }
196
+ }
197
+ /* AY.W-A11Y-PERF O-1 — the same contrast-color refinement for the
198
+ SELF-ENGAGED overlay band (the @container block above queries an ancestor;
199
+ the overlay band engages its own tint unconditionally, so its ink-flip
200
+ companion mirrors that). Progressive enhancement only — the declarative
201
+ darken above is the AA floor on all engines. */
202
+ :where(.glass-floating, .glass-overlay) {
203
+ color: contrast-color(var(--card));
204
+ }
205
+ }
206
+
207
+ /* ── The opaque escape (AX.W54) ───────────────────
208
+ The level-0 endpoint of the SAME glass machinery — a solid `--card` plate
209
+ (the opacity seam → 1) with `blur(0)` (the blur seam → 0), routed through
210
+ the ONE `--glass-level` knob. NOT a parallel solid `background:` recipe:
211
+ a `.glass-*` surface that ALSO carries `.glass-opaque` keeps its glass edge,
212
+ rim, and under-shadow (a solid plate with a glass edge, not a bare div), and
213
+ the @supports fallback + the a11y brackets compose coherently. This is the
214
+ explicit opt-out from the MAXIMAL glass default (dense data, forced-colors,
215
+ a consumer that wants a flat surface). */
216
+ .glass-opaque {
217
+ --glass-level: 0;
218
+ }
219
+
220
+ /* ── Content-aware under-shadow modifier (AV.W15 M4) ──────────────
221
+ Apple raises the under-shadow over text (so the glass reads as
222
+ lifting OFF the text) and drops it over solid light. The modifier
223
+ is ATTRIBUTE-DRIVEN, no JS: a consumer adds `.glass-over-text`
224
+ (or `[data-over-content="text"]`) to a text-bearing glass surface to
225
+ swap it ONE under-shadow rung heavier, or `[data-over-content="solid"]`
226
+ to lighten it one rung over a solid-light backdrop. It reuses the
227
+ existing `--glass-under-shadow-{quiet,default,vivid}` rungs (no new
228
+ shadow value — `vivid` is sufficient over text), redefining only the
229
+ leading under-shadow layer per tier; the lift stack is untouched.
230
+
231
+ The selectors are per-tier so the swap is rung-correct
232
+ (quiet→default, resting→vivid). `.glass-floating` already sits at the
233
+ `vivid` ceiling over text, so the heavier variant is a no-op there
234
+ (the rung saturates) — documented, not an error. */
235
+ .glass-quiet.glass-over-text,
236
+ .glass-quiet[data-over-content="text"] {
237
+ box-shadow: var(--glass-under-shadow-default), var(--glass-shadow-quiet);
238
+ }
239
+ .glass-resting.glass-over-text,
240
+ .glass-resting[data-over-content="text"] {
241
+ box-shadow: var(--glass-under-shadow-vivid), var(--glass-shadow-resting);
242
+ }
243
+
244
+ /* The inverse — over a solid-light backdrop the under-shadow lightens
245
+ one rung (the glass need not lift as hard off a flat bright field). */
246
+ .glass-resting[data-over-content="solid"] {
247
+ box-shadow: var(--glass-under-shadow-quiet), var(--glass-shadow-resting);
248
+ }
249
+ .glass-floating[data-over-content="solid"] {
250
+ box-shadow:
251
+ var(--glass-material-rim),
252
+ var(--glass-under-shadow-default),
253
+ var(--glass-shadow-floating);
254
+ }
255
+
256
+ /* Grain noise overlay — reuses paper texture SVG, no extra assets */
257
+ .glass-wash::after,
258
+ .glass-quiet::after,
259
+ .glass-resting::after,
260
+ .glass-floating::after,
261
+ .glass-overlay::after {
262
+ content: '';
263
+ position: absolute;
264
+ inset: 0;
265
+ border-radius: inherit;
266
+ background: var(--paper-clean-texture);
267
+ background-repeat: repeat;
268
+ background-size: var(--paper-texture-size);
269
+ opacity: var(--glass-grain-opacity);
270
+ pointer-events: none;
271
+ mix-blend-mode: overlay;
272
+ }
273
+
274
+ /* (b) The unified rim — `--glass-edge-light` full-perimeter inset ring on
275
+ EVERY material surface (AW.W22). Previously the rim was wired only into
276
+ the floating/overlay tiers' box-shadow stack; promoting it to the material
277
+ group makes wash/quiet/resting/card/dock-control all carry the same
278
+ silhouette catch-light from ONE token. The rim is its OWN `box-shadow`
279
+ declaration on the material group so it composes uniformly without
280
+ perturbing each tier's elevation recipe (the floating/overlay tiers drop
281
+ their now-redundant inline `--glass-edge-light` layer below). The alpha is
282
+ deliberately low so the rim never eats AA legibility over a busy
283
+ backdrop. */
284
+ .glass-material,
285
+ .glass-wash,
286
+ .glass-quiet,
287
+ .glass-resting,
288
+ .glass-floating,
289
+ .glass-overlay,
290
+ .glass-card,
291
+ .glass-specular-track,
292
+ .dock-icon-button {
293
+ --glass-material-rim: var(--glass-edge-light);
294
+ }
295
+
296
+ .dark .glass-wash::after,
297
+ .dark .glass-quiet::after,
298
+ .dark .glass-resting::after,
299
+ .dark .glass-floating::after,
300
+ .dark .glass-overlay::after {
301
+ mix-blend-mode: soft-light;
302
+ }
303
+
304
+ }
@@ -0,0 +1,238 @@
1
+ /* glass/material.css
2
+ The unified .glass-material atom (AW.W22) + the shared ::before grain/specular wiring across the glass family — ONE source for the three material atoms.
3
+ Carved from the glass.css cascade root; @import-ed by glass.css in cascade
4
+ order, each in its own @layer components (isomorphic to the monolith).
5
+ See docs/precepts/design-idioms.md §cohesion-aware partials. */
6
+ @layer components {
7
+ /* ── The unified glass material (AW.W22) ──────────────────────────────
8
+ ONE source for the three material atoms that AV.W15 scattered onto
9
+ opt-in classes + single tiers:
10
+ (a) the moving-specular `::before` catch-light (folded here from
11
+ glass-specular-track.css — that file now keeps only the thin
12
+ `.glass-specular-track` ALIAS + the brackets that point HERE),
13
+ (b) the `--glass-edge-light` full-perimeter rim (moved off the
14
+ floating-only block so EVERY rung carries it),
15
+ (c) the pointer interaction-light hooks (the `--specular-*`
16
+ `@property` channel mapped from the consumer's --mouse-x/--mouse-y
17
+ write).
18
+ The five ladder rungs + `.glass-card` + the `.dock-icon-button` CONTROL
19
+ compose `.glass-material`, so a Switch thumb, a glass Button, a Dialog,
20
+ and a Sheet all read as the SAME material without per-component wiring.
21
+
22
+ The `.glass-dock` SHELL is OUT of this group BY DESIGN — it hand-rolls a
23
+ parallel surface (its own `--glass-*-dock` family + a local rim + an
24
+ instrument-strip `::before`) the dock arm owns. The COHESION CONSEQUENCE is
25
+ DELIBERATE: the dock shell carries NO shared edge-gleam / moving-specular
26
+ `::before` (its only `::before` is the `variant-instrument-strip` engraved
27
+ bezel, dock/shell.css — a different effect). The dock's catch-light lives on
28
+ its CONTROLS (`.dock-icon-button` et al., listed below + in the opt-in
29
+ transition block), which ARE in the material group — NOT on the shell plate.
30
+ Adding a shell gleam would re-introduce glass-on-glass over the controls, so
31
+ the shell-without-gleam is a NAMED EXEMPTION, gated as `dock-shell-exempt` in
32
+ proof:glass-cohesion (the only exemption beside the legibility allowlist).
33
+
34
+ The selector GROUP is the single source. Adding a surface to the band
35
+ material is one comma-entry here, not a new opt-in class string. */
36
+ .glass-material,
37
+ .glass-wash,
38
+ .glass-quiet,
39
+ .glass-resting,
40
+ .glass-floating,
41
+ .glass-overlay,
42
+ .glass-card,
43
+ .glass-specular-track,
44
+ .dock-icon-button,
45
+ .dock-tab-button,
46
+ .dock-select-trigger,
47
+ .dock-dropdown-trigger {
48
+ position: relative;
49
+ }
50
+
51
+ /* (b) The rim — UNIFORM across all rungs (ONE `--glass-edge-light` token,
52
+ not a per-rung family). The floating/overlay tiers previously wired it
53
+ into their box-shadow stack; it now rides the material group as a
54
+ dedicated `::after` inset ring so it composes alongside (not inside) each
55
+ tier's own shadow recipe. The `::after` grain overlay already claims the
56
+ five rungs' `::after`; the rim is folded INTO that same overlay's
57
+ box-shadow below (the grain `::after` gets the rim inset ring) so no
58
+ pseudo-element collides. */
59
+
60
+ /* (a)+(c) The moving-specular `::before` catch-light — the iOS-26
61
+ illuminate-from-within behaviour. A masked radial-gradient glow rides the
62
+ surface at the pointer position (--mouse-x/--mouse-y → the typed
63
+ --specular-* channel). Folded VERBATIM from glass-specular-track.css so
64
+ there is exactly ONE specular source. */
65
+ .glass-material::before,
66
+ .glass-wash::before,
67
+ .glass-quiet::before,
68
+ .glass-resting::before,
69
+ .glass-floating::before,
70
+ .glass-overlay::before,
71
+ .glass-card::before,
72
+ .glass-specular-track::before,
73
+ .dock-icon-button::before,
74
+ .dock-tab-button::before,
75
+ .dock-select-trigger::before,
76
+ .dock-dropdown-trigger::before {
77
+ content: "";
78
+ position: absolute;
79
+ inset: 0;
80
+ border-radius: inherit;
81
+ pointer-events: none;
82
+ z-index: 1;
83
+ /* Map the consumer's pointer write onto the typed properties, ON THE
84
+ PSEUDO. The `--mouse-x/--mouse-y` write lands on the HOST (inline
85
+ style) as UNREGISTERED props that inherit down to this `::before`;
86
+ the registered `--specular-*` props are `inherits: false`, so the
87
+ mapping is declared HERE where the pseudo owns its typed value. The
88
+ `var(--mouse-x, 50%)` floor is the centred fallback. */
89
+ --specular-x: var(--mouse-x, 50%);
90
+ --specular-y: var(--mouse-y, 50%);
91
+ /* The catch-light intensity at REST — reads the token cohort
92
+ (tokens.css §specular-intensity), default 0 so a static, unwired
93
+ surface is CLEAN and the @property `initial-value: 0` dormancy is no
94
+ longer defeated by a floor. Hover/active lift it through the same
95
+ cohort (the interaction-light state machine below). */
96
+ --specular-intensity: var(--glass-specular-intensity-rest, 0);
97
+ /* AX.W52 D19 — a thin, BOUNDED, pointer-anchored EDGE gleam (not the prior
98
+ full-plate central disc that washed small tiles muddy). The geometry is an
99
+ EXPLICIT-radius circle bounded by `--glass-specular-size` (36% of the
100
+ plate) whose falloff reaches `/0` well INSIDE the plate (70%) — a tracked
101
+ catch-light reading the surface near the lit edge, NEVER a whole-surface
102
+ wash. The core is genuinely WARM-CREAM (L < 100% so the warm hue survives;
103
+ the prior `hsl(40 30% 100%)` blew out to white). The `--specular-intensity`
104
+ multiplier drives the layer `opacity`, NOT a per-stop alpha (a
105
+ registered-`@property` var() nested in an hsl() alpha computes to 0 in
106
+ Chromium — the cross-engine-safe path); the per-stop alphas are literals so
107
+ even the lifted hover/active states read as a lens, not a flash. */
108
+ background: radial-gradient(
109
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
110
+ hsl(40 35% 92% / 0.5) 0%,
111
+ hsl(40 35% 92% / 0) 70%,
112
+ transparent 100%
113
+ );
114
+ opacity: var(--specular-intensity, 0);
115
+ /* Clip the gleam to ITS OWN radius (not the whole plate) so it stays a
116
+ bounded glint. `mask-image` Baseline 2023-12-07; a non-supporting engine
117
+ ignores it and the `inset: 0` + radius-inherit + the in-paint falloff
118
+ already bound the gleam to the surface. */
119
+ mask-image: radial-gradient(
120
+ circle var(--glass-specular-size, 36%) at var(--specular-x, 50%) var(--specular-y, 50%),
121
+ black 0%,
122
+ black 60%,
123
+ transparent 100%
124
+ );
125
+ /* AX.W52 D19 — `plus-lighter` (additive but HDR-clamped, Safari 16.4+) over
126
+ the prior `screen` (a non-linear lightener that lifted the whole tile
127
+ toward white — the muddy-card defect). A non-supporting engine degrades to
128
+ a plain low-alpha warm overlay (the gleam composes normally — no blend, no
129
+ blowout), the no-workaround floor; NOT a `screen` fallback. */
130
+ mix-blend-mode: plus-lighter;
131
+ /* The moving-specular TRANSITION is NOT declared here. An idle/unwired
132
+ `::before` is STATIC (no interpolation track), so a bare glass rung / an
133
+ un-armed Card / a glass Button at rest attaches ZERO animation tracks (the
134
+ keyframes.js runtime counts 0 idle tracks, not 19). The transition rides
135
+ ONLY the WIRED + interactive surfaces — the opt-in scoped block below. */
136
+ }
137
+
138
+ /* AY.W-GLASS — the moving-specular transition is OPT-IN (the Card wire-or-omit
139
+ pattern, generalized). It attaches ONLY to a WIRED surface
140
+ (`.glass-specular-track` — Card emits it conditionally, the dock controls + the
141
+ Slider thumb compose it) OR to any glass surface under `:hover`/`:active` (the
142
+ pointer is present, so the interpolation is legitimately live). An idle/unwired
143
+ `.glass-floating` / `.glass-wash` / bare-rung `::before` carries NO transition
144
+ and thus NO keyframes.js track. The §6 register is PRESERVED (still
145
+ `--ease-standard` on the position-tracked + surface-opacity legs — H-motion §6
146
+ "position-tracked → --ease-standard"; only the SELECTOR scope changes). The dock
147
+ controls keep the always-on transition (they are interactive controls; their rest
148
+ intensity is 0 so they paint nothing at rest, but a control legitimately carries
149
+ the transition). */
150
+ .glass-specular-track::before,
151
+ .glass-material:hover::before, .glass-material:active::before,
152
+ .glass-wash:hover::before, .glass-wash:active::before,
153
+ .glass-quiet:hover::before, .glass-quiet:active::before,
154
+ .glass-resting:hover::before, .glass-resting:active::before,
155
+ .glass-floating:hover::before, .glass-floating:active::before,
156
+ .glass-overlay:hover::before, .glass-overlay:active::before,
157
+ .glass-card:hover::before, .glass-card:active::before,
158
+ .dock-icon-button::before,
159
+ .dock-tab-button::before,
160
+ .dock-select-trigger::before,
161
+ .dock-dropdown-trigger::before {
162
+ /* Smooth the position + intensity between pointer samples (the typed
163
+ @property regs make the percentage stops interpolable). */
164
+ transition:
165
+ --specular-x var(--duration-fast, 150ms) var(--ease-standard, ease-out),
166
+ --specular-y var(--duration-fast, 150ms) var(--ease-standard, ease-out),
167
+ opacity var(--duration-normal, 240ms) var(--ease-standard, ease-out);
168
+ }
169
+
170
+ .dark .glass-material::before,
171
+ .dark .glass-wash::before,
172
+ .dark .glass-quiet::before,
173
+ .dark .glass-resting::before,
174
+ .dark .glass-floating::before,
175
+ .dark .glass-overlay::before,
176
+ .dark .glass-card::before,
177
+ .dark .glass-specular-track::before,
178
+ .dark .dock-icon-button::before,
179
+ .dark .dock-tab-button::before,
180
+ .dark .dock-select-trigger::before,
181
+ .dark .dock-dropdown-trigger::before {
182
+ /* Softer over the deep canvas — `plus-lighter` still lifts on dark, so the
183
+ `.dark` cohort runs a lower hover/active rung (tokens.css §specular-
184
+ intensity `.dark` arm); the rest rung is already 0 so the dark arm only
185
+ softens hover/active via the cohort. The rest rung re-reads the (dark)
186
+ token here so a dark `:root` override resolves. */
187
+ --specular-intensity: var(--glass-specular-intensity-rest, 0);
188
+ }
189
+
190
+ /* (c) Interaction-light lockstep — hover/active lift the intensity in the
191
+ SAME rungs the scale-press squish keys off, so material-light fires in
192
+ lockstep with the press across every glass surface. Settles back on leave
193
+ via the opacity transition above. */
194
+ .glass-material:hover::before,
195
+ .glass-wash:hover::before,
196
+ .glass-quiet:hover::before,
197
+ .glass-resting:hover::before,
198
+ .glass-floating:hover::before,
199
+ .glass-overlay:hover::before,
200
+ .glass-card:hover::before,
201
+ .glass-specular-track:hover::before,
202
+ .dock-icon-button:hover::before,
203
+ .dock-tab-button:hover::before,
204
+ .dock-select-trigger:hover::before,
205
+ .dock-dropdown-trigger:hover::before {
206
+ --specular-intensity: var(--glass-specular-intensity-hover, 0.1);
207
+ }
208
+ .glass-material:active::before,
209
+ .glass-wash:active::before,
210
+ .glass-quiet:active::before,
211
+ .glass-resting:active::before,
212
+ .glass-floating:active::before,
213
+ .glass-overlay:active::before,
214
+ .glass-card:active::before,
215
+ .glass-specular-track:active::before,
216
+ .dock-icon-button:active::before,
217
+ .dock-tab-button:active::before,
218
+ .dock-select-trigger:active::before,
219
+ .dock-dropdown-trigger:active::before {
220
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
221
+ }
222
+
223
+ /* AX.W45-TUNE C5 — the SELECTED dock control reads as the keyframes-dock glass
224
+ register: a glass-tier active fill (`--dock-control-active-bg` → the floating
225
+ plate, tokens.css) WITH the specular gleam waking over it, not a flat ink
226
+ stamp. The CSS `:active` pseudo above only fires on press-down; a SELECTED tile
227
+ (`.is-active` / `[aria-pressed]` / `[aria-expanded]` / `[aria-current]`) holds
228
+ the gleam lit so the selected element reads as a lit glass tier the substrate
229
+ shows through (the model the user named, `pass-3:13`). Family-scoped addition
230
+ on the dock-control `::before`, line-disjoint from the shared recipe above. */
231
+ .dock-icon-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
232
+ .dock-tab-button:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
233
+ .dock-select-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before,
234
+ .dock-dropdown-trigger:is(.is-active, .active, [aria-pressed="true"], [aria-expanded="true"], [aria-current="page"])::before {
235
+ --specular-intensity: var(--glass-specular-intensity-active, 0.16);
236
+ }
237
+
238
+ }
@@ -0,0 +1,78 @@
1
+ /* glass/progress-rail.css
2
+ The @utility glass-progress-rail — restyles <Progress variant=default> into the deck-position rail. A @utility (not @layer components) so it outranks the variant's baked h-4/rounded-pill utilities.
3
+ Carved from the glass.css cascade root; @import-ed by glass.css in cascade
4
+ order, each in its own @layer components (isomorphic to the monolith).
5
+ See docs/precepts/design-idioms.md §cohesion-aware partials. */
6
+ /* ── Deck-position rail (AW.W16 · AX.W24) ───────────────────────────────────
7
+ A Tailwind `@utility` that RESTYLES the shipped `<Progress variant="default">`
8
+ (the reka-ui ProgressRoot track + its indicator child) into the thin
9
+ bottom-of-deck position rail. It composes the EXISTING fill — it does NOT
10
+ re-author a second track/range mechanic. Every visual axis is a
11
+ `--progress-rail-*` token, so a consumer/dark-flip re-tints with zero library
12
+ edit (`:root { --progress-rail-fill: … }`). The viewport-pinned chrome
13
+ (`position: fixed`, `env(safe-area-inset-bottom)`, the z-index) is CONSUMER-
14
+ supplied — this recipe owns only the LOOK.
15
+
16
+ AX.W24 — WHY `@utility`, not `@layer components`. The rail RESTYLES the default
17
+ Progress: it must override the `h-4` height + `rounded-pill` radius utilities the
18
+ variant bakes. Those utilities live in `@layer utilities`, which ALWAYS outranks
19
+ `@layer components` regardless of source order, so the prior `@layer components`
20
+ recipe's `height: 3px` was a silent no-op (the rail painted as a 16px bar). An
21
+ `@utility` lands the recipe IN `@layer utilities` alongside `h-4`, where a single-
22
+ class selector wins the geometry by source order — the idiomatic Tailwind-v4 way
23
+ to author a restyle-class that out-ranks base utilities (the `btn-audacious` /
24
+ `cartoon-surface` pattern).
25
+
26
+ The COLOUR fix is the SEPARATE token-read-at-source path (NOT a layer-juggle):
27
+ `ProgressDefault` reads `--progress-fill`/`--progress-track` and dropped its
28
+ `bg-secondary`/`bg-primary` utilities, so this recipe FEEDS those tokens rather
29
+ than fighting a utility colour. The `--progress-fill` set on the rail root cascades
30
+ to the indicator child (a CSS custom property inherits), so the indicator reads the
31
+ override hue. */
32
+ @utility glass-progress-rail {
33
+ /* The track hairline + zero radius — the rail reads as a thin square sliver, not
34
+ the variant's 16px `rounded-pill` bar. A single-class @utility ties `h-4`/
35
+ `rounded-pill` on SPECIFICITY (both 0,1,0) and Tailwind's utility sort can emit
36
+ `h-4` later, so the bare tie loses. The doubled-class self-reference (`&&` →
37
+ `.glass-progress-rail.glass-progress-rail`, specificity 0,2,0) wins the geometry
38
+ DETERMINISTICALLY over the base utilities regardless of emit order — the precise,
39
+ contained way to out-rank a base utility without `!important`. */
40
+ && {
41
+ height: var(--progress-rail-h, 3px);
42
+ border-radius: 0;
43
+ }
44
+ /* Feed the token-read default variant — these route the consumer's
45
+ `--progress-rail-*` axes into the `--progress-fill`/`--progress-track` tokens
46
+ the variant reads at source (the cascade-correct colour path). */
47
+ --progress-track: var(
48
+ --progress-rail-track,
49
+ color-mix(in srgb, var(--foreground) 8%, transparent)
50
+ );
51
+ --progress-fill: var(--progress-rail-fill, var(--primary));
52
+
53
+ /* The fill — the shipped ProgressIndicator child. The indicator paints the
54
+ inherited `--progress-fill`; the leading-edge glow is re-authored (AX.W24 F2)
55
+ as a TRAILING right-edge INSET box-shadow that lives INSIDE the indicator's
56
+ own box. The prior `4px 0 8px` OUTSET rightward shadow extended PAST the fill
57
+ boundary into the ProgressRoot's load-bearing `overflow-hidden` clip and was
58
+ eaten — invisible at every value. An `inset` shadow offset leftward
59
+ (`inset -Npx 0 …`) brightens just inside the indicator's right (leading) edge
60
+ — the moving position head — and never crosses the fill boundary, so the clip
61
+ cannot eat it (the clip is never lifted; that would re-break the default
62
+ Progress look for every other consumer). `box-shadow` is a separate property
63
+ from `background`, so it composes cleanly over the token-read fill. */
64
+ && > * {
65
+ border-radius: 0;
66
+ box-shadow:
67
+ inset
68
+ calc(-1 * var(--progress-rail-glow-x, 4px))
69
+ 0
70
+ var(--progress-rail-glow-blur, 8px)
71
+ calc(-1 * var(--progress-rail-glow-spread, 2px))
72
+ color-mix(
73
+ in srgb,
74
+ hsl(0 0% 100%) var(--progress-rail-glow-strength, 55%),
75
+ transparent
76
+ );
77
+ }
78
+ }