@mkbabb/glass-ui 3.0.0 → 3.1.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 (184) hide show
  1. package/dist/{CardFooter-Yi0xtLLd.js → CardFooter-CSGcJkqa.js} +1 -1
  2. package/dist/{CommandShortcut-BNDzfFnB.js → CommandShortcut-DWT19a2Y.js} +3 -3
  3. package/dist/{ContextMenuSubContent-DLEyeqbh.js → ContextMenuSubContent-gAFxJ-qi.js} +4 -4
  4. package/dist/{DataTable-Ce00dbHD.js → DataTable-R8-Zidms.js} +3 -3
  5. package/dist/{DialogContent-DSo7PKlU.js → DialogContent-2fALDSvc.js} +3 -3
  6. package/dist/{DialogFooter-D5KY6sCX.js → DialogFooter-ClrNEOVU.js} +2 -2
  7. package/dist/{DiscoGlyph-wRA02zAJ.js → DiscoGlyph-C3JfMnRV.js} +1 -1
  8. package/dist/{GlyphFace-BnPMUZ16.js → GlyphFace-BRS8vUb7.js} +1 -1
  9. package/dist/HoverPopover-CWFCfLx3.js +96 -0
  10. package/dist/{IconTooltip-GIeWdo64.js → IconTooltip-BkaA7tZ2.js} +1 -1
  11. package/dist/{Input-CBvqW8kZ.js → Input-DDpFn568.js} +3 -5
  12. package/dist/Label-DJty89bp.js +36 -0
  13. package/dist/{MetricBadge-DRBB18Xq.js → MetricBadge-DmAihkXd.js} +1 -1
  14. package/dist/{Notification-D97JO0fK.js → Notification-OqIpADml.js} +3 -3
  15. package/dist/NumberFieldContent-DTH9gb_N.js +141 -0
  16. package/dist/{PopoverContent-BCH4eYs8.js → PopoverContent-EiklFrna.js} +1 -1
  17. package/dist/{Progress-CCH-2UBR.js → Progress-FApA9fm_.js} +1 -1
  18. package/dist/{ScrollingText-7P8skg5W.js → ScrollingText-BFd0i2zJ.js} +2 -2
  19. package/dist/{SelectScrollDownButton-BwTexKeY.js → SelectScrollDownButton-Dth8-wXQ.js} +4 -4
  20. package/dist/{Toaster-CY8gJu9E.js → Toaster-Bjlunvq4.js} +1 -1
  21. package/dist/UnderlineTabs-DAWMLmJG.js +37 -0
  22. package/dist/animated-digit.js +2 -2
  23. package/dist/api/index.d.ts +2 -0
  24. package/dist/api.js +1 -1
  25. package/dist/aurora.js +3 -3
  26. package/dist/badge.js +1 -1
  27. package/dist/{button-BlOW34DT.js → button-C0aHmBbt.js} +2 -0
  28. package/dist/button.js +1 -1
  29. package/dist/card.js +1 -1
  30. package/dist/carousel.js +5 -5
  31. package/dist/{check-Nuw7H9Yh.js → check-dwgetki8.js} +1 -1
  32. package/dist/{chevron-down-Du2b9vY_.js → chevron-down-DILQA1t6.js} +1 -1
  33. package/dist/{chevron-right-CtDxpE3w.js → chevron-right-fS7fal2t.js} +1 -1
  34. package/dist/{chevron-up-CenYokvI.js → chevron-up-BtYjYQOS.js} +1 -1
  35. package/dist/collapsible.js +1 -1
  36. package/dist/command.js +1 -1
  37. package/dist/components/custom/dialog-native/GlassDialogNative.vue.d.ts +57 -0
  38. package/dist/components/custom/dialog-native/index.d.ts +1 -0
  39. package/dist/components/custom/dock/composables/useLayerTransition.d.ts +20 -10
  40. package/dist/components/custom/hover-popover/HoverPopover.vue.d.ts +26 -4
  41. package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +16 -2
  42. package/dist/components/custom/labeled-field/LabeledInput.vue.d.ts +17 -1
  43. package/dist/components/custom/labeled-field/LabeledSelect.vue.d.ts +2 -0
  44. package/dist/components/custom/labeled-field/LabeledSlider.vue.d.ts +2 -0
  45. package/dist/components/custom/labeled-field/LabeledSwitch.vue.d.ts +2 -0
  46. package/dist/components/ui/input/Input.vue.d.ts +10 -7
  47. package/dist/components/ui/label/Label.vue.d.ts +8 -0
  48. package/dist/components/ui/textarea/Textarea.vue.d.ts +45 -8
  49. package/dist/composables/dom/index.d.ts +1 -0
  50. package/dist/composables/dom/useUserInvalidAria.d.ts +32 -0
  51. package/dist/composables/motion/core/index.d.ts +2 -0
  52. package/dist/composables/motion/supportsCssTimeline.d.ts +8 -0
  53. package/dist/composables/motion/useRAFLoop.d.ts +7 -0
  54. package/dist/composables/motion/useScrollProgress.d.ts +6 -2
  55. package/dist/composables/motion/useStaggerReveal.d.ts +6 -0
  56. package/dist/composables/motion/useViewTransition.d.ts +31 -0
  57. package/dist/composables/motion/useYieldToMain.d.ts +29 -0
  58. package/dist/configurator.js +1 -1
  59. package/dist/confirm-dialog.js +3 -3
  60. package/dist/context-menu.js +2 -2
  61. package/dist/controls.js +2 -2
  62. package/dist/{createLucideIcon-rHu18UQW.js → createLucideIcon-Bn9a1b70.js} +2 -2
  63. package/dist/dark.js +1 -1
  64. package/dist/data-table.js +1 -1
  65. package/dist/dialog.js +2 -2
  66. package/dist/disco-glyph.js +1 -1
  67. package/dist/dock.js +196 -177
  68. package/dist/dom.js +5 -4
  69. package/dist/{dropdown-menu-gHSkffW7.js → dropdown-menu-BvRUamNs.js} +4 -4
  70. package/dist/dropdown-menu.js +1 -1
  71. package/dist/expandable-container.js +4 -4
  72. package/dist/forms.d.ts +1 -0
  73. package/dist/forms.js +47 -42
  74. package/dist/glass-carousel.js +1 -1
  75. package/dist/glass-panel.js +2 -2
  76. package/dist/glass-ui.css +1 -1
  77. package/dist/glass-ui.js +156 -275
  78. package/dist/glyph-face.js +2 -2
  79. package/dist/header-ribbon.js +1 -1
  80. package/dist/hover-card.js +1 -1
  81. package/dist/hover-popover.js +1 -1
  82. package/dist/icon-tooltip.js +1 -1
  83. package/dist/index.d.ts +1 -0
  84. package/dist/instrument-chassis.js +1 -1
  85. package/dist/instrument-rail.js +1 -1
  86. package/dist/keyboard.js +1 -1
  87. package/dist/label.js +1 -1
  88. package/dist/labeled-field.js +96 -57
  89. package/dist/metric-badge.js +1 -1
  90. package/dist/metric-stack.js +1 -1
  91. package/dist/{minimize-2-C_oyKVwZ.js → minimize-2-LsCJ_eNt.js} +1 -1
  92. package/dist/motion-core.js +135 -98
  93. package/dist/motion.js +3 -3
  94. package/dist/notification.js +1 -1
  95. package/dist/number-field.d.ts +1 -0
  96. package/dist/number-field.js +2 -0
  97. package/dist/paper-backdrop.js +1 -1
  98. package/dist/popover.js +1 -1
  99. package/dist/progress.js +1 -1
  100. package/dist/pulse.js +1 -1
  101. package/dist/reactive.js +2 -2
  102. package/dist/responsive-tabs.js +3 -3
  103. package/dist/scrolling-text.js +1 -1
  104. package/dist/{search-7XEx_6hq.js → search-DBAiUABx.js} +1 -1
  105. package/dist/search.js +7 -7
  106. package/dist/select.js +3 -3
  107. package/dist/separator.js +1 -1
  108. package/dist/{sheet-BsBdO5jq.js → sheet-CukNDezz.js} +53 -53
  109. package/dist/sheet.js +1 -1
  110. package/dist/{slider-BQaLYFLh.js → slider-DJvHkTRe.js} +3 -3
  111. package/dist/slider.js +1 -1
  112. package/dist/sortable-list.js +2 -2
  113. package/dist/styles/animations.css +77 -0
  114. package/dist/styles/cards.css +6 -2
  115. package/dist/styles/dock.css +37 -14
  116. package/dist/styles/glass.css +89 -6
  117. package/dist/styles/index.css +10 -1
  118. package/dist/styles/scroll-driven.css +72 -0
  119. package/dist/styles/theme.css +3 -0
  120. package/dist/styles/tokens.css +237 -24
  121. package/dist/styles/typography.css +21 -0
  122. package/dist/styles/utilities.css +176 -23
  123. package/dist/styles/view-transition.css +62 -0
  124. package/dist/switch.d.ts +1 -0
  125. package/dist/switch.js +2 -0
  126. package/dist/tabs.js +40 -36
  127. package/dist/timeline.js +2 -2
  128. package/dist/toast.js +1 -1
  129. package/dist/toggle-group.js +1 -1
  130. package/dist/tooltip.js +1 -1
  131. package/dist/typewriter.js +1 -1
  132. package/dist/{useAnimatedNumber-2l13GibX.js → useAnimatedNumber-DKQYVB7s.js} +1 -1
  133. package/dist/{useConfiguratorState-BpZi8QJu.js → useConfiguratorState-BR5vUDL8.js} +4 -4
  134. package/dist/{useIdleReady-DlzJicQH.js → useIdleReady-Cmkhm03v.js} +1 -1
  135. package/dist/{useTouchGate-BhhEMlwJ.js → useTouchGate-D9Zvrzyc.js} +1 -1
  136. package/dist/useUserInvalidAria-DVu1eTXG.js +29 -0
  137. package/dist/useViewTransition-DYIK6Gzb.js +16 -0
  138. package/dist/utils/index.d.ts +1 -0
  139. package/dist/utils/moveBefore.d.ts +15 -0
  140. package/dist/{x-Cb3NE2Ne.js → x-q7pJa83X.js} +1 -1
  141. package/package.json +17 -3
  142. package/src/styles/animations.css +77 -0
  143. package/src/styles/cards.css +6 -2
  144. package/src/styles/dock.css +37 -14
  145. package/src/styles/glass.css +89 -6
  146. package/src/styles/index.css +10 -1
  147. package/src/styles/scroll-driven.css +72 -0
  148. package/src/styles/theme.css +3 -0
  149. package/src/styles/tokens.css +237 -24
  150. package/src/styles/typography.css +21 -0
  151. package/src/styles/utilities.css +176 -23
  152. package/src/styles/view-transition.css +62 -0
  153. package/dist/HoverPopover-Btv4RQfv.js +0 -80
  154. package/dist/Label-C8QMJSsf.js +0 -32
  155. package/dist/UnderlineTabs-BtrUcXn-.js +0 -64
  156. /package/dist/{CollapsibleContent-DHRuXE3P.js → CollapsibleContent-CVMOcYlV.js} +0 -0
  157. /package/dist/{ContextMenuContent-CvXfU5qz.js → ContextMenuContent-otjFIu8v.js} +0 -0
  158. /package/dist/{HoverCardContent-4nN5-5bz.js → HoverCardContent-DaGrgJBO.js} +0 -0
  159. /package/dist/{InstrumentChassis-DOaVYyWq.js → InstrumentChassis-CnHTMxds.js} +0 -0
  160. /package/dist/{InstrumentRail-jHDqXj70.js → InstrumentRail-C6dEbi8E.js} +0 -0
  161. /package/dist/{ModalOverlay-DKLVY-cj.js → ModalOverlay-iWiAgbYH.js} +0 -0
  162. /package/dist/{PaperBackdrop-Bc2drCqJ.js → PaperBackdrop-CeZ-w0R0.js} +0 -0
  163. /package/dist/{SelectGroup-O69GTQ77.js → SelectGroup-DdR4tdDY.js} +0 -0
  164. /package/dist/{SelectSeparator-GTHxKO0a.js → SelectSeparator-CXm_hlqA.js} +0 -0
  165. /package/dist/{Separator-_NCypg_C.js → Separator-D8AUMhxY.js} +0 -0
  166. /package/dist/{Switch-CL0uxu8F.js → Switch-Cr1t_F_U.js} +0 -0
  167. /package/dist/{ToggleGroupItem-BYG_8M9M.js → ToggleGroupItem-OesUouE7.js} +0 -0
  168. /package/dist/{TooltipProvider-C5QLSPto.js → TooltipProvider-DE78vbEP.js} +0 -0
  169. /package/dist/{_plugin-vue_export-helper-n-_DRHWS.js → _plugin-vue_export-helper-Dq1MygBL.js} +0 -0
  170. /package/dist/{badge-BbxVKZfw.js → badge-x46my_Fo.js} +0 -0
  171. /package/dist/{constants-D-8FN28s.js → constants-DwBwnG8N.js} +0 -0
  172. /package/dist/{dockContext-BDGSrwsV.js → dockContext-D5NZCWJs.js} +0 -0
  173. /package/dist/{keys-DVkcUktU.js → keys-CaTQS-vx.js} +0 -0
  174. /package/dist/{menuItemVariants-B2nDL7zH.js → menuItemVariants-BsbGNq9C.js} +0 -0
  175. /package/dist/{presets-BMzCDrmR.js → presets-a-D93K1S.js} +0 -0
  176. /package/dist/{useGlassRenderer-DMDdMH55.js → useGlassRenderer-Ds-nmrGz.js} +0 -0
  177. /package/dist/{useGlobalDark-PMiP5Jku.js → useGlobalDark-B0WvLJE3.js} +0 -0
  178. /package/dist/{useIntersectionPause-CXYfYg_C.js → useIntersectionPause-IY2CwPQb.js} +0 -0
  179. /package/dist/{useInterval-COlTCeVa.js → useInterval-DVgGUf_y.js} +0 -0
  180. /package/dist/{useKeyboardShortcuts-CPO4AhLx.js → useKeyboardShortcuts-Dpw_RUcB.js} +0 -0
  181. /package/dist/{useResizeObserver-F4aRR4Cj.js → useResizeObserver-Cg9npuM3.js} +0 -0
  182. /package/dist/{useSortable-Ck0rBJ4g.js → useSortable-Cq2Y1JLO.js} +0 -0
  183. /package/dist/{useSpringMount-BTRBNzXP.js → useSpringMount-Cfk1XK1R.js} +0 -0
  184. /package/dist/{useTimer-lp5NlH4w.js → useTimer-NAaj9zNq.js} +0 -0
