@mkbabb/glass-ui 3.8.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +1 -6
  2. package/dist/{CardAction-q2qHCJFG.js → CardAction-DuArVky-.js} +4 -4
  3. package/dist/{CommandShortcut-SzWRhROC.js → CommandShortcut-CefCj5mt.js} +7 -7
  4. package/dist/{ContextMenuSubContent-Do977Cbf.js → ContextMenuSubContent-Bhg4f5jX.js} +3 -3
  5. package/dist/{DataTable-CvlWXz65.js → DataTable-CUHMukiQ.js} +1 -1
  6. package/dist/{DialogContent-DjZWT3lK.js → DialogContent-BRkT1cjP.js} +1 -1
  7. package/dist/{MetricBadge-lTc002u2.js → MetricBadge-BZVWIxNy.js} +6 -4
  8. package/dist/{Notification-BxK8LZMw.js → Notification-DLMhblXR.js} +2 -2
  9. package/dist/{NumberFieldContent-CLNVR1iY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  10. package/dist/{SelectScrollDownButton-C7TRe-ep.js → SelectScrollDownButton-T32cVFeM.js} +3 -3
  11. package/dist/{SelectSeparator-L8pPEn4L.js → SelectSeparator-C4Ql0gzV.js} +1 -1
  12. package/dist/{Switch-LDKLmmgx.js → Switch-Ch-k3Rv-.js} +1 -1
  13. package/dist/{TabsList-qyHZ2lKY.js → TabsList-B8CVOQPC.js} +2 -2
  14. package/dist/{Toaster-CabYEEF_.js → Toaster-1rYWrmAm.js} +1 -1
  15. package/dist/{ToggleGroupItem-CkXUcBlt.js → ToggleGroupItem-Cev4pOVK.js} +4 -4
  16. package/dist/animated-digit.js +1 -1
  17. package/dist/api/index.d.ts +2 -1
  18. package/dist/api.js +1 -1
  19. package/dist/aurora.js +236 -545
  20. package/dist/{badge-DHQrc_GQ.js → badge-CaoFJzRb.js} +5 -5
  21. package/dist/badge.js +1 -1
  22. package/dist/{button-CAywcrhO.js → button-DN39cGqL.js} +13 -12
  23. package/dist/button.js +1 -1
  24. package/dist/card.js +1 -1
  25. package/dist/carousel.js +1 -1
  26. package/dist/color.js +1 -1
  27. package/dist/command.js +1 -1
  28. package/dist/{compile-BBTRjvQS.js → compile-BOXjLUxu.js} +24 -24
  29. package/dist/components/custom/aurora/composables/atoms.d.ts +21 -4
  30. package/dist/components/custom/aurora/composables/runtime.d.ts +0 -9
  31. package/dist/components/custom/aurora/composables/uniformBridge.d.ts +0 -11
  32. package/dist/components/custom/aurora/constants/renderMode.d.ts +0 -32
  33. package/dist/components/custom/aurora/constants/shaders/brush.glsl.d.ts +1 -1
  34. package/dist/components/custom/aurora/constants/shaders/mediums.glsl.d.ts +2 -2
  35. package/dist/components/custom/aurora/constants/shaders/tonemap.glsl.d.ts +1 -1
  36. package/dist/components/custom/aurora/index.d.ts +1 -1
  37. package/dist/components/custom/configurator/ConfiguratorLayer.vue.d.ts +1 -1
  38. package/dist/components/custom/constellation/Constellation.vue.d.ts +73 -1
  39. package/dist/components/custom/constellation/constellationField.d.ts +255 -3
  40. package/dist/components/custom/constellation/index.d.ts +2 -2
  41. package/dist/components/custom/dock/DockSeparator.vue.d.ts +3 -0
  42. package/dist/components/custom/dock/DockTabButton.vue.d.ts +4 -3
  43. package/dist/components/custom/dock/GlassDock.vue.d.ts +45 -63
  44. package/dist/components/custom/dock/composables/dockContext.d.ts +7 -0
  45. package/dist/components/custom/dock/index.d.ts +2 -1
  46. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +29 -0
  47. package/dist/components/custom/fourier-field/FourierField.vue.d.ts +6 -0
  48. package/dist/components/custom/fourier-field/index.d.ts +25 -1
  49. package/dist/components/custom/fourier-field/math.d.ts +3 -8
  50. package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +8 -10
  51. package/dist/components/custom/goo-blob/composables/useBlobMood.d.ts +19 -5
  52. package/dist/components/custom/goo-blob/composables/useMetaballRenderer.d.ts +6 -14
  53. package/dist/components/custom/goo-blob/index.d.ts +1 -1
  54. package/dist/components/custom/goo-blob/types.d.ts +59 -25
  55. package/dist/components/custom/handmark/HandMark.vue.d.ts +29 -0
  56. package/dist/components/custom/handmark/brush.d.ts +219 -0
  57. package/dist/components/custom/handmark/freehand.d.ts +69 -0
  58. package/dist/components/custom/handmark/geometry.d.ts +32 -0
  59. package/dist/components/custom/handmark/index.d.ts +21 -0
  60. package/dist/components/custom/handmark/ink.d.ts +11 -0
  61. package/dist/components/custom/handmark/texture.d.ts +39 -0
  62. package/dist/components/custom/handmark/types.d.ts +53 -0
  63. package/dist/components/custom/handmark/useHandMark.d.ts +66 -0
  64. package/dist/components/custom/metric-badge/MetricBadge.vue.d.ts +8 -0
  65. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +92 -0
  66. package/dist/components/custom/tabs/composables/useTabIndicator.d.ts +49 -0
  67. package/dist/components/custom/tabs/index.d.ts +2 -5
  68. package/dist/components/ui/button/index.d.ts +1 -1
  69. package/dist/components/ui/card/Card.vue.d.ts +5 -3
  70. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  71. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  72. package/dist/components/ui/carousel/GlassCarouselPager.vue.d.ts +3 -4
  73. package/dist/components/ui/slider/index.d.ts +22 -11
  74. package/dist/components/ui/tabs/TabsList.vue.d.ts +1 -1
  75. package/dist/composables/color/index.d.ts +12 -7
  76. package/dist/composables/context/createContext.d.ts +1 -1
  77. package/dist/composables/glass/webgl/shaders/procedural-color.glsl.d.ts +1 -6
  78. package/dist/composables/motion/core/index.d.ts +1 -0
  79. package/dist/composables/motion/useRouteTransition.d.ts +42 -0
  80. package/dist/configurator.js +1 -1
  81. package/dist/confirm-dialog.js +1 -1
  82. package/dist/constellation.js +212 -72
  83. package/dist/context-menu.js +1 -1
  84. package/dist/controls.js +1 -1
  85. package/dist/dark.js +1 -1
  86. package/dist/data-table.js +1 -1
  87. package/dist/deck-progress.js +1 -1
  88. package/dist/dialog.js +1 -1
  89. package/dist/dock.js +257 -243
  90. package/dist/{dropdown-menu-B_4bWyyG.js → dropdown-menu-D77jX6Df.js} +3 -3
  91. package/dist/dropdown-menu.js +1 -1
  92. package/dist/expandable-container.js +61 -38
  93. package/dist/forms.js +5 -5
  94. package/dist/fourier-field.js +89 -97
  95. package/dist/fourier-math.d.ts +1 -0
  96. package/dist/fourier-math.js +2 -0
  97. package/dist/glass-panel.js +1 -1
  98. package/dist/glass-ui.css +1 -1
  99. package/dist/glass-ui.js +107 -109
  100. package/dist/goo-blob.js +316 -297
  101. package/dist/handmark.d.ts +1 -0
  102. package/dist/handmark.js +609 -0
  103. package/dist/hover-popover.js +1 -1
  104. package/dist/icon-tooltip.js +1 -1
  105. package/dist/index.d.ts +1 -2
  106. package/dist/keyboard.js +1 -1
  107. package/dist/labeled-field.js +5 -5
  108. package/dist/math-DTpRVC0e.js +27 -0
  109. package/dist/{menuItemVariants-DKM85SNE.js → menuItemVariants-CCoBNkU5.js} +1 -1
  110. package/dist/metric-badge.js +1 -1
  111. package/dist/metric-stack.js +1 -1
  112. package/dist/motion-core.js +70 -69
  113. package/dist/motion.js +2 -2
  114. package/dist/notification.js +1 -1
  115. package/dist/number-field.js +1 -1
  116. package/dist/pulse.js +1 -1
  117. package/dist/reactive.js +1 -1
  118. package/dist/scrolling-text.js +1 -1
  119. package/dist/search.js +4 -4
  120. package/dist/select.js +2 -2
  121. package/dist/{slider-D9puf-Ko.js → slider-CyzcxBoh.js} +6 -6
  122. package/dist/slider.js +1 -1
  123. package/dist/sortable-list.js +1 -1
  124. package/dist/status-dot.js +17 -16
  125. package/dist/styles/animations.css +80 -20
  126. package/dist/styles/cards.css +2 -2
  127. package/dist/styles/components.css +1 -1
  128. package/dist/styles/dock/density.css +230 -0
  129. package/dist/styles/dock/layer-group.css +275 -0
  130. package/dist/styles/dock/layers.css +355 -0
  131. package/dist/styles/dock/morph.css +244 -0
  132. package/dist/styles/dock/overflow.css +201 -0
  133. package/dist/styles/dock/shell.css +457 -0
  134. package/dist/styles/dock-controls.css +205 -55
  135. package/dist/styles/dock.css +42 -1349
  136. package/dist/styles/drawer.css +12 -4
  137. package/dist/styles/glass.css +535 -78
  138. package/dist/styles/index.css +12 -11
  139. package/dist/styles/paper.css +68 -2
  140. package/dist/styles/theme.css +58 -0
  141. package/dist/styles/tokens.css +601 -69
  142. package/dist/styles/transitions.css +20 -2
  143. package/dist/styles/utilities.css +218 -78
  144. package/dist/styles/view-transition.css +51 -0
  145. package/dist/switch.js +1 -1
  146. package/dist/tabs.js +182 -151
  147. package/dist/timeline.js +1 -1
  148. package/dist/toast.js +1 -1
  149. package/dist/toggle-group.js +1 -1
  150. package/dist/{useAnimatedNumber-C_3wZLx4.js → useAnimatedNumber-Bcpy5Etf.js} +1 -1
  151. package/dist/{useConfiguratorState-CMff4GzH.js → useConfiguratorState-DxAqksK6.js} +21 -10
  152. package/dist/{useGlassRenderer-5I0YkI4t.js → useGlassRenderer-D7YGOYiM.js} +1 -1
  153. package/dist/useViewTransition-DaN5Zrox.js +21 -0
  154. package/dist/vReveal-zUIQk-rJ.js +53 -0
  155. package/dist/watercolor-dot.js +1 -1
  156. package/package.json +80 -39
  157. package/src/styles/animations.css +80 -20
  158. package/src/styles/cards.css +2 -2
  159. package/src/styles/dock/density.css +230 -0
  160. package/src/styles/dock/layer-group.css +275 -0
  161. package/src/styles/dock/layers.css +355 -0
  162. package/src/styles/dock/morph.css +244 -0
  163. package/src/styles/dock/overflow.css +201 -0
  164. package/src/styles/dock/shell.css +457 -0
  165. package/src/styles/dock-controls.css +205 -55
  166. package/src/styles/dock.css +42 -1349
  167. package/src/styles/drawer.css +12 -4
  168. package/src/styles/glass.css +535 -78
  169. package/src/styles/index.css +12 -11
  170. package/src/styles/paper.css +68 -2
  171. package/src/styles/theme.css +58 -0
  172. package/src/styles/tokens.css +601 -69
  173. package/src/styles/transitions.css +20 -2
  174. package/src/styles/utilities.css +218 -78
  175. package/src/styles/view-transition.css +51 -0
  176. package/dist/DiscoGlyph-CG0F410s.js +0 -132
  177. package/dist/GlyphFace-DRjDkB0s.js +0 -51
  178. package/dist/UnderlineTabs-Uxn-R3MT.js +0 -39
  179. package/dist/components/custom/aurora/composables/gpuRuntime.d.ts +0 -16
  180. package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +0 -7
  181. package/dist/components/custom/aurora/constants/shaders/painterly.wgsl.d.ts +0 -7
  182. package/dist/components/custom/aurora/constants/shaders/wake.wgsl.d.ts +0 -4
  183. package/dist/components/custom/disco-glyph/DiscoGlyph.vue.d.ts +0 -58
  184. package/dist/components/custom/disco-glyph/index.d.ts +0 -1
  185. package/dist/components/custom/glass-carousel/GlassCarousel.vue.d.ts +0 -36
  186. package/dist/components/custom/glass-carousel/GlassCarouselItem.vue.d.ts +0 -28
  187. package/dist/components/custom/glass-carousel/index.d.ts +0 -4
  188. package/dist/components/custom/glass-carousel/useGlassCarousel.d.ts +0 -30
  189. package/dist/components/custom/glyph-face/GlyphFace.vue.d.ts +0 -64
  190. package/dist/components/custom/glyph-face/index.d.ts +0 -2
  191. package/dist/components/custom/glyph-face/keys.d.ts +0 -9
  192. package/dist/components/custom/responsive-tabs/ResponsiveTabs.vue.d.ts +0 -73
  193. package/dist/components/custom/responsive-tabs/index.d.ts +0 -2
  194. package/dist/components/custom/tabs/BouncyTabs.vue.d.ts +0 -27
  195. package/dist/components/custom/tabs/BouncyToggle.vue.d.ts +0 -60
  196. package/dist/components/custom/tabs/UnderlineTabs.vue.d.ts +0 -20
  197. package/dist/components/custom/tabs/composables/useBouncySlider.d.ts +0 -39
  198. package/dist/composables/glass/createGPUCanvas.d.ts +0 -40
  199. package/dist/disco-glyph.d.ts +0 -1
  200. package/dist/disco-glyph.js +0 -2
  201. package/dist/glass-carousel.d.ts +0 -1
  202. package/dist/glass-carousel.js +0 -219
  203. package/dist/glyph-face.d.ts +0 -1
  204. package/dist/glyph-face.js +0 -3
  205. package/dist/keys-BsYjEFOW.js +0 -9
  206. package/dist/responsive-tabs.d.ts +0 -1
  207. package/dist/responsive-tabs.js +0 -95
  208. package/dist/styles/disco-glyph.css +0 -26
  209. package/dist/styles/glyph-face.css +0 -92
  210. package/dist/vReveal-CqaCz_mC.js +0 -44
  211. package/src/styles/disco-glyph.css +0 -26
  212. package/src/styles/glyph-face.css +0 -92
  213. /package/dist/{DeckProgress-AVgbIULY.js → DeckProgress-Dmk4_AKN.js} +0 -0
  214. /package/dist/{HoverPopover-D56O6Ylp.js → HoverPopover-2LOIW34a.js} +0 -0
  215. /package/dist/{IconTooltip-D2T5nYOM.js → IconTooltip-Cus0fvK0.js} +0 -0
  216. /package/dist/{Input-DVG_J0ne.js → Input-xuDwALQR.js} +0 -0
  217. /package/dist/{ScrollingText-CVyqxvfv.js → ScrollingText-BPP84wKo.js} +0 -0
  218. /package/dist/{color-DMLTunJK.js → color-C5ls_QF7.js} +0 -0
  219. /package/dist/{constants-BPOqYJAm.js → constants-yKeKnE84.js} +0 -0
  220. /package/dist/{presets-D1XPuTj-.js → presets-Dkdv55Gt.js} +0 -0
  221. /package/dist/{prng-COGhh02-.js → prng-D27-B3tK.js} +0 -0
  222. /package/dist/{useGlobalDark-D3EBWzXK.js → useGlobalDark-d6waty-X.js} +0 -0
  223. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Cck5Uxk8.js} +0 -0
  224. /package/dist/{useInterval-CcLfq2WU.js → useInterval-Dsmqwi03.js} +0 -0
  225. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-CyIYrndH.js} +0 -0
  226. /package/dist/{useScrollProgress-C9ysDic5.js → useScrollProgress-CffFGLa5.js} +0 -0
  227. /package/dist/{useSortable-MGAbCGVJ.js → useSortable-C8ReQ50P.js} +0 -0
  228. /package/dist/{useTextHighlight-9nMW23Qb.js → useTextHighlight-CWEi25hf.js} +0 -0
