@mkbabb/glass-ui 3.7.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/README.md +1 -6
  2. package/dist/CardAction-DuArVky-.js +157 -0
  3. package/dist/{CommandShortcut-CY0aQTz5.js → CommandShortcut-CefCj5mt.js} +7 -7
  4. package/dist/{ContextMenuSubContent-BeDz7G6f.js → ContextMenuSubContent-Bhg4f5jX.js} +3 -3
  5. package/dist/{DataTable-gtPOLZvl.js → DataTable-CUHMukiQ.js} +4 -4
  6. package/dist/DeckProgress-Dmk4_AKN.js +23 -0
  7. package/dist/{DialogContent-DG1YMR-P.js → DialogContent-BRkT1cjP.js} +3 -3
  8. package/dist/{DialogFooter-BCIaDP15.js → DialogFooter-Gprw8H_A.js} +1 -1
  9. package/dist/{HoverPopover-DXpOEw1P.js → HoverPopover-2LOIW34a.js} +1 -1
  10. package/dist/{IconTooltip-Cu86JR4e.js → IconTooltip-yefK7cJc.js} +1 -1
  11. package/dist/{MetricBadge-D-bRaQUD.js → MetricBadge-lTc002u2.js} +1 -1
  12. package/dist/{Notification-B5WHP3_1.js → Notification-BxK8LZMw.js} +1 -1
  13. package/dist/{NumberFieldContent-CLNVR1iY.js → NumberFieldContent-BbLOh8RU.js} +2 -2
  14. package/dist/{PopoverContent-F1bWnYoh.js → PopoverContent-BId6ggf_.js} +1 -1
  15. package/dist/{Progress-c4vo4ALi.js → Progress-iEuD9pxG.js} +4 -4
  16. package/dist/{ScrollingText-BEp377U5.js → ScrollingText-BPP84wKo.js} +2 -2
  17. package/dist/{SelectScrollDownButton-DAo5NmY_.js → SelectScrollDownButton-T32cVFeM.js} +4 -4
  18. package/dist/{SelectSeparator-COFMJGng.js → SelectSeparator-C4Ql0gzV.js} +1 -1
  19. package/dist/{TabsList-COqIdW7i.js → TabsList-B8CVOQPC.js} +2 -2
  20. package/dist/{Toaster-BMaeziJJ.js → Toaster-1rYWrmAm.js} +1 -1
  21. package/dist/{ToggleGroupItem-C-AIkBUw.js → ToggleGroupItem-Cev4pOVK.js} +5 -5
  22. package/dist/animated-digit.js +1 -1
  23. package/dist/api/index.d.ts +5 -3
  24. package/dist/aurora.js +339 -408
  25. package/dist/{badge-DHQrc_GQ.js → badge-BvwvT50i.js} +4 -4
  26. package/dist/badge.js +1 -1
  27. package/dist/{button-CAywcrhO.js → button-DN39cGqL.js} +13 -12
  28. package/dist/button.js +1 -1
  29. package/dist/canvas.d.ts +1 -0
  30. package/dist/canvas.js +3 -0
  31. package/dist/card.js +1 -1
  32. package/dist/carousel.js +106 -105
  33. package/dist/collapsible.js +1 -1
  34. package/dist/{color-DjJCAQ6f.js → color-8jBjWiJ6.js} +22 -14
  35. package/dist/color.js +2 -2
  36. package/dist/command.js +1 -1
  37. package/dist/compile-DAjIoEy2.js +158 -0
  38. package/dist/components/custom/aurora/composables/atoms.d.ts +90 -25
  39. package/dist/components/custom/aurora/composables/color.d.ts +0 -12
  40. package/dist/components/custom/aurora/composables/uniformBridge.d.ts +34 -23
  41. package/dist/components/custom/aurora/constants/presets.d.ts +10 -7
  42. package/dist/components/custom/aurora/constants/renderMode.d.ts +22 -0
  43. package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +1 -1
  44. package/dist/components/custom/aurora/constants/shaders/brush.glsl.d.ts +1 -1
  45. package/dist/components/custom/aurora/constants/shaders/composition.glsl.d.ts +1 -1
  46. package/dist/components/custom/aurora/constants/shaders/mediums.glsl.d.ts +1 -1
  47. package/dist/components/custom/aurora/index.d.ts +3 -3
  48. package/dist/components/custom/configurator/ConfiguratorLayer.vue.d.ts +1 -1
  49. package/dist/components/custom/constellation/Constellation.vue.d.ts +40 -5
  50. package/dist/components/custom/constellation/constellationField.d.ts +110 -5
  51. package/dist/components/custom/constellation/index.d.ts +2 -2
  52. package/dist/components/custom/dock/DockSeparator.vue.d.ts +3 -0
  53. package/dist/components/custom/dock/GlassDock.vue.d.ts +57 -67
  54. package/dist/components/custom/dock/composables/dockContext.d.ts +7 -0
  55. package/dist/components/custom/dock/composables/dockMorphContext.d.ts +57 -0
  56. package/dist/components/custom/dock/composables/index.d.ts +3 -0
  57. package/dist/components/custom/dock/composables/useDockHold.d.ts +61 -0
  58. package/dist/components/custom/dock/composables/useLayerTransition.d.ts +13 -59
  59. package/dist/components/custom/dock/index.d.ts +4 -1
  60. package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +13 -0
  61. package/dist/components/custom/goo-blob/composables/useBlobMood.d.ts +23 -5
  62. package/dist/components/custom/goo-blob/composables/useBlobPointer.d.ts +2 -0
  63. package/dist/components/custom/goo-blob/composables/useBlobSatellites.d.ts +2 -0
  64. package/dist/components/custom/goo-blob/composables/useMetaballRenderer.d.ts +20 -5
  65. package/dist/components/custom/goo-blob/index.d.ts +1 -1
  66. package/dist/components/custom/goo-blob/shaders/sdf-body.glsl.d.ts +1 -1
  67. package/dist/components/custom/goo-blob/shaders/watercolor-edges.glsl.d.ts +2 -2
  68. package/dist/components/custom/goo-blob/types.d.ts +8 -0
  69. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +92 -0
  70. package/dist/components/custom/tabs/composables/useTabIndicator.d.ts +49 -0
  71. package/dist/components/custom/tabs/index.d.ts +2 -5
  72. package/dist/components/ui/button/index.d.ts +1 -1
  73. package/dist/components/ui/card/Card.vue.d.ts +28 -10
  74. package/dist/components/ui/card/index.d.ts +1 -1
  75. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  76. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  77. package/dist/components/ui/carousel/GlassCarouselPager.vue.d.ts +3 -4
  78. package/dist/components/ui/progress/ProgressDefault.vue.d.ts +14 -4
  79. package/dist/components/ui/slider/Slider.vue.d.ts +3 -1
  80. package/dist/components/ui/slider/index.d.ts +14 -7
  81. package/dist/components/ui/tabs/TabsList.vue.d.ts +1 -1
  82. package/dist/composables/color/index.d.ts +19 -0
  83. package/dist/composables/context/createContext.d.ts +1 -1
  84. package/dist/composables/dom/index.d.ts +1 -1
  85. package/dist/composables/dom/useResolveTokenColor.d.ts +27 -0
  86. package/dist/composables/glass/canvas2d/index.d.ts +2 -1
  87. package/dist/composables/glass/canvas2d/resolveCanvasColor.d.ts +20 -0
  88. package/dist/composables/glass/canvas2d/useCanvas2D.d.ts +15 -1
  89. package/dist/composables/glass/index.d.ts +3 -1
  90. package/dist/composables/glass/useSpecularTracking.d.ts +33 -0
  91. package/dist/composables/glass/webgl/createCanvasLifecycle.d.ts +1 -1
  92. package/dist/composables/glass/webgl/shaders/procedural-color.glsl.d.ts +4 -0
  93. package/dist/composables/glass/webgl/useWebGLCanvas.d.ts +1 -1
  94. package/dist/composables/motion/core/index.d.ts +1 -0
  95. package/dist/configurator.js +1 -1
  96. package/dist/confirm-dialog.js +2 -2
  97. package/dist/constellation.js +143 -74
  98. package/dist/context-menu.js +2 -2
  99. package/dist/controls.js +1 -1
  100. package/dist/data-table.js +1 -1
  101. package/dist/deck-progress.d.ts +1 -0
  102. package/dist/deck-progress.js +2 -0
  103. package/dist/dialog.js +2 -2
  104. package/dist/dock.js +468 -354
  105. package/dist/{dockContext-DLgrVWsU.js → dockContext-BKeIMmNk.js} +1 -1
  106. package/dist/dom.js +6 -6
  107. package/dist/{dropdown-menu-BWpwutt0.js → dropdown-menu-D77jX6Df.js} +4 -4
  108. package/dist/dropdown-menu.js +1 -1
  109. package/dist/fonts/README.md +26 -18
  110. package/dist/forms.js +5 -5
  111. package/dist/fourier-field.js +35 -35
  112. package/dist/glass-panel.js +7 -7
  113. package/dist/glass-ui.css +1 -1
  114. package/dist/glass-ui.js +154 -169
  115. package/dist/goo-blob.js +361 -274
  116. package/dist/header-ribbon.js +1 -1
  117. package/dist/hover-card.js +1 -1
  118. package/dist/hover-popover.js +1 -1
  119. package/dist/icon-tooltip.js +1 -1
  120. package/dist/index.d.ts +1 -2
  121. package/dist/instrument-chassis.js +1 -1
  122. package/dist/instrument-rail.js +1 -1
  123. package/dist/label.js +1 -1
  124. package/dist/labeled-field.js +5 -5
  125. package/dist/{menuItemVariants-B4eFR5Ix.js → menuItemVariants-CCoBNkU5.js} +1 -1
  126. package/dist/metric-badge.js +1 -1
  127. package/dist/metric-stack.js +1 -1
  128. package/dist/motion-core.js +65 -65
  129. package/dist/motion.js +1 -1
  130. package/dist/notification.js +1 -1
  131. package/dist/number-field.js +1 -1
  132. package/dist/paper-backdrop.js +1 -1
  133. package/dist/popover.js +1 -1
  134. package/dist/progress.js +1 -1
  135. package/dist/pulse.js +2 -2
  136. package/dist/reactive.js +2 -2
  137. package/dist/resolveCanvasColor-BBiYfp8g.js +11 -0
  138. package/dist/scrolling-text.js +1 -1
  139. package/dist/search.js +9 -9
  140. package/dist/select.js +3 -3
  141. package/dist/separator.js +1 -1
  142. package/dist/{sheet-Cv1uO-Gq.js → sheet-VZEtNFvO.js} +2 -2
  143. package/dist/sheet.js +1 -1
  144. package/dist/slider-DC2mwuoe.js +142 -0
  145. package/dist/slider.js +1 -1
  146. package/dist/sortable-list.js +2 -2
  147. package/dist/status-dot.js +17 -16
  148. package/dist/styles/animations.css +6 -2
  149. package/dist/styles/components.css +1 -1
  150. package/dist/styles/dock/density.css +230 -0
  151. package/dist/styles/dock/layer-group.css +263 -0
  152. package/dist/styles/dock/layers.css +355 -0
  153. package/dist/styles/dock/morph.css +244 -0
  154. package/dist/styles/dock/overflow.css +201 -0
  155. package/dist/styles/dock/shell.css +457 -0
  156. package/dist/styles/dock-controls.css +187 -50
  157. package/dist/styles/dock.css +65 -1181
  158. package/dist/styles/fonts.css +0 -25
  159. package/dist/styles/glass.css +482 -102
  160. package/dist/styles/index.css +12 -11
  161. package/dist/styles/theme.css +60 -2
  162. package/dist/styles/tokens.css +625 -72
  163. package/dist/styles/typography.css +52 -69
  164. package/dist/styles/utilities.css +91 -40
  165. package/dist/styles/view-transition.css +12 -40
  166. package/dist/switch.js +1 -1
  167. package/dist/tabs.js +183 -152
  168. package/dist/timeline.js +3 -3
  169. package/dist/toast.js +1 -1
  170. package/dist/toggle-group.js +1 -1
  171. package/dist/tooltip.js +1 -1
  172. package/dist/typewriter.js +1 -1
  173. package/dist/{useCanvas2D-C31yfUGY.js → useCanvas2D-ClrQuZtp.js} +2 -1
  174. package/dist/{useConfiguratorState-B24TcgIn.js → useConfiguratorState-DxAqksK6.js} +24 -13
  175. package/dist/useResolveTokenColor-r9pnNjqK.js +24 -0
  176. package/dist/useSpecularTracking-BVRZsRHA.js +26 -0
  177. package/dist/{useTextHighlight-aMPdEpkq.js → useTextHighlight-DON84L8w.js} +1 -1
  178. package/dist/{useTouchGate-YQRwyUGU.js → useTouchGate-WFyJYsth.js} +1 -1
  179. package/dist/vReveal-CqaCz_mC.js +44 -0
  180. package/dist/watercolor-dot.js +1 -1
  181. package/package.json +67 -36
  182. package/src/fonts/README.md +26 -18
  183. package/src/styles/animations.css +6 -2
  184. package/src/styles/dock/density.css +230 -0
  185. package/src/styles/dock/layer-group.css +263 -0
  186. package/src/styles/dock/layers.css +355 -0
  187. package/src/styles/dock/morph.css +244 -0
  188. package/src/styles/dock/overflow.css +201 -0
  189. package/src/styles/dock/shell.css +457 -0
  190. package/src/styles/dock-controls.css +187 -50
  191. package/src/styles/dock.css +65 -1181
  192. package/src/styles/fonts.css +0 -25
  193. package/src/styles/glass.css +482 -102
  194. package/src/styles/index.css +12 -11
  195. package/src/styles/theme.css +60 -2
  196. package/src/styles/tokens.css +625 -72
  197. package/src/styles/typography.css +52 -69
  198. package/src/styles/utilities.css +91 -40
  199. package/src/styles/view-transition.css +12 -40
  200. package/dist/CardAction-D8nSE62a.js +0 -163
  201. package/dist/DiscoGlyph-ZoBYpoxI.js +0 -132
  202. package/dist/GlyphFace-Ce_oe3tM.js +0 -51
  203. package/dist/UnderlineTabs-D_c1iYo-.js +0 -39
  204. package/dist/compile-iM4IUB66.js +0 -158
  205. package/dist/components/custom/aurora/constants/shaders/painterly.wgsl.d.ts +0 -7
  206. package/dist/components/custom/aurora/constants/shaders/wake.wgsl.d.ts +0 -4
  207. package/dist/components/custom/disco-glyph/DiscoGlyph.vue.d.ts +0 -58
  208. package/dist/components/custom/disco-glyph/index.d.ts +0 -1
  209. package/dist/components/custom/glass-carousel/GlassCarousel.vue.d.ts +0 -36
  210. package/dist/components/custom/glass-carousel/GlassCarouselItem.vue.d.ts +0 -28
  211. package/dist/components/custom/glass-carousel/index.d.ts +0 -4
  212. package/dist/components/custom/glass-carousel/useGlassCarousel.d.ts +0 -30
  213. package/dist/components/custom/glyph-face/GlyphFace.vue.d.ts +0 -64
  214. package/dist/components/custom/glyph-face/index.d.ts +0 -2
  215. package/dist/components/custom/glyph-face/keys.d.ts +0 -9
  216. package/dist/components/custom/responsive-tabs/ResponsiveTabs.vue.d.ts +0 -73
  217. package/dist/components/custom/responsive-tabs/index.d.ts +0 -2
  218. package/dist/components/custom/tabs/BouncyTabs.vue.d.ts +0 -27
  219. package/dist/components/custom/tabs/BouncyToggle.vue.d.ts +0 -60
  220. package/dist/components/custom/tabs/UnderlineTabs.vue.d.ts +0 -20
  221. package/dist/components/custom/tabs/composables/useBouncySlider.d.ts +0 -39
  222. package/dist/disco-glyph.d.ts +0 -1
  223. package/dist/disco-glyph.js +0 -2
  224. package/dist/fonts/fraunces/fraunces-latin.woff2 +0 -0
  225. package/dist/glass-carousel.d.ts +0 -1
  226. package/dist/glass-carousel.js +0 -214
  227. package/dist/glyph-face.d.ts +0 -1
  228. package/dist/glyph-face.js +0 -3
  229. package/dist/keys-Dyf_uTs5.js +0 -9
  230. package/dist/responsive-tabs.d.ts +0 -1
  231. package/dist/responsive-tabs.js +0 -95
  232. package/dist/slider-BA9wIs5e.js +0 -130
  233. package/dist/styles/disco-glyph.css +0 -26
  234. package/dist/styles/glyph-face.css +0 -92
  235. package/dist/useViewTransition-DaN5Zrox.js +0 -21
  236. package/dist/vReveal-BE2TsPoR.js +0 -24
  237. package/src/fonts/fraunces/fraunces-latin.woff2 +0 -0
  238. package/src/styles/disco-glyph.css +0 -26
  239. package/src/styles/glyph-face.css +0 -92
  240. /package/dist/{CollapsibleContent-D7UNsXQr.js → CollapsibleContent-CP9qF1v4.js} +0 -0
  241. /package/dist/{ContextMenuContent-DGKZX1Du.js → ContextMenuContent-DDa0v27s.js} +0 -0
  242. /package/dist/{HoverCardContent-Bn0UBMY9.js → HoverCardContent-B6CcQ8He.js} +0 -0
  243. /package/dist/{InstrumentChassis-BLJBl1BW.js → InstrumentChassis-C2f6cBaQ.js} +0 -0
  244. /package/dist/{InstrumentRail-BElFwKyt.js → InstrumentRail-CUJ05YVG.js} +0 -0
  245. /package/dist/{Label-DBc7bKzZ.js → Label-zRfbQdCn.js} +0 -0
  246. /package/dist/{ModalOverlay-D1VrWyoi.js → ModalOverlay-B1GkAjNb.js} +0 -0
  247. /package/dist/{PaperBackdrop-DCGoGatv.js → PaperBackdrop-CqwjnfLv.js} +0 -0
  248. /package/dist/{SelectGroup-BcaFjvP4.js → SelectGroup-BFiod7X2.js} +0 -0
  249. /package/dist/{Separator-DZyqsCum.js → Separator-D7sD7RKj.js} +0 -0
  250. /package/dist/{Switch-2rsAtDfA.js → Switch-LDKLmmgx.js} +0 -0
  251. /package/dist/{TooltipProvider-CD2IXfRv.js → TooltipProvider-CmZzCuaG.js} +0 -0
  252. /package/dist/{_plugin-vue_export-helper-gLzyemvl.js → _plugin-vue_export-helper-ok8pgSl5.js} +0 -0
  253. /package/dist/composables/{dom → motion}/useTextHighlight.d.ts +0 -0
  254. /package/dist/{createContext-CvNyBk4o.js → createContext-B44Sah_H.js} +0 -0
  255. /package/dist/{useGlassRenderer-HebgSEgN.js → useGlassRenderer-5I0YkI4t.js} +0 -0
  256. /package/dist/{useInterval-D3USn0yc.js → useInterval-Dsmqwi03.js} +0 -0
  257. /package/dist/{useResizeObserver-CSyxGxIX.js → useResizeObserver-CWCbk5Px.js} +0 -0
  258. /package/dist/{useSpringMount-LRZqJTaF.js → useSpringMount-BJSHcLl3.js} +0 -0
  259. /package/dist/{useTimer-DEJonOZa.js → useTimer-3xqf_54b.js} +0 -0
  260. /package/dist/{useUserInvalidAria-CQKjEfwP.js → useUserInvalidAria-DoJKMZ3s.js} +0 -0
  261. /package/dist/{useViewportReady-K96m-Mdv.js → useViewportReady-RIr5Wgkh.js} +0 -0