@@ -1,13 +1,13 @@
1
1
  import { t as e } from "./cn-DJXf4yaB.js";
2
- import { t } from "./x-Cb3NE2Ne.js";
3
- import { t as n } from "./useSpringMount-BTRBNzXP.js";
4
- import { t as r } from "./ModalOverlay-DKLVY-cj.js";
5
- import { computed as i, createBlock as a, createElementBlock as o, createVNode as s, defineComponent as c, guardReactiveProps as l, mergeProps as u, normalizeClass as d, normalizeProps as f, openBlock as p, renderSlot as m, toHandlers as h, unref as g, withCtx as _ } from "vue";
6
- import { DialogClose as v, DialogContent as y, DialogDescription as b, DialogPortal as x, DialogRoot as S, DialogTitle as C, DialogTrigger as w, injectDialogRootContext as T, useForwardPropsEmits as E } from "reka-ui";
7
- import { cva as D } from "class-variance-authority";
2
+ import { t } from "./x-q7pJa83X.js";
3
+ import { t as n } from "./useSpringMount-Cfk1XK1R.js";
4
+ import { t as r } from "./ModalOverlay-iWiAgbYH.js";
5
+ import { computed as i, createBlock as a, createElementBlock as o, createElementVNode as s, createVNode as c, defineComponent as l, guardReactiveProps as u, mergeProps as d, normalizeClass as f, normalizeProps as p, openBlock as m, renderSlot as h, toHandlers as g, unref as _, withCtx as v } from "vue";
6
+ import { DialogClose as y, DialogContent as b, DialogDescription as x, DialogPortal as S, DialogRoot as C, DialogTitle as w, DialogTrigger as T, injectDialogRootContext as E, useForwardPropsEmits as D } from "reka-ui";
7
+ import { cva as O } from "class-variance-authority";
8
8
  //#endregion