@@ -80,9 +80,12 @@
80
80
  --duration-xxl: 1.5s;
81
81
  --duration-shimmer-fast: 3s;
82
82
  --duration-shimmer: 5s;
83
- /* Sparkle micro-event — primary-CTA disco-grain sparkle sweep, success
84
- affirmations. R5 vocab.γ gap row 3 (single-site at dock.css:735 today,
85
- reserved for J.W2.7 §17 audacious-CTA buildout). */
83
+ /* Sparkle micro-event — primary-CTA disco-grain sparkle sweep.
84
+ @deprecated 3.10 — the disco-star is EXCISED (D6.b); the `sparkle-sweep`
85
+ keyframe is tombstoned (animations.css) and no live recipe consumes this
86
+ duration. Retained one minor so an out-of-tree consumer resolves a value
87
+ rather than `unset`; full delete (this token + the theme bridge + the
88
+ keyframe) lands in 3.11. */
86
89
  --duration-sparkle: 600ms;
87
90
 
88
91
  /* AH.W5-e (FA-8 §4d) — motion-duration + staged-reveal canon.
@@ -158,6 +161,35 @@
158
161
  `smooth` wants a slightly faster visual settle than `gentle`'s
159
162
  patient curve. The 0.5% peak does not read as overshoot to the
160
163
  eye but does narrowly distinguish `smooth` from `gentle`.
164
+
165
+ ── EASING DOCTRINE (AX.W52 §6 — which easing fits which job) ──
166
+ ONE recorded rule so the animation easing stops forking live. This
167
+ FORMALIZES the already-correct `transitions.css` idiom (enter=spring,
168
+ exit=bezier) as the house rule every recipe reaches for:
169
+
170
+ | Transition kind | Easing |
171
+ |--------------------------------------------------|-------------------------------------|
172
+ | Surface props (bg, border, color, box-shadow, | `--ease-standard` (bezier — a |
173
+ | opacity) | colour cross-fade reads as a |
174
+ | | wobble on a spring) |
175
+ | Transform — hover/press/active (scale, translate,| `--spring-smooth` (the ONE button/ |
176
+ | rotate) | interactive scale register) or |
177
+ | | `--spring-snappy` (crisp press) |
178
+ | Enter (mount, popover open, dialog in) | `--spring-bouncy` / `--spring-snappy`|
179
+ | Exit (unmount, close) | `--ease-out` / `--ease-standard` |
180
+ | | (bezier, NO overshoot — an exit |
181
+ | | must never overshoot past gone) |
182
+ | Position-tracked (specular pointer follow) | `--ease-standard` |
183
+
184
+ The BUTTON family (`.btn-pill` / `.tap-squish` / `.glass-btn` /
185
+ `btn-interactive`) UNIFIES its `scale` transform leg onto ONE register —
186
+ `--spring-smooth` — so hover + press read as one motion language (the
187
+ hover lift is the restrained `--scale-hover-btn` = 1.05, not the 1.08
188
+ `--scale-hover`). Springs read alive on TRANSFORM and ENTER (overshoot =
189
+ physicality); a spring on a COLOR or an EXIT reads as a wobble/hesitation.
190
+ `--ease-apple` is the ambient-only register (consumed solely by the Pulse
191
+ aura `--animate-ambient-pulse-easing` — NOT a second smooth-ease authority
192
+ for interactive transforms; those use `--spring-smooth`).
161
193
  ═══════════════════════════════════════════════ */