@@ -1,9 +1,68 @@
1
1
  /* Dock primitives exported through @mkbabb/glass-ui/styles.
2
2
  *
3
- * This file is the style authority for the dock component family. The Vue
4
- * SFCs own structure and runtime behavior; selectors, motion, glass, and
5
- * layering tokens live here so consumers have one public CSS path.
6
- */
3
+ * This file is the CORE of the dock component family — the `@property
4
+ * --dock-morph-t` registration, the @layer-components OPEN, the SHARED
5
+ * cross-control four-state contract (the :focus-visible / :disabled comma-groups
6
+ * + the motion-token :where() group — they reference every control selector but
7
+ * are shared, so they live at the import root, not per-control), and the
8
+ * `@import`s of the cohesive `dock/*.css` partials.
9
+ *
10
+ * AX.W06 — the 1762-line dock.css god-module (slice 25) was CARVED into
11
+ * src/styles/dock/ cohesive single-axis partials, each under the 500-line bound,
12
+ * @import-ed below in cascade order into the SAME `@layer components` so the
13
+ * carve is isomorphic (same layer, same source order → ZERO visual delta):
14
+ * - dock/shell.css — the `.glass-dock` structural skeleton (root, W02
15
+ * morph-clip aperture, grain, vertical-root, shape /
16
+ * variant plates, position, W45 #persistent + vertical
17
+ * three-region body).
18
+ * - dock/morph.css — the W01 single-scalar morph chrome + state response
19
+ * (--dock-expand-t interp, collapsed/summary, held /
20
+ * open, the W55 adaptive-legibility bucket).
21
+ * - dock/density.css — the W45 density × --dock-scale cascade.
22
+ * - dock/layers.css — the `.dock-layer` crossfade + hit-test + reveal-
23
+ * stagger contract + the `layout="grid"` tile grid.
24
+ * - dock/layer-group.css — `.dock-layer-group` / layer-switcher rail / stack.
25
+ * - dock/overflow.css — the `overflow=` scroll/wrap strategies + the coarse
26
+ * multiplier.
27
+ *
28
+ * The FIVE interactive control families stay in dock-controls.css (the AU.W8b.3
29
+ * carve, @import-ed by index.css directly after this file). The Vue SFCs own
30
+ * structure + runtime behavior; selectors, motion, glass, and layering tokens
31
+ * live here + in the partials so consumers have one public CSS path. */
32
+
33
+ /* CSS `@import` rules must precede every other rule (a `@property`/`@layer`
34
+ block after an `@import` would render it invalid + dropped). The six partials
35
+ @import in cascade order; each opens its own `@layer components` so the layered
36
+ cascade is preserved bit-for-bit (the carve-isomorphism gate is the witness). */
37
+ @import "./dock/shell.css";
38
+ @import "./dock/morph.css";
39
+ @import "./dock/density.css";
40
+ @import "./dock/layers.css";
41
+ @import "./dock/layer-group.css";
42
+ @import "./dock/overflow.css";
43
+
44
+ /* AX.W01 — the SINGLE morph scalar. `useLayerTransition` writes it once per frame
45
+ to the `.glass-dock` root; EVERY morph axis (box size, padding, radius, scale,
46
+ background/border color, child stagger) is a pure `calc()` read off it — one
47
+ driver, one clock, on every engine (the View-Transitions collapse fork is
48
+ retired). `@property`-registered `<number>` so it interpolates COMPOSITED, not
49
+ discretely (an UNregistered custom property jumps + animates on the main
50
+ thread). `initial-value:0` = the collapsed-progress floor.
51
+
52
+ `inherits:true` (NOT false) — the SOTA inheritance-bomb guard is specifically
53
+ "never write the scalar to `:root`" (a whole-document subtree recalc per frame
54
+ over 1300+ elements). The scalar is written LOCALLY on the small `.glass-dock`
55
+ subtree, and its CONSUMERS are DESCENDANTS (`.dock-layers`/`.dock-layer-stack`
56
+ size + the active pane's child stagger) that read it via inheritance, so it MUST
57
+ inherit. Writing one inheriting var over a ~10–20-element dock subtree is the
58
+ exact pattern the prior `--dock-morph-progress` used (on `.dock-layers`); the
59
+ bomb only fires from a `:root` write, which never happens here. The root-chrome
60
+ reads (padding/bg/border) sit on the same element it is written to. */
61
+ @property --dock-morph-t {
62
+ syntax: "<number>";
63
+ inherits: true;
64
+ initial-value: 0;
65
+ }
7
66
 
