@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
@@ -0,0 +1,201 @@
1
+ /* dock/overflow.css — the OVER-cap overflow strategies (AX.W06 carve).
2
+ *
3
+ * Carved from the dock.css god-module (slice 25). This partial owns the
4
+ * `overflow=` axis: the `overflow="scroll"` inline/block scroll ports
5
+ * (`.dock-scroll-x` / `.dock-scroll-y`, hidden scrollbar, momentum-trapped), the
6
+ * W04 CONTENT-DRIVEN `overflow="wrap"` intrinsic-flex recipe (the
7
+ * `.dock-overflow-wrap` pill↔card radius + floating-tier elevation morph on the
8
+ * ONE `--dock-expand-t` scalar — RELOCATED verbatim, never re-authored), and the
9
+ * W45 D15 single coarse-pointer `--dock-scale` multiplier.
10
+ *
11
+ * @import-ed by dock.css in cascade order, in the SAME `@layer components` — the
12
+ * carve is isomorphic (same layer, same source order → ZERO visual delta). */
13
+
14
+ @layer components {
15
+ /* ── Scroll-on-overflow opt-in (GlassDock `overflow="scroll"`) ───────
16
+ The default contract grows-to-fit then overflows visibly past the
17
+ axis cap. `overflow="scroll"` instead makes the dock the scroll port
18
+ on its layout axis, pairing the existing cap with a hidden-scrollbar
19
+ scroll region so over-cap content stays reachable. The rounded pill
20
+ masks the scroll edge; both axes keep their cap. */
21
+
22
+ /* Inline axis (horizontal docks). The active layer becomes the scroll
23
+ port: `min-width: 0` releases the flex item's `min-content` floor so
24
+ it can shrink under the clamped `.dock-layers` track, then `overflow-x:
25
+ auto` scrolls its over-cap content. `.dock-layers` must KEEP clipping
26
+ so the pill's rounded edge masks the scroll boundary — hence the
27
+ grow-mode `overflow-x: visible` (`.dock-layers`, above) is overridden
28
+ back to `hidden` here. */
29
+ .glass-dock.dock-scroll-x.expanded:not(.dock-overflow-wrap) > .dock-layers {
30
+ overflow-x: hidden;
31
+ }
32
+
33
+ .glass-dock.dock-scroll-x .dock-layer--full {
34
+ min-width: 0;
35
+ overflow-x: auto;
36
+ scrollbar-width: none;
37
+ /* Trap the inline-scroll momentum at the dock's own boundary so a
38
+ wheel/trackpad gesture that bottoms out the pill does NOT chain into
39
+ scrolling the page behind it (the dock is a self-contained scroll
40
+ port, not a window into the route scroller). */
41
+ overscroll-behavior-x: contain;
42
+ }
43
+
44
+ .glass-dock.dock-scroll-x .dock-layer--full::-webkit-scrollbar {
45
+ display: none;
46
+ }
47
+
48
+ /* Block axis (vertical rails). The root keeps its `max-block-size` cap
49
+ and scrolls its over-cap children — cap + scroll is the correct
50
+ pairing the grow-mode contract split apart. Ties the
51
+ `.vertical.always-expanded` visible default on specificity and wins on
52
+ source order. */
53
+ .glass-dock.vertical.dock-scroll-y {
54
+ overflow-y: auto;
55
+ scrollbar-width: none;
56
+ /* Same momentum-trap as the inline port — a rail that bottoms out must
57
+ not chain its remaining wheel delta into the page scroller behind it. */
58
+ overscroll-behavior-y: contain;
59
+ }
60
+
61
+ .glass-dock.vertical.dock-scroll-y::-webkit-scrollbar {
62
+ display: none;
63
+ }
64
+
65
+ /* ── `overflow="wrap"` recipe — CONTENT-DRIVEN intrinsic flex reflow ──
66
+ (AX.W04 F0). Parallel to the `.dock-scroll-{x,y}` hooks the
67
+ `overflow="scroll"` member emits, `overflow="wrap"` emits this class.
68
+ (HORIZONTAL-ONLY — GlassDock.vue guards the emit on
69
+ `orientation !== 'vertical'`; a vertical rail grows-to-fit + clamps via
70
+ `--dock-max-block-size`, its own overflow story.)
71
+
72
+ The reflow is INTRINSIC: `flex-wrap: wrap` is ALWAYS-ON (no viewport MQ),
73
+ and the dock shrink-wraps to content with `max-inline-size` capping it at
74
+ the canonical `--dock-max-inline-size` token (the SAME cap every
75
+ overflow strategy reads — `min(80vw, 64rem)` default, consumer-overridable
76
+ per-instance). So the layer wraps to N rows EXACTLY when its intrinsic row
77
+ exceeds the cap — at ANY viewport width — and collapses to one row when it
78
+ fits. The magic-640 `@media` snap-back + the `--dock-overflow-bp` token are
79
+ DELETED (the inherited mobile-responsive debt, origin 078dd79). */
80
+ .glass-dock.dock-overflow-wrap {
81
+ white-space: normal;
82
+ /* The content-driven cap. The dock ALREADY shrink-wraps to its content's
83
+ intrinsic width (the base `.glass-dock` rule), so `max-inline-size` caps
84
+ that intrinsic width at `--dock-max-inline-size`: under the cap the
85
+ shrink-wrap wins → one row; over the cap the dock holds at the cap and the
86
+ inner `flex-wrap: wrap` row reflows to N rows. ONE token, no breakpoint.
87
+ (The `min(max-content, …)` form is INVALID CSS — the math functions reject
88
+ the `max-content` intrinsic keyword, computing the property to its initial
89
+ `none` and silently dropping the cap; intrinsic-shrink + this plain cap IS
90
+ the valid `min(max-content, cap)`.) */
91
+ max-inline-size: var(--dock-max-inline-size);
92
+ padding: var(--dock-wrap-padding-block, var(--dock-padding-block, 0.375rem))
93
+ var(--dock-wrap-padding-inline, 0.625rem);
94
+
95
+ /* F4 — the pill↔card radius morph. A wrap dock is a FINITE multi-row CARD
96
+ surface when expanded and a stadium PILL when collapsed — the SAME
97
+ pill↔card morph the big-dock `shape-card` path rides. The corner glides
98
+ on the `--dock-expand-t` W01 single-scalar: `--radius-pill` at expand-t 0
99
+ (collapsed), `--dock-card-radius` at expand-t 1 (expanded — UNIFIED on
100
+ the SAME finite-radius token the big-dock card uses; the bare 16px
101
+ `--radius-2xl` literal is DELETED). ONE register, no discrete snap. */
102
+ border-radius: calc(
103
+ var(--radius-pill) +
104
+ (var(--dock-card-radius) - var(--radius-pill)) *
105
+ var(--dock-expand-t, 1)
106
+ );
107
+
108
+ /* F1 — the card-tier elevation morph ("material thickens as glass flexes
109
+ larger", WWDC25 §219). The wrap dock lifts from the flat thin-pill
110
+ `--shadow-dock` glow onto the FLOATING-tier stack (the `--shadow-dock-wrap`
111
+ token names the canonical composite on `:root`; a consumer retints the
112
+ whole card shadow by overriding THAT one token per the cartoon-shadow
113
+ contract). The three floating layers — drop / material-rim / under-cast —
114
+ fade in driven by the SAME `--dock-expand-t` scalar the radius glides on:
115
+ `--dock-wrap-elev` is the scalar as a 0→1 percent, so each layer's alpha
116
+ tracks the corner morph in LOCKSTEP (ONE clock, ONE register). At
117
+ expand-t 0 (collapsed/pill) the floating layers are 0%-alpha (invisible)
118
+ → only the base `--shadow-dock` glow shows; at expand-t 1 (expanded/card)
119
+ the full floating stack grounds the multi-row silhouette. The per-layer
120
+ recipe mirrors `--shadow-dock-wrap` (= `--shadow-xl` + `--glass-material-rim`
121
+ + `--glass-under-shadow-vivid`) so the token stays the source-of-record. */
122
+ --dock-wrap-elev: calc(var(--dock-expand-t, 1) * 100%);
123
+ box-shadow:
124
+ var(--glass-edge-light),
125
+ var(--shadow-dock-override, var(--shadow-dock)),
126
+ 0 8px 24px color-mix(in srgb, var(--shadow-color) calc(0.14 * var(--dock-wrap-elev)), transparent),
127
+ 0 0 0 0.5px color-mix(in srgb, var(--shadow-color) calc(0.05 * var(--dock-wrap-elev)), transparent),
128
+ 0 8px 32px -4px color-mix(in srgb, oklch(0 0 0 / 0.12) var(--dock-wrap-elev), transparent);
129
+ }
130
+
131
+ .glass-dock.dock-overflow-wrap .dock-layer--full {
132
+ flex-wrap: wrap;
133
+ justify-content: center;
134
+ height: auto;
135
+ min-height: var(--dock-wrap-layer-min-height, var(--dock-layer-height, 2rem));
136
+ gap: var(--dock-wrap-row-gap, 0.25rem)
137
+ var(--dock-wrap-column-gap, var(--dock-layer-gap, 0.375rem));
138
+ /* AX.W04 — NO `transition: min-height` JS-morph (the AW.W3b spring-keyed
139
+ min-height detector is RETIRED — the false `proof:dock-layering-polish`
140
+ wrap-reflow claim is STRUCK). The reflow is intrinsic flex: rows
141
+ appear/vanish on the cap crossing with no second clock. The radius +
142
+ shadow lift ride the `--dock-expand-t` scalar (the W01 single clock),
143
+ NOT a CSS transition on the retired `--dock-motion-resize` list. */
144
+ }
145
+
146
+ .glass-dock.dock-overflow-wrap .dock-layer--summary {
147
+ height: auto;
148
+ min-height: var(--dock-wrap-layer-min-height, var(--dock-layer-height, 2rem));
149
+ }
150
+
151
+ .glass-dock.dock-overflow-wrap .dock-separator {
152
+ display: none;
153
+ }
154
+
155
+ /* Collapsed, a wrap dock is the single-row summary PILL. `white-space: nowrap`
156
+ keeps the summary on one line; the inline cap stays `max-inline-size:
157
+ var(--dock-max-inline-size)` (inherited from the `.dock-overflow-wrap` rule
158
+ above) so the collapsed box still shrink-wraps to the small summary's
159
+ max-content (NOT the full cap). The
160
+ radius morph resolves to `--radius-pill` at collapsed (--dock-expand-t 0) and
161
+ the box-shadow to the flat `--shadow-dock` glow (--dock-wrap-elev 0%). */
162
+ .glass-dock.dock-overflow-wrap.collapsed {
163
+ white-space: nowrap;
164
+ }
165
+
166
+ /* AX.W45 D15 / AX.W51 D18 RECONCILE — the coarse-pointer dock growth now rides
167
+ the GLOBAL `--ui-scale` comfort axis, NOT a parallel dock-only 1.5×. The
168
+ library-wide `@media (pointer: coarse) { :root { --ui-scale:
169
+ var(--ui-coarse-scale, 1.5) } }` block (tokens.css) lifts the master scalar,
170
+ and `--dock-scale: calc(var(--ui-scale) * var(--dock-local-scale, 1))` (its
171
+ re-homed definition) inherits it FOR FREE — so the dock grows ~1.5× on touch
172
+ WITH the buttons/inputs/badges (ONE consistent touch scale; at HEAD the dock
173
+ grew but the rest of the library did not — the three-scale split this resolves).
174
+ The whole density cascade (box + padding + gap + tab + tile-min + glyph) scales
175
+ in LOCKSTEP through its existing `calc(<base> * --dock-scale)` chain, zero edit.
176
+
177
+ This block keeps ONLY the dock-LOCAL extras the global axis cannot supply:
178
+ • `--dock-local-scale: var(--dock-mobile-scale, 1)` — the dock-local EXTRA
179
+ multiplier (default 1 → no extra; the dock matches the global comfort by
180
+ default). A consumer who wants the dock LARGER than the library on touch
181
+ sets `--dock-mobile-scale` and it STACKS on top of the global coarse default
182
+ (NOT a parallel hardcoded 1.5 — the no-double-scale reconcile).
183
+ • the 44px touch floor: `--dock-control-floor` + `--size-icon-btn` lift to
184
+ `--dock-touch-target` so the `max(…, floor)` clamp in the scaled control-size
185
+ guarantees ≥ 44px regardless of the scalar (a sub-1 scale cannot drop the
186
+ target). `--size-icon-btn` keeps its floor for STANDALONE icon-button
187
+ surfaces (a routed gear, no dock ancestor) that read it directly.
188
+ Fine pointer byte-identical (`--ui-scale` stays 1).
189
+
190
+ AP.W3 R0G-6 — selector is `.glass-dock[data-density]`, not bare `.glass-dock`:
191
+ the always-present density setter (0,2,0) would shadow a bare (0,1,0) rule. The
192
+ presence-selector (0,2,0) wins by source order, lifting `--dock-local-scale` +
193
+ the floor so the cascade re-resolves at touch scale. */
194
+ @media (pointer: coarse) {
195
+ .glass-dock[data-density] {
196
+ --dock-local-scale: var(--dock-mobile-scale, 1);
197
+ --dock-control-floor: var(--dock-touch-target, 2.75rem);
198
+ --size-icon-btn: var(--dock-touch-target, 2.75rem);
199
+ }
200
+ }
201
+ }
@@ -0,0 +1,457 @@
1
+ /* dock/shell.css — the `.glass-dock` structural skeleton (AX.W06 carve).
2
+ *
3
+ * Carved from the dock.css god-module (slice 25). This partial owns the dock's
4
+ * STATIC structural surface: the `.glass-dock` root + the W02 single-axis
5
+ * `overflow: clip` morph aperture, the paper-grain `::after`, the vertical-root
6
+ * column layout, the shape/variant plates (rail · instrument-strip · the
7
+ * horizontal shape-rounded/card + the W56 squircle), the position helpers, and
8
+ * the W45 `#persistent` / vertical three-region body. The dynamic single-scalar
9
+ * morph chrome lives in dock/morph.css; the density × `--dock-scale` cascade in
10
+ * dock/density.css; the layer crossfade/hit-test in dock/layers.css.
11
+ *
12
+ * @import-ed by dock.css in cascade order, in the SAME `@layer components` — the
13
+ * carve is isomorphic (same layer, same source order → ZERO visual delta). */
14
+
15
+ @layer components {
16
+ .glass-dock {
17
+ --dock-surface-blur: var(--glass-blur-dock, var(--glass-blur-wash));
18
+ /* J.W3.C — vertical-rail max-block + horizontal max-inline caps
19
+ live as semantic tokens (defaults in `tokens.css`). When
20
+ content exceeds the cap, the appropriate axis container
21
+ scrolls with a mask-fade. Consumers override per-instance by
22
+ setting `--dock-max-block-size` / `--dock-max-inline-size`
23
+ on a `.glass-dock` directly. */
24
+ --dock-separator-height: calc(var(--dock-h, var(--size-icon-btn)) * 0.5);
25
+ --dock-collapsed-hover-scale: var(--scale-hover-dock);
26
+ /* AW.W3 — the spring-keyed child stagger knobs. `--dock-stagger-window-size`
27
+ is the fraction of the morph each child reveals over; `--dock-stagger-rise`
28
+ is the px the child rises from as it fades in. Consumers retune the
29
+ cascade feel per instance.
30
+
31
+ AX.W02 — `--dock-stagger-step` is the per-child onset BEAT: each
32
+ successive control's reveal starts this fraction-of-morph later than the
33
+ one before it, so the row fills outer→in. ONE token × the child index
34
+ replaces the hand-typed 0.08/0.16/0.24/0.32/0.4 onset ladder — the onset
35
+ is `step × (childIndex − 1)`, capped (the cap below). 0.08 = ~5% of the
36
+ ~0.32s morph between items — inside Emil Kowalski's 30–60ms stagger band,
37
+ never the >100ms "slideshow" register. The onset rides the NORMALIZED
38
+ morph progress (`--dock-expand-t`), NOT a wall-clock timer, so a fast
39
+ flick and a slow hover-open both choreograph correctly and an interrupted
40
+ morph orphans no timers.
41
+
42
+ AX.W45 DK1/DK7 — the window NARROWED 0.55 → 0.4. The per-child onset caps
43
+ at `step × 5 = 0.40` (child 6+), so the LAST detail child used to finish at
44
+ `0.40 + 0.55 = 0.95` of the morph — it barely appeared until 95% through
45
+ (the "shrunken icon does not appear for a while" tail). Tightening the
46
+ window to 0.4 lands the last child at `0.40 + 0.4 = 0.80` (the iOS front-
47
+ loaded register: stagger the EXPANDING detail, never the persistent/summary
48
+ glyph). The step (0.08, Kowalski's band) is KEPT — it is the window, not the
49
+ beat, that was too wide. The summary/persistent glyph is front-loaded
50
+ structurally (onset 0, scalar-keyed below). */
51
+ --dock-stagger-window-size: 0.4;
52
+ --dock-stagger-rise: 4px;
53
+ --dock-stagger-step: 0.08;
54
+ /* AW.W3b — big-dock tokens. `--dock-card-radius` is the finite card-shell
55
+ radius (default --radius-dock-card = --radius-3xl, density-scaled
56
+ below); `--dock-tile-min` is the grid tile minimum (auto-fill track
57
+ floor). Both are density-scaled (compact tighter, spacious looser) — the
58
+ card radius + tile size ride the density cascade, never magic numbers. */
59
+ --dock-card-radius: var(--radius-dock-card);
60
+ --dock-tile-min: 4.5rem;
61
+ /* Individual-transform identity base (AQ.W3 §W3.2). `scale: 1` at rest
62
+ mints the stacking context once so a portaled popover over `--z-dock`
63
+ stays above the dock during a hover scale (the load-bearing
64
+ stacking-context guarantee). Covers every dock scale site. */
65
+ scale: 1;
66
+ position: relative;
67
+ display: inline-flex;
68
+ align-items: center;
69
+ /* AW.W1 — the dock does NOT establish a default inline-size container.
70
+ `container-type: inline-size` applies `contain: inline-size`, which
71
+ makes an element's inline size INDEPENDENT of its contents — fatally
72
+ incompatible with a shrink-to-fit pill: under it `.glass-dock` cannot
73
+ size to its content and collapses to its padding floor (~19px) with the
74
+ active layer overflowing (the 3.3.0 regression — every horizontal dock,
75
+ collapsed AND always-expanded, rendered as a sliver). The `dock`-named
76
+ container is now OPT-IN via the `containerName` prop: a consumer
77
+ embedding the dock in a width-CONSTRAINED host (a 320px sidebar) sets
78
+ `containerName="dock"` to get the descendant container-query reads (the
79
+ audacious-label compression below), trading shrink-to-fit for the
80
+ host-constrained width it already has there. The default free-floating
81
+ dock shrink-wraps to its content (AV.W16 TW3 made this a default and
82
+ silently broke dock sizing for the common case). */
83
+ border-radius: var(--radius-dock);
84
+ white-space: nowrap;
85
+ max-inline-size: var(--dock-max-inline-size);
86
+ padding: var(--dock-padding-block, 0.375rem) var(--dock-padding-inline, 0.5rem);
87
+ /* AX.W55 — the dock SHELL composes the oklab tint at the ELEMENT (not via the
88
+ pre-substituted `--glass-bg-dock` token, which resolves its tint at the
89
+ `:root` 0% strength before the @container bucket can re-point it — the
90
+ substitution-vs-inheritance trap). Wrapping here lets the bright-bucket
91
+ block below (which re-points --glass-tint-source/-strength on `.glass-dock`)
92
+ reach the shell: the inner `--glass-bg-dock` mix is a 0% no-op at rest, the
93
+ outer element mix does the adaptive darken. Zero-delta at the `0%` default
94
+ (both mixes resolve to the flat dock bg = byte-identical to today). */
95
+ background: color-mix(
96
+ in oklab,
97
+ var(--glass-bg-dock, var(--glass-bg-resting)),
98
+ var(--glass-tint-source) var(--glass-tint-strength)
99
+ );
100
+ backdrop-filter: var(--dock-surface-blur);
101
+ border: 1.5px solid var(--glass-border-dock, var(--glass-border-resting));
102
+ /* AV.W15 M3 — the full-perimeter `--glass-edge-light` rim rides as the
103
+ leading inset layer of the dock shadow stack (the navigation-band
104
+ silhouette catch-light, distinct from the top-only highlight). */
105
+ box-shadow: var(--glass-edge-light), var(--shadow-dock-override, var(--shadow-dock));
106
+ }
107
+
108
+ /* AW.W2 — the box IS the reveal aperture (clip-reveal one-clock morph).
109
+ Migrated from `overflow: hidden` to a SINGLE-AXIS `overflow: clip` on the
110
+ MORPH axis (horizontal clips X / visible Y; vertical clips Y / visible X),
111
+ gated on a `data-morphing` attribute the driver owns (set at gesture START,
112
+ cleared on SETTLE). The clip PERSISTS through the morph — content is laid
113
+ out ONCE at its natural size behind the aperture and the growing/shrinking
114
+ box uncovers it, never spills it — and lifts to `visible` only at REST
115
+ expanded (so grown content + the focus ring paint past the box). The
116
+ prior `.expanded { overflow: visible }` (bound synchronously to
117
+ `visualExpanded`) lifted the clip at frame 0, leaving no aperture to reveal
118
+ through; the `:not([data-morphing])` guard holds the clip for the whole
119
+ gesture and lifts it on the final paint.
120
+
121
+ `overflow: clip` is PAINT-ONLY (not a scroll container): it never
122
+ participates in `scrollIntoView`/scroll-anchoring, cannot be a
123
+ scroll-driven-animation `scroller`, and drops the `min-width:0` scroll-box
124
+ dance for the non-scroll shell. The cross axis is ALWAYS explicitly
125
+ `visible` (the MDN single-axis-clip-degrades-to-hidden caveat). The
126
+ legitimate scroll ports (`.dock-scroll-{x,y}`, `overflow: auto`) STAY
127
+ `auto` — they are NOT migrated. AT.W7-dock-a's orthogonality holds: the
128
+ `containerName` opt-in does not touch the clip. */
129
+ .glass-dock:not(.vertical) {
130
+ overflow-x: clip;
131
+ overflow-y: visible;
132
+ }
133
+
134
+ .glass-dock.vertical {
135
+ overflow-x: visible;
136
+ overflow-y: clip;
137
+ }
138
+
139
+ /* DURING a morph the clip is the aperture — keyed off `data-morphing`, NOT
140
+ off `.expanded`, so it survives the whole gesture and the box reveals its
141
+ content rather than letting it spill. */
142
+ .glass-dock[data-morphing]:not(.vertical) {
143
+ overflow-x: clip;
144
+ overflow-y: visible;
145
+ }
146
+
147
+ .glass-dock[data-morphing].vertical {
148
+ overflow-x: visible;
149
+ overflow-y: clip;
150
+ }
151
+
152
+ /* AT REST EXPANDED — lift the morph-axis clip (grown content + focus ring
153
+ paint past the box). Fires ONLY when NOT morphing; the [data-morphing]
154
+ rules above win during the gesture by being more specific + later. */
155
+ .glass-dock.expanded:not([data-morphing]),
156
+ .glass-dock.always-expanded:not([data-morphing]) {
157
+ overflow: visible;
158
+ }
159
+
160
+ /* AX.W04 F6 — the vertical-dock max-block-size + internal-scroll CONTRACT.
161
+ A vertical rail caps at `--dock-max-block-size` (the `.vertical` rule), but
162
+ at rest the `overflow: visible` above let over-cap content SPILL — forcing a
163
+ consumer (bbnf-buddy ToolsLayer) to hand-anchor a max-height + scroll. Ship
164
+ the contract here: at rest a vertical column scrolls its OWN block axis when
165
+ content exceeds the cap (cross axis stays `visible` for focus rings + grown
166
+ popovers). When content fits under the cap (`height:auto` < cap) nothing
167
+ scrolls — the scroll port only engages on real over-cap content. The
168
+ block-axis morph clip stays `data-morphing`-gated above; this is the
169
+ AT-REST port only. Consumers set `--dock-max-block-size` per-instance to
170
+ anchor the column to the viewport without re-deriving the scroll plumbing. */
171
+ .glass-dock.vertical.always-expanded:not([data-morphing]),
172
+ .glass-dock.vertical.expanded:not([data-morphing]) {
173
+ overflow-x: visible;
174
+ overflow-y: auto;
175
+ scrollbar-width: none;
176
+ overscroll-behavior-y: contain;
177
+ }
178
+
179
+ .glass-dock.vertical.always-expanded:not([data-morphing])::-webkit-scrollbar,
180
+ .glass-dock.vertical.expanded:not([data-morphing])::-webkit-scrollbar {
181
+ display: none;
182
+ }
183
+
184
+ .glass-dock::after {
185
+ content: "";
186
+ position: absolute;
187
+ inset: 0;
188
+ border-radius: inherit;
189
+ background: var(--paper-clean-texture);
190
+ background-repeat: repeat;
191
+ background-size: var(--paper-texture-size);
192
+ opacity: var(--glass-grain-opacity);
193
+ pointer-events: none;
194
+ mix-blend-mode: overlay;
195
+ }
196
+
197
+ .dark .glass-dock::after {
198
+ mix-blend-mode: soft-light;
199
+ }
200
+
201
+ /* Vertical rails grow-to-fit then clamp at `--dock-max-block-size` (the
202
+ AX.W04 F6 contract). At rest a capped column scrolls its OWN block axis
203
+ internally (the `.vertical.always-expanded:not([data-morphing])` port above)
204
+ so a consumer setting `--dock-max-block-size` gets a viewport-anchored
205
+ scrollable tool palette without hand-anchoring it. `overflow="wrap"` is
206
+ horizontal-only (the class is not emitted for a vertical orientation); a
207
+ vertical column's natural overflow story is this cap + internal scroll. No
208
+ edge-fade mask — the scroll is scrollbar-hidden, not feathered. */
209
+ .glass-dock.vertical {
210
+ display: inline-flex;
211
+ flex-direction: column;
212
+ align-items: stretch;
213
+ justify-content: flex-start;
214
+ /* AX.W45 D13-b — H/V PROPORTION PARITY. The hardcoded `gap: 0.25rem` + the
215
+ density-blind `--dock-vertical-padding` override are DELETED. The vertical
216
+ dock now reads the SAME `--dock-layer-gap` / `--dock-padding-*` density
217
+ cascade the horizontal dock tunes, so `density="spacious"` paints a LARGER
218
+ gap than `compact` on BOTH axes (the density axis was dead on the vertical
219
+ dock). ONE token ladder, both orientations; the `--dock-scale` multiplier
220
+ threads it for free (the cascade is `calc(* --dock-scale)`-keyed). */
221
+ gap: var(--dock-layer-gap, 0.375rem);
222
+ white-space: normal;
223
+ width: auto;
224
+ height: auto;
225
+ max-block-size: var(--dock-max-block-size);
226
+ /* overflow on the block (morph) axis is the data-morphing-gated clip
227
+ shell above; the cross axis stays visible there. */
228
+ padding: var(--dock-padding-block, 0.375rem);
229
+ border-radius: var(--radius-dock);
230
+ /* AX.W01 — a vertical rail is ALWAYS-EXPANDED (no collapse↔expand morph),
231
+ so its root padding/background/border-color never morph; the prior
232
+ `padding/background/border-color var(--dock-motion-*)` transition arms
233
+ are DELETED (a residual root CSS-transition on the morph-chrome props is
234
+ the second-clock smell the single-scalar rebuild retires). The block-axis
235
+ (height) morph is owned by the inner `.dock-layer-stack` / DockLayerGroup
236
+ via the `--dock-morph-t` scalar (the size `calc()` above), never a CSS
237
+ transition here. KEPT: the DECORATIVE hover-scale + press-squish (the
238
+ individual `scale`/`transform`) and the box-shadow fade — these are
239
+ interaction polish on the static rail, NOT the morph. */
240
+ transition:
241
+ box-shadow var(--dock-motion-standard),
242
+ transform var(--dock-motion-resize),
243
+ scale var(--dock-motion-resize);
244
+ }
245
+
246
+ .glass-dock.variant-rail {
247
+ padding: var(--dock-rail-padding, var(--dock-padding-inline, 0.5rem));
248
+ background: var(--glass-bg-dock, var(--glass-bg-wash));
249
+ border-color: var(--glass-border-dock, var(--glass-border-wash));
250
+ }
251
+
252
+ .glass-dock.variant-rail.shape-pill {
253
+ border-radius: var(--radius-pill);
254
+ }
255
+
256
+ .glass-dock.variant-rail.shape-rounded {
257
+ border-radius: var(--radius-xl);
258
+ }
259
+
260
+ /* AW.W3b — horizontal-root shape rules. The `shape-*` class previously bound
261
+ ONLY under `.variant-rail`; on a horizontal `variant-dock` the prop silently
262
+ no-op'd (the root hardwired `--radius-dock` = `--radius-pill`). These rules
263
+ close that documented-but-dead prop — `shape="rounded"` / `shape="card"` now
264
+ paint on a horizontal dock. Scoped to `variant-dock:not(.vertical)` so the
265
+ rail + instrument-strip variants (which own their own radius) are untouched. */
266
+ .glass-dock.variant-dock:not(.vertical).shape-rounded {
267
+ border-radius: var(--radius-xl);
268
+ }
269
+
270
+ /* The big-dock CARD shell — a FINITE concentric radius above 2xl, below pill.
271
+ It does NOT collapse to a stadium. Collapsed it returns to a pill (the morph
272
+ target); the pill↔card radius now MORPHS on the SAME `--dock-expand-t` scalar
273
+ the box + chrome ride (ONE clock, no discrete snap) — `--radius-pill` at
274
+ expand-t 0 (collapsed), `--dock-card-radius` at expand-t 1 (expanded). The
275
+ prior two discrete `.shape-card` / `.shape-card.collapsed` rules + their
276
+ reliance on the deleted `border-radius var(--dock-motion-resize)` transition
277
+ are RETIRED for this single interpolation. */
278
+ .glass-dock.variant-dock:not(.vertical).shape-card {
279
+ border-radius: calc(
280
+ var(--radius-pill) +
281
+ (var(--dock-card-radius) - var(--radius-pill)) *
282
+ var(--dock-expand-t, 1)
283
+ );
284
+ }
285
+
286
+ /* AX.W56 — the big-dock IS the one squircle surface (the rounded-vs-squircle
287
+ policy: cards/pills/panels stay round, big-docks + the like → superellipse).
288
+ The squircle reads markedly better at the large `--radius-dock-card` (24px)
289
+ shell — an `@supports`-gated ENHANCEMENT only (Chrome 139+, no FF/Safari 2026).
290
+ The `border-radius` arc is the cross-engine CONTRACT; the squircle is the
291
+ better tier (NOT a degraded fallback). The shape is now the tokenized
292
+ `var(--corner-shape-bigdock)` (theme.css) so it is as overridable as the
293
+ radius — a consumer retints the corner shape from `:root`, and W42's
294
+ dock-morph reads the same `--corner-k-*` vocabulary. The `@supports`
295
+ condition tests the LITERAL `superellipse(2)` (a `var()` is not evaluable in
296
+ an `@supports` query) — the same Chrome-139 feature the token resolves to. */
297
+ @supports (corner-shape: superellipse(2)) {
298
+ .glass-dock.variant-dock:not(.vertical).shape-card {
299
+ corner-shape: var(--corner-shape-bigdock);
300
+ }
301
+ }
302
+
303
+ /* AJ-W1-δ — `instrument-strip` variant (per G-AJ-D7 Path 1).
304
+ *
305
+ * The speedtest survey cockpit's vertical rail needs chassis-strip
306
+ * aesthetics, not the dock-rail's stadium-pill chrome. Adopts the
307
+ * surface vocabulary of the `<InstrumentChassis>` family so the
308
+ * strip reads as a journey-station slot — the same surface the
309
+ * speedtest + complete + thankyou stations ride.
310
+ *
311
+ * The variant intentionally inherits the rail variant's vertical
312
+ * layout (orientation: vertical; flex-direction: column) — the
313
+ * orientation + fitContent computeds in GlassDock.vue branch on
314
+ * `variant === "instrument-strip"` alongside the existing rail
315
+ * branch. Only the surface vocabulary changes vs the rail:
316
+ * - Border-radius drops from `--radius-pill` to `--radius-card`
317
+ * (matches `<InstrumentChassis> { border-radius: var(--radius-card) }`).
318
+ * - Background plate routes through `--glass-bg-chassis` (0.28α
319
+ * per tokens.css §V) instead of `--glass-bg-wash`.
320
+ * - Border routes through `--glass-border-quiet` to match the
321
+ * chassis primitive's at-rest stroke.
322
+ * - Box-shadow routes through `--glass-shadow-quiet` plus the
323
+ * inset-bottom hairline matching the chassis primitive
324
+ * (instrument-chassis.css:42-45).
325
+ *
326
+ * The `.shape-pill` / `.shape-rounded` class hooks are still emitted
327
+ * by the template but no rule binds them under
328
+ * `.variant-instrument-strip` — chassis-strip carries ONE canonical
329
+ * border-radius (`--radius-card`), per the chassis family. */
330
+ .glass-dock.variant-instrument-strip {
331
+ padding: var(
332
+ --dock-instrument-strip-padding,
333
+ var(--dock-padding-inline, 0.75rem)
334
+ );
335
+ /* AX.W55 — the chassis-strip threads the SAME oklab tint wrapper the five
336
+ rungs + the dock shell (--glass-bg-dock) carry, so the adaptive darken
337
+ reaches it. Zero-delta at the `0%` rest default (the mix is 0% toward the
338
+ source = byte-identical to the flat `var(--glass-bg-chassis)`); it only
339
+ activates under the bright bucket below. */
340
+ background: color-mix(
341
+ in oklab,
342
+ var(--glass-bg-chassis, var(--glass-bg-wash)),
343
+ var(--glass-tint-source) var(--glass-tint-strength)
344
+ );
345
+ border: 1px solid var(--glass-border-quiet, var(--glass-border-resting));
346
+ border-radius: var(--radius-card);
347
+ box-shadow:
348
+ var(--glass-shadow-quiet, var(--shadow-dock)),
349
+ inset 0 -0.5px 0 0 rgb(0 0 0 / 0.06);
350
+ }
351
+
352
+ /* Engraved-bezel inner stroke — matches `<InstrumentChassis>::before`
353
+ * (instrument-chassis.css:85-93). The chassis-strip silhouette without
354
+ * this stroke reads as a flat plate; with it the strip reads as the
355
+ * polished sleeve of an instrument-panel module. The `::before`
356
+ * z-index sits above the chassis backdrop but below the slotted
357
+ * content (the MetricBadge stack), matching the chassis primitive's
358
+ * z-order. The host `.glass-dock` is already `position: relative`. */
359
+ .glass-dock.variant-instrument-strip::before {
360
+ content: "";
361
+ position: absolute;
362
+ inset: 0.5px;
363
+ border-radius: calc(var(--radius-card) - 0.5px);
364
+ border: 1px solid var(--surface-tint-4);
365
+ pointer-events: none;
366
+ z-index: 1;
367
+ }
368
+
369
+ .dark .glass-dock.variant-instrument-strip::before {
370
+ border-color: var(--surface-tint-6);
371
+ }
372
+
373
+ .glass-dock:where(.fixed) {
374
+ z-index: var(--z-dock);
375
+ }
376
+
377
+ .dock-inline {
378
+ margin: 0 auto;
379
+ }
380
+
381
+ .dock-sticky {
382
+ position: sticky;
383
+ top: 0;
384
+ z-index: var(--z-dock);
385
+ margin: 0 auto;
386
+ }
387
+
388
+ /* AX.W45 D13-a — the PERSISTENT region (the iOS Now-Playing / Stage-Manager
389
+ idiom done STRUCTURALLY). The `#persistent` slot lives in-flow as a root flex
390
+ SIBLING of the morph-region (`.dock-layers`) in BOTH collapsed AND expanded —
391
+ NEVER `:inert`, NEVER a crossfade pane, NEVER a `registerGroup` morph target.
392
+ It is a stable always-present rail beside the expand-on-demand content region,
393
+ so a consumer keeps a control visible while collapsed WITHOUT hand-duplicating
394
+ it into both the `#default` and `#collapsed` slots. The region co-laid by the
395
+ root flex/grid; the morph scalar `--dock-morph-t` co-drives only its chrome
396
+ (it inherits the root padding/radius morph), it is NOT a morph TARGET. It holds
397
+ steady (no jitter) while the morph-region's aperture animates on the ONE
398
+ spring. `align-items: center` keeps it on the dock's centerline; the
399
+ `--dock-layer-gap` separates it from the morph region (same rhythm both
400
+ orientations). */
401
+ .dock-persistent {
402
+ display: flex;
403
+ align-items: center;
404
+ flex-shrink: 0;
405
+ gap: var(--dock-layer-gap, 0.375rem);
406
+ }
407
+
408
+ .glass-dock:not(.vertical) .dock-persistent {
409
+ flex-direction: row;
410
+ }
411
+
412
+ .glass-dock.vertical .dock-persistent {
413
+ flex-direction: column;
414
+ align-items: stretch;
415
+ }
416
+
417
+ /* The persistent region + the morph region share the dock's gap rhythm. The
418
+ region renders only when the consumer authors a `#persistent` slot
419
+ (GlassDock.vue guards it with `v-if="$slots.persistent"`), so a dock with no
420
+ persistent controls is byte-identical to before (no empty flex item). */
421
+ .glass-dock:not(.vertical) .dock-persistent + .dock-layers {
422
+ margin-inline-start: var(--dock-layer-gap, 0.375rem);
423
+ }
424
+
425
+ .glass-dock.vertical .dock-persistent + .dock-layers {
426
+ margin-block-start: var(--dock-layer-gap, 0.375rem);
427
+ }
428
+
429
+ /* AX.W45-TUNE C7 — the VERTICAL three-region body. The vertical dock's default
430
+ slot is now wrapped in a structural `.dock-layers` column (parity with the
431
+ horizontal morph-region container) instead of a bare slot. A vertical dock is
432
+ always-expanded (no width morph), so this `.dock-layers` is NOT the grid-stacked
433
+ crossfade pair the horizontal `.dock-layers` is — it is a single column stack
434
+ carrying the dock's `--dock-layer-gap` rhythm so authored item groups +
435
+ `<DockSeparator>` rules read with the correct vertical cadence. The base
436
+ `.dock-layers { display: grid }` is re-pointed to a column flex here (the
437
+ vertical body is content-stacked, not pane-stacked). */
438
+ .glass-dock.vertical .dock-layer--vertical-body {
439
+ display: flex;
440
+ flex-direction: column;
441
+ align-items: stretch;
442
+ gap: var(--dock-layer-gap, 0.375rem);
443
+ min-width: 0;
444
+ }
445
+
446
+ /* The OPTIONAL trailing `#collapsed` section (the vertical analogue of the
447
+ horizontal summary pane) — a persistent secondary group below a structural
448
+ `<DockSeparator>`, sharing the column's gap rhythm. Renders only when the
449
+ consumer authors a `#collapsed` slot (GlassDock.vue guards it), so a vertical
450
+ dock with no collapsed slot keeps the prior single-stack body. */
451
+ .glass-dock.vertical .dock-layer--vertical-section {
452
+ display: flex;
453
+ flex-direction: column;
454
+ align-items: stretch;
455
+ gap: var(--dock-layer-gap, 0.375rem);
456
+ }
457
+ }