162
194
  --spring-smooth: linear(0, 0.09804 2.041%, 0.29288 4.082%, 0.49447 6.122%, 0.66436 8.163%, 0.79208 10.204%, 0.88050 12.245%, 0.93754 14.286%, 0.97182 16.327%, 0.99083 18.367%, 1.00027 20.408%, 1.00413 22.449%, 1.00502 24.490%, 1.00453 26.531%, 1.00355 28.571%, 1.00254 30.612%, 1.00169 32.653%, 1.00105 34.694%, 1.00060 36.735%, 1.00031 38.776%, 1.00014 40.816%, 1.00005 42.857%, 1.00000 44.898%, 1.00000 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
163
195
  --spring-snappy: linear(0, 0.10438 2.041%, 0.32622 4.082%, 0.56668 6.122%, 0.77153 8.163%, 0.91961 10.204%, 1.01073 12.245%, 1.05549 14.286%, 1.06804 16.327%, 1.06171 18.367%, 1.04686 20.408%, 1.03044 22.449%, 1.01629 24.490%, 1.00596 26.531%, 0.99954 28.571%, 0.99633 30.612%, 0.99537 32.653%, 0.99575 34.694%, 0.99674 36.735%, 0.99786 38.776%, 0.99884 40.816%, 0.99956 42.857%, 1.00001 44.898%, 1.00024 46.939%, 1.00000 48.980%, 1.00000 51.020%, 1.00000 53.061%, 1.00000 55.102%, 1.00000 57.143%, 1.00000 59.184%, 1.00000 61.224%, 1.00000 63.265%, 1.00000 65.306%, 1.00000 67.347%, 1.00000 69.388%, 1.00000 71.429%, 1.00000 73.469%, 1.00000 75.510%, 1.00000 77.551%, 1.00000 79.592%, 1.00000 81.633%, 1.00000 83.673%, 1.00000 85.714%, 1.00000 87.755%, 1.00000 89.796%, 1.00000 91.837%, 1.00000 93.878%, 1.00000 95.918%, 1.00000 97.959%, 1);
@@ -190,17 +222,40 @@
190
222
  Breathing rhythm for `<Pulse variant="aura">`. The 6s duration is the
191
223
  canon ambient-pulse rate; scale 1.0 ↔ 1.15 reads as a quiet halo at
192
224
  intensity="normal" (Pulse remaps min/max from its `intensity` prop).
193
- The aura always keeps a visible halo at the trough (opacity min 0.55).
194
225
  Reduced motion: Pulse.vue parks at the min stop, breath cycle disabled.
195
- ═══════════════════════════════════════════════ */
226
+
227
+ AX.W57 (P6) — the aura re-baselined from a glowing DISC to an AMBIENT
228
+ halo. The egregiousness was doubly-stacked: a 0.55-density currentColor
229
+ radial multiplied by an element opacity the `ambient-pulse` keyframe
230
+ drove up to 0.95 mid-breath (so a saturated viz hue read as a near-
231
+ opaque throbbing blob). The fix is two decoupled, single-source knobs:
232
+ · `--pulse-aura-strength` (0..1) — the ONE gradient-density scalar
233
+ both color-mix stops derive via calc() (replaces the
234
+ `--pulse-aura-opacity-pct` / `-pct-num` twin desync trap — the
235
+ percent and the raw number had to be hand-kept in sync).
236
+ · `--pulse-aura-breath-{min,max}` — the aura's OWN element-opacity
237
+ range, decoupled from the shared `--pulse-aura-opacity-*` shimmer
238
+ tokens (those stay 0.55/0.95 for the neutral skeleton-breath, where
239
+ a grey shimmer at that range is the correct soft swell).
240
+ The loud old read is the explicit `intensity="vivid"` opt-in. */
196
241
  --animate-ambient-pulse-duration: 6s;
197
242
  --animate-ambient-pulse-scale-min: 1.0;
198
243
  --animate-ambient-pulse-scale-max: 1.15;
199
244
  --animate-ambient-pulse-easing: var(--ease-apple);
200
245
 
201
- /* Aura opacity range — keep the trough visible (the colour reads
202
- at every phase of the cycle). Consumers may override per site
203
- (e.g. the completion one-shot uses min=0 to fade out). */
246
+ /* Aura gradient density — ONE scalar (0..1). The center stop paints at
247
+ `strength`, the mid stop at `strength * 0.35` (both via calc() in
248
+ Pulse.vue). 0.22 reads as an ambient wash, not a glowing disc. */
249
+ --pulse-aura-strength: 0.22;
250
+
251
+ /* Aura element-opacity breath range (the `ambient-pulse` keyframe stops).
252
+ Quiet: the halo stays a wash at every phase of the 6s cycle. */
253
+ --pulse-aura-breath-min: 0.28;
254
+ --pulse-aura-breath-max: 0.42;
255
+
256
+ /* Skeleton-breath shimmer range — the SHARED neutral-shimmer stops
257
+ (`.skeleton-breath` reads these; a grey shimmer at 0.55↔0.95 is the
258
+ correct soft swell, distinct from the aura's calmer breath above). */
204
259
  --pulse-aura-opacity-min: 0.55;
205
260
  --pulse-aura-opacity-max: 0.95;
206
261
 
@@ -412,7 +467,7 @@
412
467
 
413
468
  /* Muted-tinted surface rungs — canonical handles for the 9 raw
414
469
  `color-mix(in srgb, var(--muted) N%, transparent)` sites in
415
- FuzzySearch / BouncyToggle / Slider scoped CSS. (AI.W5-δ — the
470
+ FuzzySearch / SegmentedTabs / Slider scoped CSS. (AI.W5-δ — the
416
471
  ProgressiveSidebar consumer retired at the wave; the canonical token
417
472
  rung lives on for the remaining consumers.) Auto-dark via --muted.
418
473
  R5 vocab.γ axis-1 row. */
@@ -459,6 +514,26 @@
459
514
  field recedes further: BELOW the slides 0.92 max-legibility reference. */
460
515
  --constellation-alpha: 0.80;
461
516
 
517
+ /* §interaction — the warp spring + the gravity-well tunings (NUMERIC, NOT
518
+ colors — read ONCE on mount via parseFloat, never reach a Canvas2D
519
+ fillStyle, so immune to the W30 light-dark()/Canvas2D leak; AY.W-CON2).
520
+ Mode-INVARIANT, declared ONCE in :root (the .dark arm needs no numeric
521
+ re-declare — a per-mode value SPLIT is what proof:constellation-tokens
522
+ clause (c) flags, and these tunings are identical in both modes).
523
+ `--constellation-warp-response` is the keyframes.js ANGULAR PERIOD (the
524
+ SwiftUI .spring(response:) axis), NOT a settle-duration — at ζ=1 the 2%
525
+ settle lands at t₂ ≈ 5.83/ω₀ ≈ 0.93·response (the engine keeps the
526
+ keyframes.js ω₀ = 2π/response convention, mints no second ω). */
527
+ --constellation-warp-response: 0.55; /* s — keyframes.js angular period (NOT a settle) */
528
+ --constellation-warp-zeta: 1.0; /* critically damped — a focal mark must NOT ring */
529
+ --constellation-well-gain: 14000; /* inverse-square force scale (the held-pull gain) */
530
+ --constellation-well-reach: 340; /* base-width px — the well's reach (k-scaled at step) */
531
+ --constellation-well-ramp: 4.0; /* 1/s — the ARM rate (≈0.25s bloom; release is the fixed brisk WELL_RELEASE_RAMP — the field-cools invariant, not consumer-tunable) */
532
+ --constellation-well-max-speed: 4.0; /* base-width px/frame cap — the no-slingshot clamp */
533
+ --constellation-well-hold-ms: 140; /* ms hold before the well arms */
534
+ --constellation-wander-idle: 8000; /* ms — min idle between auto re-targets (the W-CON1 drift cadence) */
535
+ --constellation-wander-jitter: 8000; /* ms — random extra idle per cadence (so the rhythm is not metronomic) */
536
+
462
537
  /* ═══════════════════════════════════════════════
463
538
  §6 SECTION PALETTE — 13-stop jewel tones (light)
464
539
  ═══════════════════════════════════════════════ */
@@ -656,7 +731,12 @@
656
731
  opacity-only register. */
657
732
  --glass-blur-dock-radius: 11px;
658
733
 
659
- --glass-blur-wash: blur(var(--glass-blur-wash-radius)) saturate(1.05);
734
+ /* AX.W54 — each blur radius is scaled by the ONE `--glass-level` scalar (in
735
+ lockstep with the opacity seam above): level=1 byte-identical; level=0 →
736
+ blur(0) (the clean solid floor with the opacity); level>1 → more diffusion.
737
+ The per-rung `saturate()`/`brightness()` companions are UNTOUCHED (the level
738
+ scales the RADIUS, not the saturation — W52's calm light-concentration). */
739
+ --glass-blur-wash: blur(calc(var(--glass-blur-wash-radius) * var(--glass-level))) saturate(1.05);
660
740
  /* AV.W15 M1 — the `quiet` rung gained `saturate(1.05) brightness(1.02)`
661
741
  so the lower ladder reads with the same saturation life as `resting`+
662
742
  (Apple: Liquid Glass concentrates light, it does not desaturate). The
@@ -664,12 +744,27 @@
664
744
  between bare `wash` and `resting` without over-brightening the rung.
665
745
  The `prefers-reduced-transparency: reduce` bracket at glass.css maps
666
746
  `--glass-blur-quiet: none`, so this whole chain drops with the blur. */
667
- --glass-blur-quiet: blur(var(--glass-blur-quiet-radius)) saturate(1.05) brightness(1.02);
668
- --glass-blur-resting: blur(var(--glass-blur-resting-radius)) saturate(1.05);
669
- --glass-blur-floating: blur(var(--glass-blur-floating-radius)) saturate(1.4);
670
- --glass-blur-overlay: blur(var(--glass-blur-overlay-radius)) saturate(1.5);
747
+ --glass-blur-quiet: blur(calc(var(--glass-blur-quiet-radius) * var(--glass-level))) saturate(1.05) brightness(1.02);
748
+ --glass-blur-resting: blur(calc(var(--glass-blur-resting-radius) * var(--glass-level))) saturate(1.05);
749
+ /* AX.W52 D19 — the floating/overlay backdrop saturate tamed from 1.4/1.5 to a
750
+ gentle ~1.18/1.2 (real liquid glass concentrates light ~1.1–1.2×; the prior
751
+ 1.4–1.5× over-juiced the bleed-through into a garish smear over a colored
752
+ substrate). wash/quiet/resting already sit at 1.05 — untouched. */
753
+ --glass-blur-floating: blur(calc(var(--glass-blur-floating-radius) * var(--glass-level))) saturate(1.18);
754
+ --glass-blur-overlay: blur(calc(var(--glass-blur-overlay-radius) * var(--glass-level))) saturate(1.2);
671
755
  /* Dock blur composes blur() only — no saturate. */
672
- --glass-blur-dock: blur(var(--glass-blur-dock-radius));
756
+ --glass-blur-dock: blur(calc(var(--glass-blur-dock-radius) * var(--glass-level)));
757
+
758
+ /* AX.W52 — the GLASS BUTTON blur. The `glass`/`glass-wash` button variants
759
+ compose the `.glass-wash` tier (`--glass-blur-wash` = blur(1px)) — a
760
+ sub-perceptual diffusion authored for a small detail TILE, not a button
761
+ the user reads as "glass." A button is a hero control: it wants a real
762
+ glass blur. `--glass-blur-btn` lifts the variant onto the `quiet`-tier
763
+ radius (10px — a genuine liquid-glass diffusion) with the same gentle
764
+ `saturate(1.05) brightness(1.02)` light-concentration the quiet rung
765
+ carries (NOT a colour-juice). The wash TILE tier (MetricCell et al.) keeps
766
+ its 1px — only the glass BUTTON variants reach for this. */
767
+ --glass-blur-btn: blur(calc(var(--glass-blur-quiet-radius) * var(--glass-level))) saturate(1.05) brightness(1.02);
673
768
 
674
769
  /* Dock-specific opacity (0.42) — lighter than `resting` (0.65) so the dock
675
770
  reads as a translucent overlay rather than a panel, backdrop bleed
@@ -686,7 +781,14 @@
686
781
  muted icon weight the control mixes it down with `--opacity-icon-muted`.
687
782
  Defaults to `var(--foreground)` so the dock paints byte-identically to
688
783
  today; a consumer overrides it per-backdrop (e.g. a near-white over a
689
- dark aurora) without touching library source. */
784
+ dark aurora) without touching library source.
785
+
786
+ AX.W55 — this is the FOREGROUND half of the adaptive story, now reconciled
787
+ INTO the `--glass-backdrop` probe (not a third fork): under the bright bucket
788
+ (`@container style(--glass-backdrop: light)` in dock.css) it re-points toward
789
+ the contrast-clearing ink, and an `@supports (color: contrast-color(…))`
790
+ block flips it natively on supporting engines. The `var(--foreground)`
791
+ default keeps the zero-delta rest state. */
690
792
  --dock-fg-on-aurora: var(--foreground);