9
9
  //#region src/components/ui/sheet/Sheet.vue
10
- var O = /* @__PURE__ */ c({
10
+ var k = /* @__PURE__ */ l({
11
11
  __name: "Sheet",
12
12
  props: {
13
13
  open: { type: Boolean },
@@ -16,13 +16,13 @@ var O = /* @__PURE__ */ c({
16
16
  },
17
17
  emits: ["update:open"],
18
18
  setup(e, { emit: t }) {
19
- let n = E(e, t);
20
- return (e, t) => (p(), a(g(S), f(l(g(n))), {
21
- default: _(() => [m(e.$slots, "default")]),
19
+ let n = D(e, t);
20
+ return (e, t) => (m(), a(_(C), p(u(_(n))), {
21
+ default: v(() => [h(e.$slots, "default")]),
22
22
  _: 3
23
23
  }, 16));
24
24
  }
25
- }), k = /* @__PURE__ */ c({
25
+ }), A = /* @__PURE__ */ l({
26
26
  __name: "SheetTrigger",
27
27
  props: {
28
28
  asChild: { type: Boolean },
@@ -30,12 +30,12 @@ var O = /* @__PURE__ */ c({
30
30
  },
31
31
  setup(e) {
32
32
  let t = e;
33
- return (e, n) => (p(), a(g(w), f(l(t)), {
34
- default: _(() => [m(e.$slots, "default")]),
33
+ return (e, n) => (m(), a(_(T), p(u(t)), {
34
+ default: v(() => [h(e.$slots, "default")]),
35
35
  _: 3
36
36
  }, 16));
37
37
  }
38
- }), A = /* @__PURE__ */ c({
38
+ }), j = /* @__PURE__ */ l({
39
39
  __name: "SheetClose",
40
40
  props: {
41
41
  asChild: { type: Boolean },
@@ -43,12 +43,12 @@ var O = /* @__PURE__ */ c({
43
43
  },
44
44
  setup(e) {
45
45
  let t = e;
46
- return (e, n) => (p(), a(g(v), f(l(t)), {
47
- default: _(() => [m(e.$slots, "default")]),
46
+ return (e, n) => (m(), a(_(y), p(u(t)), {
47
+ default: v(() => [h(e.$slots, "default")]),
48
48
  _: 3
49
49
  }, 16));
50
50
  }
51
- }), j = /* @__PURE__ */ c({
51
+ }), M = /* @__PURE__ */ l({
52
52
  inheritAttrs: !1,
53
53
  __name: "SheetContent",
54
54
  props: {
@@ -76,17 +76,17 @@ var O = /* @__PURE__ */ c({
76
76
  "openAutoFocus",
77
77
  "closeAutoFocus"
78
78
  ],
79
- setup(o, { emit: c }) {
80
- let l = o, d = c, f = E(i(() => {
81
- let { class: e, side: t, spring: n, dragDismiss: r, dragThreshold: i, ...a } = l;
79
+ setup(o, { emit: l }) {
80
+ let u = o, f = l, p = D(i(() => {
81
+ let { class: e, side: t, spring: n, dragDismiss: r, dragThreshold: i, ...a } = u;
82
82
  return a;
83
- }), d), b = l.spring ? T() : null, S = l.spring && b ? n({
84
- open: b.open,
85
- preset: typeof l.spring == "string" ? l.spring : "smooth",
86
- dismissThreshold: l.dragThreshold ?? .3,
87
- onDismiss: () => b.onOpenChange(!1)
88
- }) : null, C = i(() => l.side ?? "right");
89
- function w(e, t) {
83
+ }), f), x = u.spring ? E() : null, C = u.spring && x ? n({
84
+ open: x.open,
85
+ preset: typeof u.spring == "string" ? u.spring : "smooth",
86
+ dismissThreshold: u.dragThreshold ?? .3,
87
+ onDismiss: () => x.onOpenChange(!1)
88
+ }) : null, w = i(() => u.side ?? "right");
89
+ function T(e, t) {
90
90
  let n = `${e * 100}%`;
91
91
  switch (t) {
92
92
  case "top": return `translateY(-${n})`;
@@ -95,28 +95,28 @@ var O = /* @__PURE__ */ c({
95
95
  default: return `translateX(${n})`;
96
96
  }
97
97
  }
98
- let D = i(() => {
99
- if (S) return {
100
- transform: w(S.position.value, C.value),
98
+ let O = i(() => {
99
+ if (C) return {
100
+ transform: T(C.position.value, w.value),
101
101
  animation: "none",
102
102
  transition: "none"
103
103
  };
104
- }), O = i(() => l.spring && l.dragDismiss && S ? S.dragHandlers : {});
105
- return (n, i) => (p(), a(g(x), null, {
106
- default: _(() => [s(r, {
104
+ }), k = i(() => u.spring && u.dragDismiss && C ? C.dragHandlers : {});
105
+ return (n, i) => (m(), a(_(S), null, {
106
+ default: v(() => [c(r, {
107
107
  scrim: "glass",
108
108
  animate: "fade",
109
109
  layout: "centered"
110
- }), s(g(y), u({ class: g(e)(g(I)({ side: C.value }), l.spring ? "transition-none" : "", l.class) }, {
111
- ...g(f),
110
+ }), c(_(b), d({ class: _(e)(_(L)({ side: w.value }), u.spring ? "transition-none" : "", u.class) }, {
111
+ ..._(p),
112
112
  ...n.$attrs
113
113
  }, {
114
- style: D.value,
115
- "data-spring": l.spring ? typeof l.spring == "string" ? l.spring : "smooth" : void 0,
116
- "data-drag-dismiss": l.spring && l.dragDismiss ? "" : void 0
117
- }, h(O.value)), {
118
- default: _(() => [m(n.$slots, "default"), s(g(v), { class: "focus-ring absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none data-[state=open]:bg-secondary" }, {
119
- default: _(() => [s(g(t), { class: "w-4 h-4 text-muted-foreground" })]),
114
+ style: O.value,
115
+ "data-spring": u.spring ? typeof u.spring == "string" ? u.spring : "smooth" : void 0,
116
+ "data-drag-dismiss": u.spring && u.dragDismiss ? "" : void 0
117
+ }, g(k.value)), {
118
+ default: v(() => [h(n.$slots, "default"), c(_(y), { class: "focus-ring absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 disabled:pointer-events-none data-[state=open]:bg-secondary" }, {
119
+ default: v(() => [c(_(t), { class: "w-4 h-4 text-muted-foreground" }), i[0] ||= s("span", { class: "sr-only" }, "Close", -1)]),
120
120
  _: 1
121
121
  })]),
122
122
  _: 3
@@ -129,7 +129,7 @@ var O = /* @__PURE__ */ c({
129
129
  _: 3
130
130
  }));
131
131
  }
132
- }), M = /* @__PURE__ */ c({
132
+ }), N = /* @__PURE__ */ l({
133
133
  __name: "SheetHeader",
134
134
  props: { class: { type: [
135
135
  Boolean,
@@ -140,9 +140,9 @@ var O = /* @__PURE__ */ c({
140
140
  ] } },
141
141
  setup(t) {
142
142
  let n = t;
143
- return (t, r) => (p(), o("div", { class: d(g(e)("flex flex-col gap-y-2 text-center sm:text-left", n.class)) }, [m(t.$slots, "default")], 2));
143
+ return (t, r) => (m(), o("div", { class: f(_(e)("flex flex-col gap-y-2 text-center sm:text-left", n.class)) }, [h(t.$slots, "default")], 2));
144
144
  }
145
- }), N = /* @__PURE__ */ c({
145
+ }), P = /* @__PURE__ */ l({
146
146
  __name: "SheetTitle",
147
147
  props: {
148
148
  asChild: { type: Boolean },
@@ -160,12 +160,12 @@ var O = /* @__PURE__ */ c({
160
160
  let { class: e, ...t } = n;
161
161
  return t;
162
162
  });
163
- return (t, i) => (p(), a(g(C), u({ class: g(e)("text-subheading text-foreground", n.class) }, r.value), {
164
- default: _(() => [m(t.$slots, "default")]),
163
+ return (t, i) => (m(), a(_(w), d({ class: _(e)("text-subheading text-foreground", n.class) }, r.value), {
164
+ default: v(() => [h(t.$slots, "default")]),
165
165
  _: 3
166
166
  }, 16, ["class"]));
167
167
  }
168
- }), P = /* @__PURE__ */ c({
168
+ }), F = /* @__PURE__ */ l({
169
169
  __name: "SheetDescription",
170
170
  props: {
171
171
  asChild: { type: Boolean },
@@ -183,12 +183,12 @@ var O = /* @__PURE__ */ c({
183
183
  let { class: e, ...t } = n;
184
184
  return t;
185
185
  });
186
- return (t, i) => (p(), a(g(b), u({ class: g(e)("text-sm text-muted-foreground", n.class) }, r.value), {
187
- default: _(() => [m(t.$slots, "default")]),
186
+ return (t, i) => (m(), a(_(x), d({ class: _(e)("text-sm text-muted-foreground", n.class) }, r.value), {
187
+ default: v(() => [h(t.$slots, "default")]),
188
188
  _: 3
189
189
  }, 16, ["class"]));
190
190
  }
191
- }), F = /* @__PURE__ */ c({
191
+ }), I = /* @__PURE__ */ l({
192
192
  __name: "SheetFooter",
193
193
  props: { class: { type: [
194
194
  Boolean,
@@ -199,9 +199,9 @@ var O = /* @__PURE__ */ c({
199
199
  ] } },
200
200
  setup(t) {
201
201
  let n = t;
202
- return (t, r) => (p(), o("div", { class: d(g(e)("flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2", n.class)) }, [m(t.$slots, "default")], 2));
202
+ return (t, r) => (m(), o("div", { class: f(_(e)("flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2", n.class)) }, [h(t.$slots, "default")], 2));
203
203
  }
204
- }), I = D("fixed z-modal gap-4 glass-floating p-6 transition ease-in-out sheet-animate", {
204
+ }), L = O("fixed z-modal gap-4 glass-floating p-6 transition ease-in-out sheet-animate", {
205
205
  variants: { side: {
206
206
  top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
207
207
  bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
@@ -211,4 +211,4 @@ var O = /* @__PURE__ */ c({
211
211
  defaultVariants: { side: "right" }
212
212
  });
213
213
  //#endregion
214
- export { M as a, k as c, N as i, O as l, F as n, j as o, P as r, A as s, I as t };
214
+ export { N as a, A as c, P as i, k as l, I as n, M as o, F as r, j as s, L as t };
package/dist/sheet.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./sheet-BsBdO5jq.js";
1
+ import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./sheet-CukNDezz.js";
2
2
  export { r as Sheet, s as SheetClose, a as SheetContent, o as SheetDescription, i as SheetFooter, e as SheetHeader, n as SheetTitle, t as SheetTrigger, c as sheetVariants };
@@ -1,7 +1,7 @@
1
1
  import { t as e } from "./cn-DJXf4yaB.js";
2
- import { t } from "./_plugin-vue_export-helper-n-_DRHWS.js";
3
- import { i as n } from "./dockContext-BDGSrwsV.js";
4
- import { t as r } from "./useTouchGate-BhhEMlwJ.js";
2
+ import { t } from "./_plugin-vue_export-helper-Dq1MygBL.js";
3
+ import { i as n } from "./dockContext-D5NZCWJs.js";
4
+ import { t as r } from "./useTouchGate-D9Zvrzyc.js";
5
5
  import { Fragment as i, computed as a, createBlock as o, createElementBlock as s, createVNode as c, defineComponent as l, mergeProps as u, onBeforeUnmount as d, openBlock as f, renderList as p, unref as m, useTemplateRef as h, watch as g, withCtx as _ } from "vue";
6
6
  import { SliderRange as v, SliderRoot as y, SliderThumb as b, SliderTrack as x, useForwardPropsEmits as S } from "reka-ui";
7
7
  import { cva as C } from "class-variance-authority";
package/dist/slider.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./slider-BQaLYFLh.js";
1
+ import { n as e, t } from "./slider-DJvHkTRe.js";
2
2
  export { e as Slider, t as sliderVariants };
@@ -1,5 +1,5 @@
1
- import { t as e } from "./_plugin-vue_export-helper-n-_DRHWS.js";
2
- import { t } from "./useSortable-Ck0rBJ4g.js";
1
+ import { t as e } from "./_plugin-vue_export-helper-Dq1MygBL.js";
2
+ import { t } from "./useSortable-Cq2Y1JLO.js";
3
3
  import { computed as n, createBlock as r, defineComponent as i, inject as a, mergeProps as o, openBlock as s, provide as c, renderSlot as l, resolveDynamicComponent as u, toRef as d, unref as f, withCtx as p } from "vue";
4
4
  //#region src/components/custom/sortable-list/context.ts
5
5
  var m = Symbol("glass-ui:sortable");
@@ -296,3 +296,80 @@
296
296
  animation: none;
297
297
  }
298
298
  }
299
+
300
+ /* ── §TOP-LAYER ENTRY/EXIT (AQ.W5 §Design 2) ───────────────────────────────
301
+ *
302
+ * A pure-CSS entry/exit grammar for NATIVE top-layer surfaces — `[popover]`
303
+ * elements and native `<dialog>` — keyed off `:popover-open` / `dialog[open]`,
304
+ * plus a glass `::backdrop`. This replaces the per-frame inline-style entry the
305
+ * platform now owns: `@starting-style` + `transition` + `transition-behavior:
306
+ * allow-discrete` + `overlay`.
307
+ *
308
+ * SCOPE: this applies ONLY to elements tagged `.glass-top-layer`. It does NOT
309
+ * touch reka-ui's portaled overlays — those keep their `tw-animate-css`
310
+ * data-state fade (distinct selectors, no cascade fight, mirroring the
311
+ * `[data-scrim-animation]` discipline above). `DialogContent`'s `spring` opt-in
312
+ * (`useSpringMount`) is also untouched — a legitimate iOS-physics variant, not a
313
+ * duplicate of this fade.
314
+ *
315
+ * Baseline: `@starting-style` = Widely Available; `transition-behavior:
316
+ * allow-discrete` + `overlay` = Newly Available → adopt natively, gate the
317
+ * whole grammar on `@supports (overlay: auto)`. A non-supporting engine shows
318
+ * the element instantly (acceptable for a native top-layer surface; glass-ui
319
+ * ships no JS top-layer coordinator — that is reka-ui Dialog's remit).
320
+ *
321
+ * Uses `scale:` (the longhand) not `transform: scale()` so it composes with the
322
+ * identity-base transform work and does not mint a stacking context. Every
323
+ * visual axis reads a `--top-layer-*` token (tokens.css §20).
324
+ */
325
+ @supports (overlay: auto) {
326
+ /* Base (closed / exit) + the transition list. `allow-discrete` MUST come
327
+ * after the property longhands, never negated. */
328
+ .glass-top-layer[popover],
329
+ dialog.glass-top-layer {
330
+ opacity: 0;
331
+ scale: var(--top-layer-enter-scale, 0.96);
332
+ transition-property: opacity, scale, display, overlay;
333
+ transition-duration: var(--duration-normal);
334
+ transition-timing-function: var(--ease-apple-spring);
335
+ transition-behavior: allow-discrete;
336
+ }
337
+
338
+ /* Open state + `@starting-style` entry (starting-style AFTER the open
339
+ * selector so the entry interpolates from the closed values). */
340
+ .glass-top-layer[popover]:popover-open,
341
+ dialog.glass-top-layer[open] {
342
+ opacity: 1;
343
+ scale: 1;
344
+ @starting-style {
345
+ opacity: 0;
346
+ scale: var(--top-layer-enter-scale, 0.96);
347
+ }
348
+ }
349
+
350
+ /* Glass backdrop — blur + dim, animated discretely. `::backdrop` only
351
+ * exists for `showModal()` dialogs, NOT `[popover]` (popovers are
352
+ * non-modal — correct, no scrim). */
353
+ dialog.glass-top-layer::backdrop {
354
+ background-color: hsl(var(--background) / 0);
355
+ backdrop-filter: blur(var(--top-layer-backdrop-blur, 8px));
356
+ transition: display var(--duration-normal) allow-discrete,
357
+ overlay var(--duration-normal) allow-discrete,
358
+ background-color var(--duration-normal) var(--ease-standard);
359
+ }
360
+ dialog.glass-top-layer[open]::backdrop {
361
+ background-color: hsl(var(--background) / var(--top-layer-backdrop-dim, 0.5));
362
+ @starting-style {
363
+ background-color: hsl(var(--background) / 0);
364
+ }
365
+ }
366
+ }
367
+
368
+ /* Reduced-motion carve — flatten the scale to a fade, shorten the duration. */
369
+ @media (prefers-reduced-motion: reduce) {
370
+ .glass-top-layer[popover],
371
+ dialog.glass-top-layer {
372
+ scale: none;
373
+ transition-duration: var(--duration-fast);
374
+ }
375
+ }
@@ -33,12 +33,16 @@
33
33
  @utility cartoon-surface {
34
34
  border-width: 2px;
35
35
  box-shadow: var(--shadow-cartoon-md);
36
+ /* Individual-transform identity base (AQ.W3 §W3.2) — state-driven 2D lift on
37
+ a card surface that often hosts portaled content; `translate: 0` at rest
38
+ mints the stacking context once. Longhand maps `translate(x, y)` 1:1. */
39
+ translate: 0;
36
40
  transition:
37
- transform var(--duration-normal) var(--ease-apple-spring),
41
+ translate var(--duration-normal) var(--ease-apple-spring),
38
42
  box-shadow var(--duration-normal) var(--ease-apple);
39
43
 
40
44
  &:hover:not(:disabled) {
41
- transform: translate(var(--lift-sm), var(--lift-sm));
45
+ translate: var(--lift-sm) var(--lift-sm);
42
46
  box-shadow: var(--shadow-cartoon-lg);
43
47
  }
44
48
  }
@@ -56,6 +56,11 @@
56
56
  --dock-wrap-max-width: calc(100vw - var(--dock-viewport-inline-gutter, 1rem));
57
57
  --dock-separator-height: calc(var(--dock-h, var(--size-icon-btn)) * 0.5);
58
58
  --dock-collapsed-hover-scale: var(--scale-hover-dock);
59
+ /* Individual-transform identity base (AQ.W3 §W3.2). `scale: 1` at rest
60
+ mints the stacking context once so a portaled popover over `--z-dock`
61
+ stays above the dock during a hover scale (the load-bearing
62
+ stacking-context guarantee). Covers every dock scale site. */
63
+ scale: 1;
59
64
  position: relative;
60
65
  display: inline-flex;
61
66
  align-items: center;
@@ -308,7 +313,7 @@
308
313
  background: var(--glass-bg-wash);
309
314
  border-color: var(--glass-border-floating);
310
315
  box-shadow: var(--shadow-dock-override, var(--shadow-dock));
311
- transform: scale(var(--dock-collapsed-hover-scale));
316
+ scale: var(--dock-collapsed-hover-scale);
312
317
  }
313
318
 
314
319
  /* J.W5.C — held-state substrate response.
@@ -331,6 +336,15 @@
331
336
  box-shadow var(--duration-fast) var(--ease-standard);
332
337
  }
333
338
 
339
+ /* AQ.W3 §W3.1b — open-descendant surface response. When a dock-hosted
340
+ trigger (`[data-state="open"]`) is open, the dock root holds its elevated
341
+ read natively (no consumer JS). Idempotent with `[data-held]` above (same
342
+ floating paint, different trigger). Decorative; `:has()` Baseline Widely. */
343
+ .glass-dock:has([data-state="open"]) {
344
+ background: var(--glass-bg-floating, var(--glass-bg-resting));
345
+ border-color: var(--glass-border-floating, var(--glass-border-resting));
346
+ }
347
+
334
348
  .glass-dock:where(.fixed) {
335
349
  z-index: var(--z-dock);
336
350
  }
@@ -647,6 +661,8 @@
647
661
  align-items: center;
648
662
  justify-content: center;
649
663
  flex-shrink: 0;
664
+ /* AQ.W3 §W3.2 identity base */
665
+ scale: 1;
650
666
  width: var(--dock-control-size, var(--size-icon-btn));
651
667
  height: var(--dock-control-size, var(--size-icon-btn));
652
668
  padding: var(--dock-icon-padding, 0);
@@ -659,7 +675,7 @@
659
675
  transition:
660
676
  background-color var(--dock-motion-fast),
661
677
  color var(--dock-motion-fast),
662
- transform var(--dock-motion-fast),
678
+ scale var(--dock-motion-fast),
663
679
  opacity var(--dock-motion-fast);
664
680
  }
665
681
 
@@ -673,11 +689,11 @@
673
689
  .dock-icon-button:hover:not(:disabled) {
674
690
  background: var(--muted);
675
691
  color: var(--btn-hover-color, var(--foreground));
676
- transform: scale(var(--scale-hover-dock));
692
+ scale: var(--scale-hover-dock);
677
693
  }
678
694
 
679
695
  .dock-icon-button:active:not(:disabled) {
680
- transform: scale(var(--scale-press-dock));
696
+ scale: var(--scale-press-dock);
681
697
  }
682
698
 
683
699
  .dock-icon-button:focus:not(:focus-visible) {
@@ -691,7 +707,7 @@
691
707
  transition:
692
708
  background-color var(--dock-motion-fast),
693
709
  color var(--dock-motion-fast),
694
- transform var(--dock-motion-fast),
710
+ scale var(--dock-motion-fast),
695
711
  opacity var(--dock-motion-fast),
696
712
  box-shadow var(--dock-motion-fast);
697
713
  }
@@ -705,7 +721,7 @@
705
721
  .dock-icon-button:is(.is-active, .active, [aria-expanded="true"], [aria-pressed="true"]) {
706
722
  background: var(--dock-active-bg);
707
723
  color: var(--dock-active-color);
708
- transform: scale(var(--dock-active-scale));
724
+ scale: var(--dock-active-scale);
709
725
  border: var(--dock-active-border);
710
726
  box-shadow: var(--dock-active-shadow);
711
727
  }
@@ -809,10 +825,12 @@
809
825
  cursor: pointer;
810
826
  white-space: nowrap;
811
827
  outline: none;
828
+ /* AQ.W3 §W3.2 identity base */
829
+ scale: 1;
812
830
  transition:
813
831
  background-color var(--dock-motion-fast),
814
832
  color var(--dock-motion-fast),
815
- transform var(--dock-motion-fast);
833
+ scale var(--dock-motion-fast);
816
834
  }
817
835
 
818
836
  .dock-tab-button:hover:not(:disabled) {
@@ -821,7 +839,7 @@
821
839
  }
822
840
 
823
841
  .dock-tab-button:active:not(:disabled) {
824
- transform: scale(var(--scale-press-dock));
842
+ scale: var(--scale-press-dock);
825
843
  }
826
844
 
827
845
  .dock-tab-button:focus:not(:focus-visible) {
@@ -938,6 +956,8 @@
938
956
  align-items: center;
939
957
  justify-content: center;
940
958
  flex-shrink: 0;
959
+ /* AQ.W3 §W3.2 identity base */
960
+ scale: 1;
941
961
  gap: var(--dock-trigger-gap, 0.25rem);
942
962
  min-height: var(--dock-trigger-min-height, auto);
943
963
  padding:
@@ -953,7 +973,7 @@
953
973
  transition:
954
974
  background-color var(--dock-motion-fast),
955
975
  color var(--dock-motion-fast),
956
- transform var(--dock-motion-fast),
976
+ scale var(--dock-motion-fast),
957
977
  opacity var(--dock-motion-fast);
958
978
  }
959
979
 
@@ -964,12 +984,12 @@
964
984
  }
965
985
 
966
986
  .dock-dropdown-trigger:hover:not(:disabled) {
967
- transform: scale(var(--scale-hover-dock));
987
+ scale: var(--scale-hover-dock);
968
988
  }
969
989
 
970
990
  .dock-select-trigger:active:not(:disabled),
971
991
  .dock-dropdown-trigger:active:not(:disabled) {
972
- transform: scale(var(--scale-press-dock));
992
+ scale: var(--scale-press-dock);
973
993
  }
974
994
 
975
995
  .dock-select-trigger:focus:not(:focus-visible),
@@ -985,7 +1005,7 @@
985
1005
  transition:
986
1006
  background-color var(--dock-motion-fast),
987
1007
  color var(--dock-motion-fast),
988
- transform var(--dock-motion-fast),
1008
+ scale var(--dock-motion-fast),
989
1009
  opacity var(--dock-motion-fast),
990
1010
  box-shadow var(--dock-motion-fast);
991
1011
  }
@@ -1001,11 +1021,14 @@
1001
1021
  height: var(--dock-trigger-icon-size, 0.75rem);
1002
1022
  flex-shrink: 0;
1003
1023
  opacity: 0.5;
1004
- transition: transform var(--dock-motion-fast);
1024
+ /* Individual-transform identity base (AQ.W3 §W3.2) — `rotate:` longhand
1025
+ for family consistency (not a stacking-context hazard: child glyph). */
1026
+ rotate: 0deg;
1027
+ transition: rotate var(--dock-motion-fast);
1005
1028
  }
1006
1029
 
1007
1030
  .dock-select-trigger[data-state="open"] .dock-select-trigger__chevron {
1008
- transform: rotate(180deg);
1031
+ rotate: 180deg;
1009
1032
  }
1010
1033
 
1011
1034
  @media (min-width: 640px) {
@@ -101,13 +101,30 @@
101
101
  Interactive cards live in <Card> (which owns its own hover composition)
102
102
  or in components that explicitly opt into a hover variant. */
103
103
  .glass-card {
104
+ /* Focus-elevation rungs (AQ.W3 §W3.1a) — identity = at-rest paint; the
105
+ `:has(:focus-visible)` rule redefines them (one source, shared with
106
+ the fallback). */
107
+ --card-focus-shadow: var(--shadow-card);
108
+ --card-focus-border: var(--glass-border-quiet);
104
109
  position: relative;
105
110
  background: var(--glass-bg-quiet);
106
111
  backdrop-filter: var(--glass-blur-quiet);
107
- border: 1px solid var(--glass-border-quiet);
112
+ border: 1px solid var(--card-focus-border);
108
113
  border-radius: var(--radius-card);
109
- box-shadow: var(--shadow-card);
114
+ box-shadow: var(--card-focus-shadow);
110
115
  contain: layout style;
116
+ transition:
117
+ box-shadow var(--duration-fast) var(--ease-standard),
118
+ border-color var(--duration-fast) var(--ease-standard);
119
+ }
120
+
121
+ /* Elevate one rung on descendant KEYBOARD focus (`:focus-visible`, not
122
+ pointer). Scoped to `.glass-card`. `:has()` Baseline Widely; the
123
+ `@supports not selector(:has(*))` class fallback (below) ships anyway
124
+ (focus-elevation is UX-critical — child-state-styling MANDATORY clause). */
125
+ .glass-card:has(:focus-visible) {
126
+ --card-focus-shadow: var(--shadow-md);
127
+ --card-focus-border: var(--glass-border-floating);
111
128
  }
112
129
 
113
130
  /* ── Glassmorphic circular icon button ── */
@@ -115,6 +132,10 @@
115
132
  .glass-btn {
116
133
  @apply flex items-center justify-center cursor-pointer;
117
134
 
135
+ /* Individual-transform identity base (AQ.W3 §W3.2) — `scale: 1` at rest
136
+ mints the stacking context once so the hover/press scale below does
137
+ not flicker it into being (the z-index/anchor hazard). */
138
+ scale: 1;
118
139
  width: var(--size-icon-btn);
119
140
  height: var(--size-icon-btn);
120
141
  border-radius: var(--radius-pill);
@@ -126,18 +147,18 @@
126
147
  background var(--duration-fast) var(--ease-standard),
127
148
  border-color var(--duration-fast) var(--ease-standard),
128
149
  color var(--duration-fast) var(--ease-standard),
129
- transform var(--duration-normal) var(--spring-snappy);
150
+ scale var(--duration-normal) var(--spring-snappy);
130
151
  }
131
152
 
132
153
  .glass-btn:hover:not(:disabled) {
133
154
  background: color-mix(in srgb, var(--background) 85%, transparent);
134
155
  border-color: var(--surface-tint-22);
135
156
  color: var(--foreground);
136
- transform: scale(var(--scale-hover));
157
+ scale: var(--scale-hover);
137
158
  }
138
159
 
139
160
  .glass-btn:active:not(:disabled) {
140
- transform: scale(var(--scale-press));
161
+ scale: var(--scale-press);
141
162
  }
142
163
 
143
164
  .glass-btn:focus-visible {
@@ -210,12 +231,60 @@
210
231
  color: var(--surface-tint-35);
211
232
  }
212
233
 
213
- .input-pill:focus {
234
+ /* AQ.W4 §W4.6 — keyboard-focus ring only. Was bare `:focus` (showed the
235
+ accent ring on a mouse click); `:focus-visible` matches the
236
+ `.focus-ring` / `.glass-btn` / dock-control discipline. Ordered BEFORE
237
+ the `:user-invalid` rungs so an invalid focused field shows destructive,
238
+ not accent (the `:user-invalid:focus-visible` rule below wins by order +
239
+ specificity). `:focus-visible` Baseline Widely — no fallback. */
240
+ .input-pill:focus-visible {
214
241
  outline: none;
215
242
  border-color: var(--color-accent-opaque, var(--ring));
216
243
  box-shadow: 0 0 0 2px var(--color-accent, color-mix(in srgb, var(--ring) 30%, transparent));
217
244
  }
218
245
 
246
+ /* AQ.W4 §W4.1 — validity vocabulary on `.input-pill` (Input + Textarea).
247
+ The forgiving `:where(:user-invalid, .user-invalid-fallback)` group is
248
+ ONE rule covering native + the `useUserInvalidAria` fallback class (css
249
+ §3.2; NOT a live+dead alias — the class is the SOLE fallback for engines
250
+ without `:user-invalid`). The destructive/success tints reuse the
251
+ semantic tokens via `color-mix` per the house pattern (W2). Non-color
252
+ reinforcement is the error TEXT (W4.5 `error` slot) + the `required`
253
+ asterisk — the border/bg shift is the supplementary cue, never the sole
254
+ one. `:user-valid` is intentionally subtle (border only, no bg fill) so
255
+ a long valid form is not a wall of green. */
256
+ .input-pill:where(:user-invalid, .user-invalid-fallback) {
257
+ border-color: var(--destructive);
258
+ background: color-mix(in srgb, var(--destructive) 8%, var(--glass-bg-quiet));
259
+ }
260
+ .input-pill:where(:user-valid, .user-valid-fallback) {
261
+ border-color: var(--success);
262
+ }
263
+ /* Invalid + keyboard-focused → destructive ring (overrides the accent
264
+ `:focus-visible` ring above by order + the extra `:user-invalid`
265
+ compound). */
266
+ .input-pill:where(:user-invalid, .user-invalid-fallback):focus-visible {
267
+ border-color: var(--destructive);
268
+ box-shadow: 0 0 0 var(--focus-ring-width)
269
+ color-mix(in srgb, var(--destructive) 35%, transparent);
270
+ }
271
+
272
+ /* AQ.W4 §W4.3 — `field-sizing: content` autosize (opt-in via the Textarea
273
+ `autosize` prop → `[data-autosize]`). The textarea grows vertically with
274
+ content between a 3-line floor and a token-driven ceiling, then scrolls.
275
+ `field-sizing` Baseline Newly (Chromium 2024) — on a non-supporting
276
+ engine the declaration is ignored and the element keeps the
277
+ `min/max-block-size` bounds + standard scroll (no JS, no `@supports`,
278
+ no grid-mirror polyfill). The fixed-size path (default, `min-h-20`) is
279
+ the unchanged no-op fallback. */
280
+ .input-pill[data-autosize] {
281
+ field-sizing: content;
282
+ width: 100%;
283
+ min-block-size: 3lh;
284
+ max-block-size: var(--textarea-autosize-max, 12lh);
285
+ resize: vertical;
286
+ }
287
+
219
288
  .input-pill:disabled {
220
289
  opacity: 0.5;
221
290
  cursor: not-allowed;
@@ -275,3 +344,17 @@
275
344
  }
276
345
  }
277
346
  }
347
+
348
+ /* ── :has() focus-elevation fallback (AQ.W3 §W3.1a) ──────────────────────
349
+ SOLE fallback for engines without `:has()`. `.is-focus-within` is toggled
350
+ by a ≤6-LOC focusin/focusout guard in `Card.vue` that runs ONLY when
351
+ `!CSS.supports('selector(:has(*))')` (modern engines run zero JS). The
352
+ class redefines the SAME `--card-focus-*` rungs as the `:has()` rule, so the
353
+ override values have one source. NOT a live+dead alias — `:has()` is the
354
+ enhancement, this the documented degradation path. */
355
+ @supports not selector(:has(*)) {
356
+ .glass-card.is-focus-within {
357
+ --card-focus-shadow: var(--shadow-md);
358
+ --card-focus-border: var(--glass-border-floating);
359
+ }
360
+ }