8
67
  @layer components {
9
68
  :where(
@@ -32,7 +91,8 @@
32
91
  group keeps full class+pseudo specificity (NOT `:where()`, which would
33
92
  zero the class and let a per-control :hover box-shadow override the focus
34
93
  ring). Per-control transition extensions (the box-shadow fade on
35
- focus-visible) stay with their own selectors below where they differ. */
94
+ focus-visible) stay with their own selectors in dock-controls.css where
95
+ they differ. */
36
96
  .dock-icon-button:focus-visible,
37
97
  .dock-tab-button:focus-visible,
38
98
  .dock-select-trigger:focus-visible,
@@ -48,1180 +108,4 @@
48
108
  opacity: var(--opacity-disabled);
49
109
  cursor: not-allowed;
50
110
  }
51
-
52
- .glass-dock {
53
- --dock-surface-blur: var(--glass-blur-dock, var(--glass-blur-wash));
54
- /* J.W3.C — vertical-rail max-block + horizontal max-inline caps
55
- live as semantic tokens (defaults in `tokens.css`). When
56
- content exceeds the cap, the appropriate axis container
57
- scrolls with a mask-fade. Consumers override per-instance by
58
- setting `--dock-max-block-size` / `--dock-max-inline-size`
59
- on a `.glass-dock` directly. */
60
- --dock-wrap-max-width: calc(100vw - var(--dock-viewport-inline-gutter, 1rem));
61
- --dock-separator-height: calc(var(--dock-h, var(--size-icon-btn)) * 0.5);
62
- --dock-collapsed-hover-scale: var(--scale-hover-dock);
63
- /* AW.W3 — the spring-keyed child stagger knobs. `--dock-stagger-window-size`
64
- is the fraction of the morph each child reveals over; `--dock-stagger-rise`
65
- is the px the child rises from as it fades in. Consumers retune the
66
- cascade feel per instance. */
67
- --dock-stagger-window-size: 0.55;
68
- --dock-stagger-rise: 4px;
69
- /* AW.W3b — big-dock tokens. `--dock-card-radius` is the finite card-shell
70
- radius (default --radius-dock-card = --radius-3xl, density-scaled
71
- below); `--dock-tile-min` is the grid tile minimum (auto-fill track
72
- floor). Both are density-scaled (compact tighter, spacious looser) — the
73
- card radius + tile size ride the density cascade, never magic numbers. */
74
- --dock-card-radius: var(--radius-dock-card);
75
- --dock-tile-min: 4.5rem;
76
- /* Individual-transform identity base (AQ.W3 §W3.2). `scale: 1` at rest
77
- mints the stacking context once so a portaled popover over `--z-dock`
78
- stays above the dock during a hover scale (the load-bearing
79
- stacking-context guarantee). Covers every dock scale site. */
80
- scale: 1;
81
- position: relative;
82
- display: inline-flex;
83
- align-items: center;
84
- /* AW.W1 — the dock does NOT establish a default inline-size container.
85
- `container-type: inline-size` applies `contain: inline-size`, which
86
- makes an element's inline size INDEPENDENT of its contents — fatally
87
- incompatible with a shrink-to-fit pill: under it `.glass-dock` cannot
88
- size to its content and collapses to its padding floor (~19px) with the
89
- active layer overflowing (the 3.3.0 regression — every horizontal dock,
90
- collapsed AND always-expanded, rendered as a sliver). The `dock`-named
91
- container is now OPT-IN via the `containerName` prop: a consumer
92
- embedding the dock in a width-CONSTRAINED host (a 320px sidebar) sets
93
- `containerName="dock"` to get the descendant container-query reads (the
94
- audacious-label compression below), trading shrink-to-fit for the
95
- host-constrained width it already has there. The default free-floating
96
- dock shrink-wraps to its content (AV.W16 TW3 made this a default and
97
- silently broke dock sizing for the common case). */
98
- border-radius: var(--radius-dock);
99
- white-space: nowrap;
100
- max-inline-size: var(--dock-max-inline-size);
101
- padding: var(--dock-padding-block, 0.375rem) var(--dock-padding-inline, 0.5rem);
102
- background: var(--glass-bg-dock, var(--glass-bg-resting));
103
- backdrop-filter: var(--dock-surface-blur);
104
- border: 1.5px solid var(--glass-border-dock, var(--glass-border-resting));
105
- /* AV.W15 M3 — the full-perimeter `--glass-edge-light` rim rides as the
106
- leading inset layer of the dock shadow stack (the navigation-band
107
- silhouette catch-light, distinct from the top-only highlight). */
108
- box-shadow: var(--glass-edge-light), var(--shadow-dock-override, var(--shadow-dock));
109
- }
110
-
111
- /* AW.W2 — the box IS the reveal aperture (clip-reveal one-clock morph).
112
- Migrated from `overflow: hidden` to a SINGLE-AXIS `overflow: clip` on the
113
- MORPH axis (horizontal clips X / visible Y; vertical clips Y / visible X),
114
- gated on a `data-morphing` attribute the driver owns (set at gesture START,
115
- cleared on SETTLE). The clip PERSISTS through the morph — content is laid
116
- out ONCE at its natural size behind the aperture and the growing/shrinking
117
- box uncovers it, never spills it — and lifts to `visible` only at REST
118
- expanded (so grown content + the focus ring paint past the box). The
119
- prior `.expanded { overflow: visible }` (bound synchronously to
120
- `visualExpanded`) lifted the clip at frame 0, leaving no aperture to reveal
121
- through; the `:not([data-morphing])` guard holds the clip for the whole
122
- gesture and lifts it on the final paint.
123
-
124
- `overflow: clip` is PAINT-ONLY (not a scroll container): it never
125
- participates in `scrollIntoView`/scroll-anchoring, cannot be a
126
- scroll-driven-animation `scroller`, and drops the `min-width:0` scroll-box
127
- dance for the non-scroll shell. The cross axis is ALWAYS explicitly
128
- `visible` (the MDN single-axis-clip-degrades-to-hidden caveat). The
129
- legitimate scroll ports (`.dock-scroll-{x,y}`, `overflow: auto`) STAY
130
- `auto` — they are NOT migrated. AT.W7-dock-a's orthogonality holds: the
131
- `containerName` opt-in does not touch the clip. */
132
- .glass-dock:not(.vertical) {
133
- overflow-x: clip;
134
- overflow-y: visible;
135
- }
136
-
137
- .glass-dock.vertical {
138
- overflow-x: visible;
139
- overflow-y: clip;
140
- }
141
-
142
- /* DURING a morph the clip is the aperture — keyed off `data-morphing`, NOT
143
- off `.expanded`, so it survives the whole gesture and the box reveals its
144
- content rather than letting it spill. */
145
- .glass-dock[data-morphing]:not(.vertical) {
146
- overflow-x: clip;
147
- overflow-y: visible;
148
- }
149
-
150
- .glass-dock[data-morphing].vertical {
151
- overflow-x: visible;
152
- overflow-y: clip;
153
- }
154
-
155
- /* AT REST EXPANDED — lift the morph-axis clip (grown content + focus ring
156
- paint past the box). Fires ONLY when NOT morphing; the [data-morphing]
157
- rules above win during the gesture by being more specific + later. */
158
- .glass-dock.expanded:not([data-morphing]),
159
- .glass-dock.always-expanded:not([data-morphing]) {
160
- overflow: visible;
161
- }
162
-
163
- .glass-dock[data-density="compact"] {
164
- --dock-padding-block: var(--dock-density-compact-padding-block, 0.25rem);
165
- --dock-padding-inline: var(--dock-density-compact-padding-inline, 0.375rem);
166
- --dock-control-size: var(--dock-density-compact-control-size, 2rem);
167
- --dock-layer-height: var(--dock-density-compact-layer-height, 2rem);
168
- --dock-layer-gap: var(--dock-density-compact-gap, 0.25rem);
169
- --dock-trigger-padding-block: var(
170
- --dock-density-compact-trigger-padding-block,
171
- 0.1875rem
172
- );
173
- --dock-trigger-padding-inline: var(
174
- --dock-density-compact-trigger-padding-inline,
175
- 0.4375rem
176
- );
177
- --dock-tab-padding-block: var(
178
- --dock-density-compact-tab-padding-block,
179
- 0.3125rem
180
- );
181
- --dock-tab-padding-inline: var(
182
- --dock-density-compact-tab-padding-inline,
183
- 0.625rem
184
- );
185
- --dock-tab-h: 32px;
186
- }
187
-
188
- /* Comfortable density — the GlassDock default. Sits between compact
189
- and spacious. */
190
- .glass-dock[data-density="comfortable"] {
191
- --dock-padding-block: var(--dock-density-comfortable-padding-block, 0.375rem);
192
- --dock-padding-inline: var(--dock-density-comfortable-padding-inline, 0.5rem);
193
- --dock-control-size: var(--dock-density-comfortable-control-size, 2.5rem);
194
- --dock-layer-height: var(--dock-density-comfortable-layer-height, 2.5rem);
195
- --dock-layer-gap: var(--dock-density-comfortable-gap, 0.375rem);
196
- --dock-trigger-padding-block: var(
197
- --dock-density-comfortable-trigger-padding-block,
198
- 0.25rem
199
- );
200
- --dock-trigger-padding-inline: var(
201
- --dock-density-comfortable-trigger-padding-inline,
202
- 0.5rem
203
- );
204
- --dock-tab-padding-block: var(
205
- --dock-density-comfortable-tab-padding-block,
206
- 0.4375rem
207
- );
208
- --dock-tab-padding-inline: var(
209
- --dock-density-comfortable-tab-padding-inline,
210
- 0.75rem
211
- );
212
- --dock-tab-h: 38px;
213
- }
214
-
215
- .glass-dock[data-density="spacious"] {
216
- --dock-padding-block: var(--dock-density-spacious-padding-block, 0.5rem);
217
- --dock-padding-inline: var(--dock-density-spacious-padding-inline, 0.75rem);
218
- --dock-control-size: var(--dock-density-spacious-control-size, 2.75rem);
219
- --dock-layer-height: var(--dock-density-spacious-layer-height, 2.75rem);
220
- --dock-layer-gap: var(--dock-density-spacious-gap, 0.5rem);
221
- --dock-trigger-padding-block: var(
222
- --dock-density-spacious-trigger-padding-block,
223
- 0.375rem
224
- );
225
- --dock-trigger-padding-inline: var(
226
- --dock-density-spacious-trigger-padding-inline,
227
- 0.625rem
228
- );
229
- --dock-tab-padding-block: var(
230
- --dock-density-spacious-tab-padding-block,
231
- 0.5rem
232
- );
233
- --dock-tab-padding-inline: var(
234
- --dock-density-spacious-tab-padding-inline,
235
- 0.875rem
236
- );
237
- --dock-tab-h: 44px;
238
- }
239
-
240
- /* Audacious density — typography-forward chrome where the dock reads as
241
- a primary surface, not a tray. Tab buttons set their own min-height so
242
- consumer-bumped fonts no longer drift the button height — the
243
- `--dock-tab-min-height` token reserves the row regardless of glyph rise. */
244
- .glass-dock[data-density="audacious"] {
245
- --dock-padding-block: var(--dock-density-audacious-padding-block, 0.5rem);
246
- --dock-padding-inline: var(--dock-density-audacious-padding-inline, 0.875rem);
247
- --dock-control-size: var(--dock-density-audacious-control-size, 4rem);
248
- --dock-layer-height: var(--dock-density-audacious-layer-height, 4rem);
249
- --dock-layer-gap: var(--dock-density-audacious-gap, 0.875rem);
250
- --dock-trigger-padding-block: var(
251
- --dock-density-audacious-trigger-padding-block,
252
- 0.625rem
253
- );
254
- --dock-trigger-padding-inline: var(
255
- --dock-density-audacious-trigger-padding-inline,
256
- 1rem
257
- );
258
- --dock-tab-padding-block: var(
259
- --dock-density-audacious-tab-padding-block,
260
- 0.5rem
261
- );
262
- --dock-tab-padding-inline: var(
263
- --dock-density-audacious-tab-padding-inline,
264
- 1.5rem
265
- );
266
- --dock-tab-min-height: var(--dock-density-audacious-tab-min-height, 3.5rem);
267
- --dock-tab-h: var(--dock-density-audacious-tab-min-height, 3.5rem);
268
- }
269
-
270
- /* Density-audacious narrow-box carve (AV.W16 TW3) — when the dock's OWN
271
- box is narrow the audacious-dock label glyphs compress so the chrome
272
- doesn't overflow its host (≤14px below 30rem, 15px 30–45rem). Keyed off
273
- the dock's `dock` inline-size container — now OPT-IN via the
274
- `containerName="dock"` prop (AW.W1 removed the always-on default that
275
- broke shrink-to-fit), so it fires only for a dock the consumer has
276
- width-CONSTRAINED into a host (the 320px sidebar case) where the
277
- compression is meaningful and the containment does not collapse the box.
278
- A free-floating dock shrink-wraps (box == content) so there is nothing to
279
- compress. The var
280
- is set on the `.dock-label` descendant (which reads it via
281
- `font-size: var(--dock-label-size)`, typography.css). Thresholds keep
282
- the prior 479/719px viewport cadence as box widths (30rem ≈ 480px,
283
- 45rem ≈ 720px at the 16px root). */
284
- @container dock (max-width: 29.9375rem) {
285
- .glass-dock[data-density="audacious"] .dock-label {
286
- --dock-label-size: 14px;
287
- }
288
- }
289
- @container dock (min-width: 30rem) and (max-width: 44.9375rem) {
290
- .glass-dock[data-density="audacious"] .dock-label {
291
- --dock-label-size: 15px;
292
- }
293
- }
294
-
295
- .glass-dock::after {
296
- content: "";
297
- position: absolute;
298
- inset: 0;
299
- border-radius: inherit;
300
- background: var(--paper-clean-texture);
301
- background-repeat: repeat;
302
- background-size: var(--paper-texture-size);
303
- opacity: var(--glass-grain-opacity);
304
- pointer-events: none;
305
- mix-blend-mode: overlay;
306
- }
307
-
308
- .dark .glass-dock::after {
309
- mix-blend-mode: soft-light;
310
- }
311
-
312
- /* J.W3.A — horizontal docks transition padding/shadow/transform/background/border
313
- only. Width is driven by the inner `.dock-layers` FLIP via
314
- `useLayerTransition`; pinning it here would race the FLIP and
315
- reintroduce the `width: auto` non-interpolation diagnosed in
316
- R1+R6.
317
-
318
- AW.W3 — the collapsed-hover `scale` (the `.collapsed:hover` rule below) +
319
- the press squish (`--scale-press-dock` on the dock controls) ride the
320
- INDIVIDUAL `scale` property, NOT `transform`. Adding `scale
321
- var(--dock-motion-resize)` here unifies the hover scale onto the SAME dock
322
- spring vocabulary as the morph, so a collapsed→hover→expand gesture reads as
323
- ONE continuous spring rather than a `scale`-ease handed off to the
324
- width-spring. Under PRM the global gate strips `scale` from the
325
- transition-property → the hover scale snaps (0 morph frames). */
326
- .glass-dock:not(.vertical) {
327
- transition:
328
- padding var(--dock-motion-resize),
329
- box-shadow var(--dock-motion-standard),
330
- transform var(--dock-motion-resize),
331
- scale var(--dock-motion-resize),
332
- /* AW.W3b — the pill↔card corner radius morphs on the SAME spring the
333
- aperture rides (ONE free interpolation). Without this the
334
- shape-card collapsed↔expanded radius snaps discretely. The list is
335
- shared by ALL horizontal docks — the radius transition also glides
336
- the wrap collapsed↔expanded radius swap (desirable). */
337
- border-radius var(--dock-motion-resize),
338
- background var(--dock-motion-standard),
339
- border-color var(--dock-motion-standard);
340
- }
341
-
342
- /* Vertical rails grow-to-fit + clamp, no scroll: descendants wrap to
343
- multiple rows (opt-in via `overflow="wrap"`) or clamp via
344
- `--dock-max-block-size`; the cap fails visibly rather than masking
345
- overflow as a scroll affordance. No edge-fade mask — a rail that never
346
- scrolls has nothing to feather. */
347
- .glass-dock.vertical {
348
- display: inline-flex;
349
- flex-direction: column;
350
- align-items: stretch;
351
- justify-content: flex-start;
352
- gap: 0.25rem;
353
- white-space: normal;
354
- width: auto;
355
- height: auto;
356
- max-block-size: var(--dock-max-block-size);
357
- /* overflow on the block (morph) axis is the data-morphing-gated clip
358
- shell above; the cross axis stays visible there. */
359
- padding: var(--dock-vertical-padding, var(--dock-padding-block, 0.375rem));
360
- border-radius: var(--radius-dock);
361
- /* AW.W2 — axis-parity carve: NON-morph properties only. The block-axis
362
- (height) morph is owned by the inner `.dock-layer-stack` / DockLayerGroup
363
- spring (or the VT path); a `height var(--dock-motion-resize)` here would
364
- be a second driver on the same axis (the AV.W9.0 dual-driver race),
365
- and `width` is the cross axis the spring never writes. Matches how
366
- `:not(.vertical)` already excludes `width`. */
367
- transition:
368
- padding var(--dock-motion-resize),
369
- box-shadow var(--dock-motion-standard),
370
- transform var(--dock-motion-resize),
371
- scale var(--dock-motion-resize),
372
- background var(--dock-motion-standard),
373
- border-color var(--dock-motion-standard);
374
- }
375
-
376
- .glass-dock.variant-rail {
377
- padding: var(--dock-rail-padding, var(--dock-padding-inline, 0.5rem));
378
- background: var(--glass-bg-dock, var(--glass-bg-wash));
379
- border-color: var(--glass-border-dock, var(--glass-border-wash));
380
- }
381
-
382
- .glass-dock.variant-rail.shape-pill {
383
- border-radius: var(--radius-pill);
384
- }
385
-
386
- .glass-dock.variant-rail.shape-rounded {
387
- border-radius: var(--radius-xl);
388
- }
389
-
390
- /* AW.W3b — horizontal-root shape rules. The `shape-*` class previously bound
391
- ONLY under `.variant-rail`; on a horizontal `variant-dock` the prop silently
392
- no-op'd (the root hardwired `--radius-dock` = `--radius-pill`). These rules
393
- close that documented-but-dead prop — `shape="rounded"` / `shape="card"` now
394
- paint on a horizontal dock. Scoped to `variant-dock:not(.vertical)` so the
395
- rail + instrument-strip variants (which own their own radius) are untouched. */
396
- .glass-dock.variant-dock:not(.vertical).shape-rounded {
397
- border-radius: var(--radius-xl);
398
- }
399
-
400
- /* The big-dock CARD shell — a FINITE concentric radius above 2xl, below pill.
401
- It does NOT collapse to a stadium. Collapsed it returns to a pill (the morph
402
- target); the pill↔card swap glides on the `--dock-motion-resize` spring
403
- (`border-radius` is in the `:not(.vertical)` transition list). */
404
- .glass-dock.variant-dock:not(.vertical).shape-card {
405
- border-radius: var(--dock-card-radius);
406
- }
407
-
408
- .glass-dock.variant-dock:not(.vertical).shape-card.collapsed {
409
- border-radius: var(--radius-pill);
410
- }
411
-
412
- /* The squircle reads markedly better at the large card radius — an
413
- `@supports`-gated ENHANCEMENT only (Chrome 139+, no FF/Safari 2026). The
414
- border-radius arc is the CONTRACT; the squircle is the better tier (the
415
- baseline arc is the acceptable contract, NOT a degraded fallback). */
416
- @supports (corner-shape: squircle) {
417
- .glass-dock.variant-dock:not(.vertical).shape-card {
418
- corner-shape: squircle;
419
- }
420
- }
421
-
422
- /* AJ-W1-δ — `instrument-strip` variant (per G-AJ-D7 Path 1).
423
- *
424
- * The speedtest survey cockpit's vertical rail needs chassis-strip
425
- * aesthetics, not the dock-rail's stadium-pill chrome. Adopts the
426
- * surface vocabulary of the `<InstrumentChassis>` family so the
427
- * strip reads as a journey-station slot — the same surface the
428
- * speedtest + complete + thankyou stations ride.
429
- *
430
- * The variant intentionally inherits the rail variant's vertical
431
- * layout (orientation: vertical; flex-direction: column) — the
432
- * orientation + fitContent computeds in GlassDock.vue branch on
433
- * `variant === "instrument-strip"` alongside the existing rail
434
- * branch. Only the surface vocabulary changes vs the rail:
435
- * - Border-radius drops from `--radius-pill` to `--radius-card`
436
- * (matches `<InstrumentChassis> { border-radius: var(--radius-card) }`).
437
- * - Background plate routes through `--glass-bg-chassis` (0.28α
438
- * per tokens.css §V) instead of `--glass-bg-wash`.
439
- * - Border routes through `--glass-border-quiet` to match the
440
- * chassis primitive's at-rest stroke.
441
- * - Box-shadow routes through `--glass-shadow-quiet` plus the
442
- * inset-bottom hairline matching the chassis primitive
443
- * (instrument-chassis.css:42-45).
444
- *
445
- * The `.shape-pill` / `.shape-rounded` class hooks are still emitted
446
- * by the template but no rule binds them under
447
- * `.variant-instrument-strip` — chassis-strip carries ONE canonical
448
- * border-radius (`--radius-card`), per the chassis family. */
449
- .glass-dock.variant-instrument-strip {
450
- padding: var(
451
- --dock-instrument-strip-padding,
452
- var(--dock-padding-inline, 0.75rem)
453
- );
454
- background: var(--glass-bg-chassis, var(--glass-bg-wash));
455
- border: 1px solid var(--glass-border-quiet, var(--glass-border-resting));
456
- border-radius: var(--radius-card);
457
- box-shadow:
458
- var(--glass-shadow-quiet, var(--shadow-dock)),
459
- inset 0 -0.5px 0 0 rgb(0 0 0 / 0.06);
460
- }
461
-
462
- /* Engraved-bezel inner stroke — matches `<InstrumentChassis>::before`
463
- * (instrument-chassis.css:85-93). The chassis-strip silhouette without
464
- * this stroke reads as a flat plate; with it the strip reads as the
465
- * polished sleeve of an instrument-panel module. The `::before`
466
- * z-index sits above the chassis backdrop but below the slotted
467
- * content (the MetricBadge stack), matching the chassis primitive's
468
- * z-order. The host `.glass-dock` is already `position: relative`. */
469
- .glass-dock.variant-instrument-strip::before {
470
- content: "";
471
- position: absolute;
472
- inset: 0.5px;
473
- border-radius: calc(var(--radius-card) - 0.5px);
474
- border: 1px solid var(--surface-tint-4);
475
- pointer-events: none;
476
- z-index: 1;
477
- }
478
-
479
- .dark .glass-dock.variant-instrument-strip::before {
480
- border-color: var(--surface-tint-6);
481
- }
482
-
483
- .glass-dock.collapsed {
484
- cursor: pointer;
485
- padding: var(--dock-collapsed-padding, var(--dock-padding-block, 0.375rem));
486
- justify-content: center;
487
- background: var(--glass-bg-wash);
488
- border-color: var(--glass-border-floating);
489
- /* Idiomatic override path: the consumer-supplied
490
- `--shadow-dock-override` variable engages in every dock state
491
- (was: base only, leaking through here in collapsed). */
492
- box-shadow: var(--shadow-dock-override, var(--shadow-dock-collapsed));
493
- }
494
-
495
- .glass-dock.collapsed .dock-layer--summary {
496
- min-width: var(
497
- --dock-collapsed-summary-min-size,
498
- var(--dock-layer-height, 2.5rem)
499
- );
500
- justify-content: center;
501
- }
502
-
503
- /* AW.W3 — the collapsed-hover scale rides the unified dock spring vocabulary.
504
- The `scale var(--dock-motion-resize)` arm was added to the `.glass-dock`
505
- root transition above, so this hover scale settles on the SAME spring curve
506
- the expand morph uses — a collapsed→hover→expand gesture is one continuous
507
- spring, not a `scale`-ease handed off to the width-spring. The hover scale
508
- and the press squish (`--scale-press-dock`) are now one register on the dock
509
- surface. */
510
- .glass-dock.collapsed:hover {
511
- background: var(--glass-bg-wash);
512
- border-color: var(--glass-border-floating);
513
- box-shadow: var(--shadow-dock-override, var(--shadow-dock));
514
- scale: var(--dock-collapsed-hover-scale);
515
- }
516
-
517
- /* J.W5.C — held-state substrate response.
518
- *
519
- * When a descendant signals `dockKeepOpen` (e.g. an active slider drag),
520
- * `useDockState.isHeld` flips true and the root carries `data-held`.
521
- * The dock background lifts a tier (resting → floating-equivalent) and
522
- * the border quiets to the floating ring; the change tracks pointer
523
- * movement on `--duration-fast` so it reads as a held-cursor cue, not
524
- * a state change. The same flag is consumed by descendants (Slider
525
- * thumb halo) via `useOptionalDockContext().held` for cross-substrate
526
- * coordination (typed-key canonical shape; O.W2 invariant 25).
527
- */
528
- .glass-dock[data-held] {
529
- background: var(--glass-bg-floating, var(--glass-bg-resting));
530
- border-color: var(--glass-border-floating, var(--glass-border-resting));
531
- transition:
532
- background var(--duration-fast) var(--ease-standard),
533
- border-color var(--duration-fast) var(--ease-standard),
534
- box-shadow var(--duration-fast) var(--ease-standard);
535
- }
536
-
537
- /* AQ.W3 §W3.1b — open-descendant surface response. When a dock-hosted
538
- trigger (`[data-state="open"]`) is open, the dock root holds its elevated
539
- read natively (no consumer JS). Idempotent with `[data-held]` above (same
540
- floating paint, different trigger). Decorative; `:has()` Baseline Widely. */
541
- .glass-dock:has([data-state="open"]) {
542
- background: var(--glass-bg-floating, var(--glass-bg-resting));
543
- border-color: var(--glass-border-floating, var(--glass-border-resting));
544
- }
545
-
546
- .glass-dock:where(.fixed) {
547
- z-index: var(--z-dock);
548
- }
549
-
550
- .dock-inline {
551
- margin: 0 auto;
552
- }
553
-
554
- .dock-sticky {
555
- position: sticky;
556
- top: 0;
557
- z-index: var(--z-dock);
558
- margin: 0 auto;
559
- }
560
-
561
- /* J.W3.A — outer collapsed↔expanded pair drives width via FLIP.
562
- `useLayerTransition` measures the natural width before/after the
563
- slot swap and animates `width` between fixed pixel values via
564
- the `--dock-motion-resize` spring; this eliminates the
565
- `width: auto` non-interpolation diagnosed in R1+R6. The two
566
- layers stack on a CSS grid (1/1 area) and crossfade opacity
567
- in step with the FLIP. Spatial motion (width) is automatically
568
- suppressed by the global `prefers-reduced-motion` gate in
569
- `utilities.css` (which strips width from transition-property).
570
- Opacity transitions remain — the 0.1s shortened cadence in PRM
571
- still reads as a snap.
572
-
573
- J.W3.C — when the active layer's natural width exceeds
574
- `--dock-max-inline-size`, the dock root clips and the layer
575
- scrolls horizontally with a mask-fade. `min-width: 0` lets the
576
- grid item shrink under the cap (default min-content is the
577
- child's intrinsic width which would prevent the clamp). */
578
- .dock-layers {
579
- display: grid;
580
- min-width: 0;
581
- transition: width var(--dock-motion-resize);
582
- }
583
-
584
- /* AV.W9.0 — the AU.W8b native container-morph arm (the `@supports` block that
585
- opted the subtree into auto-to-length width interpolation and declared the
586
- active layer's destination width as intrinsic) is RETIRED. It was never made
587
- mutually exclusive with the `SpringProgress` FLIP driver in
588
- `useLayerTransition.ts`: on Chrome 129+ the native arm interpolated
589
- `.dock-layers` width on the browser's own clock WHILE the spring wrote inline
590
- `width` per frame — a dual-driver race over the SAME property that cancelled
591
- the morph and froze the dock at runtime (born-RED under
592
- `proof:dock-animation-live`). One authority per concern: the size morph now
593
- has exactly ONE driver on every engine — the `SpringProgress` FLIP path above
594
- (`:382`), or the orthogonal View-Transitions path inside
595
- `startViewTransition` (which owns size + crossfade as a single browser-side
596
- mutation and never touches inline width). Neither coexists with a CSS-native
597
- intrinsic-width destination, so the race is gone. This re-expresses the
598
- `e8380d7` "one driver owns the morph" invariant on the modern
599
- FLIP+spring(+VT) architecture. */
600
-
601
- /* Horizontal dock content grows visibly when the active layer's natural
602
- width exceeds the content area (grow-to-fit; consumers needing wrap opt
603
- into `overflow="wrap"`). No edge-fade mask — content never clips or scrolls,
604
- so a feather has nothing to feather and only bleeds a stray ramp onto
605
- the edge controls. */
606
- .glass-dock.expanded:not(.dock-overflow-wrap) > .dock-layers {
607
- overflow-x: visible;
608
- }
609
-
610
- /* AU.W8b-visibility-fork — the 3-state active/inactive/leaving visibility
611
- contract below is LOAD-BEARING (the a11y-006 bite-anchor). A later refactor
612
- greps for this marker so the semantics are not collapsed: the inactive layer
613
- leaves the hit-test tree (`visibility:hidden`), the leaving layer stays
614
- painted-but-untouchable through its fade (`visibility:visible` +
615
- `pointer-events:none`), and the active layer shows IMMEDIATELY (`visibility
616
- 0s`, no fade-in delay). The hand-rolled 3-state fork below is now the SOLE
617
- visibility authority on every engine — AV.W9.1 retired the native
618
- discrete-visibility arm that used to second-drive it, so one owner governs
619
- visibility (one owner governs size, one owns opacity). */
620
-
621
- /* ── Layer crossfade + hit-test contract (shared) ──────────────────
622
- Two dock-layer surfaces stack on a 1/1 CSS grid and crossfade:
623
- `.dock-layer` (GlassDock's built-in collapsed↔expanded pair) and
624
- `.dock-layer-item-host` (a DockLayer inside a DockLayerGroup). They
625
- differ only in base layout — the active/inactive/leaving paint +
626
- hit-test semantics are identical, so the contract is expressed ONCE
627
- here over both state vocabularies (`.layer-active` / `.is-active` /
628
- `.is-leaving`) rather than copied per rule-set (Q-coh-5 — `beec35e`
629
- patched the `visibility` fix into two parallel copies).
630
-
631
- An inactive layer must leave the paint AND hit-test tree: `opacity:0`
632
- alone leaves the box answering `elementFromPoint()`, so an inactive
633
- layer's button intercepts clicks meant for the active one.
634
- `visibility:hidden` removes it from both while KEEPING it in layout
635
- flow, so the FLIP width measurement in `useLayerTransition` still
636
- reads its geometry (`display:none` would zero it). The delayed
637
- `visibility` transition holds a leaving layer `visible` for the
638
- length of the opacity crossfade, then flips it `hidden`.
639
-
640
- AU.W2 — the opacity-lockstep fold (slides-F P0, the "not iOS-smooth"
641
- report). The layer fade rides `--dock-motion-resize` (the SAME duration +
642
- spring the container morph runs at, `:189`/`:216`/`:385`) — NOT the faster
643
- `--dock-motion-fast` (0.2s). Before, the host faded in 0.2s while the
644
- container morphed in 0.3s: a 100ms-apart settle (the items appeared to lag
645
- the pill). Now the fade and the morph settle in lockstep. The matched
646
- `visibility` hold extends to `--duration-normal` so the leaving layer stays
647
- paintable for the FULL (now longer) crossfade. */
648
- .dock-layer,
649
- .dock-layer-item-host {
650
- transition:
651
- opacity var(--dock-motion-resize),
652
- visibility 0s linear var(--duration-normal);
653
- }
654
-
655
- .dock-layer:not(.layer-active),
656
- .dock-layer-item-host:not(.is-active):not(.is-leaving) {
657
- opacity: 0;
658
- visibility: hidden;
659
- pointer-events: none;
660
- }
661
-
662
- .dock-layer.layer-active,
663
- .dock-layer-item-host.is-active {
664
- opacity: 1;
665
- visibility: visible;
666
- pointer-events: auto;
667
- /* AW.W2 — the active pane is STATICALLY opacity:1, REVEALED by the clip
668
- aperture (the box is the reveal mechanism), never faded. The prior
669
- `opacity var(--dock-motion-resize)` arm is DELETED: there is ZERO
670
- opacity authority on the active pane now — the aperture uncovers a
671
- layout that is laid out ONCE at natural size behind it. Only `visibility
672
- 0s` survives (the active layer must paint at once, no fade-in delay —
673
- the AU.W2 governing rule). The leaving pane keeps the shared-token
674
- opacity fade below (the ONLY surviving opacity animation, the thin
675
- polish proof:dock-opacity-lockstep names). */
676
- transition: visibility 0s;
677
- }
678
-
679
- /* A leaving layer is inactive for hit-testing but still painted
680
- through its fade-out. (`.dock-layer` has no separate leaving state —
681
- its `:not(.layer-active)` rule above covers the crossfade-out via the
682
- delayed `visibility` transition.) */
683
- .dock-layer-item-host.is-leaving {
684
- opacity: 0;
685
- visibility: visible;
686
- pointer-events: none;
687
- }
688
-
689
- /* AV.W9.1 — the AU.W8b native discrete-visibility arm (the second `@supports`
690
- block that expressed the 3-state contract as one discrete transition over
691
- opacity + visibility with a `@starting-style` entry anchor) is RETIRED. It
692
- was a THIRD opacity/visibility authority overlapping the hand-rolled 3-state
693
- fork above and the spring's settle — three owners for one concern. With the
694
- native size arm gone (W9.0), opacity now has ONE owner everywhere: the
695
- `opacity var(--dock-motion-resize)` crossfade on `.dock-layer{,-item-host}`
696
- (the AU.W2 lockstep token — kept), and visibility has ONE owner: the delayed
697
- `visibility 0s linear var(--duration-normal)` hold of the
698
- `AU.W8b-visibility-fork` 3-state fallback above (the a11y-006 bite-anchor,
699
- LOAD-BEARING). One authority per concern: size = spring/VT, opacity = the
700
- CSS crossfade, visibility = the delayed-hold fork. */
701
-
702
- /* ── Base layout — distinct per surface ─────────────────────────── */
703
- .dock-layer {
704
- display: flex;
705
- align-items: center;
706
- grid-area: 1 / 1;
707
- gap: var(--dock-layer-gap, 0.375rem);
708
- }
709
-
710
- /* AW.W2 — content-intrinsic axis follows the MORPH axis. A horizontal dock
711
- lays its inline content out ONCE at `width: max-content` (nowrap) so the
712
- width aperture uncovers a static row; the fixed `height` keeps the row a
713
- single line. Scoped to `:not(.vertical)` so a vertical rail (whose
714
- block-axis morph reveals a column) is NOT forced onto one nowrap row — the
715
- vertical group's active host block-sizes to `height: max-content` below
716
- (the AP.W3 column treatment, KEPT). */
717
- .glass-dock:not(.vertical) .dock-layer {
718
- white-space: nowrap;
719
- height: var(--dock-layer-height, 2.5rem);
720
- }
721
-
722
- .dock-layer.layer-active {
723
- position: relative;
724
- }
725
-
726
- .dock-layer:not(.layer-active) {
727
- position: absolute;
728
- inset: 0;
729
- }
730
-
731
- /* AW.W3 — the spring-keyed child stagger. While the size spring drives the
732
- morph, the driver arms the container (`.dock-layers` / `.dock-layer-stack`)
733
- with `data-revealing` and writes the morph's normalized progress to
734
- `--dock-morph-progress` (0 → 1) every frame. Each direct child of the
735
- ACTIVE pane reveals when that progress crosses a per-child onset, so the
736
- controls cascade IN ON the physical morph — a fast flick and a slow
737
- hover-open both choreograph correctly, and an interrupted morph carries the
738
- cascade with it (no orphaned timers). This is a per-CHILD opacity onset; the
739
- active PANE itself stays statically opacity:1 (revealed by the aperture —
740
- the W2 clip-reveal contract is NOT regressed).
741
-
742
- The reveal is a pure `calc` ramp: `opacity = clamp(0, (progress − onset) /
743
- window, 1)`. `--dock-stagger-onset` steps per child (nth-child); the window
744
- is `--dock-stagger-window`. The children also rise a few px on a `translate`
745
- that resolves on the same ramp. ONLY children inside the `[data-revealing]`
746
- active pane are armed — at rest the children carry no opacity authority (the
747
- default cascade leaves them at 1).
748
-
749
- PRM: the driver never arms `data-revealing` on the synchronous PRM swap (the
750
- FLIP fast-path returns before the spring; the spring's `respectReducedMotion`
751
- settles instantly), so the children paint at full opacity at once. The
752
- global PRM gate also strips `translate` from the transition-property — the
753
- rise snaps. The cascade collapses to 0 stagger frames under PRM. */
754
- .dock-layers[data-revealing] .dock-layer--full > *,
755
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > * {
756
- --dock-stagger-window: var(--dock-stagger-window-size, 0.55);
757
- --dock-stagger-onset: 0;
758
- opacity: clamp(
759
- 0,
760
- calc(
761
- (var(--dock-morph-progress, 1) - var(--dock-stagger-onset)) /
762
- var(--dock-stagger-window)
763
- ),
764
- 1
765
- );
766
- translate: 0
767
- calc(
768
- (1 - clamp(0, calc((var(--dock-morph-progress, 1) - var(--dock-stagger-onset)) / var(--dock-stagger-window)), 1)) *
769
- var(--dock-stagger-rise, 4px)
770
- );
771
- }
772
-
773
- /* Per-child onsets — each successive control starts a beat later, so the row
774
- fills outer→in on expand. The onsets are fractions of the morph progress;
775
- capped so even a long row finishes within the morph window. */
776
- .dock-layers[data-revealing] .dock-layer--full > *:nth-child(2),
777
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > *:nth-child(2) {
778
- --dock-stagger-onset: 0.08;
779
- }
780
- .dock-layers[data-revealing] .dock-layer--full > *:nth-child(3),
781
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > *:nth-child(3) {
782
- --dock-stagger-onset: 0.16;
783
- }
784
- .dock-layers[data-revealing] .dock-layer--full > *:nth-child(4),
785
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > *:nth-child(4) {
786
- --dock-stagger-onset: 0.24;
787
- }
788
- .dock-layers[data-revealing] .dock-layer--full > *:nth-child(5),
789
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > *:nth-child(5) {
790
- --dock-stagger-onset: 0.32;
791
- }
792
- .dock-layers[data-revealing] .dock-layer--full > *:nth-child(n + 6),
793
- .dock-layer-stack[data-revealing] .dock-layer-item-host.is-active > *:nth-child(n + 6) {
794
- --dock-stagger-onset: 0.4;
795
- }
796
-
797
- /* AW.W2 — the at-rest clip-lift moved to `.expanded:not([data-morphing])` /
798
- `.always-expanded:not([data-morphing])` (the clip-shell block at the top).
799
- A plain `overflow: visible` here would lift the clip DURING the morph (the
800
- load-bearing sequencing gap), so the `overflow` declarations are dropped
801
- from these state rules; they keep only their non-overflow concerns. */
802
- .glass-dock.expanded:not(.fit-content) .dock-layers {
803
- width: 100%;
804
- }
805
-
806
- .glass-dock.expanded:not(.fit-content) .dock-layer--full {
807
- width: 100%;
808
- }
809
-
810
- .glass-dock.always-expanded {
811
- cursor: default;
812
- }
813
-
814
- /* ── AW.W3b — `layout="grid"` the 2D auto-grid big dock ──────────────
815
- The active layer becomes a self-wrapping tile grid (Launchpad / Stage-Manager
816
- track symmetry — `auto-fill` columns floored at `--dock-tile-min`, explicit
817
- `grid-auto-rows` so the concentric look holds). DISTINCT from
818
- `overflow="wrap"`'s content-ordered flex-wrap. A `layout="grid"` dock is
819
- `alwaysExpanded` by contract (GlassDock.vue), so there is NO width morph and
820
- hence NO per-frame grid-column reflow. `white-space: normal` releases the
821
- single-row nowrap so the tiles wrap. */
822
- .glass-dock.layout-grid {
823
- white-space: normal;
824
- }
825
-
826
- .glass-dock.layout-grid .dock-layer--full {
827
- display: grid;
828
- grid-template-columns: repeat(
829
- auto-fill,
830
- minmax(var(--dock-tile-min, 4.5rem), 1fr)
831
- );
832
- grid-auto-rows: var(--dock-tile-min, 4.5rem);
833
- gap: var(--dock-layer-gap, 0.375rem);
834
- width: 100%;
835
- height: auto;
836
- white-space: normal;
837
- }
838
-
839
- /* A grid dock fills the inline cap; the active layer is the panel body, not a
840
- shrink-to-fit row. The cap is the `--dock-max-inline-size` clamp (KEPT). */
841
- .glass-dock.layout-grid .dock-layers {
842
- width: 100%;
843
- }
844
-
845
- /* CONCENTRIC inner tiles — inner radius = outer card radius − padding (the
846
- universal macOS / visionOS / Raycast rule). NEVER nest two pills
847
- (stadium-in-stadium); a finite outer + a stepped-down inner. */
848
- .glass-dock.layout-grid.shape-card .dock-layer--full > * {
849
- border-radius: calc(
850
- var(--dock-card-radius) - var(--dock-padding-inline, 0.5rem)
851
- );
852
- }
853
-
854
- /* ── Scroll-on-overflow opt-in (GlassDock `overflow="scroll"`) ───────
855
- The default contract grows-to-fit then overflows visibly past the
856
- axis cap. `overflow="scroll"` instead makes the dock the scroll port
857
- on its layout axis, pairing the existing cap with a hidden-scrollbar
858
- scroll region so over-cap content stays reachable. The rounded pill
859
- masks the scroll edge; both axes keep their cap. */
860
-
861
- /* Inline axis (horizontal docks). The active layer becomes the scroll
862
- port: `min-width: 0` releases the flex item's `min-content` floor so
863
- it can shrink under the clamped `.dock-layers` track, then `overflow-x:
864
- auto` scrolls its over-cap content. `.dock-layers` must KEEP clipping
865
- so the pill's rounded edge masks the scroll boundary — hence the
866
- grow-mode `overflow-x: visible` (`.dock-layers`, above) is overridden
867
- back to `hidden` here. */
868
- .glass-dock.dock-scroll-x.expanded:not(.dock-overflow-wrap) > .dock-layers {
869
- overflow-x: hidden;
870
- }
871
-
872
- .glass-dock.dock-scroll-x .dock-layer--full {
873
- min-width: 0;
874
- overflow-x: auto;
875
- scrollbar-width: none;
876
- /* Trap the inline-scroll momentum at the dock's own boundary so a
877
- wheel/trackpad gesture that bottoms out the pill does NOT chain into
878
- scrolling the page behind it (the dock is a self-contained scroll
879
- port, not a window into the route scroller). */
880
- overscroll-behavior-x: contain;
881
- }
882
-
883
- .glass-dock.dock-scroll-x .dock-layer--full::-webkit-scrollbar {
884
- display: none;
885
- }
886
-
887
- /* Block axis (vertical rails). The root keeps its `max-block-size` cap
888
- and scrolls its over-cap children — cap + scroll is the correct
889
- pairing the grow-mode contract split apart. Ties the
890
- `.vertical.always-expanded` visible default on specificity and wins on
891
- source order. */
892
- .glass-dock.vertical.dock-scroll-y {
893
- overflow-y: auto;
894
- scrollbar-width: none;
895
- /* Same momentum-trap as the inline port — a rail that bottoms out must
896
- not chain its remaining wheel delta into the page scroller behind it. */
897
- overscroll-behavior-y: contain;
898
- }
899
-
900
- .glass-dock.vertical.dock-scroll-y::-webkit-scrollbar {
901
- display: none;
902
- }
903
-
904
- /* ── `overflow="wrap"` recipe (the `.dock-overflow-wrap` hook) ────────
905
- Parallel to the `.dock-scroll-{x,y}` hooks the `overflow="scroll"`
906
- member emits: the `overflow="wrap"` enum member emits this class. (The
907
- prior `wrap` boolean's hook is retired — clean break, no alias.)
908
- Expanded content wraps to multiple rows; the pill narrows to the
909
- viewport gutter and snaps back to a single nowrap row past
910
- `--dock-overflow-bp` (the `@media` at the tail). */
911
- .glass-dock.dock-overflow-wrap {
912
- white-space: normal;
913
- border-radius: var(--radius-2xl);
914
- max-width: var(--dock-wrap-max-width);
915
- padding: var(--dock-wrap-padding-block, var(--dock-padding-block, 0.375rem))
916
- var(--dock-wrap-padding-inline, 0.625rem);
917
- }
918
-
919
- .glass-dock.dock-overflow-wrap .dock-layer--full {
920
- flex-wrap: wrap;
921
- justify-content: center;
922
- height: auto;
923
- min-height: var(--dock-wrap-layer-min-height, var(--dock-layer-height, 2rem));
924
- gap: var(--dock-wrap-row-gap, 0.25rem)
925
- var(--dock-wrap-column-gap, var(--dock-layer-gap, 0.375rem));
926
- /* AW.W3b — the graceful wrap-morph. The wrap/unwrap row-reflow flips
927
- `flex-wrap` at the `--dock-overflow-bp` `@media` boundary; without a
928
- transition the rows JUMP-CUT. Sequencing the layer's `min-height`
929
- through the `--dock-motion-resize` spring MORPHS the reflow. The global
930
- PRM gate strips `min-height` from the transition-property under reduce →
931
- the morph snaps (0 morph frames) while the reflow still completes. The
932
- wrap radius swap (`.collapsed` / `@media`) glides too — `border-radius`
933
- is in the shared `:not(.vertical)` transition list (AW.W3b scope 2). */
934
- transition: min-height var(--dock-motion-resize);
935
- }
936
-
937
- .glass-dock.dock-overflow-wrap .dock-layer--summary {
938
- height: auto;
939
- min-height: var(--dock-wrap-layer-min-height, var(--dock-layer-height, 2rem));
940
- }
941
-
942
- .glass-dock.dock-overflow-wrap .dock-separator {
943
- display: none;
944
- }
945
-
946
- .glass-dock.dock-overflow-wrap.collapsed {
947
- border-radius: var(--radius-pill);
948
- white-space: nowrap;
949
- max-width: none;
950
- }
951
-
952
- .dock-separator {
953
- @apply flex-shrink-0;
954
- width: 1px;
955
- height: var(--dock-separator-height);
956
- margin: 0 0.375rem;
957
- background: var(--surface-tint-15);
958
- }
959
-
960
- .dock-spacer {
961
- @apply flex-1;
962
- }
963
-
964
- .dock-layer-group {
965
- display: flex;
966
- gap: var(--dock-layer-group-gap, var(--dock-layer-gap, 0.25rem));
967
- min-width: 0;
968
- min-height: 0;
969
- }
970
-
971
- .dock-layer-group.horizontal {
972
- flex-direction: row;
973
- align-items: stretch;
974
- }
975
-
976
- .dock-layer-group.horizontal.rail-end {
977
- flex-direction: row-reverse;
978
- }
979
-
980
- .dock-layer-group.vertical {
981
- flex-direction: column;
982
- align-items: stretch;
983
- }
984
-
985
- .dock-layer-group.vertical.rail-end {
986
- flex-direction: column-reverse;
987
- }
988
-
989
- .dock-layer-rail {
990
- display: flex;
991
- flex-direction: column;
992
- flex-shrink: 0;
993
- gap: var(--dock-layer-rail-gap, 0.125rem);
994
- padding: var(--dock-layer-rail-padding, 0.125rem);
995
- border-right: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
996
- }
997
-
998
- .dock-layer-group.vertical .dock-layer-rail {
999
- flex-direction: row;
1000
- border-right: none;
1001
- border-bottom: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
1002
- }
1003
-
1004
- .dock-layer-group.horizontal.rail-end .dock-layer-rail {
1005
- border-right: none;
1006
- border-left: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
1007
- }
1008
-
1009
- .dock-layer-group.vertical.rail-end .dock-layer-rail {
1010
- border-bottom: none;
1011
- border-top: 1px solid color-mix(in srgb, var(--border) 30%, transparent);
1012
- }
1013
-
1014
- /* AU.W8.4 — the rail is a reka-ui Tabs contract. The travelling
1015
- `.dock-layer-tab-indicator` (the reka TabsIndicator) now carries the
1016
- active affordance; the rail is `position: relative` so the indicator's
1017
- absolute placement is rail-local. */
1018
- .dock-layer-rail {
1019
- position: relative;
1020
- }
1021
-
1022
- .dock-layer-rail .dock-layer-tab {
1023
- position: relative;
1024
- display: inline-flex;
1025
- align-items: center;
1026
- justify-content: center;
1027
- width: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
1028
- height: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
1029
- border: 0;
1030
- border-radius: var(--dock-layer-tab-radius, var(--radius-sm));
1031
- background: transparent;
1032
- color: var(--muted-foreground);
1033
- cursor: pointer;
1034
- font: inherit;
1035
- font-size: 0.75rem;
1036
- /* The tab glyph rides above the travelling indicator backplate. */
1037
- z-index: 1;
1038
- transition:
1039
- background var(--dock-motion-fast),
1040
- color var(--dock-motion-fast);
1041
- }
1042
-
1043
- .dock-layer-rail .dock-layer-tab:hover {
1044
- background: color-mix(in srgb, var(--accent) 40%, transparent);
1045
- color: var(--foreground);
1046
- }
1047
-
1048
- /* AU.W8.4 — KEEP the active glyph tint on the selected tab (reka emits
1049
- `data-state="active"` + `aria-selected="true"`); the per-button active
1050
- BACKGROUND is RETIRED — the travelling indicator carries that affordance. */
1051
- .dock-layer-rail .dock-layer-tab[data-state="active"] {
1052
- color: var(--primary);
1053
- }
1054
-
1055
- /* AU.W8.4 — the dock control focus-ring contract does not cover
1056
- `.dock-layer-tab` (the rail tab is not in the `.dock-icon-button` family).
1057
- The roving tabindex means only the active tab is in the tab order; a
1058
- focus-visible tab paints the shared dock ring. */
1059
- .dock-layer-rail [role="tab"]:focus-visible {
1060
- box-shadow: var(--focus-ring-shadow);
1061
- outline: none;
1062
- }
1063
-
1064
- /* AU.W8.4 — the travelling indicator (reka TabsIndicator). reka computes
1065
- `--reka-tabs-indicator-position` + `--reka-tabs-indicator-size` from the
1066
- active tab's geometry; the indicator morphs between tabs riding
1067
- `--dock-motion-resize` (= `--spring-dock` after AU.W8.2) — NOT a hardcoded
1068
- `--spring-snappy`. It paints the active-tab backplate the per-button
1069
- `.is-active` background used to. */
1070
- .dock-layer-rail .dock-layer-tab-indicator {
1071
- position: absolute;
1072
- left: 0;
1073
- top: 0;
1074
- height: var(--dock-layer-tab-size, var(--dock-control-size, 1.75rem));
1075
- width: var(--reka-tabs-indicator-size);
1076
- transform: translateX(var(--reka-tabs-indicator-position));
1077
- border-radius: var(--dock-layer-tab-radius, var(--radius-sm));
1078
- background: color-mix(in srgb, var(--primary) 15%, transparent);
1079
- transition:
1080
- width var(--dock-motion-resize),
1081
- transform var(--dock-motion-resize);
1082
- pointer-events: none;
1083
- }
1084
-
1085
- /* For a vertical rail the indicator travels along the inline axis still
1086
- (the horizontal-always keyboard decision keeps the indicator inline);
1087
- reka's position var resolves to the active tab offset regardless. */
1088
-
1089
- .dock-layer-stack {
1090
- position: relative;
1091
- display: grid;
1092
- /* AW.W2 — the morph axis (width for a horizontal group, height for a
1093
- vertical one) is driven by the `useLayerTransition` SpringProgress in
1094
- pixel space (FLIP path) or the View-Transition (native path); a CSS
1095
- `width`/`height` transition here would be a SECOND driver on the same
1096
- axis (the AV.W9.0 dual-driver race that froze the dock). The cross axis
1097
- is intrinsic-sized and never morphs. So NO size transition on the stack
1098
- — one owner per axis. */
1099
- }
1100
-
1101
- /* Base layout — the crossfade + hit-test contract is shared with
1102
- `.dock-layer` above (see "Layer crossfade + hit-test contract"). The
1103
- default state is inactive: absolute + inset:0. */
1104
- .dock-layer-item-host {
1105
- grid-area: 1 / 1;
1106
- display: flex;
1107
- align-items: center;
1108
- white-space: nowrap;
1109
- gap: var(--dock-layer-gap, 0.375rem);
1110
- position: absolute;
1111
- inset: 0;
1112
- }
1113
-
1114
- .dock-layer-item-host.is-active {
1115
- position: relative;
1116
- inset: auto;
1117
- width: max-content;
1118
- min-width: 0;
1119
- }
1120
-
1121
- /* AP.W3 — axis-aware layer pane. The stack + `useLayerTransition` are
1122
- axis-aware, but the pane was hardcoded to a no-wrap ROW with
1123
- `width: max-content` — forcing a `vertical` group's content onto one
1124
- horizontal line that could not grow down (the vertical-overflow fight).
1125
- A vertical group stacks in a column, stretches, wraps, and block-sizes
1126
- to the height the stack animates. Horizontal byte-identical. */
1127
- .dock-layer-group.vertical .dock-layer-item-host {
1128
- flex-direction: column;
1129
- align-items: stretch;
1130
- white-space: normal;
1131
- }
1132
-
1133
- .dock-layer-group.vertical .dock-layer-item-host.is-active {
1134
- width: auto;
1135
- height: max-content;
1136
- }
1137
-
1138
- /* AU.W8b.3 — the five dock CONTROL families (.dock-icon-button,
1139
- .dark-mode-toggle-button, .dock-tab-button + tiers, the
1140
- .dock-select-trigger / .dock-dropdown-trigger pair, and the coarse-pointer
1141
- per-button touch floor) carved out to dock-controls.css (imported directly
1142
- after this file in index.css, same @layer components). dock.css keeps the
1143
- shell / density / grain / layer-crossfade contract + the shared
1144
- cross-control four-state comma-groups (the :focus-visible / :disabled groups
1145
- + the motion-token :where() group above). */
1146
-
1147
- /* J.W3.B — `.dock-popover` substrate + `pop-up-*` / `pop-down-*`
1148
- Vue Transition keyframes retired. Hover-driven dock popovers
1149
- compose `<HoverPopover keep-dock-open>`, which inherits reka-ui
1150
- HoverCard's collision-avoidance + the canonical
1151
- `popover-animate` motion vocabulary. Click-anchored popovers
1152
- (no dock-keep semantics) compose `<Popover>` directly. */
1153
-
1154
- /* The `overflow="wrap"` desktop snap-back. Past the overflow breakpoint a
1155
- wrap-mode dock reverts from the narrow multi-row pill to a single nowrap
1156
- row. The breakpoint is the named token `--dock-overflow-bp` (tokens.css §9
1157
- Layout) — its single source-of-record. A `var()` cannot drive a
1158
- media-query feature in Baseline CSS, so this one `@media` realizes the
1159
- token's value; there is no longer a bare unexplained magic number — the
1160
- threshold lives under one name and is documented at its mint.
1161
- AV.W16 TW3 — KEPT as `@media` (not converted to `@container`): the wrap
1162
- dock is `max-width: calc(100vw - gutter)` — it spans the VIEWPORT by
1163
- contract, so the snap-back is genuinely viewport-semantic. The dock
1164
- establishes its own `dock` container and cannot self-query that
1165
- container for a rule on the dock root; the descendant-readable
1166
- label/density rules above are the container-query candidates. */
1167
- @media (min-width: 640px /* = var(--dock-overflow-bp) */) {
1168
- .glass-dock.dock-overflow-wrap {
1169
- white-space: nowrap;
1170
- border-radius: var(--radius-pill);
1171
- max-width: none;
1172
- padding: var(
1173
- --dock-wrap-desktop-padding-block,
1174
- var(--dock-padding-block, 0.375rem)
1175
- )
1176
- var(--dock-wrap-desktop-padding-inline, 0.75rem);
1177
- }
1178
-
1179
- .glass-dock.dock-overflow-wrap .dock-layer--full {
1180
- flex-wrap: nowrap;
1181
- height: var(--dock-layer-height, 2.5rem);
1182
- gap: var(--dock-wrap-desktop-gap, var(--dock-layer-gap, 0.25rem));
1183
- }
1184
-
1185
- .glass-dock.dock-overflow-wrap .dock-layer--summary {
1186
- height: var(--dock-layer-height, 2.5rem);
1187
- }
1188
-
1189
- .glass-dock.dock-overflow-wrap .dock-separator {
1190
- display: block;
1191
- }
1192
- }
1193
-
1194
- /* O.W6 Lane D — Touch-target floor (speedtest AC.W6 F2.AA-03 / WCAG
1195
- 2.5.5). On coarse-pointer devices (touch), every dock-control's
1196
- width/height floor lifts to the 44px WCAG target-size minimum.
1197
- The lift composes via `--dock-control-size` (the canonical knob
1198
- every dock-control surface — `.dock-icon-button`,
1199
- `.dock-tab-button`, `.dock-select-trigger`, `.dock-dropdown-trigger`
1200
- — already consumes) so the cascade reaches every control without
1201
- per-selector re-declaration. `--size-icon-btn` lifts in lockstep
1202
- so bare icon-button surfaces outside the dock (e.g.,
1203
- `.dark-mode-toggle-button[data-size="dock"]` and any consumer
1204
- that wires `var(--size-icon-btn)` for trigger sizing) inherit
1205
- the same floor.
1206
-
1207
- AP.W3 R0G-6 — selector is `.glass-dock[data-density]`, not bare
1208
- `.glass-dock`: the always-present density setter (0,2,0) shadowed a
1209
- bare (0,1,0) coarse floor, pinning the touch box at 40px. The
1210
- presence-selector (0,2,0) wins by source order, lifting
1211
- `--dock-control-size` to 44px — read by both the button box and the
1212
- dock width-math, so the slot reserves 44px (no overflow). Fine pointer
1213
- byte-identical. Proof: design/W1.2-motion-carve-and-dock.md §B.2. */
1214
- @media (pointer: coarse) {
1215
- .glass-dock[data-density] {
1216
- --dock-control-size: var(--dock-touch-target, 2.75rem);
1217
- --size-icon-btn: var(--dock-touch-target, 2.75rem);
1218
- }
1219
-
1220
- /* S-2 — the in-dock floor above lifts the control-SIZE token (shell /
1221
- width-math), which only reaches a DockIconButton that has a
1222
- `.glass-dock` ancestor. The companion button-level floor (the
1223
- `.dock-icon-button:not(--compact)` `min-{block,inline}-size` that
1224
- reaches a STANDALONE DockIconButton with no dock wrapper) moved to
1225
- dock-controls.css with the rest of the control family (AU.W8b.3). */
1226
- }
1227
111
  }