691
793
 
692
794
  /* Chassis-specific opacity. Looser than `default` (0.50) so the
@@ -698,14 +800,24 @@
698
800
  `glass-bg-medium` (0.65) down to its own 0.32. */
699
801
  --glass-opacity-chassis: 0.28;
700
802
 
701
- /* Composed backgrounds */
702
- --glass-bg-wash: color-mix(in srgb, var(--card) calc(var(--glass-opacity-wash) * 100%), transparent);
703
- --glass-bg-quiet: color-mix(in srgb, var(--card) calc(var(--glass-opacity-quiet) * 100%), transparent);
704
- --glass-bg-resting: color-mix(in srgb, var(--card) calc(var(--glass-opacity-resting) * 100%), transparent);
705
- --glass-bg-floating: color-mix(in srgb, var(--card) calc(var(--glass-opacity-floating) * 100%), transparent);
706
- --glass-bg-overlay: color-mix(in srgb, var(--card) calc(var(--glass-opacity-overlay) * 100%), transparent);
707
- --glass-bg-dock: color-mix(in srgb, var(--card) calc(var(--glass-opacity-dock) * 100%), transparent);
708
- --glass-bg-chassis: color-mix(in srgb, var(--card) calc(var(--glass-opacity-chassis) * 100%), transparent);
803
+ /* Composed backgrounds — AX.W54: the opacity is threaded through the ONE
804
+ `--glass-level` clarity scalar. Each rung's effective alpha is
805
+ `1 - (1 - <rung-opacity>) * --glass-level`: at level=1 it collapses to the
806
+ hand-tuned `<rung-opacity>` (byte-identical); at level=0 it resolves `1`
807
+ (solid `--card` — the opaque escape); at level>1 it goes clearer. ONE
808
+ expression, the same seven rungs. */
809
+ --glass-bg-wash: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-wash)) * var(--glass-level)) * 100%), transparent);
810
+ --glass-bg-quiet: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-quiet)) * var(--glass-level)) * 100%), transparent);
811
+ --glass-bg-resting: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-resting)) * var(--glass-level)) * 100%), transparent);
812
+ --glass-bg-floating: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-floating)) * var(--glass-level)) * 100%), transparent);
813
+ --glass-bg-overlay: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-overlay)) * var(--glass-level)) * 100%), transparent);
814
+ /* The dock bg ALSO rides the oklab tint seam (AX.W54 amendment): the same
815
+ `color-mix(in oklab, …, --glass-tint-source --glass-tint-strength)` wrapper
816
+ the rungs reach for, ZERO-delta at `--glass-tint-strength: 0%` — so W55's
817
+ adaptive darken can reach the dock (the G2 over-light surface) without a
818
+ second hand-rolled recipe. */
819
+ --glass-bg-dock: color-mix(in oklab, color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-dock)) * var(--glass-level)) * 100%), transparent), var(--glass-tint-source) var(--glass-tint-strength));
820
+ --glass-bg-chassis: color-mix(in srgb, var(--card) calc((1 - (1 - var(--glass-opacity-chassis)) * var(--glass-level)) * 100%), transparent);
709
821
 
710
822
  /* Composed borders — foreground-tinted */
711
823
  --glass-border-wash: color-mix(in srgb, var(--foreground) 8%, transparent);
@@ -767,10 +879,58 @@
767
879
  and `--glass-tint-strength` is 0%, so the rung background mixes 0% toward
768
880
  the source = byte-identical to today. A consumer sets `--glass-tint-source`
769
881
  to a sampled aurora hue + a strength ≤30% to bias the surface. Alpha-safe:
770
- the mix is bounded ≤30% and never re-points the card's own alpha. */
882
+ the mix is bounded ≤30% and never re-points the card's own alpha.
883
+
884
+ AX.W55 — the DEFAULTS stay `var(--card)`/`0%` (the zero-delta rest state).
885
+ The backdrop-luminance probe (`--glass-backdrop`, below) is what OVERRIDES
886
+ them under a bright backdrop; the `:root` defaults are NEVER touched — the
887
+ bucket blocks (glass.css / dock.css `@container style(--glass-backdrop:
888
+ light)`) do the lift, so a surface over today's rich/dark background reads
889
+ byte-identical. */
771
890
  --glass-tint-source: var(--card);
772
891
  --glass-tint-strength: 0%;
773
892
 
893
+ /* AX.W55 — adaptive glass legibility (the iOS-26/27 "locally darken the glass
894
+ over light content" move; G2). There is NO web API that reads the pixels
895
+ painted BEHIND a `backdrop-filter` element, so the backdrop-luminance signal
896
+ is a DECLARATIVE BUCKET a consumer sets where it KNOWS the backdrop is bright
897
+ (a near-white card surface, a pale aurora bleed, a bright data grid). It is
898
+ read by the `@container style(--glass-backdrop: light)` blocks on every glass
899
+ family (the shipped density-cascade mechanism — utilities.css §density) which
900
+ lift `--glass-tint-strength` toward the AA floor + re-point `--glass-tint-
901
+ source` to the warm-ink below, mixing the rung TOWARD ink via the EXISTING
902
+ `color-mix(in oklab)` seam — ZERO new compositing seam.
903
+
904
+ --glass-backdrop: the bucket. `dark` (or unset) = today's zero-delta;
905
+ `light` engages the bright-bucket darken. An
906
+ INHERITING ident set on any ancestor reaches every
907
+ descendant glass surface (the @container read).
908
+ --glass-backdrop-luma: the numeric escape hatch — a sampled backdrop
909
+ relative-luminance (0..1) a heavier JS observer sets
910
+ when the declarative bucket is too coarse. The TOKEN
911
+ is minted (the cascade reads it if set); the OBSERVER
912
+ that sets it stays demo-private until a 2nd consumer
913
+ arrives (the no-overfitting bar — the DEFAULT path is
914
+ the declarative bucket, not a speculative sampler).
915
+ --glass-tint-ink: the LOW-LUMINANCE warm-ink the bright bucket re-points
916
+ `--glass-tint-source` to — the warm dark `--foreground`
917
+ family (NOT white; a lightener over light content is
918
+ exactly the W52-fixed wrong direction). It auto-flips
919
+ with `--foreground` (dark-mode it resolves the light
920
+ warm ink — but the bright-backdrop case is a light-mode
921
+ concern). Overridable like every magnitude here.
922
+
923
+ The bright-bucket `--glass-tint-strength` is clamped to a BOUNDED AA-clearing
924
+ floor — `--glass-tint-strength-aa` (≤24%, the iOS clamp; the lowest value that
925
+ clears 4.5:1 over synthetic white, capped LOW so the surface STAYS translucent,
926
+ "let as much content through as possible"). Recorded here as the ceiling the
927
+ bucket blocks drive to; the live 4.5:1 readback (proof:adaptive-glass π arm)
928
+ ratifies the exact value. */
929
+ --glass-backdrop: dark;
930
+ --glass-backdrop-luma: ;
931
+ --glass-tint-ink: var(--foreground);
932
+ --glass-tint-strength-aa: 18%;
933
+
774
934
  /* AW.W23 — chromatic edge dispersion (the "polished glass" rim fringe Apple
775
935
  shows). A warm fringe on one edge + a cool fringe on the other, low-alpha,
776
936
  biased warm-cream/NCSU-red (NOT iOS-blue). Composed OVER the W22 uniform
@@ -783,19 +943,36 @@
783
943
  inset 0.75px 0 0 0 var(--glass-fringe-warm),
784
944
  inset -0.75px 0 0 0 var(--glass-fringe-cool);
785
945
 
946
+ /* AX.W52 D19 — the moving-specular gleam radius (glass.css `.glass-material::
947
+ before`). The ONE knob that BOUNDS the gleam geometry as a percentage of the
948
+ plate so it can NEVER again become a whole-surface disc (the prior implicit
949
+ `circle at …` ran its stops to 55–75% of the half-diagonal — a wash on a
950
+ small tile). 36% reads as a tracked edge glint. Override on `:root` to retune
951
+ library-wide; a per-surface override clips the gleam tighter/wider. */
952
+ --glass-specular-size: 36%;
953
+
786
954
  /* Chassis curvature illusion — a subtle radial gradient at the chassis
787
955
  top centre that lifts the surface without committing to literal 3D.
788
- Composed into <InstrumentChassis>'s background stack. */
956
+ Composed into <InstrumentChassis>'s background stack. AX.W52 D19 — the
957
+ prior pure-white `hsl(0 0% 100% / 0.06)` reaching `transparent 60%` was a
958
+ broad top-centre WASH (the #1 fixed-anchor rest-bloom culprit). Re-derived
959
+ onto the warm-cream house identity (`hsl(40 30% 96%)`, L < 100% so the warm
960
+ hue survives — mirroring the moving gleam), the alpha routed through the
961
+ SINGLE overridable `--glass-curvature-intensity` knob (0.02 default, a third
962
+ of the old 0.06), and the ellipse tightened to `transparent 38%` so it reads
963
+ as a thin top-edge sheen, not a central wash. */
964
+ --glass-curvature-intensity: 0.02;
789
965
  --glass-curvature-overlay: radial-gradient(
790
966
  ellipse at 50% -20%,
791
- hsl(0 0% 100% / 0.06),
792
- transparent 60%
793
- );
794
- --glass-curvature-overlay-dark: radial-gradient(
795
- ellipse at 50% -20%,
796
- hsl(0 0% 100% / 0.06),
797
- transparent 60%
967
+ hsl(40 30% 96% / var(--glass-curvature-intensity)),
968
+ transparent 38%
798
969
  );
970
+ /* The light-arm dark alias kept on the same warm-cream + token recipe so a
971
+ non-`.dark` consumer reading `…-overlay-dark` still resolves a softened
972
+ sheen; the `.dark` block below lowers `--glass-curvature-intensity` so the
973
+ deep-canvas arm is genuinely softer (the prior byte-identical dark arm read
974
+ HARDER over the dark canvas). */
975
+ --glass-curvature-overlay-dark: var(--glass-curvature-overlay);
799
976
 
800
977
  /* Chart palette aliases — speedtest et al. read these for phase tinting.
801
978
  Defaults map to viz-basis hues; consumers can override per app. */
@@ -898,13 +1075,22 @@
898
1075
 
899
1076
  /* Overlay scrim rungs — substrate-aware modal/dialog backdrop tints.
900
1077
  Three weights cover the deployed range: dialog-scroll (subtle),
901
- canonical modal (default), drawer/full-cover (strong). Currently
902
- 5 raw `bg-black/{40,50,80}` sites across Dialog/Sheet/Drawer/
903
- ConfirmDialog hardcode the value; W2.A migrates consumers.
904
- R5 vocab.γ gap row 2. */
905
- --overlay-scrim: color-mix(in srgb, var(--shadow-color) 50%, transparent);
906
- --overlay-scrim-strong: color-mix(in srgb, var(--shadow-color) 80%, transparent);
907
- --overlay-scrim-subtle: color-mix(in srgb, var(--shadow-color) 40%, transparent);
1078
+ canonical modal (default), drawer/full-cover (strong).
1079
+
1080
+ AY.W-PRIM-POLISH D3 — the scrim is its OWN identity token, NOT derived
1081
+ from `--shadow-color`. A scrim's role is to RECEDE: it must pin to INK in
1082
+ BOTH modes. The cartoon-shadow family rides `--shadow-color: var(--foreground)`
1083
+ (correct — a shadow re-tints under `.dark` by construction), but a scrim
1084
+ that does the same FLOODS the dark room with a cream fog (the old dark
1085
+ overlay painted `srgb(0.91… / 0.5)`, a near-white wash that BRIGHTENED the
1086
+ page at the modal moment). `--overlay-scrim-ink` is a fixed warm near-black
1087
+ (the light-mode `--foreground` value), re-resolved verbatim in `.dark` so
1088
+ the scrim recedes in both modes. Clean break, no alias (no-backwards-compat).
1089
+ The `--shadow-color` / `--shadow-cartoon-*` family is UNTOUCHED. */
1090
+ --overlay-scrim-ink: hsl(24 10% 10%);
1091
+ --overlay-scrim: color-mix(in srgb, var(--overlay-scrim-ink) 50%, transparent);
1092
+ --overlay-scrim-strong: color-mix(in srgb, var(--overlay-scrim-ink) 80%, transparent);
1093
+ --overlay-scrim-subtle: color-mix(in srgb, var(--overlay-scrim-ink) 40%, transparent);
908
1094
 
909
1095
  /* ═══════════════════════════════════════════════
910
1096
  §9 ANIMATION OFFSETS
@@ -981,6 +1167,105 @@
981
1167
  /* ═══════════════════════════════════════════════
982
1168
  §10 SIZING
983
1169
  ═══════════════════════════════════════════════ */
1170
+ /* ── The ONE comfortable-sizing scale doctrine (AX.W51 D18) ──────────────
1171
+ `--ui-scale` is the MASTER comfortable-sizing scalar — ONE unitless knob
1172
+ (registered @property <number>, inherits:true, default the identity 1)
1173
+ every interactive-control magnitude derives through `calc(<base> *
1174
+ var(--ui-scale))`, so a single override grows control HEIGHT + PADDING +
1175
+ GAP + FONT-SIZE + GLYPH in LOCKSTEP, proportion preserved, no per-component
1176
+ hack. The cohorts below (`--control-h-*` heights, `--control-text*` control
1177
+ fonts, `--ui-glyph*` glyphs) are its reading surfaces; the CVA bases + the
1178
+ `.btn-pill`/`.input-pill` pills consume them.
1179
+
1180
+ ONE scale system, not three. The dock (`--dock-scale`) and the dropdown
1181
+ family (`--dropdown-text`, W50) are SPECIALIZATIONS that read this axis:
1182
+ `--dock-scale: calc(var(--ui-scale) * var(--dock-local-scale, 1))` — the
1183
+ dock multiplies ON TOP of the global comfort axis (its existing geometry
1184
+ `calc` cascade inherits the global axis for free, zero edit). A consumer
1185
+ re-tints the whole library's comfort from ONE `:root { --ui-scale: … }`
1186
+ override (or a scoped region — a dense data-table sets it lower) — the
1187
+ token-first axis.
1188
+
1189
+ EXCLUDED — the φ-DISPLAY ladder (`--type-display-*` / `--type-title` /
1190
+ `--type-heading` / `--type-subheading`): a hero/title is a TYPOGRAPHIC
1191
+ identity, NOT a touch target, so it does NOT grow on the comfort/coarse
1192
+ axis. Only interactive-CONTROL text rides `--ui-scale`. Containers (card /
1193
+ panel radii + paddings) are separate `--radius-*` / `--space-*` axes.
1194
+
1195
+ The desktop default is the IDENTITY (1) — byte-exact preservation, no
1196
+ reflow of shipped consumers. The comfort GROWTH lives at the coarse-pointer
1197
+ default (`--ui-coarse-scale`, §below) + the consumer override. The
1198
+ WCAG-2.5.5 44px touch floor survives as a `max(…, --control-floor)` clamp
1199
+ inside the scaled control-size (the coarse block lifts `--control-floor` to
1200
+ `--touch-target`, so a sub-1 scale cannot drop a control under the target).
1201
+ Coordinates with W54's `--glass-level` + W55's `--glass-tint-*` — SEPARATE
1202
+ axes (size vs material vs legibility); a control is comfortably-sized AND
1203
+ glass AND legible, three orthogonal knobs. */
1204
+ --ui-scale: 1;
1205
+ /* The global coarse-pointer comfort default — the WHOLE library grows ~1.5×
1206
+ on touch from ONE place (the @media (pointer: coarse) block at §below lifts
1207
+ :root --ui-scale to this). The dock's prior parallel 1.5× becomes the global
1208
+ default it now shares. Public library-default identity — a consumer sets
1209
+ 1.3 / 1.75 on :root or a scope. */
1210
+ --ui-coarse-scale: 1.5;
1211
+ /* The control-height cohort — the h-7/h-9/h-10/h-11 register (28/36/40/44px)
1212
+ the CVA size rungs encode, each scaled by the master axis. The CVA rungs
1213
+ read these via `h-[var(--control-h-*)]` instead of the raw `h-N` literal.
1214
+ `--control-floor` is the WCAG-2.5.5 clamp seam (0 at desktop, lifted to
1215
+ --touch-target under coarse-pointer); each height is `max(scaled, floor)`. */
1216
+ --control-floor: 0px;
1217
+ --control-h-xs: max(calc(1.75rem * var(--ui-scale)), var(--control-floor));
1218
+ --control-h-sm: max(calc(2.25rem * var(--ui-scale)), var(--control-floor));
1219
+ --control-h-md: max(calc(2.5rem * var(--ui-scale)), var(--control-floor));
1220
+ --control-h-lg: max(calc(2.75rem * var(--ui-scale)), var(--control-floor));
1221
+ /* The control-FONT register (RED 3 — the user's "font too small"). A comfort
1222
+ multiplier BETWEEN the static φ-ladder rung and the painted control font,
1223
+ so interactive-control text grows on the comfort axis while the φ-DISPLAY
1224
+ ladder stays a pure typographic scale (display headings do NOT grow on
1225
+ touch). `--control-text` is the workhorse (the `text-sm` register the
1226
+ buttons/inputs/triggers carried); `--control-text-sm` is the quieter rung
1227
+ (the `text-xs` badge/caption register). W50's `--dropdown-text` IS the
1228
+ picker-family specialization of this register. */
1229
+ --control-text: calc(var(--type-small) * var(--ui-scale));
1230
+ --control-text-sm: calc(var(--type-caption) * var(--ui-scale));
1231
+ /* The control-GLYPH cohort (RED 4 — the glyph grows WITH the box). The
1232
+ 1rem/0.875rem control-glyph register the `size-4`/`size-3.5` literals
1233
+ encode; the un-sized-<svg> CVA rule reads these via
1234
+ `size-[var(--ui-glyph)]`, KEEPING the `:not([class*=size-])` host-sized-icon
1235
+ escape intact (an explicit `size-9` still wins). */
1236
+ --ui-glyph: calc(1rem * var(--ui-scale));
1237
+ --ui-glyph-sm: calc(0.875rem * var(--ui-scale));
1238
+
1239
+ /* ── The picker-family type-scale (AX.W50 D17) ───────────────────────────
1240
+ ONE governed two-rung scale the WHOLE shadcn picker family (Select /
1241
+ DropdownMenu / Combobox / ContextMenu / Command / MultiSelect) reads, so the
1242
+ family paints at ONE uniform scale instead of the scattered raw
1243
+ `text-sm`/`text-xs` Tailwind-literal lottery (item rows at `text-sm`,
1244
+ headings/shortcuts at `text-xs`, the two filter inputs at mismatched heights).
1245
+ A consumer re-tints the whole family from ONE override.
1246
+
1247
+ It is a SPECIALIZATION of W51's control-font register (one scale system, not
1248
+ three): `--dropdown-text` reads `--control-text` (the comfort-scaled `text-sm`)
1249
+ and `--dropdown-text-secondary` reads `--control-text-sm` (the comfort-scaled
1250
+ `text-xs`), so the picker family rides the SAME `--ui-scale` comfort axis as
1251
+ every other control — a `--ui-scale` bump grows the dropdowns too. A consumer
1252
+ wanting the family LARGER than the rest overrides `--dropdown-text` directly
1253
+ (e.g. `var(--type-body)`); the override re-resolves every family surface.
1254
+
1255
+ Scale-contract (which surface reads which rung):
1256
+ • PRIMARY (`--dropdown-text`) → item rows, triggers, filter inputs, empties.
1257
+ • SECONDARY (`--dropdown-text-secondary`) → section labels, group-headings,
1258
+ keyboard shortcuts (the quieter-than-item caption register; resolves the
1259
+ witness-2 contradiction — the Select/DropdownMenu/ContextMenu labels
1260
+ collapse DOWN to the secondary rung to match the Combobox/Command headings,
1261
+ ONE rung for the section-label role family-wide).
1262
+ `--dropdown-input-height` unifies the two filter-input heights (Combobox was
1263
+ h-10, Command was h-11) onto ONE register — a specialization of W51's
1264
+ `--control-h-md` so the picker input scales on the comfort axis with the font. */
1265
+ --dropdown-text: var(--control-text);
1266
+ --dropdown-text-secondary: var(--control-text-sm);
1267
+ --dropdown-input-height: var(--control-h-md);
1268
+
984
1269
  --size-icon-btn: 2.5rem;
985
1270
  --icon-xs: 0.75rem;
986
1271
  --icon-sm: 0.875rem;
@@ -1014,6 +1299,96 @@
1014
1299
  --dock-margin: 0.5rem;
1015
1300
  --dock-menubar-reserve: 4rem;
1016
1301
 
1302
+ /* AX.W45 — the dock geometry multiplier. `--dock-scale` threads the WHOLE
1303
+ `.glass-dock[data-density]` geometry cascade (box, padding, gap, tab,
1304
+ tile-min, glyph) via `calc(<base> * --dock-scale)`, so a single knob grows
1305
+ every dock axis in lockstep. The WCAG 2.5.5 44px floor survives as a `max(…,
1306
+ 44px)` clamp INSIDE the scaled control-size.
1307
+
1308
+ AX.W51 RECONCILE (D18) — `--dock-scale` is RE-HOMED as a SPECIALIZATION of
1309
+ the global `--ui-scale` comfort axis: `calc(var(--ui-scale) *
1310
+ var(--dock-local-scale, 1))`. The dock now MULTIPLIES on top of the global
1311
+ comfort scalar — its whole existing geometry `calc` chain inherits the global
1312
+ axis for FREE (zero edit to the density cascade; the reconcile is at this ONE
1313
+ definition line). At the desktop identity (`--ui-scale: 1`,
1314
+ `--dock-local-scale: 1`) the dock is byte-identical to HEAD. On coarse-pointer
1315
+ the GLOBAL `:root { --ui-scale: var(--ui-coarse-scale, 1.5) }` block grows the
1316
+ dock WITH the rest of the library — ONE consistent touch scale, not a parallel
1317
+ dock-only 1.5×. `--dock-local-scale` is the dock-local EXTRA multiplier
1318
+ (default 1): a consumer who wants the dock LARGER than the global comfort sets
1319
+ it, and the coarse block lifts it to `--dock-mobile-scale` (default 1, the
1320
+ stack-extra) so the dock can grow an extra notch ON TOP of the global coarse
1321
+ default. `--dock-mobile-scale` is the public library-default identity
1322
+ (presets-in-consumers: a consumer sets 1.3/1.75 on `:root` or a dock scope). */
1323
+ --dock-scale: calc(var(--ui-scale) * var(--dock-local-scale, 1));
1324
+ --dock-local-scale: 1;
1325
+ --dock-mobile-scale: 1;
1326
+ /* Library glyph ownership — `.dock-icon-button > svg` reads this so the dock
1327
+ icon glyph scales WITH the box (mirroring `.dark-mode-toggle-button > svg`).
1328
+ A consumer-passed explicit lucide size class still WINS (utility layer >
1329
+ component layer); this is a DEFAULT, not a ceiling. */
1330
+ --dock-icon-glyph: calc(1.25rem * var(--dock-scale));
1331
+
1332
+ /* AX.W45-TUNE Q1 — the COLLAPSED-pill floor tokens. The collapsed summary
1333
+ used to fall to `--dock-layer-height` (the FULL control height, ~2.5rem) for
1334
+ its `min-width` with NO block floor, so the shrunken pill read as an
1335
+ un-collapsed control row, not a tight proportioned squircle. These two floor
1336
+ tokens (referenced by dock.css's `.collapsed .dock-layer--summary` min-size +
1337
+ the `--dock-pad-collapsed` morph floor) mint a TIGHT proportioned pill: the
1338
+ summary min-size is ≈70% of the full control height (a proportioned dot, not a
1339
+ full-row stub — the ratified default), and the collapsed padding is a step
1340
+ BELOW the expanded `--dock-padding-block` so the collapsed chrome hugs the
1341
+ glyph. The summary carries a SYMMETRIC `min-block-size` (dock.css) keyed to the
1342
+ same token so the pill floors on BOTH axes — a squircle, not a stub. Consumers
1343
+ retune the pill geometry per-instance via these two handles. */
1344
+ --dock-collapsed-summary-min-size: calc(var(--dock-layer-height, 2.5rem) * 0.7);
1345
+ /* AX.W61 — the collapsed padding now threads the ONE `--dock-scale` coarse-pointer
1346
+ multiplier DIRECTLY (at HEAD it was a flat 0.25rem off the scale, so the
1347
+ collapsed pad alone stayed desktop-sized at the 1.5x mobile scale while the
1348
+ box/glyph/min-size grew — a desync the morph then interpolated FROM). The
1349
+ summary min-size already threads `--dock-scale` transitively through
1350
+ `--dock-layer-height` (itself `calc(* --dock-scale)` at every density rung); this
1351
+ lands the collapsed pad on the same thread so the whole collapsed pill scales
1352
+ coherently on touch. The 0.25rem base stays the ratified tight floor. */
1353
+ --dock-collapsed-padding: calc(0.25rem * var(--dock-scale));
1354
+
1355
+ /* AX.W45-TUNE Q3/C3 + C5 — the dock-control family reads a real GLASS register
1356
+ on hover/active, NOT a same-hue `--card` mix at an alpha adjacent to the dock's
1357
+ own `--glass-bg-dock` substrate (a sub-1%-ΔL no-op — the loud Q3 tell: "nothing
1358
+ on hover, something on click"). Both legs now point at NAMED glass tiers a
1359
+ measurable step ABOVE the dock's 42%-opacity substrate:
1360
+ • hover → `--glass-bg-resting` (the 65% glass plate) — the control surface
1361
+ WAKES as a brighter glass tier on hover, reading the blurred dock
1362
+ substrate through it. The +ΔL above `--glass-bg-dock` is perceptible
1363
+ BEFORE click; the specular gleam + scale ride alongside (one register).
1364
+ • active → `--glass-bg-floating` (the 80% glass plate) — a tier ABOVE hover,
1365
+ the keyframes-dock "selected element reads as glass" model the user
1366
+ named (`pass-3:13`): the selected tile is a glass tier that shows the
1367
+ substrate through it, NOT the flat `--surface-tint-12` ink wash. The
1368
+ active ≠ hover register is the glass-tier step, not an alpha nudge.
1369
+ This is a REGISTER change (substrate→glass-tier), not a magnitude knob. The
1370
+ per-control `--dock-icon-hover-bg` override still wins if a consumer set it. */
1371
+ --dock-control-hover-bg: var(--glass-bg-resting);
1372
+ --dock-control-active-bg: var(--glass-bg-floating);
1373
+
1374
+ /* AX.W45-TUNE C4/C5 — the small-tile specular override. The 40px dock-control
1375
+ tile is a fraction of a card's plate, so the global `--glass-specular-size`
1376
+ (36% of the plate) blooms a disproportionate disc on a hover/active dock tile
1377
+ (the I.W6 finding). The dock controls scope a TIGHTER radius (22%) so the gleam
1378
+ wakes as a restrained EDGE-catch on the small tile, not a tile-filling bloom —
1379
+ the right resolution of I.W6 (sized-down on the small surface), not turning the
1380
+ specular off everywhere. Read by the dock-control `::before` recipe (glass.css)
1381
+ via the family-scoped override below; the global card/panel size is untouched. */
1382
+ --dock-control-specular-size: 22%;
1383
+
1384
+ /* AX.W45 DK8 — the layer-switcher rail surface ladder. The rail
1385
+ (`.dock-layer-rail` inside a `<DockLayerGroup>`) gets its own quiet plate +
1386
+ a tunable hover/active affordance, replacing the raw `--primary 15%` /
1387
+ `--accent 40%` mixes the indicator/tab used against an absent plate. */
1388
+ --dock-layer-rail-bg: var(--surface-tint-8);
1389
+ --dock-layer-rail-hover: color-mix(in srgb, var(--accent) 40%, transparent);
1390
+ --dock-layer-rail-active: color-mix(in srgb, var(--primary) 15%, transparent);
1391
+
1017
1392
  /* Dock active-state ladder (O.W6 Lane B)
1018
1393
  Token-overridable active paint for `.dock-icon-button`. Promoted
1019
1394
  from hardcoded `background: var(--muted); color: var(--foreground)`
@@ -1024,8 +1399,14 @@
1024
1399
  take effect per-instance via `:root` or a parent scope, e.g.
1025
1400
  `.tools-layer { --dock-active-scale: 1.2; --dock-active-bg: …; }`.
1026
1401
  ≥ 2-consumer coverage: bbnf-buddy ToolsLayer (override consumer) +
1027
- speedtest dock (default consumer). */
1028
- --dock-active-bg: var(--muted);
1402
+ speedtest dock (default consumer).
1403
+
1404
+ AX.W45 DK2 — re-pointed off the opaque `--muted` plate onto the glass-
1405
+ correct `--dock-control-active-bg` (a translucent tint a ladder step above
1406
+ hover), so the icon-button active no longer stamps a solid cream rectangle
1407
+ over the dock glass. The O.W6 active-ladder override consumers still retint
1408
+ per-instance; only the DEFAULT moved to glass-correct. */
1409
+ --dock-active-bg: var(--dock-control-active-bg);
1029
1410
  --dock-active-color: var(--foreground);
1030
1411
  --dock-active-scale: 1;
1031
1412
  --dock-active-border: none;
@@ -1046,7 +1427,7 @@
1046
1427
 
1047
1428
  /* AQ.W3 §7 — canonical WCAG 2.5.5 (44px) touch-target floor for the
1048
1429
  NON-dock coarse-pointer surfaces (`Button size="icon"`,
1049
- ExpandableContainer triggers, ResponsiveTabs mobile trigger). One
1430
+ ExpandableContainer triggers, SegmentedTabs responsive mobile trigger). One
1050
1431
  named rung the `@media (pointer: coarse)` block in utilities.css reads,
1051
1432
  retiring the per-consumer one-liner `min-h-[44px]` patches. Equals
1052
1433
  `--dock-touch-target` numerically; kept as a distinct token so the
@@ -1088,6 +1469,21 @@
1088
1469
  §11 INTERACTIVE SCALES & FOCUS
1089
1470
  ═══════════════════════════════════════════════ */
1090
1471
  --scale-hover: 1.08;
1472
+ /* AX.W52 — the restrained BUTTON hover lift. `--scale-hover` (1.08) is an
1473
+ 8% jump — emphatic for a marquee CTA, jarring as the general hover. The
1474
+ button family (the audacious CTAs + `btn-interactive`) lifts on the
1475
+ smaller `--scale-hover-btn` routed through `--spring-smooth` (the
1476
+ sub-perceptual settle, not the snappy bounce), so the hover reads as ONE
1477
+ coherent glide with the surface-leg cross-fade rather than a mechanical
1478
+ pop. The dock keeps its proportionally-larger `--scale-hover-dock` (small
1479
+ icon, bigger lift reads smaller).
1480
+ AX.W54 Q3 — lifted 1.035 → 1.05: the 1.035 overshot DOWN (W52 tamed the
1481
+ 1.08 snap so hard the lift read as nothing), so the glass hover now reads
1482
+ as THREE legs together on hover — the specular gleam waking, a perceptible
1483
+ scale, and the bg/border cross-fade — distinguishable from rest BEFORE the
1484
+ click. Still sub-perceptual-bounce on `--spring-smooth`; the magnitude
1485
+ moved, the easing register did not. */
1486
+ --scale-hover-btn: 1.05;
1091
1487
  --scale-hover-dock: 1.1;
1092
1488
  --scale-press: 0.96;
1093
1489
 
@@ -1105,12 +1501,31 @@
1105
1501
  --scale-press-dock: var(--scale-press);
1106
1502
  --scale-press-sm: 0.97;
1107
1503
  --scale-press-btn: var(--scale-press-sm);
1504
+
1505
+ /* AX.W53 — the SegmentedTabs travel-squish cap. The active indicator
1506
+ (segmented/pill slider OR the underline rule) STRETCHES along its travel
1507
+ axis as it glides between tabs, then settles to fit — the Material 3
1508
+ ELASTIC / Apple Liquid-Glass "controls insist on animating themselves"
1509
+ register, kept RESTRAINED. The deform is volume-preserving (stretch X,
1510
+ compress Y in lockstep: `scale: var(--stretch) calc(1 / var(--stretch))`)
1511
+ so it reads as an elastic warp, never a size pump. The cap holds the peak
1512
+ LOW (1.08 ≈ +8%) — iOS 26.2 dialed motion DOWN; a high-frequency control
1513
+ wants a whisper of squish, not a bounce. A consumer dials the elasticity
1514
+ (or to 1 for none) without touching source. */
1515
+ --tab-indicator-max-stretch: 1.08;
1108
1516
  --opacity-disabled: 0.5;
1109
1517
  --opacity-icon-muted: 0.8;
1110
1518
 
1111
1519
  --focus-ring-width: 2px;
1112
- --focus-ring-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--ring) 30%, transparent),
1113
- 0 0 8px color-mix(in srgb, var(--ring) 15%, transparent);
1520
+ /* D6.b — the focus-ring color routes through a `--focus-ring-color`
1521
+ indirection (default `--ring`, so the resolved shadow is byte-identical to
1522
+ the prior hard `--ring` recipe). An opt-in channel (the `focus-ring-gold`
1523
+ utility, utilities.css) overrides ONLY this color to mint a gilded
1524
+ "you are here / this is live" ring — gold is the transient STATE voice;
1525
+ the resting active mark stays its structural color (the four-voice law). */
1526
+ --focus-ring-color: var(--ring);
1527
+ --focus-ring-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--focus-ring-color) 30%, transparent),
1528
+ 0 0 8px color-mix(in srgb, var(--focus-ring-color) 15%, transparent);
1114
1529
  --focus-ring: var(--focus-ring-shadow);
1115
1530
 
1116
1531
  /* ═══════════════════════════════════════════════
@@ -1132,10 +1547,40 @@
1132
1547
  --gold: oklch(0.751 0.147 84.2);
1133
1548
  --gold-light: oklch(0.890 0.183 96.1);
1134
1549
  --gold-dark: oklch(0.599 0.132 64.2);
1550
+ /* AY.W-PRIM-POLISH D1 — the saturated CTA plate the AW.W13 gold-CTA contract
1551
+ names. A FIXED deep gold (mode-INVARIANT — the gold-CTA hover backplate must
1552
+ be dark in BOTH modes so the white label clears ≥4.5:1; deepening toward the
1553
+ mode-flipping `--foreground` brightened the dark plate to a cream-gold and
1554
+ broke dark). ~`--gold-dark` deepened toward warm-ink → ~rgb(120,87,45),
1555
+ 6.5:1 white in light / 5.5:1 in dark. The opaque base of `btn-audacious-gold`
1556
+ :hover. */
1557
+ --gold-deep: oklch(0.487 0.103 63.0);
1558
+
1559
+ /* D6.b — the chrome-gold additions (the rim + the legible ink), completing
1560
+ the gold quad into the gilt FAMILY. Gold is a metal, not a hue — it must
1561
+ read as reflectance, so it lives at the EDGE and the HIGHLIGHT, rarely as
1562
+ an area.
1563
+
1564
+ --gold-rim — the gilt EDGE catch: `--gold` at 40% over the surface, the
1565
+ 1px tooled bevel light the `.glass-gilt` modifier + the gilt dock button
1566
+ paint. Non-text → no contrast floor.
1567
+
1568
+ --gold-ink — legible gold-toned TEXT. Derived (NOT guessed) to clear the
1569
+ cream-law ② floor (APCA |Lc| ≥ 45) against `--card` in BOTH arms; the raw
1570
+ `--gold-dark` does not (it was minted as a plate hue). LIGHT arm:
1571
+ oklch(0.560 0.118 70) → |Lc| 69.9 on the cream `--card` (hsl 48 12% 98%).
1572
+ The dark-arm pair lifts L (the warm-dark stock) in the `.dark` block,
1573
+ reaching |Lc| 77.1 on the dark `--card`. Both verified by
1574
+ `proof:gold-ink-contrast`. */
1575
+ --gold-rim: color-mix(in oklab, var(--gold) 40%, transparent);
1576
+ --gold-ink: oklch(0.560 0.118 70);
1135
1577
 
1136
1578
  --color-gold: var(--gold);
1137
1579
  --color-gold-light: var(--gold-light);
1138
1580
  --color-gold-dark: var(--gold-dark);
1581
+ --color-gold-deep: var(--gold-deep);
1582
+ --color-gold-rim: var(--gold-rim);
1583
+ --color-gold-ink: var(--gold-ink);
1139
1584
 
1140
1585
  /* ═══════════════════════════════════════════════
1141
1586
  §14 RAINBOW PALETTE — oklch (AV.W16 TW2; mode-independent, no .dark
@@ -1391,8 +1836,36 @@
1391
1836
  flat ease. STRICTLY transform-scoped: it must never touch the surface-tier
1392
1837
  `[data-held]` fades (background/border/box-shadow), which stay on
1393
1838
  `--duration-fast var(--ease-standard)`. The duration pairs with
1394
- `--duration-fast`; consumers retune the whole feel via this one token. */
1395
- --dock-press-spring: var(--duration-fast) var(--spring-bouncy);
1839
+ `--duration-fast`; consumers retune the whole feel via this one token.
1840
+
1841
+ AY.W-DOCK2 (D6) — the register is `--spring-smooth`, the §6 easing-doctrine
1842
+ transform-press register (tokens.css §2: transform hover/press/active →
1843
+ `--spring-smooth`/`--spring-snappy`, NEVER `--spring-bouncy`; a press must
1844
+ settle, never overshoot into a visible bounce). The prior `--spring-bouncy`
1845
+ ROOT default was off-doctrine, shadowed for the four named controls by a
1846
+ per-surface re-point in dock-controls.css — the exact per-surface fork the
1847
+ doctrine kills. The re-point is now a DEAD byte-identical redeclaration and is
1848
+ DELETED; the ROOT token IS the doctrine register, so any other consumer of
1849
+ `--dock-press-spring` inherits the correct smooth register. */
1850
+ --dock-press-spring: var(--duration-fast) var(--spring-smooth);
1851
+ }
1852
+
1853
+ /* AX.W51 D18 — the GLOBAL coarse-pointer comfort amplification. The WHOLE library
1854
+ — buttons, inputs, badges, toggles, the dock (a specialization that reads
1855
+ `--ui-scale`) — grows ~1.5× on touch from this ONE place, the W45 dock-only 1.5×
1856
+ lifted to the master scalar so the touch scale is CONSISTENT across the library
1857
+ (at HEAD the dock grew but the buttons did not — the three-scale split). The
1858
+ WCAG-2.5.5 44px touch floor is enforced HERE too: `--control-floor` lifts to
1859
+ `--touch-target`, so every scaled control-height `max(scaled, floor)` clamps at
1860
+ ≥ 44px regardless of the scalar (a consumer dialing `--ui-scale` below 1 still
1861
+ cannot drop a control under the target). Fine-pointer is byte-identical
1862
+ (`--ui-scale` stays 1). `--ui-coarse-scale` is the public default a consumer
1863
+ retunes. */
1864
+ @media (pointer: coarse) {
1865
+ :root {
1866
+ --ui-scale: var(--ui-coarse-scale, 1.5);
1867
+ --control-floor: var(--touch-target, 2.75rem);
1868
+ }
1396
1869
  }
1397
1870
 
1398
1871
  /* AV.W7 F2 — high-resolution overlay-blur restore. On a 2dppx+ display the
@@ -1457,7 +1930,14 @@
1457
1930
 
1458
1931
  --primary: light-dark(hsl(24 10% 10%), hsl(48 10% 90%));
1459
1932
  --primary-foreground: light-dark(var(--neutral-0), hsl(24 10% 10%));
1460
- --destructive: light-dark(hsl(0 72% 50%), hsl(0 62.8% 30.6%));
1933
+ /* AX.W44 — dark-arm lift. The stock shadcn dark `hsl(0 62.8% 30.6%)`
1934
+ (L≈30.6) was a saturated-PLATE value used AS INK over `--card` by the
1935
+ Alert destructive variant — 1.75:1 over card (illegible) / 1.91:1 vs the
1936
+ page. Lifted to `hsl(0 80% 60%)`: 4.60:1 as text over `--card` (clears the
1937
+ 4.5 body floor) AND 5.03:1 as a plate vs the dark page (clears the 3.0
1938
+ graphic floor). The light arm is UNCHANGED (already 4.70:1). Lockstep with
1939
+ the `.dark` fallback floor below (§2c). */
1940
+ --destructive: light-dark(hsl(0 72% 50%), hsl(0 80% 60%));
1461
1941
  --destructive-foreground: light-dark(var(--neutral-0), hsl(48 10% 90%));
1462
1942
  --ring: light-dark(hsl(24 10% 10%), hsl(48 10% 70%));
1463
1943
  --shadow: light-dark(hsl(24 10% 10%), hsl(0 0% 5%));
@@ -1579,7 +2059,11 @@
1579
2059
 
1580
2060
  --primary: hsl(48 10% 90%);
1581
2061
  --primary-foreground: hsl(24 10% 10%);
1582
- --destructive: hsl(0 62.8% 30.6%);
2062
+ /* AX.W44 — the `.dark` class fallback floor, in LOCKSTEP with the light-dark()
2063
+ enhancement arm above (§2c). Same lifted `hsl(0 80% 60%)` so a
2064
+ @supports-split engine and a class-toggle engine paint the SAME dark red
2065
+ (4.60:1 as ink over --card / 5.03:1 as a plate vs page). */
2066
+ --destructive: hsl(0 80% 60%);
1583
2067
  --destructive-foreground: hsl(48 10% 90%);
1584
2068
  --ring: hsl(48 10% 70%);
1585
2069
  --shadow: hsl(0 0% 5%);
@@ -1695,16 +2179,25 @@
1695
2179
  resolves the dark card). */
1696
2180
  --glass-fringe-warm: oklch(0.78 0.07 40 / 0.18);
1697
2181
  --glass-fringe-cool: oklch(0.74 0.06 230 / 0.14);
1698
- --glass-curvature-overlay: radial-gradient(
1699
- ellipse at 50% -20%,
1700
- hsl(0 0% 100% / 0.06),
1701
- transparent 60%
1702
- );
2182
+ /* AX.W52 D19 — the curvature sheen is genuinely SOFTER on the deep canvas (the
2183
+ prior dark arm re-declared the overlay BYTE-IDENTICAL to light, so it read
2184
+ HARDER over the dark substrate — an unsoftened-dark defect). The `:root`
2185
+ `--glass-curvature-overlay` already reads `var(--glass-curvature-intensity)`,
2186
+ so lowering just the intensity here re-resolves the SAME warm-cream recipe at
2187
+ a softer alpha — no byte-identical re-declaration. */
2188
+ --glass-curvature-intensity: 0.012;
1703
2189
 
1704
2190
  /* Gold — boosted for dark (oklch; AV.W16 TW2) */
1705
2191
  --gold: oklch(0.784 0.143 86.0);
1706
2192
  --gold-light: oklch(0.898 0.182 97.4);
1707
2193
  --gold-dark: oklch(0.678 0.150 63.8);
2194
+ /* D6.b — the dark-arm gilt ink. `--gold-rim` auto-re-resolves (its color-mix
2195
+ reads the dark `--gold` above — no override). `--gold-ink` MUST lift L for
2196
+ the dark `--card` (hsl 24 8% 10%): a deep gold-dark ink would vanish into
2197
+ the near-black plate, so the dark ink is a BRIGHT gold —
2198
+ oklch(0.860 0.158 90) → |Lc| 77.1 on the dark `--card` (cream-law ②;
2199
+ verified by proof:gold-ink-contrast). */
2200
+ --gold-ink: oklch(0.860 0.158 90);
1708
2201
  }
1709
2202
 
1710
2203
  /* ═══════════════════════════════════════════════
@@ -1803,6 +2296,44 @@
1803
2296
  initial-value: 0;
1804
2297
  }
1805
2298
 
2299
+ /* AX.W54 — the GLASS-FIRST single knob. `--glass-level` is the ONE clarity
2300
+ scalar threaded through BOTH glass ladders at their single sites (the
2301
+ `--glass-bg-*` opacity recipe + the `--glass-blur-*` radii). It is a typed,
2302
+ INHERITING <number> so a host setting it on any ancestor retunes every
2303
+ descendant glass surface (the @container-free cascade path) — and so it
2304
+ animates smoothly rather than snapping. The level acts as a clarity multiplier
2305
+ that PRESERVES level=1 (byte-identical to the hand-tuned ladder):
2306
+ • level 1 — the calibrated glass (today's surfaces, unchanged).
2307
+ • level 0 — the OPAQUE escape: solid `--card` + `blur(0)` through the SAME
2308
+ machinery (the `.glass-opaque` rung + the a11y brackets ride it).
2309
+ • level >1 — clearer (more transparent + more diffuse) in lockstep.
2310
+ Glass is the DEFAULT surface register for EVERY band (USER-DECIDED MAXIMAL);
2311
+ the opaque level-0 rung is the explicit opt-out. W55 carries the over-light
2312
+ legibility on the SEPARATE `--glass-tint-*` axis (the `--glass-backdrop` probe
2313
+ lifts the tint toward ink — level = opacity+blur, tint = darken-over-light, the
2314
+ two axes coordinate but never collapse: the a11y Clear↔Tinted escape rides
2315
+ level-up here AND tint-toward-ink under `prefers-contrast: more`). */
2316
+ @property --glass-level {
2317
+ syntax: "<number>";
2318
+ inherits: true;
2319
+ initial-value: 1;
2320
+ }
2321
+
2322
+ /* AX.W51 D18 — the master comfortable-sizing scalar registered typed. The
2323
+ `<number>` syntax guarantees `calc(<base> * var(--ui-scale))` is always valid (a
2324
+ malformed override CLAMPS to the initial value 1, not an invalidated calc — the
2325
+ fail-safe); `inherits: true` (unlike the per-element specular @property cohort)
2326
+ so a SCOPED override (a dense data-table region) cascades to every descendant
2327
+ control without a per-element set; the type makes it animatable (a density
2328
+ toggle COULD spring it). Mirrors the `--glass-level` registration above (the
2329
+ cascading-scalar idiom), distinct from the per-element specular @property cohort
2330
+ (those are `inherits: false`). */
2331
+ @property --ui-scale {
2332
+ syntax: "<number>";
2333
+ inherits: true;
2334
+ initial-value: 1;
2335
+ }
2336
+
1806
2337
  /* ── The specular-intensity magnitude cohort (AX.W09) ──────────────────────
1807
2338
  The catch-light alpha multiplier at each interaction state, as a SINGLE
1808
2339
  overridable token cohort (was three buried literals across glass.css —
@@ -1812,24 +2343,25 @@
1812
2343
  arm) retunes ON THE CASCADE — never a re-buried literal. Override on `:root`
1813
2344
  to retune library-wide; the cartoon-shadow override contract is the precedent.
1814
2345
 
1815
- Re-baselined to a SUBTLE ladder (≈ half the retired `0.35/0.6/0.85`):
1816
- • rest 0 — static, unwired surfaces are CLEAN; the catch-light wakes
1817
- only on hover/active or on a pointer-wired surface. This
1818
- aligns the painted rest behaviour with the @property
1819
- `--specular-intensity { initial-value: 0 }` dormancy the
1820
- prior unconditional `0.35` floor defeated.
1821
- • hover 0.22 — a subtle warm-cream lens, not a flash.
1822
- • active 0.32 — the press whisper; ≈ 0.22α × the warm-cream core, a lens
1823
- not the prior ≈ 0.47 pure-white-screen hotspot. */
2346
+ Re-baselined AGAIN at AX.W52 D19 — with the central screen-disc replaced by a
2347
+ BOUNDED plus-lighter edge gleam (glass.css), the gleam is a whisper at every
2348
+ rung, so the cohort drops further (the W09 0.22/0.32 ceiling still lifted the
2349
+ whole-tile disc on hover):
2350
+ • rest 0 — static, unwired surfaces are CLEAN; the gleam wakes only on
2351
+ hover/active or on a pointer-wired surface. Aligns the painted
2352
+ rest with the @property `--specular-intensity { initial-value:
2353
+ 0 }` dormancy.
2354
+ • hover 0.10 — a whisper edge gleam, not a bloom.
2355
+ • active 0.16 — the press whisper. */
1824
2356
  :root {
1825
2357
  --glass-specular-intensity-rest: 0;
1826
- --glass-specular-intensity-hover: 0.22;
1827
- --glass-specular-intensity-active: 0.32;
2358
+ --glass-specular-intensity-hover: 0.1;
2359
+ --glass-specular-intensity-active: 0.16;
1828
2360
  }
1829
2361
 
1830
- /* Over the deep canvas the `screen` blend lifts harder, so the dark arm runs a
1831
- touch softer on the interaction rungs (rest already 0). */
2362
+ /* Over the deep canvas `plus-lighter` still lifts, so the dark arm runs a touch
2363
+ softer on the interaction rungs (rest already 0). */
1832
2364
  .dark {
1833
- --glass-specular-intensity-hover: 0.18;
1834
- --glass-specular-intensity-active: 0.26;
2365
+ --glass-specular-intensity-hover: 0.08;
2366
+ --glass-specular-intensity-active: 0.12;
1835
2367
  }