react-marketing-ui 0.0.2 → 0.0.4

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 (178) hide show
  1. package/dist/accordion.js +1 -1
  2. package/dist/accordion.js.map +1 -1
  3. package/dist/accordion.mjs +222 -2
  4. package/dist/accordion.mjs.map +1 -1
  5. package/dist/action-swap.js +1 -0
  6. package/dist/action-swap.mjs +77 -3
  7. package/dist/action-swap.mjs.map +1 -1
  8. package/dist/animated-beam.js +1 -0
  9. package/dist/animated-beam.mjs +127 -2
  10. package/dist/animated-beam.mjs.map +1 -1
  11. package/dist/button.js +1 -1
  12. package/dist/button.js.map +1 -1
  13. package/dist/button.mjs +115 -2
  14. package/dist/button.mjs.map +1 -1
  15. package/dist/card.js +1 -2
  16. package/dist/card.js.map +1 -1
  17. package/dist/card.mjs +135 -3
  18. package/dist/card.mjs.map +1 -1
  19. package/dist/dia-text-reveal.js +1 -0
  20. package/dist/dia-text-reveal.mjs +331 -2
  21. package/dist/dia-text-reveal.mjs.map +1 -1
  22. package/dist/elevated-input.js +1 -1
  23. package/dist/elevated-input.js.map +1 -1
  24. package/dist/elevated-input.mjs +48 -2
  25. package/dist/elevated-input.mjs.map +1 -1
  26. package/dist/fade-in.js +1 -0
  27. package/dist/fade-in.mjs +84 -2
  28. package/dist/fade-in.mjs.map +1 -1
  29. package/dist/feature-card.js +1 -1
  30. package/dist/feature-card.js.map +1 -1
  31. package/dist/feature-card.mjs +34 -2
  32. package/dist/feature-card.mjs.map +1 -1
  33. package/dist/flowchart-parts.js +1 -1
  34. package/dist/flowchart-parts.js.map +1 -1
  35. package/dist/flowchart-parts.mjs +91 -2
  36. package/dist/flowchart-parts.mjs.map +1 -1
  37. package/dist/glossy-button.js +1 -1
  38. package/dist/glossy-button.js.map +1 -1
  39. package/dist/glossy-button.mjs +82 -2
  40. package/dist/glossy-button.mjs.map +1 -1
  41. package/dist/grainient.js +1 -0
  42. package/dist/grainient.mjs +327 -2
  43. package/dist/grainient.mjs.map +1 -1
  44. package/dist/highlighter.js +1 -0
  45. package/dist/highlighter.mjs +122 -3
  46. package/dist/highlighter.mjs.map +1 -1
  47. package/dist/index.js +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +2642 -32
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/input.js +1 -0
  52. package/dist/input.mjs +107 -2
  53. package/dist/input.mjs.map +1 -1
  54. package/dist/lib/breakpoints.js +1 -1
  55. package/dist/lib/breakpoints.js.map +1 -1
  56. package/dist/lib/breakpoints.mjs +34 -1
  57. package/dist/lib/breakpoints.mjs.map +1 -1
  58. package/dist/lib/cn.js +1 -1
  59. package/dist/lib/cn.js.map +1 -1
  60. package/dist/lib/cn.mjs +17 -1
  61. package/dist/lib/cn.mjs.map +1 -1
  62. package/dist/lib/ease.js +1 -0
  63. package/dist/lib/ease.mjs +9 -1
  64. package/dist/lib/ease.mjs.map +1 -1
  65. package/dist/lib/surface.js +1 -0
  66. package/dist/lib/surface.mjs +37 -1
  67. package/dist/lib/surface.mjs.map +1 -1
  68. package/dist/lib/use-media-query.js +1 -0
  69. package/dist/lib/use-media-query.mjs +16 -1
  70. package/dist/lib/use-media-query.mjs.map +1 -1
  71. package/dist/liquid-metal.js +1 -0
  72. package/dist/liquid-metal.mjs +40 -2
  73. package/dist/liquid-metal.mjs.map +1 -1
  74. package/dist/navigation-menu-icons.js +1 -1
  75. package/dist/navigation-menu-icons.js.map +1 -1
  76. package/dist/navigation-menu-icons.mjs +36 -1
  77. package/dist/navigation-menu-icons.mjs.map +1 -1
  78. package/dist/navigation-menu-styles.js +1 -1
  79. package/dist/navigation-menu-styles.js.map +1 -1
  80. package/dist/navigation-menu-styles.mjs +11 -1
  81. package/dist/navigation-menu-styles.mjs.map +1 -1
  82. package/dist/navigation-menu.js +1 -2
  83. package/dist/navigation-menu.js.map +1 -1
  84. package/dist/navigation-menu.mjs +350 -5
  85. package/dist/navigation-menu.mjs.map +1 -1
  86. package/dist/password-input.js +1 -0
  87. package/dist/password-input.mjs +171 -3
  88. package/dist/password-input.mjs.map +1 -1
  89. package/dist/rainbow-button.js +1 -0
  90. package/dist/rainbow-button.mjs +45 -2
  91. package/dist/rainbow-button.mjs.map +1 -1
  92. package/dist/range-slider.js +1 -0
  93. package/dist/range-slider.mjs +82 -1
  94. package/dist/range-slider.mjs.map +1 -1
  95. package/dist/rolling-badge.js +1 -0
  96. package/dist/rolling-badge.mjs +68 -2
  97. package/dist/rolling-badge.mjs.map +1 -1
  98. package/dist/savings-badge.js +1 -1
  99. package/dist/savings-badge.js.map +1 -1
  100. package/dist/savings-badge.mjs +22 -2
  101. package/dist/savings-badge.mjs.map +1 -1
  102. package/dist/shine-border.js +1 -0
  103. package/dist/shine-border.mjs +44 -2
  104. package/dist/shine-border.mjs.map +1 -1
  105. package/dist/sparkles-text.js +1 -0
  106. package/dist/sparkles-text.mjs +84 -3
  107. package/dist/sparkles-text.mjs.map +1 -1
  108. package/dist/tabs.js +1 -0
  109. package/dist/tabs.mjs +118 -2
  110. package/dist/tabs.mjs.map +1 -1
  111. package/dist/theme-toggle.js +1 -0
  112. package/dist/theme-toggle.mjs +248 -5
  113. package/dist/theme-toggle.mjs.map +1 -1
  114. package/package.json +68 -68
  115. package/dist/chunk-3SB6HUBA.mjs +0 -31
  116. package/dist/chunk-3SB6HUBA.mjs.map +0 -1
  117. package/dist/chunk-4PBVBXGY.mjs +0 -84
  118. package/dist/chunk-4PBVBXGY.mjs.map +0 -1
  119. package/dist/chunk-4VCFWVSJ.mjs +0 -42
  120. package/dist/chunk-4VCFWVSJ.mjs.map +0 -1
  121. package/dist/chunk-5QQAPGR2.mjs +0 -109
  122. package/dist/chunk-5QQAPGR2.mjs.map +0 -1
  123. package/dist/chunk-6MB4UKRX.mjs +0 -19
  124. package/dist/chunk-6MB4UKRX.mjs.map +0 -1
  125. package/dist/chunk-6T5LR34O.mjs +0 -45
  126. package/dist/chunk-6T5LR34O.mjs.map +0 -1
  127. package/dist/chunk-AYLCYDUM.mjs +0 -275
  128. package/dist/chunk-AYLCYDUM.mjs.map +0 -1
  129. package/dist/chunk-AYY7D2RJ.mjs +0 -112
  130. package/dist/chunk-AYY7D2RJ.mjs.map +0 -1
  131. package/dist/chunk-CTZEI2YS.mjs +0 -324
  132. package/dist/chunk-CTZEI2YS.mjs.map +0 -1
  133. package/dist/chunk-DA3I3Y5O.mjs +0 -71
  134. package/dist/chunk-DA3I3Y5O.mjs.map +0 -1
  135. package/dist/chunk-EYHT2EWJ.mjs +0 -18
  136. package/dist/chunk-EYHT2EWJ.mjs.map +0 -1
  137. package/dist/chunk-IHLGCS63.mjs +0 -36
  138. package/dist/chunk-IHLGCS63.mjs.map +0 -1
  139. package/dist/chunk-JVXJ6SFX.mjs +0 -38
  140. package/dist/chunk-JVXJ6SFX.mjs.map +0 -1
  141. package/dist/chunk-KBHYXLRG.mjs +0 -13
  142. package/dist/chunk-KBHYXLRG.mjs.map +0 -1
  143. package/dist/chunk-KMXUQYR3.mjs +0 -74
  144. package/dist/chunk-KMXUQYR3.mjs.map +0 -1
  145. package/dist/chunk-KNPOZ34H.mjs +0 -88
  146. package/dist/chunk-KNPOZ34H.mjs.map +0 -1
  147. package/dist/chunk-KRNWCJ4D.mjs +0 -219
  148. package/dist/chunk-KRNWCJ4D.mjs.map +0 -1
  149. package/dist/chunk-M5MESV26.mjs +0 -124
  150. package/dist/chunk-M5MESV26.mjs.map +0 -1
  151. package/dist/chunk-MJYBPJBA.mjs +0 -115
  152. package/dist/chunk-MJYBPJBA.mjs.map +0 -1
  153. package/dist/chunk-NNHPQ67J.mjs +0 -10
  154. package/dist/chunk-NNHPQ67J.mjs.map +0 -1
  155. package/dist/chunk-OCZFHVVD.mjs +0 -71
  156. package/dist/chunk-OCZFHVVD.mjs.map +0 -1
  157. package/dist/chunk-QAWSH567.mjs +0 -19
  158. package/dist/chunk-QAWSH567.mjs.map +0 -1
  159. package/dist/chunk-R2E2J42H.mjs +0 -38
  160. package/dist/chunk-R2E2J42H.mjs.map +0 -1
  161. package/dist/chunk-TPGLLSYV.mjs +0 -65
  162. package/dist/chunk-TPGLLSYV.mjs.map +0 -1
  163. package/dist/chunk-VJENJHXJ.mjs +0 -72
  164. package/dist/chunk-VJENJHXJ.mjs.map +0 -1
  165. package/dist/chunk-W22G7XHR.mjs +0 -104
  166. package/dist/chunk-W22G7XHR.mjs.map +0 -1
  167. package/dist/chunk-WDR5VPZJ.mjs +0 -79
  168. package/dist/chunk-WDR5VPZJ.mjs.map +0 -1
  169. package/dist/chunk-WLUGKBH7.mjs +0 -37
  170. package/dist/chunk-WLUGKBH7.mjs.map +0 -1
  171. package/dist/chunk-WYJYLDUA.mjs +0 -84
  172. package/dist/chunk-WYJYLDUA.mjs.map +0 -1
  173. package/dist/chunk-XZEDZVXT.mjs +0 -38
  174. package/dist/chunk-XZEDZVXT.mjs.map +0 -1
  175. package/dist/chunk-YKGP5JIL.mjs +0 -328
  176. package/dist/chunk-YKGP5JIL.mjs.map +0 -1
  177. package/dist/chunk-YM3U2OBE.mjs +0 -99
  178. package/dist/chunk-YM3U2OBE.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,34 +1,2644 @@
1
- export { ArrowLeft, ArrowRight, FlowDiamond, FlowNode, FlowPill, JoinArrow, SplitArrow, TurnDown } from './chunk-KNPOZ34H.mjs';
2
- export { NavigationMenu, NavigationMenuArrow, NavigationMenuBackdrop, NavigationMenuContent, NavigationMenuIcon, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuPortal, NavigationMenuSub, NavigationMenuSubTrigger, NavigationMenuTrigger, NavigationMenuViewport } from './chunk-AYLCYDUM.mjs';
3
- export { navigationMenuSubTriggerStyle, navigationMenuTriggerStyle } from './chunk-KBHYXLRG.mjs';
4
- export { ArrowSvg, ChevronDownIcon, ChevronRightIcon } from './chunk-JVXJ6SFX.mjs';
5
- export { BREAKPOINTS, getBreakpoint, onBreakpointChange, useBreakpoint } from './chunk-IHLGCS63.mjs';
6
- export { PasswordInput } from './chunk-VJENJHXJ.mjs';
7
- export { Input } from './chunk-W22G7XHR.mjs';
8
- export { RangeSlider } from './chunk-4PBVBXGY.mjs';
9
- export { SavingsBadge } from './chunk-6MB4UKRX.mjs';
10
- export { ThemeToggle } from './chunk-KMXUQYR3.mjs';
11
- export { Button } from './chunk-AYY7D2RJ.mjs';
12
- export { ActionSwapRollIcon, ActionSwapRollText } from './chunk-DA3I3Y5O.mjs';
13
- export { grainient_default as Grainient } from './chunk-CTZEI2YS.mjs';
14
- export { DiaTextReveal } from './chunk-YKGP5JIL.mjs';
15
- export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger } from './chunk-KRNWCJ4D.mjs';
16
- export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './chunk-YM3U2OBE.mjs';
17
- export { solidSurface } from './chunk-XZEDZVXT.mjs';
18
- export { AnimatedBeam } from './chunk-M5MESV26.mjs';
19
- export { GlossyButton, glossyButtonVariants } from './chunk-WDR5VPZJ.mjs';
20
- export { FeatureCard } from './chunk-3SB6HUBA.mjs';
21
- export { RollingBadge } from './chunk-TPGLLSYV.mjs';
22
- export { ElevatedInput } from './chunk-6T5LR34O.mjs';
23
- export { SparklesText } from './chunk-OCZFHVVD.mjs';
24
- export { RainbowButton, rainbowButtonVariants } from './chunk-4VCFWVSJ.mjs';
25
- export { ShineBorder } from './chunk-R2E2J42H.mjs';
26
- export { LiquidMetal } from './chunk-WLUGKBH7.mjs';
27
- export { Tabs } from './chunk-MJYBPJBA.mjs';
28
- export { Highlighter } from './chunk-5QQAPGR2.mjs';
29
- import './chunk-EYHT2EWJ.mjs';
30
- export { cn, hasKey, noop, validCssVars } from './chunk-QAWSH567.mjs';
31
- export { FadeIn, Stagger, StaggerItem } from './chunk-WYJYLDUA.mjs';
32
- export { EASE_OUT, EASE_OUT_CSS, SPRING_SWAP, easeOut, easeOutBack } from './chunk-NNHPQ67J.mjs';
1
+ "use client";
2
+ import { Accordion as Accordion$1 } from '@base-ui/react/accordion';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { useReducedMotion, AnimatePresence, motion, useInView, useSpring, useTransform } from 'framer-motion';
7
+ import { createContext, useRef, useState, useLayoutEffect, useId, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
8
+ import { cva } from 'class-variance-authority';
9
+ import { Renderer, Triangle, Mesh, Program } from 'ogl';
10
+ import { annotate } from 'rough-notation';
11
+ import { LiquidMetal as LiquidMetal$1 } from '@paper-design/shaders-react';
12
+ import { NavigationMenu as NavigationMenu$1 } from '@base-ui/react/navigation-menu';
13
+ import { Slot } from '@radix-ui/react-slot';
14
+
15
+ function cn(...inputs) {
16
+ return twMerge(clsx(inputs));
17
+ }
18
+ function validCssVars(style) {
19
+ return style;
20
+ }
21
+ function hasKey(key, obj) {
22
+ return obj !== null && typeof obj === "object" && Object.hasOwn(obj, key);
23
+ }
24
+ function noop() {
25
+ }
26
+ function Accordion({
27
+ className,
28
+ multiple = false,
29
+ variant = "default",
30
+ ...props
31
+ }) {
32
+ return /* @__PURE__ */ jsx(
33
+ Accordion$1.Root,
34
+ {
35
+ "data-slot": "accordion",
36
+ "data-variant": variant,
37
+ multiple,
38
+ className: cn(
39
+ "group flex w-full flex-col",
40
+ variant === "split" && "space-y-2",
41
+ variant === "outline" && "overflow-hidden rounded-lg border bg-(--surface)",
42
+ variant === "nested" && "rounded-lg border bg-muted p-1",
43
+ className
44
+ ),
45
+ ...props
46
+ }
47
+ );
48
+ }
49
+ function AccordionItem({ className, ...props }) {
50
+ return /* @__PURE__ */ jsx(
51
+ Accordion$1.Item,
52
+ {
53
+ "data-slot": "accordion-item",
54
+ className: cn(
55
+ "transition-[margin,border-radius,border] duration-250 ease-out-expo",
56
+ // Default variant styles
57
+ "group-data-[variant=default]:border-(--border) group-data-[variant=default]:border-b group-data-[variant=default]:last:border-b-0",
58
+ // Split variant styles (individual cards)
59
+ "group-data-[variant=split]:overflow-hidden group-data-[variant=split]:rounded-lg group-data-[variant=split]:border group-data-[variant=split]:border-(--border) group-data-[variant=split]:bg-(--surface)",
60
+ // Outline variant styles (items within single card)
61
+ "group-data-[variant=outline]:border-(--border) group-data-[variant=outline]:border-b group-data-[variant=outline]:last:border-b-0",
62
+ // Nested variant styles - items within the single outer card
63
+ "group-data-[variant=nested]:mt-0.5 group-data-[variant=nested]:first:mt-0",
64
+ // Isolated bordered variant styles - dynamically separates open items from closed ones
65
+ // Base styles: all items have borders and background to look like cards
66
+ "group-data-[variant=isolated-bordered]:overflow-hidden group-data-[variant=isolated-bordered]:border group-data-[variant=isolated-bordered]:border-(--border) group-data-[variant=isolated-bordered]:bg-(--surface)",
67
+ // Closed items: group together by overlapping borders with negative margin
68
+ // Only apply to closed items that follow another closed item (not open items, first item, or items after open items)
69
+ "group-data-[variant=isolated-bordered]:relative group-data-[variant=isolated-bordered]:not-first:not-data-open:not-[[data-open]+&]:-mt-px",
70
+ // Opened item - separated with margins
71
+ "group-data-[variant=isolated-bordered]:data-open:mt-2 group-data-[variant=isolated-bordered]:data-open:mb-2 group-data-[variant=isolated-bordered]:data-open:rounded-lg",
72
+ // First item
73
+ "group-data-[variant=isolated-bordered]:first:rounded-t-lg group-data-[variant=isolated-bordered]:data-open:first:mt-0",
74
+ // Last item
75
+ "group-data-[variant=isolated-bordered]:last:rounded-b-lg group-data-[variant=isolated-bordered]:data-open:last:mb-0",
76
+ // Item after open item: round top corners (start of new group)
77
+ "group-data-[variant=isolated-bordered]:[[data-open]+&]:rounded-t-lg",
78
+ // Item before open item: round bottom corners (end of group)
79
+ "group-data-[variant=isolated-bordered]:[&:has(+_[data-open])]:rounded-b-lg",
80
+ // Isolated filled variant
81
+ "group-data-[variant=isolated-filled]:overflow-hidden group-data-[variant=isolated-filled]:bg-muted",
82
+ // Opened item - separated with margins and rounded
83
+ "group-data-[variant=isolated-filled]:data-open:my-2 group-data-[variant=isolated-filled]:data-open:rounded-lg",
84
+ // First item
85
+ "group-data-[variant=isolated-filled]:first:rounded-t-lg group-data-[variant=isolated-filled]:data-open:first:mt-0",
86
+ // Last item
87
+ "group-data-[variant=isolated-filled]:last:rounded-b-lg group-data-[variant=isolated-filled]:data-open:last:mb-0",
88
+ // Item after open item: round top corners (start of new group)
89
+ "group-data-[variant=isolated-filled]:[[data-open]+&]:rounded-t-lg",
90
+ // Item before open item: round bottom corners (end of group)
91
+ "group-data-[variant=isolated-filled]:[&:has(+_[data-open])]:rounded-b-lg",
92
+ // Isolated filled bordered variant - filled background with borders between closed items
93
+ "group-data-[variant=isolated-filled-bordered]:overflow-hidden group-data-[variant=isolated-filled-bordered]:bg-muted",
94
+ // All items except last have border-bottom to prevent layout shift, default to visible border
95
+ "group-data-[variant=isolated-filled-bordered]:not-last:border-(--border) group-data-[variant=isolated-filled-bordered]:not-last:border-b",
96
+ // Make border transparent (invisible) for: items before open items, and open items themselves
97
+ "group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:border-transparent",
98
+ "group-data-[variant=isolated-filled-bordered]:data-open:border-transparent",
99
+ // Opened item - separated with margins and rounded
100
+ "group-data-[variant=isolated-filled-bordered]:data-open:my-2 group-data-[variant=isolated-filled-bordered]:data-open:rounded-lg",
101
+ // First item
102
+ "group-data-[variant=isolated-filled-bordered]:first:rounded-t-lg group-data-[variant=isolated-filled-bordered]:data-open:first:mt-0",
103
+ // Last item
104
+ "group-data-[variant=isolated-filled-bordered]:last:rounded-b-lg group-data-[variant=isolated-filled-bordered]:data-open:last:mb-0",
105
+ // Item after open item: round top corners (start of new group)
106
+ "group-data-[variant=isolated-filled-bordered]:[[data-open]+&]:rounded-t-lg",
107
+ // Item before open item: round bottom corners (end of group)
108
+ "group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:rounded-b-lg",
109
+ className
110
+ ),
111
+ ...props
112
+ }
113
+ );
114
+ }
115
+ function AccordionHeader({ className, ...props }) {
116
+ return /* @__PURE__ */ jsx(
117
+ Accordion$1.Header,
118
+ {
119
+ "data-slot": "accordion-header",
120
+ className: cn("not-prose", className),
121
+ ...props
122
+ }
123
+ );
124
+ }
125
+ function AccordionTrigger({
126
+ children,
127
+ className,
128
+ showIndicator = true,
129
+ indicatorType = "plus",
130
+ indicatorPosition = "end",
131
+ indicatorColor,
132
+ icon,
133
+ subtitle,
134
+ ...props
135
+ }) {
136
+ const hasStartIndicator = showIndicator && indicatorPosition === "start";
137
+ const hasEndIndicator = showIndicator && indicatorPosition === "end";
138
+ const renderIndicator = () => {
139
+ if (!showIndicator) return null;
140
+ const indicatorClassName = cn("size-4 shrink-0 transition-transform duration-200 ease-out-expo", indicatorColor);
141
+ const indicatorIcon = indicatorType === "chevron" ? /* @__PURE__ */ jsx(ChevronDownIcon, { "data-slot": "accordion-indicator", className: indicatorClassName }) : /* @__PURE__ */ jsx(PlusIcon, { "data-slot": "accordion-indicator", className: indicatorClassName });
142
+ return /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: indicatorIcon });
143
+ };
144
+ return /* @__PURE__ */ jsx(AccordionHeader, { children: /* @__PURE__ */ jsxs(
145
+ Accordion$1.Trigger,
146
+ {
147
+ "data-slot": "accordion-trigger",
148
+ "data-has-icon": hasStartIndicator ? "true" : void 0,
149
+ className: cn(
150
+ "group/trigger flex w-full cursor-pointer items-center justify-between gap-3 py-5 px-3.5 text-left font-medium text-sm outline-none disabled:pointer-events-none disabled:opacity-60",
151
+ // Default variant styles
152
+ "group-data-[variant=default]:px-0",
153
+ // Split variant styles
154
+ "group-data-[variant=split]:rounded-t-lg",
155
+ // Nested variant styles - trigger with subtle interaction
156
+ "group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:px-3 group-data-[variant=nested]:py-2.5 group-data-[variant=nested]:hover:bg-background group-data-[variant=nested]:dark:hover:bg-background/50",
157
+ // Indicator rotation animations
158
+ indicatorType === "chevron" && "[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-180",
159
+ indicatorType === "plus" && "[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-90",
160
+ className
161
+ ),
162
+ ...props,
163
+ children: [
164
+ hasStartIndicator ? renderIndicator() : null,
165
+ icon && !hasStartIndicator && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: icon }),
166
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
167
+ /* @__PURE__ */ jsx("span", { className: "underline-offset-2 group-hover/trigger:underline", children }),
168
+ subtitle ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm no-underline", children: subtitle }) : null
169
+ ] }),
170
+ hasEndIndicator ? renderIndicator() : null
171
+ ]
172
+ }
173
+ ) });
174
+ }
175
+ function AccordionContent({ children, className, ...props }) {
176
+ return /* @__PURE__ */ jsx(
177
+ Accordion$1.Panel,
178
+ {
179
+ "data-slot": "accordion-content",
180
+ className: cn(
181
+ "h-(--accordion-panel-height) overflow-hidden text-sm transition-[height,opacity] duration-250 ease-out-expo data-ending-style:h-0 data-starting-style:h-0 data-ending-style:opacity-0 data-starting-style:opacity-0"
182
+ ),
183
+ ...props,
184
+ children: /* @__PURE__ */ jsx(
185
+ "div",
186
+ {
187
+ className: cn(
188
+ "p-3.5 text-muted-foreground",
189
+ "group-data-[variant=default]:px-0 group-data-[variant=default]:pt-0",
190
+ "group-data-[variant=split]:pt-0",
191
+ "group-data-[variant=outline]:pt-0",
192
+ // Nested variant
193
+ "group-data-[variant=nested]:mt-1 group-data-[variant=nested]:mb-0.5 group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:border group-data-[variant=nested]:bg-background group-data-[variant=nested]:p-3 group-data-[variant=nested]:[[data-slot=accordion-item]:last-child_&]:mb-0",
194
+ // Isolated bordered variant
195
+ "group-data-[variant=isolated-bordered]:pt-0",
196
+ // Isolated filled variant
197
+ "group-data-[variant=isolated-filled]:pt-0",
198
+ // Isolated filled bordered variant
199
+ "group-data-[variant=isolated-filled-bordered]:pt-0",
200
+ // Icon alignment - add left padding when parent item contains a trigger with icon
201
+ "[[data-slot=accordion-item]:has([data-has-icon])_&]:pl-[calc(1rem+0.75rem)]",
202
+ "[[data-slot=accordion-item]:has([data-has-icon])_&]:group-data-[variant=default]:pl-[calc(1rem+0.75rem)]",
203
+ className
204
+ ),
205
+ children
206
+ }
207
+ )
208
+ }
209
+ );
210
+ }
211
+ function PlusIcon(props) {
212
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", ...props, children: [
213
+ /* @__PURE__ */ jsx(
214
+ "path",
215
+ {
216
+ fillRule: "evenodd",
217
+ clipRule: "evenodd",
218
+ d: "M2.75 12C2.75 11.3096 3.30964 10.75 4 10.75H20C20.6904 10.75 21.25 11.3096 21.25 12C21.25 12.6904 20.6904 13.25 20 13.25H4C3.30964 13.25 2.75 12.6904 2.75 12Z",
219
+ fill: "currentColor",
220
+ className: "in-data-panel-open:opacity-0 transition-opacity duration-200 ease-out-expo"
221
+ }
222
+ ),
223
+ /* @__PURE__ */ jsx(
224
+ "path",
225
+ {
226
+ fillRule: "evenodd",
227
+ clipRule: "evenodd",
228
+ d: "M12 2.75C12.6904 2.75 13.25 3.30964 13.25 4V20C13.25 20.6904 12.6904 21.25 12 21.25C11.3096 21.25 10.75 20.6904 10.75 20V4C10.75 3.30964 11.3096 2.75 12 2.75Z",
229
+ fill: "currentColor"
230
+ }
231
+ )
232
+ ] });
233
+ }
234
+ function ChevronDownIcon(props) {
235
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M1 3.5L5 7.5L9 3.5", stroke: "currentColor", strokeWidth: "1.5" }) });
236
+ }
237
+
238
+ // src/lib/ease.ts
239
+ var easeOut = [0.22, 1, 0.36, 1];
240
+ var easeOutBack = [0.34, 1.56, 0.64, 1];
241
+ var EASE_OUT = [0.16, 1, 0.3, 1];
242
+ var EASE_OUT_CSS = "cubic-bezier(0.16, 1, 0.3, 1)";
243
+ var SPRING_SWAP = { type: "spring", stiffness: 460, damping: 30, mass: 0.55 };
244
+ var ROLL_EXIT_TRANSITION = { duration: 0.14, ease: EASE_OUT };
245
+ var ROLL_BLUR = "blur(3px)";
246
+ var AT_REST = { opacity: 1, y: 0, filter: "blur(0px)" };
247
+ var TEXT_VARIANTS = {
248
+ initial: { opacity: 0, y: "90%", filter: ROLL_BLUR },
249
+ animate: { opacity: 1, y: "0%", filter: "blur(0px)", transition: SPRING_SWAP },
250
+ exit: { opacity: 0, y: "-90%", filter: ROLL_BLUR, transition: ROLL_EXIT_TRANSITION }
251
+ };
252
+ var ICON_VARIANTS = {
253
+ initial: { opacity: 0, y: 12, filter: ROLL_BLUR },
254
+ animate: { opacity: 1, y: 0, filter: "blur(0px)", transition: SPRING_SWAP },
255
+ exit: { opacity: 0, y: -12, filter: ROLL_BLUR, transition: ROLL_EXIT_TRANSITION }
256
+ };
257
+ function ActionSwapRollText({ value, children, className }) {
258
+ const reduce = useReducedMotion() ?? false;
259
+ const measureRef = useRef(null);
260
+ const [width, setWidth] = useState();
261
+ useLayoutEffect(() => {
262
+ const nextWidth = measureRef.current?.offsetWidth;
263
+ if (!nextWidth) return;
264
+ setWidth((current) => current === nextWidth ? current : nextWidth);
265
+ });
266
+ return /* @__PURE__ */ jsxs(
267
+ "span",
268
+ {
269
+ className: cn("relative inline-block overflow-hidden whitespace-nowrap align-bottom", className),
270
+ style: { width, transition: reduce ? void 0 : `width 220ms ${EASE_OUT_CSS}` },
271
+ children: [
272
+ /* @__PURE__ */ jsx("span", { ref: measureRef, "aria-hidden": true, className: "invisible inline-block whitespace-nowrap", children }),
273
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
274
+ motion.span,
275
+ {
276
+ variants: TEXT_VARIANTS,
277
+ initial: reduce ? false : "initial",
278
+ animate: reduce ? AT_REST : "animate",
279
+ exit: reduce ? void 0 : "exit",
280
+ className: "absolute top-0 left-0 inline-block will-change-[opacity,filter,transform]",
281
+ children
282
+ },
283
+ value
284
+ ) })
285
+ ]
286
+ }
287
+ );
288
+ }
289
+ function ActionSwapRollIcon({ value, children, className }) {
290
+ const reduce = useReducedMotion() ?? false;
291
+ return /* @__PURE__ */ jsx("span", { className: cn("relative inline-grid shrink-0 place-items-center overflow-hidden", className), children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsx(
292
+ motion.span,
293
+ {
294
+ "aria-hidden": true,
295
+ variants: ICON_VARIANTS,
296
+ initial: reduce ? false : "initial",
297
+ animate: reduce ? AT_REST : "animate",
298
+ exit: reduce ? void 0 : "exit",
299
+ className: "col-start-1 row-start-1 inline-flex items-center justify-center will-change-[opacity,filter,transform]",
300
+ children
301
+ },
302
+ value
303
+ ) }) });
304
+ }
305
+ function AnimatedBeam({
306
+ className,
307
+ containerRef,
308
+ fromRef,
309
+ toRef,
310
+ curvature = 0,
311
+ reverse = false,
312
+ duration = 5,
313
+ delay = 0,
314
+ pathColor = "gray",
315
+ pathWidth = 2,
316
+ pathOpacity = 0.2,
317
+ gradientStartColor = "#ffaa40",
318
+ gradientStopColor = "#9c40ff",
319
+ repeat = Number.POSITIVE_INFINITY,
320
+ repeatDelay = 0,
321
+ startXOffset = 0,
322
+ startYOffset = 0,
323
+ endXOffset = 0,
324
+ endYOffset = 0
325
+ }) {
326
+ const id = useId();
327
+ const [pathD, setPathD] = useState("");
328
+ const [svgDimensions, setSvgDimensions] = useState({
329
+ width: 0,
330
+ height: 0
331
+ });
332
+ const gradientCoordinates = reverse ? {
333
+ x1: ["90%", "-10%"],
334
+ x2: ["100%", "0%"],
335
+ y1: ["0%", "0%"],
336
+ y2: ["0%", "0%"]
337
+ } : {
338
+ x1: ["10%", "110%"],
339
+ x2: ["0%", "100%"],
340
+ y1: ["0%", "0%"],
341
+ y2: ["0%", "0%"]
342
+ };
343
+ useEffect(() => {
344
+ const updatePath = () => {
345
+ if (containerRef.current && fromRef.current && toRef.current) {
346
+ const containerRect = containerRef.current.getBoundingClientRect();
347
+ const rectA = fromRef.current.getBoundingClientRect();
348
+ const rectB = toRef.current.getBoundingClientRect();
349
+ const svgWidth = containerRect.width;
350
+ const svgHeight = containerRect.height;
351
+ setSvgDimensions({ width: svgWidth, height: svgHeight });
352
+ const startX = rectA.left - containerRect.left + rectA.width / 2 + startXOffset;
353
+ const startY = rectA.top - containerRect.top + rectA.height / 2 + startYOffset;
354
+ const endX = rectB.left - containerRect.left + rectB.width / 2 + endXOffset;
355
+ const endY = rectB.top - containerRect.top + rectB.height / 2 + endYOffset;
356
+ const controlY = startY - curvature;
357
+ const d = `M ${startX},${startY} Q ${(startX + endX) / 2},${controlY} ${endX},${endY}`;
358
+ setPathD(d);
359
+ }
360
+ };
361
+ const resizeObserver = new ResizeObserver(() => {
362
+ updatePath();
363
+ });
364
+ if (containerRef.current) resizeObserver.observe(containerRef.current);
365
+ updatePath();
366
+ return () => {
367
+ resizeObserver.disconnect();
368
+ };
369
+ }, [containerRef, fromRef, toRef, curvature, startXOffset, startYOffset, endXOffset, endYOffset]);
370
+ return /* @__PURE__ */ jsxs(
371
+ "svg",
372
+ {
373
+ "aria-hidden": "true",
374
+ fill: "none",
375
+ width: svgDimensions.width,
376
+ height: svgDimensions.height,
377
+ xmlns: "http://www.w3.org/2000/svg",
378
+ className: cn("pointer-events-none absolute top-0 left-0 transform-gpu stroke-2", className),
379
+ viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
380
+ children: [
381
+ /* @__PURE__ */ jsx("path", { d: pathD, stroke: pathColor, strokeWidth: pathWidth, strokeOpacity: pathOpacity, strokeLinecap: "round" }),
382
+ /* @__PURE__ */ jsx("path", { d: pathD, strokeWidth: pathWidth, stroke: `url(#${id})`, strokeOpacity: "1", strokeLinecap: "round" }),
383
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
384
+ motion.linearGradient,
385
+ {
386
+ className: "transform-gpu",
387
+ id,
388
+ gradientUnits: "userSpaceOnUse",
389
+ initial: {
390
+ x1: "0%",
391
+ x2: "0%",
392
+ y1: "0%",
393
+ y2: "0%"
394
+ },
395
+ animate: {
396
+ x1: gradientCoordinates.x1,
397
+ x2: gradientCoordinates.x2,
398
+ y1: gradientCoordinates.y1,
399
+ y2: gradientCoordinates.y2
400
+ },
401
+ transition: {
402
+ delay,
403
+ duration,
404
+ ease: [0.16, 1, 0.3, 1],
405
+ repeat,
406
+ repeatDelay
407
+ },
408
+ children: [
409
+ /* @__PURE__ */ jsx("stop", { stopColor: gradientStartColor, stopOpacity: "0" }),
410
+ /* @__PURE__ */ jsx("stop", { stopColor: gradientStartColor }),
411
+ /* @__PURE__ */ jsx("stop", { offset: "32.5%", stopColor: gradientStopColor }),
412
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: gradientStopColor, stopOpacity: "0" })
413
+ ]
414
+ }
415
+ ) })
416
+ ]
417
+ }
418
+ );
419
+ }
420
+ var buttonVariants = cva(
421
+ "group inline-flex items-center justify-center gap-1.5 font-medium [transition:opacity_.24s_80ms,transform_.15s_cubic-bezier(.4,0,.2,1),box-shadow_.15s_cubic-bezier(.4,0,.2,1),filter_.15s_cubic-bezier(.4,0,.2,1)] disabled:[transition:opacity_.1s]",
422
+ {
423
+ variants: {
424
+ variant: {
425
+ filled: "bg-(--foreground) text-(--primary-foreground) shadow-elevated-3 hover:opacity-90",
426
+ bordered: "border border-(--border-hi) bg-surface-3 text-foreground shadow-elevated-3 hover:bg-(--muted)",
427
+ ghost: "text-(--foreground-secondary) hover:bg-(--surface-hover) hover:text-(--foreground)"
428
+ },
429
+ size: {
430
+ sm: "h-8 px-3.5 text-[15px]",
431
+ md: "h-9 px-5 text-[17px]",
432
+ lg: "h-11 px-6 text-[17px]",
433
+ icon: "size-11"
434
+ },
435
+ shape: {
436
+ rounded: "rounded-interactive",
437
+ pill: "rounded-full"
438
+ }
439
+ },
440
+ // Pill is the house standard — every CTA is fully rounded.
441
+ defaultVariants: { variant: "filled", size: "md", shape: "pill" }
442
+ }
443
+ );
444
+ function Button({
445
+ variant,
446
+ size,
447
+ shape,
448
+ showArrow = false,
449
+ external = false,
450
+ title,
451
+ actionOrLink,
452
+ children,
453
+ className,
454
+ "aria-label": ariaLabel,
455
+ "aria-expanded": ariaExpanded
456
+ }) {
457
+ const buttonClassName = cn(buttonVariants({ variant, size, shape }), className);
458
+ const arrowSlot = showArrow && /* @__PURE__ */ jsxs(
459
+ "svg",
460
+ {
461
+ viewBox: "0 0 14 14",
462
+ width: "14",
463
+ height: "14",
464
+ fill: "none",
465
+ stroke: "currentColor",
466
+ strokeWidth: "2",
467
+ strokeLinecap: "round",
468
+ strokeLinejoin: "round",
469
+ "aria-hidden": true,
470
+ className: "shrink-0",
471
+ children: [
472
+ /* @__PURE__ */ jsx(
473
+ "line",
474
+ {
475
+ x1: "0",
476
+ y1: "7",
477
+ x2: "9",
478
+ y2: "7",
479
+ strokeDasharray: "9",
480
+ className: "[stroke-dashoffset:9] [transition:stroke-dashoffset_.08s_cubic-bezier(.22,1,.36,1)] group-hover:[stroke-dashoffset:0] group-hover:[transition-duration:.22s]"
481
+ }
482
+ ),
483
+ /* @__PURE__ */ jsx(
484
+ "path",
485
+ {
486
+ d: "M5 3l4 4-4 4",
487
+ className: "[transform:translateX(0)] [transition:transform_.22s_cubic-bezier(.22,1,.36,1)] group-hover:[transform:translateX(2px)]"
488
+ }
489
+ )
490
+ ]
491
+ }
492
+ );
493
+ if (typeof actionOrLink === "string")
494
+ return /* @__PURE__ */ jsxs(
495
+ "a",
496
+ {
497
+ href: actionOrLink,
498
+ className: cn(buttonClassName, "no-underline"),
499
+ "aria-label": ariaLabel,
500
+ title,
501
+ ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
502
+ children: [
503
+ children,
504
+ arrowSlot
505
+ ]
506
+ }
507
+ );
508
+ return /* @__PURE__ */ jsxs(
509
+ "button",
510
+ {
511
+ type: "button",
512
+ className: buttonClassName,
513
+ onClick: actionOrLink,
514
+ "aria-label": ariaLabel,
515
+ "aria-expanded": ariaExpanded,
516
+ title,
517
+ children: [
518
+ children,
519
+ arrowSlot
520
+ ]
521
+ }
522
+ );
523
+ }
524
+
525
+ // src/lib/surface.ts
526
+ var SURFACE_BG = {
527
+ 1: "bg-surface-1",
528
+ 2: "bg-surface-2",
529
+ 3: "bg-surface-3",
530
+ 4: "bg-surface-4",
531
+ 5: "bg-surface-5",
532
+ 6: "bg-surface-6",
533
+ 7: "bg-surface-7",
534
+ 8: "bg-surface-8"
535
+ };
536
+ var SURFACE_VAR = {
537
+ 1: "[--popup-surface:var(--surface-1)]",
538
+ 2: "[--popup-surface:var(--surface-2)]",
539
+ 3: "[--popup-surface:var(--surface-3)]",
540
+ 4: "[--popup-surface:var(--surface-4)]",
541
+ 5: "[--popup-surface:var(--surface-5)]",
542
+ 6: "[--popup-surface:var(--surface-6)]",
543
+ 7: "[--popup-surface:var(--surface-7)]",
544
+ 8: "[--popup-surface:var(--surface-8)]"
545
+ };
546
+ var SURFACE_SHADOW_COMBINED = {
547
+ 1: "shadow-elevated-1",
548
+ 2: "shadow-elevated-2",
549
+ 3: "shadow-elevated-3",
550
+ 4: "shadow-elevated-4",
551
+ 5: "shadow-elevated-5",
552
+ 6: "shadow-elevated-6",
553
+ 7: "shadow-elevated-7",
554
+ 8: "shadow-elevated-8"
555
+ };
556
+ function solidSurface(level, shadowLevel = level) {
557
+ return `${SURFACE_BG[level]} ${SURFACE_SHADOW_COMBINED[shadowLevel]} ${SURFACE_VAR[level]}`;
558
+ }
559
+ var cardVariants = cva("text-foreground flex flex-col", {
560
+ variants: {
561
+ variant: {
562
+ default: "gap-6 rounded-2xl py-6",
563
+ inset: "rounded-2xl p-1"
564
+ }
565
+ },
566
+ defaultVariants: {
567
+ variant: "default"
568
+ }
569
+ });
570
+ function Card({ className, variant = "default", level = 3, shadowLevel = 1, ...props }) {
571
+ return /* @__PURE__ */ jsx(
572
+ "div",
573
+ {
574
+ "data-slot": "card",
575
+ "data-variant": variant,
576
+ "data-level": level,
577
+ className: cn(
578
+ cardVariants({ variant }),
579
+ solidSurface(level, shadowLevel),
580
+ // bg-muted overrides solidSurface's bg, making the outer a gray frame
581
+ // while keeping its shadow, rim, and --popup-surface.
582
+ variant === "inset" && "bg-muted",
583
+ className
584
+ ),
585
+ ...props
586
+ }
587
+ );
588
+ }
589
+ function CardHeader({ className, ...props }) {
590
+ return /* @__PURE__ */ jsx(
591
+ "div",
592
+ {
593
+ "data-slot": "card-header",
594
+ className: cn(
595
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start has-[[data-slot=card-action]]:grid-cols-[1fr_auto] [.border-b]:pb-6",
596
+ "[[data-variant=default]>_&]:gap-1.5 [[data-variant=default]>_&]:px-6",
597
+ "[[data-variant=inset]>_&]:px-3 [[data-variant=inset]>_&]:py-2 [[data-variant=inset]>_&]:pt-1",
598
+ className
599
+ ),
600
+ ...props
601
+ }
602
+ );
603
+ }
604
+ function CardTitle({ className, ...props }) {
605
+ return /* @__PURE__ */ jsx("div", { "data-slot": "card-title", className: cn("font-semibold [[data-variant=default]_&]:leading-none", className), ...props });
606
+ }
607
+ function CardDescription({ className, ...props }) {
608
+ return /* @__PURE__ */ jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props });
609
+ }
610
+ function CardAction({ className, ...props }) {
611
+ return /* @__PURE__ */ jsx(
612
+ "div",
613
+ {
614
+ "data-slot": "card-action",
615
+ className: cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className),
616
+ ...props
617
+ }
618
+ );
619
+ }
620
+ function CardContent({ className, ...props }) {
621
+ return /* @__PURE__ */ jsx(
622
+ "div",
623
+ {
624
+ "data-slot": "card-content",
625
+ className: cn(
626
+ "[[data-variant=default]>_&]:px-6",
627
+ "[[data-variant=inset]>_&]:flex [[data-variant=inset]>_&]:flex-1 [[data-variant=inset]>_&]:flex-col [[data-variant=inset]>_&]:rounded-lg [[data-variant=inset]>_&]:bg-surface-3 [[data-variant=inset]>_&]:p-4 [[data-variant=inset]>_&]:shadow-elevated-3 [[data-variant=inset]>_&]:[--popup-surface:var(--surface-3)]",
628
+ className
629
+ ),
630
+ ...props
631
+ }
632
+ );
633
+ }
634
+ function CardFooter({ className, ...props }) {
635
+ return /* @__PURE__ */ jsx(
636
+ "div",
637
+ {
638
+ "data-slot": "card-footer",
639
+ className: cn(
640
+ "flex items-center [.border-t]:pt-6",
641
+ "[[data-variant=default]>_&]:px-6",
642
+ "[[data-variant=inset]>_&]:mt-auto [[data-variant=inset]>_&]:justify-end [[data-variant=inset]>_&]:pt-4",
643
+ className
644
+ ),
645
+ ...props
646
+ }
647
+ );
648
+ }
649
+ function HeightClipper({ height, delay, children }) {
650
+ return /* @__PURE__ */ jsx(
651
+ motion.span,
652
+ {
653
+ className: "block w-full overflow-hidden",
654
+ animate: height === void 0 ? {} : { height },
655
+ transition: {
656
+ height: { duration: 0.4, ease: [0.4, 0, 0.2, 1], delay }
657
+ },
658
+ children
659
+ }
660
+ );
661
+ }
662
+ function ExitingLine({ text, textColor, duration, fallDuration, opacityEase, wrap = false, onDone }) {
663
+ return /* @__PURE__ */ jsx(
664
+ motion.span,
665
+ {
666
+ "aria-hidden": true,
667
+ className: cn(
668
+ wrap ? "pointer-events-none absolute top-0 left-0 w-full" : "pointer-events-none absolute top-0 left-1/2 whitespace-nowrap"
669
+ ),
670
+ style: { color: textColor },
671
+ initial: wrap ? { opacity: 1, y: 0 } : { opacity: 1, x: "-50%", y: 0 },
672
+ animate: wrap ? { opacity: 0, y: 14 } : { opacity: 0, x: "-50%", y: 14 },
673
+ transition: {
674
+ opacity: { duration, ease: opacityEase },
675
+ y: { duration: fallDuration, ease: [0.22, 0.61, 0.36, 1] }
676
+ },
677
+ onAnimationComplete: onDone,
678
+ children: text
679
+ }
680
+ );
681
+ }
682
+ function WidthReservation({ texts }) {
683
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible block h-0 overflow-hidden", children: texts.map((t) => /* @__PURE__ */ jsx("span", { className: "block", children: t }, t)) });
684
+ }
685
+
686
+ // src/components/dia-text-reveal.sweep.ts
687
+ var BAND_HALF = 17;
688
+ var SWEEP_START = -BAND_HALF;
689
+ var SWEEP_END = 100 + BAND_HALF;
690
+ var sweepEaseFn = (t) => t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2;
691
+ var coverageAt = (progress) => Math.min(1, sweepEaseFn(progress) * (SWEEP_END - SWEEP_START) / 100);
692
+ var COVERAGE_SPAN = (() => {
693
+ let lo = 0;
694
+ let hi = 1;
695
+ for (let i = 0; i < 40; i += 1) {
696
+ const mid = (lo + hi) / 2;
697
+ if (coverageAt(mid) < 1) lo = mid;
698
+ else hi = mid;
699
+ }
700
+ return hi;
701
+ })();
702
+ var EXIT_FADE_BIAS = 0.4;
703
+ var exitEase = (t) => coverageAt(t * COVERAGE_SPAN) ** EXIT_FADE_BIAS;
704
+ var makeExitEase = (leadFraction) => {
705
+ if (leadFraction <= 0) return exitEase;
706
+ if (leadFraction >= 1) return () => 0;
707
+ return (t) => t <= leadFraction ? 0 : exitEase((t - leadFraction) / (1 - leadFraction));
708
+ };
709
+ var SWEEP_SCALE = 3;
710
+ var BAND_HALF_IMAGE = BAND_HALF / SWEEP_SCALE;
711
+ var positionFor = (pos) => (pos - 50 * SWEEP_SCALE) / (1 - SWEEP_SCALE);
712
+ var SWEEP_FROM = `${positionFor(SWEEP_START).toFixed(3)}%`;
713
+ var SWEEP_TO = `${positionFor(SWEEP_END).toFixed(3)}%`;
714
+ var SWEEP_SIZE = `${SWEEP_SCALE * 100}% 100%`;
715
+ var EASE_SAMPLES = 24;
716
+ var sweepEaseCss = `linear(${Array.from({ length: EASE_SAMPLES + 1 }, (_, i) => sweepEaseFn(i / EASE_SAMPLES).toFixed(5)).join(
717
+ ", "
718
+ )})`;
719
+ function buildSweepGradient(colors, textColor) {
720
+ const bandStart = 50 - BAND_HALF_IMAGE;
721
+ const bandEnd = 50 + BAND_HALF_IMAGE;
722
+ const n = colors.length;
723
+ const parts = [`${textColor} 0%`, `${textColor} ${bandStart.toFixed(3)}%`];
724
+ for (const [i, c] of colors.entries()) {
725
+ const pct = n === 1 ? 50 : bandStart + i / (n - 1) * BAND_HALF_IMAGE * 2;
726
+ parts.push(`${c} ${pct.toFixed(3)}%`);
727
+ }
728
+ parts.push(`transparent ${bandEnd.toFixed(3)}%`, "transparent 100%");
729
+ return `linear-gradient(90deg, ${parts.join(", ")})`;
730
+ }
731
+ function buildSweepStyle({ colors, textColor, duration, delay, sweep, paused, reduced }) {
732
+ return {
733
+ color: "transparent",
734
+ backgroundClip: "text",
735
+ WebkitBackgroundClip: "text",
736
+ backgroundImage: buildSweepGradient(colors, textColor),
737
+ backgroundRepeat: "no-repeat",
738
+ backgroundSize: SWEEP_SIZE,
739
+ backgroundPositionX: reduced ? SWEEP_TO : SWEEP_FROM,
740
+ "--dia-sweep-from": SWEEP_FROM,
741
+ "--dia-sweep-to": SWEEP_TO,
742
+ ...sweep !== null && !reduced && {
743
+ animationName: sweep.cycle % 2 === 0 ? "dia-sweep-a" : "dia-sweep-b",
744
+ animationDuration: `${duration}s`,
745
+ animationDelay: `${delay}s`,
746
+ animationTimingFunction: sweepEaseCss,
747
+ animationFillMode: "both",
748
+ animationIterationCount: 1,
749
+ animationPlayState: paused ? "paused" : "running"
750
+ }
751
+ };
752
+ }
753
+
754
+ // src/components/dia-text-reveal.utils.ts
755
+ function measureWidths(el, texts) {
756
+ const parent = el.parentElement;
757
+ if (!parent) return texts.map(() => 0);
758
+ const ghost = el.cloneNode();
759
+ if (!(ghost instanceof HTMLElement)) return texts.map(() => 0);
760
+ Object.assign(ghost.style, {
761
+ position: "absolute",
762
+ visibility: "hidden",
763
+ pointerEvents: "none",
764
+ width: "auto",
765
+ whiteSpace: "nowrap"
766
+ });
767
+ parent.appendChild(ghost);
768
+ const widths = texts.map((t) => {
769
+ ghost.textContent = t;
770
+ return ghost.getBoundingClientRect().width;
771
+ });
772
+ ghost.remove();
773
+ return widths;
774
+ }
775
+ var DEFAULT_COLORS = ["#c679c4", "#fa3d1d", "#ffb005", "#e1e1fe", "#0358f7"];
776
+ var EXIT_LEAD_RATIO = 0.3;
777
+ function DiaTextReveal({
778
+ text,
779
+ colors = DEFAULT_COLORS,
780
+ textColor = "var(--color-foreground)",
781
+ duration = 1,
782
+ delay = 0,
783
+ repeat = false,
784
+ repeatDelay = 0.5,
785
+ exitDuration,
786
+ exitLead,
787
+ startOnView = true,
788
+ start = true,
789
+ once = true,
790
+ className,
791
+ fixedWidth = false,
792
+ wrap = false,
793
+ ...props
794
+ }) {
795
+ const texts = Array.isArray(text) ? text : [text];
796
+ const isMulti = texts.length > 1;
797
+ const prefersReducedMotion2 = useReducedMotion();
798
+ const exitSpan = exitDuration ?? duration * COVERAGE_SPAN;
799
+ const lead = Math.max(0, exitLead ?? duration * EXIT_LEAD_RATIO);
800
+ const exitTotal = lead + exitSpan;
801
+ const leadFraction = exitTotal > 0 ? lead / exitTotal : 0;
802
+ const exitOpacityEase = useMemo(() => makeExitEase(leadFraction), [leadFraction]);
803
+ const spanRef = useRef(null);
804
+ const optsRef = useRef({ repeat, repeatDelay, texts });
805
+ optsRef.current = { repeat, repeatDelay, texts };
806
+ const indexRef = useRef(0);
807
+ const hasPlayedRef = useRef(false);
808
+ const timerRef = useRef(void 0);
809
+ const pendingRepeatRef = useRef(false);
810
+ const [activeIndex, setActiveIndex] = useState(0);
811
+ const [sweep, setSweep] = useState(null);
812
+ const [exiting, setExiting] = useState(null);
813
+ const clearExiting = useCallback(() => setExiting(null), []);
814
+ const [measuredWidths, setMeasuredWidths] = useState([]);
815
+ const [wrapHeight, setWrapHeight] = useState(null);
816
+ const innerRef = useRef(null);
817
+ const isInView = useInView(spanRef, { once, amount: 0.1 });
818
+ const isLiveInView = useInView(spanRef, {
819
+ once: false,
820
+ amount: 0.1
821
+ });
822
+ useEffect(() => {
823
+ const el = spanRef.current;
824
+ if (!(el && isMulti) || wrap) return;
825
+ const measure = () => setMeasuredWidths(measureWidths(el, texts));
826
+ measure();
827
+ if (document.fonts.status !== "loaded") document.fonts.ready.then(measure);
828
+ }, [Array.isArray(text) ? text.join("\0") : text, isMulti, wrap, texts]);
829
+ useEffect(() => {
830
+ const el = innerRef.current;
831
+ if (!(el && wrap && isMulti)) return;
832
+ const observer = new ResizeObserver(([entry]) => {
833
+ if (!entry) return;
834
+ const h = entry.contentRect.height;
835
+ setWrapHeight(
836
+ (prev) => prev !== null && prev.h === h ? prev : {
837
+ h,
838
+ shrink: prev !== null && h < prev.h
839
+ }
840
+ );
841
+ });
842
+ observer.observe(el);
843
+ return () => observer.disconnect();
844
+ }, [wrap, isMulti]);
845
+ const advance = useCallback(() => {
846
+ const opts = optsRef.current;
847
+ const current = indexRef.current;
848
+ const next = (current + 1) % opts.texts.length;
849
+ indexRef.current = next;
850
+ setExiting({ index: current, token: Date.now() });
851
+ setActiveIndex(next);
852
+ setSweep((prev) => ({
853
+ cycle: (prev?.cycle ?? 0) + 1,
854
+ lead: true
855
+ }));
856
+ }, []);
857
+ const scheduleRepeat = useCallback(() => {
858
+ timerRef.current = setTimeout(() => {
859
+ timerRef.current = void 0;
860
+ advance();
861
+ }, optsRef.current.repeatDelay * 1e3);
862
+ }, [advance]);
863
+ const onSweepEnd = useCallback(
864
+ (event) => {
865
+ if (!event.animationName.startsWith("dia-sweep")) return;
866
+ if (!optsRef.current.repeat) return;
867
+ scheduleRepeat();
868
+ },
869
+ [scheduleRepeat]
870
+ );
871
+ useEffect(() => {
872
+ if (prefersReducedMotion2) return;
873
+ if (startOnView && !isInView) return;
874
+ if (!start) return;
875
+ if (once && hasPlayedRef.current) return;
876
+ hasPlayedRef.current = true;
877
+ setSweep((prev) => prev === null ? { cycle: 0, lead: false } : { cycle: prev.cycle + 1, lead: false });
878
+ }, [isInView, start, startOnView, once, prefersReducedMotion2]);
879
+ useEffect(() => {
880
+ if (!repeat || prefersReducedMotion2) return;
881
+ if (!isLiveInView) {
882
+ if (timerRef.current === void 0) return;
883
+ clearTimeout(timerRef.current);
884
+ timerRef.current = void 0;
885
+ pendingRepeatRef.current = true;
886
+ } else if (pendingRepeatRef.current) {
887
+ pendingRepeatRef.current = false;
888
+ scheduleRepeat();
889
+ }
890
+ }, [isLiveInView, repeat, prefersReducedMotion2, scheduleRepeat]);
891
+ useEffect(() => () => clearTimeout(timerRef.current), []);
892
+ const paused = repeat && sweep !== null && !isLiveInView;
893
+ const revealStyle = buildSweepStyle({
894
+ colors,
895
+ textColor,
896
+ duration,
897
+ delay: delay + (sweep?.lead ? lead : 0),
898
+ sweep,
899
+ paused,
900
+ reduced: prefersReducedMotion2 === true
901
+ });
902
+ if (!isMulti)
903
+ return /* @__PURE__ */ jsx(
904
+ motion.span,
905
+ {
906
+ ref: spanRef,
907
+ className: cn("align-baseline text-inherit leading-[100%]", className),
908
+ style: revealStyle,
909
+ ...props,
910
+ onAnimationEnd: onSweepEnd,
911
+ children: texts[activeIndex]
912
+ }
913
+ );
914
+ const fixedW = !wrap && fixedWidth && measuredWidths.length > 0 ? Math.max(...measuredWidths) : void 0;
915
+ const animatedW = wrap || fixedWidth ? void 0 : measuredWidths[activeIndex];
916
+ const animatedH = wrap ? wrapHeight?.h : void 0;
917
+ const heightDelay = exiting !== null && wrapHeight?.shrink ? exitTotal : 0;
918
+ const incoming = /* @__PURE__ */ jsx(
919
+ "span",
920
+ {
921
+ ref: innerRef,
922
+ className: cn("inline-block", wrap && "w-full", !wrap && "whitespace-nowrap"),
923
+ style: revealStyle,
924
+ onAnimationEnd: onSweepEnd,
925
+ children: texts[activeIndex]
926
+ }
927
+ );
928
+ return /* @__PURE__ */ jsxs(
929
+ motion.span,
930
+ {
931
+ ref: spanRef,
932
+ className: cn(
933
+ wrap ? "relative inline-block w-full text-center align-baseline text-inherit" : "relative inline-block whitespace-nowrap text-center align-baseline text-inherit leading-[100%]",
934
+ className
935
+ ),
936
+ style: {
937
+ ...fixedW !== void 0 && { width: fixedW }
938
+ },
939
+ animate: {
940
+ ...animatedW !== void 0 && { width: animatedW }
941
+ },
942
+ transition: {
943
+ width: { duration: 0.4, ease: [0.4, 0, 0.2, 1] }
944
+ },
945
+ ...props,
946
+ children: [
947
+ wrap ? /* @__PURE__ */ jsxs(HeightClipper, { height: animatedH, delay: heightDelay, children: [
948
+ /* @__PURE__ */ jsx(WidthReservation, { texts }),
949
+ incoming
950
+ ] }) : incoming,
951
+ exiting && !prefersReducedMotion2 && /* @__PURE__ */ jsx(
952
+ ExitingLine,
953
+ {
954
+ text: texts[exiting.index],
955
+ textColor,
956
+ duration: 0.4,
957
+ fallDuration: 0.25,
958
+ opacityEase: exitOpacityEase,
959
+ wrap,
960
+ onDone: clearExiting
961
+ },
962
+ exiting.token
963
+ )
964
+ ]
965
+ }
966
+ );
967
+ }
968
+ function ElevatedInput({
969
+ className,
970
+ type = "text",
971
+ ref,
972
+ ...props
973
+ }) {
974
+ return /* @__PURE__ */ jsx(
975
+ "input",
976
+ {
977
+ ref,
978
+ type,
979
+ className: cn(
980
+ // Layout & shape
981
+ "relative w-full overflow-hidden rounded-lg",
982
+ // Typography
983
+ "text-(--color-foreground) text-sm placeholder:text-(--color-muted-foreground)",
984
+ // Sizing
985
+ "h-9 px-3",
986
+ // Reset native input chrome
987
+ "appearance-none border-none outline-none",
988
+ // Background — a barely-there top darkening that reads as cavity depth.
989
+ "bg-[linear-gradient(to_bottom,oklch(0_0_0/0.04),transparent)]",
990
+ "dark:bg-[linear-gradient(to_bottom,oklch(1_0_0/0.04),transparent)]",
991
+ // Shadow stack — light mode
992
+ "shadow-[inset_0_1px_0_0_oklch(1_0_0/0.08),inset_0_2px_2px_-1px_oklch(0_0_0/0.08),inset_0_4px_4px_-2px_oklch(0_0_0/0.08),0_1px_0_0_oklch(0_0_0/0.12),inset_0_0_0_1px_oklch(0_0_0/0.16)]",
993
+ // Shadow stack — dark mode
994
+ "dark:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.1),inset_0_2px_2px_-1px_oklch(0_0_0/0.28),inset_0_4px_4px_-2px_oklch(0_0_0/0.22),0_1px_0_0_oklch(0_0_0/0.36),inset_0_0_0_1px_oklch(1_0_0/0.16)]",
995
+ // Focus
996
+ "focus-visible:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.08),inset_0_2px_2px_-1px_oklch(0_0_0/0.04),inset_0_4px_4px_-2px_oklch(0_0_0/0.04),0_0_0_3px_oklch(0_0_0/0.08),inset_0_0_0_1.5px_oklch(0_0_0/0.36)]",
997
+ "dark:focus-visible:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.12),inset_0_2px_2px_-1px_oklch(0_0_0/0.16),inset_0_4px_4px_-2px_oklch(0_0_0/0.12),0_0_0_3px_oklch(1_0_0/0.08),inset_0_0_0_1.5px_oklch(1_0_0/0.28)]",
998
+ "transition-shadow duration-150",
999
+ "disabled:cursor-not-allowed disabled:opacity-50",
1000
+ className
1001
+ ),
1002
+ ...props
1003
+ }
1004
+ );
1005
+ }
1006
+ var viewport = { once: true, margin: "-60px" };
1007
+ var ROW_TOLERANCE = 8;
1008
+ var StaggerContext = createContext(null);
1009
+ function FadeIn({ children, className, delay = 0, duration = 1, yOffset = 20, start = true }) {
1010
+ const ref = useRef(null);
1011
+ const inView = useInView(ref, viewport);
1012
+ const hidden = { opacity: 0, y: yOffset };
1013
+ return /* @__PURE__ */ jsx(
1014
+ motion.div,
1015
+ {
1016
+ ref,
1017
+ className,
1018
+ initial: hidden,
1019
+ animate: inView && start ? { opacity: 1, y: 0 } : hidden,
1020
+ transition: { duration, delay, ease: easeOut },
1021
+ children
1022
+ }
1023
+ );
1024
+ }
1025
+ function Stagger({ children, className, staggerDelay = 0.15, baseDelay = 0, start = true }) {
1026
+ const queue = useRef([]);
1027
+ const frame = useRef(null);
1028
+ const started = useRef(start);
1029
+ started.current = start;
1030
+ const flush = useCallback(() => {
1031
+ frame.current = null;
1032
+ const batch = queue.current;
1033
+ queue.current = [];
1034
+ const positioned = batch.map((entry) => ({
1035
+ ...entry,
1036
+ rect: entry.element.getBoundingClientRect()
1037
+ }));
1038
+ positioned.sort(
1039
+ (a, b) => Math.abs(a.rect.top - b.rect.top) > ROW_TOLERANCE ? a.rect.top - b.rect.top : a.rect.left - b.rect.left
1040
+ );
1041
+ for (const [index, entry] of positioned.entries()) entry.reveal(baseDelay + index * staggerDelay);
1042
+ }, [baseDelay, staggerDelay]);
1043
+ const register = useCallback(
1044
+ (element, reveal) => {
1045
+ queue.current.push({ element, reveal });
1046
+ if (started.current) frame.current ??= requestAnimationFrame(flush);
1047
+ },
1048
+ [flush]
1049
+ );
1050
+ useEffect(() => {
1051
+ if (start && queue.current.length > 0) frame.current ??= requestAnimationFrame(flush);
1052
+ }, [start, flush]);
1053
+ return /* @__PURE__ */ jsx(StaggerContext, { value: register, children: /* @__PURE__ */ jsx("div", { className, children }) });
1054
+ }
1055
+ function StaggerItem({ children, className }) {
1056
+ const register = useContext(StaggerContext);
1057
+ const ref = useRef(null);
1058
+ const claimed = useRef(false);
1059
+ const [delay, setDelay] = useState(null);
1060
+ const onViewportEnter = useCallback(() => {
1061
+ if (claimed.current) return;
1062
+ claimed.current = true;
1063
+ const element = ref.current;
1064
+ if (register && element) register(element, setDelay);
1065
+ else setDelay(0);
1066
+ }, [register]);
1067
+ return /* @__PURE__ */ jsx(
1068
+ motion.div,
1069
+ {
1070
+ ref,
1071
+ className,
1072
+ initial: { opacity: 0, y: 18 },
1073
+ animate: delay === null ? { opacity: 0, y: 18 } : { opacity: 1, y: 0 },
1074
+ transition: { duration: 0.45, delay: delay ?? 0, ease: easeOut },
1075
+ viewport,
1076
+ onViewportEnter,
1077
+ children
1078
+ }
1079
+ );
1080
+ }
1081
+ function FeatureCard({ icon, title, body, iconColor, className }) {
1082
+ return /* @__PURE__ */ jsxs(
1083
+ "div",
1084
+ {
1085
+ className: cn(
1086
+ "flex w-full flex-col justify-between gap-6 rounded-[20px] bg-(--muted) p-6 lg:gap-8 lg:rounded-3xl lg:p-8 xl:gap-10 xl:p-10",
1087
+ className
1088
+ ),
1089
+ children: [
1090
+ /* @__PURE__ */ jsx("div", { className: "flex size-10 items-center justify-center rounded-[10px] bg-(--surface) shadow-(--shadow-sm) lg:size-12 lg:rounded-md", children: /* @__PURE__ */ jsx(
1091
+ "span",
1092
+ {
1093
+ className: cn("flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6", iconColor ?? "text-(--foreground-secondary)"),
1094
+ children: icon
1095
+ }
1096
+ ) }),
1097
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
1098
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-[15px] text-foreground lg:text-base", children: title }),
1099
+ /* @__PURE__ */ jsx("p", { className: "text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm", children: body })
1100
+ ] })
1101
+ ]
1102
+ }
1103
+ );
1104
+ }
1105
+ var downChevronClass = "absolute left-1/2 top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)";
1106
+ var rightChevronClass = "absolute right-0 top-1/2 size-2 translate-x-1/2 -translate-y-1/2 rotate-45 border-t border-r border-(--foreground-muted)";
1107
+ var leftChevronClass = "absolute left-0 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 -rotate-45 border-t border-l border-(--foreground-muted)";
1108
+ var microLabelClass = "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 whitespace-nowrap rounded-full border border-(--border) bg-(--muted) px-1.5 py-px font-mono text-[8.5px] leading-tight text-(--foreground-secondary)";
1109
+ function ArrowRight({ label, className }) {
1110
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
1111
+ /* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
1112
+ /* @__PURE__ */ jsx("span", { className: rightChevronClass }),
1113
+ label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
1114
+ ] });
1115
+ }
1116
+ function ArrowLeft({ label, className }) {
1117
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
1118
+ /* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
1119
+ /* @__PURE__ */ jsx("span", { className: leftChevronClass }),
1120
+ label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
1121
+ ] });
1122
+ }
1123
+ function TurnDown({ className }) {
1124
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-4", className), children: [
1125
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1126
+ /* @__PURE__ */ jsx("span", { className: downChevronClass })
1127
+ ] });
1128
+ }
1129
+ function SplitArrow({ leftLabel, rightLabel, className }) {
1130
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
1131
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1132
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
1133
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1134
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1135
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" }),
1136
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" }),
1137
+ leftLabel ? /* @__PURE__ */ jsx("span", { className: "absolute left-[30%] top-1/2 -translate-y-1/2 rounded-full border border-(--border) bg-(--muted) px-2 py-0.5 font-mono text-[10px] text-(--foreground-secondary)", children: leftLabel }) : null,
1138
+ rightLabel ? /* @__PURE__ */ jsx("span", { className: "absolute right-[30%] top-1/2 -translate-y-1/2 rounded-full border border-(--border) bg-(--muted) px-2 py-0.5 font-mono text-[10px] text-(--foreground-secondary)", children: rightLabel }) : null
1139
+ ] });
1140
+ }
1141
+ function JoinArrow({ className }) {
1142
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
1143
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1144
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1145
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
1146
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
1147
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" })
1148
+ ] });
1149
+ }
1150
+ function FlowNode({ icon, chipClass, title, body, tag, children, className }) {
1151
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5", className), children: [
1152
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
1153
+ icon ? /* @__PURE__ */ jsx("div", { className: cn("flex size-7 shrink-0 items-center justify-center rounded-[8px]", chipClass ?? "bg-(--muted)"), children: icon }) : null,
1154
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1155
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-1.5 gap-y-0.5", children: [
1156
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]", children: title }),
1157
+ tag ? /* @__PURE__ */ jsx("span", { className: "rounded-full border border-(--border) px-1.5 py-px font-mono text-[8.5px] text-(--foreground-muted)", children: tag }) : null
1158
+ ] }),
1159
+ body ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]", children: body }) : null
1160
+ ] })
1161
+ ] }),
1162
+ children ? /* @__PURE__ */ jsx("div", { className: "mt-2", children }) : null
1163
+ ] });
1164
+ }
1165
+ function FlowPill({ title, className }) {
1166
+ return /* @__PURE__ */ jsx(
1167
+ "div",
1168
+ {
1169
+ className: cn(
1170
+ "mx-auto flex w-fit max-w-full items-center justify-center rounded-full border border-(--border) bg-(--surface) px-4 py-2 text-center",
1171
+ className
1172
+ ),
1173
+ children: /* @__PURE__ */ jsx("p", { className: "text-[12px] font-semibold leading-snug text-foreground", children: title })
1174
+ }
1175
+ );
1176
+ }
1177
+ function FlowDiamond({ label, sub, className }) {
1178
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-14 w-36 justify-self-center sm:h-16 sm:w-44", className), children: [
1179
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]" }),
1180
+ /* @__PURE__ */ jsxs("div", { className: "absolute inset-[1px] flex flex-col items-center justify-center gap-0.5 bg-(--surface) px-6 text-center [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]", children: [
1181
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]", children: label }),
1182
+ sub ? /* @__PURE__ */ jsx("p", { className: "text-[8.5px] leading-tight text-(--foreground-muted)", children: sub }) : null
1183
+ ] })
1184
+ ] });
1185
+ }
1186
+ var glossLayer = cn(
1187
+ "pointer-events-none absolute inset-0 z-[-1] rounded-[inherit]",
1188
+ "[background-color:var(--btn-face)] [box-shadow:var(--shadow-button)]",
1189
+ "transition-shadow duration-150",
1190
+ // Pressed (and disabled): bevel + cast go transparent, the rim stays.
1191
+ "group-active/glossy:[box-shadow:var(--shadow-button-pressed)]",
1192
+ "group-disabled/glossy:[box-shadow:var(--shadow-button-pressed)]",
1193
+ // Dome — fixed direction, per-variant stops. Above the face, below the tint.
1194
+ "before:absolute before:inset-0 before:rounded-[inherit] before:content-[''] before:[background-image:var(--gradient-button)]",
1195
+ // Interaction tint. Hidden outright when disabled, and on touch (no hover
1196
+ // state to speak of) so the root's active:opacity can carry the press instead.
1197
+ "after:absolute after:inset-0 after:rounded-[inherit] after:content-[''] after:opacity-0",
1198
+ "after:[background-color:var(--btn-tint-hover)] after:transition-opacity after:duration-150 after:[will-change:opacity]",
1199
+ "group-hover/glossy:after:opacity-100",
1200
+ "group-active/glossy:after:[background-color:var(--btn-tint-active)]",
1201
+ "group-disabled/glossy:after:hidden [@media(hover:none)]:after:hidden"
1202
+ );
1203
+ var glossyButtonVariants = cva(
1204
+ cn(
1205
+ "glossy group/glossy relative isolate inline-flex cursor-pointer select-none items-center justify-center gap-1 whitespace-nowrap rounded-full font-normal",
1206
+ // Label colour rides the variant. Kept as a utility rather than a plain
1207
+ // declaration on `.glossy` so a caller's own text-* class still wins.
1208
+ "[color:var(--btn-fg)]",
1209
+ "disabled:cursor-default disabled:opacity-50",
1210
+ // Touch devices get no hover layer, so the whole key dims on press instead.
1211
+ "[@media(hover:none)]:active:opacity-80"
1212
+ ),
1213
+ {
1214
+ variants: {
1215
+ size: {
1216
+ sm: "h-8 px-2.5 text-sm",
1217
+ md: "h-9 px-5 text-[17px]",
1218
+ lg: "h-11 px-6 text-[17px]"
1219
+ },
1220
+ /**
1221
+ * Written out as literal class names — Tailwind's scanner is static, so a
1222
+ * `glossy-${variant}` template would never make it into the stylesheet.
1223
+ * `neutral` is the bare recipe, so it needs no class of its own.
1224
+ */
1225
+ variant: {
1226
+ neutral: "",
1227
+ accent: "glossy-accent",
1228
+ destructive: "glossy-destructive",
1229
+ special: "glossy-special",
1230
+ positive: "glossy-positive",
1231
+ attention: "glossy-attention",
1232
+ highlight: "glossy-highlight",
1233
+ inverse: "glossy-inverse"
1234
+ }
1235
+ },
1236
+ defaultVariants: { size: "md", variant: "neutral" }
1237
+ }
1238
+ );
1239
+ function GlossyButton({
1240
+ size,
1241
+ variant,
1242
+ actionOrLink,
1243
+ children,
1244
+ disabled,
1245
+ className,
1246
+ "aria-label": ariaLabel
1247
+ }) {
1248
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1249
+ /* @__PURE__ */ jsx("span", { "data-fx-layer": "gloss", "aria-hidden": true, className: glossLayer }),
1250
+ /* @__PURE__ */ jsx("span", { className: "px-0.5", children })
1251
+ ] });
1252
+ const buttonClassName = cn(glossyButtonVariants({ size, variant }), className);
1253
+ if (typeof actionOrLink === "string")
1254
+ return /* @__PURE__ */ jsx("a", { href: actionOrLink, className: cn(buttonClassName, "no-underline"), "aria-label": ariaLabel, children: content });
1255
+ return /* @__PURE__ */ jsx("button", { type: "button", className: buttonClassName, onClick: actionOrLink, disabled, "aria-label": ariaLabel, children: content });
1256
+ }
1257
+ var vertex = `#version 300 es
1258
+ in vec2 position;
1259
+ void main() {
1260
+ gl_Position = vec4(position, 0.0, 1.0);
1261
+ }
1262
+ `;
1263
+ var fragment = `#version 300 es
1264
+ precision highp float;
1265
+ uniform vec2 iResolution;
1266
+ uniform float iTime;
1267
+ uniform float uTimeSpeed;
1268
+ uniform float uColorBalance;
1269
+ uniform float uWarpStrength;
1270
+ uniform float uWarpFrequency;
1271
+ uniform float uWarpSpeed;
1272
+ uniform float uWarpAmplitude;
1273
+ uniform float uBlendAngle;
1274
+ uniform float uBlendSoftness;
1275
+ uniform float uRotationAmount;
1276
+ uniform float uNoiseScale;
1277
+ uniform float uGrainAmount;
1278
+ uniform float uGrainScale;
1279
+ uniform float uGrainAnimated;
1280
+ uniform float uContrast;
1281
+ uniform float uGamma;
1282
+ uniform float uSaturation;
1283
+ uniform vec2 uCenterOffset;
1284
+ uniform float uZoom;
1285
+ uniform vec3 uColor1;
1286
+ uniform vec3 uColor2;
1287
+ uniform vec3 uColor3;
1288
+ out vec4 fragColor;
1289
+ #define S(a,b,t) smoothstep(a,b,t)
1290
+ mat2 Rot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);}
1291
+ vec2 hash(vec2 p){p=vec2(dot(p,vec2(2127.1,81.17)),dot(p,vec2(1269.5,283.37)));return fract(sin(p)*43758.5453);}
1292
+ float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.0-2.0*f);float n=mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)),f-vec2(0.0,0.0)),dot(-1.0+2.0*hash(i+vec2(1.0,0.0)),f-vec2(1.0,0.0)),u.x),mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)),f-vec2(0.0,1.0)),dot(-1.0+2.0*hash(i+vec2(1.0,1.0)),f-vec2(1.0,1.0)),u.x),u.y);return 0.5+0.5*n;}
1293
+ void mainImage(out vec4 o, vec2 C){
1294
+ float t=iTime*uTimeSpeed;
1295
+ vec2 uv=C/iResolution.xy;
1296
+ float ratio=iResolution.x/iResolution.y;
1297
+ vec2 tuv=uv-0.5+uCenterOffset;
1298
+ tuv/=max(uZoom,0.001);
1299
+ float degree=noise(vec2(t*0.1,tuv.x*tuv.y)*uNoiseScale);
1300
+ tuv.y*=1.0/ratio;
1301
+ tuv*=Rot(radians((degree-0.5)*uRotationAmount+180.0));
1302
+ tuv.y*=ratio;
1303
+ float frequency=uWarpFrequency;
1304
+ float ws=max(uWarpStrength,0.001);
1305
+ float amplitude=uWarpAmplitude/ws;
1306
+ float warpTime=t*uWarpSpeed;
1307
+ tuv.x+=sin(tuv.y*frequency+warpTime)/amplitude;
1308
+ tuv.y+=sin(tuv.x*(frequency*1.5)+warpTime)/(amplitude*0.5);
1309
+ vec3 colLav=uColor1;
1310
+ vec3 colOrg=uColor2;
1311
+ vec3 colDark=uColor3;
1312
+ float b=uColorBalance;
1313
+ float s=max(uBlendSoftness,0.0);
1314
+ mat2 blendRot=Rot(radians(uBlendAngle));
1315
+ float blendX=(tuv*blendRot).x;
1316
+ float edge0=-0.3-b-s;
1317
+ float edge1=0.2-b+s;
1318
+ float v0=0.5-b+s;
1319
+ float v1=-0.3-b-s;
1320
+ vec3 layer1=mix(colDark,colOrg,S(edge0,edge1,blendX));
1321
+ vec3 layer2=mix(colOrg,colLav,S(edge0,edge1,blendX));
1322
+ vec3 col=mix(layer1,layer2,S(v0,v1,tuv.y));
1323
+ vec2 grainUv=uv*max(uGrainScale,0.001);
1324
+ if(uGrainAnimated>0.5){grainUv+=vec2(iTime*0.05);}
1325
+ float grain=fract(sin(dot(grainUv,vec2(12.9898,78.233)))*43758.5453);
1326
+ col+=(grain-0.5)*uGrainAmount;
1327
+ col=(col-0.5)*uContrast+0.5;
1328
+ float luma=dot(col,vec3(0.2126,0.7152,0.0722));
1329
+ col=mix(vec3(luma),col,uSaturation);
1330
+ col=pow(max(col,0.0),vec3(1.0/max(uGamma,0.001)));
1331
+ col=clamp(col,0.0,1.0);
1332
+ o=vec4(col,1.0);
1333
+ }
1334
+ void main(){
1335
+ vec4 o=vec4(0.0);
1336
+ mainImage(o,gl_FragCoord.xy);
1337
+ fragColor=o;
1338
+ }
1339
+ `;
1340
+ function createGrainientProgram(gl) {
1341
+ return new Program(gl, {
1342
+ vertex,
1343
+ fragment,
1344
+ uniforms: {
1345
+ iTime: { value: 0 },
1346
+ iResolution: { value: new Float32Array([1, 1]) },
1347
+ uTimeSpeed: { value: 0.25 },
1348
+ uColorBalance: { value: 0 },
1349
+ uWarpStrength: { value: 1 },
1350
+ uWarpFrequency: { value: 5 },
1351
+ uWarpSpeed: { value: 2 },
1352
+ uWarpAmplitude: { value: 50 },
1353
+ uBlendAngle: { value: 0 },
1354
+ uBlendSoftness: { value: 0.05 },
1355
+ uRotationAmount: { value: 500 },
1356
+ uNoiseScale: { value: 2 },
1357
+ uGrainAmount: { value: 0.1 },
1358
+ uGrainScale: { value: 2 },
1359
+ uGrainAnimated: { value: 0 },
1360
+ uContrast: { value: 1.5 },
1361
+ uGamma: { value: 1 },
1362
+ uSaturation: { value: 1 },
1363
+ uCenterOffset: { value: new Float32Array([0, 0]) },
1364
+ uZoom: { value: 0.9 },
1365
+ uColor1: { value: new Float32Array([1, 1, 1]) },
1366
+ uColor2: { value: new Float32Array([1, 1, 1]) },
1367
+ uColor3: { value: new Float32Array([1, 1, 1]) }
1368
+ }
1369
+ });
1370
+ }
1371
+ var ctxMap = /* @__PURE__ */ new WeakMap();
1372
+ var HEX_COLOR_RE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
1373
+ var hexToRgb = (hex) => {
1374
+ const result = HEX_COLOR_RE.exec(hex);
1375
+ if (!result) return [1, 1, 1];
1376
+ const [, r = "ff", g = "ff", b = "ff"] = result;
1377
+ return [Number.parseInt(r, 16) / 255, Number.parseInt(g, 16) / 255, Number.parseInt(b, 16) / 255];
1378
+ };
1379
+ var prefersReducedMotion = () => typeof globalThis !== "undefined" && globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
1380
+ var isLowPowerClient = () => {
1381
+ if (typeof globalThis === "undefined") return false;
1382
+ const narrow = globalThis.matchMedia?.("(max-width: 1023px)").matches === true;
1383
+ const fewCores = typeof navigator !== "undefined" && typeof navigator.hardwareConcurrency === "number" && navigator.hardwareConcurrency <= 4;
1384
+ return narrow || fewCores;
1385
+ };
1386
+ var GRAIN_LAYER = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.12'/%3E%3C/svg%3E")`;
1387
+ var fallbackGradient = (c1, c2, c3) => `${GRAIN_LAYER}, linear-gradient(135deg, ${c1} 0%, ${c2} 55%, ${c3} 100%)`;
1388
+ var applyStaticBg = (el, src) => {
1389
+ el.style.backgroundImage = `url(${src})`;
1390
+ el.style.backgroundSize = "cover";
1391
+ el.style.backgroundPosition = "center";
1392
+ };
1393
+ function initGrainient(container) {
1394
+ const renderer = new Renderer({
1395
+ webgl: 2,
1396
+ alpha: true,
1397
+ antialias: false,
1398
+ dpr: Math.min(globalThis.devicePixelRatio || 1, 2)
1399
+ });
1400
+ const gl = renderer.gl;
1401
+ const canvas = gl.canvas;
1402
+ canvas.style.width = "100%";
1403
+ canvas.style.height = "100%";
1404
+ canvas.style.display = "block";
1405
+ container.appendChild(canvas);
1406
+ const geometry = new Triangle(gl);
1407
+ const program = createGrainientProgram(gl);
1408
+ const mesh = new Mesh(gl, { geometry, program });
1409
+ ctxMap.set(container, { renderer, program, mesh });
1410
+ const setSize = () => {
1411
+ const rect = container.getBoundingClientRect();
1412
+ renderer.setSize(Math.max(1, Math.floor(rect.width)), Math.max(1, Math.floor(rect.height)));
1413
+ const res = program.uniforms.iResolution.value;
1414
+ res[0] = gl.drawingBufferWidth;
1415
+ res[1] = gl.drawingBufferHeight;
1416
+ renderer.render({ scene: mesh });
1417
+ };
1418
+ const ro = new ResizeObserver(setSize);
1419
+ ro.observe(container);
1420
+ setSize();
1421
+ let raf = 0;
1422
+ let isVisible = true;
1423
+ let isPageVisible = !document.hidden;
1424
+ const t0 = performance.now();
1425
+ const loop = (t) => {
1426
+ program.uniforms.iTime.value = (t - t0) * 1e-3;
1427
+ renderer.render({ scene: mesh });
1428
+ raf = requestAnimationFrame(loop);
1429
+ };
1430
+ const tryStart = () => {
1431
+ if (isVisible && isPageVisible && raf === 0) raf = requestAnimationFrame(loop);
1432
+ };
1433
+ const tryStop = () => {
1434
+ if (raf !== 0) {
1435
+ cancelAnimationFrame(raf);
1436
+ raf = 0;
1437
+ }
1438
+ };
1439
+ const reduce = prefersReducedMotion();
1440
+ const io = new IntersectionObserver(
1441
+ ([entry]) => {
1442
+ if (!entry) return;
1443
+ isVisible = entry.isIntersecting;
1444
+ if (isVisible) tryStart();
1445
+ else tryStop();
1446
+ },
1447
+ { threshold: 0 }
1448
+ );
1449
+ if (!reduce) io.observe(container);
1450
+ const onVisibility = () => {
1451
+ isPageVisible = !document.hidden;
1452
+ if (isPageVisible) tryStart();
1453
+ else tryStop();
1454
+ };
1455
+ if (!reduce) document.addEventListener("visibilitychange", onVisibility);
1456
+ if (!reduce) tryStart();
1457
+ return () => {
1458
+ tryStop();
1459
+ ro.disconnect();
1460
+ io.disconnect();
1461
+ document.removeEventListener("visibilitychange", onVisibility);
1462
+ ctxMap.delete(container);
1463
+ try {
1464
+ container.removeChild(canvas);
1465
+ } catch {
1466
+ }
1467
+ };
1468
+ }
1469
+ var Grainient = (props) => {
1470
+ const {
1471
+ timeSpeed = 0.25,
1472
+ colorBalance = 0,
1473
+ warpStrength = 1,
1474
+ warpFrequency = 5,
1475
+ warpSpeed = 2,
1476
+ warpAmplitude = 50,
1477
+ blendAngle = 0,
1478
+ blendSoftness = 0.05,
1479
+ rotationAmount = 500,
1480
+ noiseScale = 2,
1481
+ grainAmount = 0.1,
1482
+ grainScale = 2,
1483
+ grainAnimated = false,
1484
+ contrast = 1.5,
1485
+ gamma = 1,
1486
+ saturation = 1,
1487
+ centerX = 0,
1488
+ centerY = 0,
1489
+ zoom = 0.9,
1490
+ color1 = "#FF9FFC",
1491
+ color2 = "#5227FF",
1492
+ color3 = "#B497CF",
1493
+ staticSrc = "",
1494
+ className = ""
1495
+ } = props;
1496
+ const containerRef = useRef(null);
1497
+ const fallbackRef = useRef(false);
1498
+ useEffect(() => {
1499
+ const container = containerRef.current;
1500
+ if (!container) return;
1501
+ if (isLowPowerClient() || prefersReducedMotion()) {
1502
+ fallbackRef.current = true;
1503
+ container.dataset.fallback = "true";
1504
+ if (staticSrc) applyStaticBg(container, staticSrc);
1505
+ else container.style.background = fallbackGradient(color1, color2, color3);
1506
+ return;
1507
+ }
1508
+ return initGrainient(container);
1509
+ }, []);
1510
+ useEffect(() => {
1511
+ const container = containerRef.current;
1512
+ if (!container) return;
1513
+ if (fallbackRef.current) {
1514
+ if (staticSrc) applyStaticBg(container, staticSrc);
1515
+ else container.style.background = fallbackGradient(color1, color2, color3);
1516
+ return;
1517
+ }
1518
+ const ctx = ctxMap.get(container);
1519
+ if (!ctx) return;
1520
+ const { program, renderer, mesh } = ctx;
1521
+ const u = program.uniforms;
1522
+ u.uTimeSpeed.value = timeSpeed;
1523
+ u.uColorBalance.value = colorBalance;
1524
+ u.uWarpStrength.value = warpStrength;
1525
+ u.uWarpFrequency.value = warpFrequency;
1526
+ u.uWarpSpeed.value = warpSpeed;
1527
+ u.uWarpAmplitude.value = warpAmplitude;
1528
+ u.uBlendAngle.value = blendAngle;
1529
+ u.uBlendSoftness.value = blendSoftness;
1530
+ u.uRotationAmount.value = rotationAmount;
1531
+ u.uNoiseScale.value = noiseScale;
1532
+ u.uGrainAmount.value = grainAmount;
1533
+ u.uGrainScale.value = grainScale;
1534
+ u.uGrainAnimated.value = grainAnimated ? 1 : 0;
1535
+ u.uContrast.value = contrast;
1536
+ u.uGamma.value = gamma;
1537
+ u.uSaturation.value = saturation;
1538
+ u.uCenterOffset.value = new Float32Array([centerX, centerY]);
1539
+ u.uZoom.value = zoom;
1540
+ u.uColor1.value = new Float32Array(hexToRgb(color1));
1541
+ u.uColor2.value = new Float32Array(hexToRgb(color2));
1542
+ u.uColor3.value = new Float32Array(hexToRgb(color3));
1543
+ if (prefersReducedMotion()) renderer.render({ scene: mesh });
1544
+ }, [
1545
+ timeSpeed,
1546
+ colorBalance,
1547
+ warpStrength,
1548
+ warpFrequency,
1549
+ warpSpeed,
1550
+ warpAmplitude,
1551
+ blendAngle,
1552
+ blendSoftness,
1553
+ rotationAmount,
1554
+ noiseScale,
1555
+ grainAmount,
1556
+ grainScale,
1557
+ grainAnimated,
1558
+ contrast,
1559
+ gamma,
1560
+ saturation,
1561
+ centerX,
1562
+ centerY,
1563
+ zoom,
1564
+ color1,
1565
+ color2,
1566
+ color3,
1567
+ staticSrc
1568
+ ]);
1569
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, className: cn("grainient-container", className) });
1570
+ };
1571
+ var grainient_default = Grainient;
1572
+ function useMediaQuery(query, defaultState = false) {
1573
+ const [matches, setMatches] = useState(defaultState);
1574
+ useEffect(() => {
1575
+ const mql = globalThis.matchMedia(query);
1576
+ setMatches(mql.matches);
1577
+ const onChange = (e) => setMatches(e.matches);
1578
+ mql.addEventListener("change", onChange);
1579
+ return () => mql.removeEventListener("change", onChange);
1580
+ }, [query]);
1581
+ return matches;
1582
+ }
1583
+ function resolveColor(element, color) {
1584
+ if (!color.startsWith("var(")) return color;
1585
+ const token = color.slice(4, -1).trim();
1586
+ return globalThis.getComputedStyle(element).getPropertyValue(token).trim() || color;
1587
+ }
1588
+ var BREAKPOINTS = [
1589
+ ["xs", 30],
1590
+ ["sm", 40],
1591
+ ["md", 50],
1592
+ ["lg", 64],
1593
+ ["xl", 80],
1594
+ ["2xl", 96]
1595
+ ];
1596
+ function getBreakpoint() {
1597
+ let current = "base";
1598
+ for (const [name, rem] of BREAKPOINTS) {
1599
+ if (globalThis.matchMedia(`(min-width: ${rem}rem)`).matches) current = name;
1600
+ }
1601
+ return current;
1602
+ }
1603
+ function onBreakpointChange(listener) {
1604
+ const queries = BREAKPOINTS.map(([, rem]) => globalThis.matchMedia(`(min-width: ${rem}rem)`));
1605
+ for (const query of queries) query.addEventListener("change", listener);
1606
+ return () => {
1607
+ for (const query of queries) query.removeEventListener("change", listener);
1608
+ };
1609
+ }
1610
+ function Highlighter({
1611
+ children,
1612
+ className,
1613
+ action = "highlight",
1614
+ color = "var(--marker-highlight)",
1615
+ strokeWidth = 1.5,
1616
+ animationDuration = 600,
1617
+ delay = 0,
1618
+ iterations = 2,
1619
+ padding = 2,
1620
+ multiline = true,
1621
+ isView = false
1622
+ }) {
1623
+ const elementRef = useRef(null);
1624
+ const isInView = useInView(elementRef, { once: true, margin: "-10%" });
1625
+ const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
1626
+ const [themeVersion, setThemeVersion] = useState(0);
1627
+ const shouldShow = !isView || isInView;
1628
+ useLayoutEffect(() => {
1629
+ const observer = new MutationObserver(() => setThemeVersion((v) => v + 1));
1630
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
1631
+ return () => observer.disconnect();
1632
+ }, []);
1633
+ useLayoutEffect(() => {
1634
+ const element = elementRef.current;
1635
+ if (!(shouldShow && element)) return;
1636
+ let annotation;
1637
+ let untrack;
1638
+ const draw = () => {
1639
+ annotation = annotate(element, {
1640
+ type: action,
1641
+ color: resolveColor(element, color),
1642
+ strokeWidth,
1643
+ animationDuration,
1644
+ animate: !reducedMotion,
1645
+ iterations,
1646
+ padding,
1647
+ multiline
1648
+ });
1649
+ annotation.show();
1650
+ let drawnAt = getBreakpoint();
1651
+ untrack = onBreakpointChange(() => {
1652
+ const current = getBreakpoint();
1653
+ if (current === drawnAt) return;
1654
+ drawnAt = current;
1655
+ annotation?.show();
1656
+ });
1657
+ };
1658
+ const startDelay = reducedMotion ? 0 : delay;
1659
+ const timer2 = startDelay > 0 ? globalThis.setTimeout(draw, startDelay) : void 0;
1660
+ if (timer2 === void 0) draw();
1661
+ return () => {
1662
+ globalThis.clearTimeout(timer2);
1663
+ untrack?.();
1664
+ annotation?.remove();
1665
+ };
1666
+ }, [
1667
+ shouldShow,
1668
+ action,
1669
+ color,
1670
+ strokeWidth,
1671
+ animationDuration,
1672
+ delay,
1673
+ iterations,
1674
+ padding,
1675
+ multiline,
1676
+ reducedMotion,
1677
+ themeVersion
1678
+ ]);
1679
+ return /* @__PURE__ */ jsx("span", { className: cn("relative inline-block bg-transparent", className), children: /* @__PURE__ */ jsx("span", { ref: elementRef, children }) });
1680
+ }
1681
+ var FIELD_BORDER = {
1682
+ idle: "border-(--color-border)",
1683
+ focused: "border-(--color-foreground)/40",
1684
+ error: "border-(--color-destructive)"
1685
+ };
1686
+ var FIELD_HEIGHT = {
1687
+ sm: "h-8",
1688
+ md: "h-9",
1689
+ lg: "h-11"
1690
+ };
1691
+ var FIELD_SHAPE = {
1692
+ rounded: "rounded-lg",
1693
+ pill: "rounded-full"
1694
+ };
1695
+ var INPUT_SIZE = {
1696
+ sm: "text-xs",
1697
+ md: "text-sm",
1698
+ lg: "text-base"
1699
+ };
1700
+ var INPUT_PAD = {
1701
+ sm: "px-2.5",
1702
+ md: "px-3",
1703
+ lg: "px-3.5"
1704
+ };
1705
+ function Input({
1706
+ label,
1707
+ error,
1708
+ hint,
1709
+ leftAdornment,
1710
+ rightAdornment,
1711
+ size = "md",
1712
+ shape = "rounded",
1713
+ className,
1714
+ inputClassName,
1715
+ inputType = "text",
1716
+ id: idProp,
1717
+ onFocus,
1718
+ onBlur,
1719
+ disabled,
1720
+ autoFocus,
1721
+ ...inputProps
1722
+ }) {
1723
+ const autoId = useId();
1724
+ const id = idProp ?? autoId;
1725
+ const [focused, setFocused] = useState(false);
1726
+ const hasError = Boolean(error);
1727
+ const errorMessage = typeof error === "string" ? error : null;
1728
+ const state = hasError ? "error" : focused ? "focused" : "idle";
1729
+ const hasLeft = Boolean(leftAdornment);
1730
+ const hasRight = Boolean(rightAdornment);
1731
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
1732
+ label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "px-1 font-medium text-(--color-foreground) text-sm", children: label }) : null,
1733
+ /* @__PURE__ */ jsxs(
1734
+ "div",
1735
+ {
1736
+ className: cn(
1737
+ "relative flex flex-row items-center overflow-hidden border",
1738
+ FIELD_BORDER[state],
1739
+ FIELD_HEIGHT[size],
1740
+ FIELD_SHAPE[shape],
1741
+ disabled && "opacity-60"
1742
+ ),
1743
+ children: [
1744
+ hasLeft ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute top-0 bottom-0 left-3 z-10 flex items-center justify-center", children: leftAdornment }) : null,
1745
+ /* @__PURE__ */ jsx(
1746
+ "input",
1747
+ {
1748
+ id,
1749
+ type: inputType,
1750
+ disabled,
1751
+ autoFocus,
1752
+ onFocus: (event_) => {
1753
+ setFocused(true);
1754
+ onFocus?.(event_);
1755
+ },
1756
+ onBlur: (event_) => {
1757
+ setFocused(false);
1758
+ onBlur?.(event_);
1759
+ },
1760
+ className: cn(
1761
+ "h-full min-w-0 flex-1 bg-transparent text-(--color-foreground) outline-none",
1762
+ INPUT_SIZE[size],
1763
+ hasLeft ? "pl-10" : INPUT_PAD[size],
1764
+ hasRight ? "pr-10" : INPUT_PAD[size],
1765
+ inputClassName
1766
+ ),
1767
+ ...inputProps
1768
+ }
1769
+ ),
1770
+ hasRight ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute top-0 right-3 bottom-0 z-10 flex items-center justify-center", children: rightAdornment }) : null
1771
+ ]
1772
+ }
1773
+ ),
1774
+ errorMessage ? /* @__PURE__ */ jsx("p", { role: "alert", className: "px-1 text-(--color-destructive) text-xs", children: errorMessage }) : hint ? /* @__PURE__ */ jsx("p", { className: "px-1 text-(--color-muted-foreground) text-xs", children: hint }) : null
1775
+ ] });
1776
+ }
1777
+ function LiquidMetal({
1778
+ colorBack = "#aaaaac",
1779
+ colorTint = "#ffffff",
1780
+ speed = 0.5,
1781
+ repetition = 4,
1782
+ distortion = 0.1,
1783
+ scale = 1,
1784
+ className,
1785
+ style
1786
+ }) {
1787
+ return /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-0 z-0 overflow-hidden", className), style, children: /* @__PURE__ */ jsx(
1788
+ LiquidMetal$1,
1789
+ {
1790
+ colorBack,
1791
+ colorTint,
1792
+ speed,
1793
+ repetition,
1794
+ distortion,
1795
+ softness: 0,
1796
+ shiftRed: 0.3,
1797
+ shiftBlue: -0.3,
1798
+ angle: 45,
1799
+ shape: "none",
1800
+ scale,
1801
+ fit: "cover",
1802
+ style: { width: "100%", height: "100%" }
1803
+ }
1804
+ ) });
1805
+ }
1806
+ function ChevronDownIcon2(props) {
1807
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M1 3.5L5 7.5L9 3.5", stroke: "currentColor", strokeWidth: "1.5" }) });
1808
+ }
1809
+ function ChevronRightIcon(props) {
1810
+ return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M3.5 1L7.5 5L3.5 9", stroke: "currentColor", strokeWidth: "1.5" }) });
1811
+ }
1812
+ function ArrowSvg(props) {
1813
+ return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", width: "20", height: "10", viewBox: "0 0 20 10", fill: "none", ...props, children: [
1814
+ /* @__PURE__ */ jsx(
1815
+ "path",
1816
+ {
1817
+ d: "M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z",
1818
+ className: "fill-(--popup-surface,var(--surface-3))"
1819
+ }
1820
+ ),
1821
+ /* @__PURE__ */ jsx(
1822
+ "path",
1823
+ {
1824
+ d: "M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z",
1825
+ className: "fill-border"
1826
+ }
1827
+ ),
1828
+ /* @__PURE__ */ jsx(
1829
+ "path",
1830
+ {
1831
+ d: "M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z",
1832
+ className: "fill-border"
1833
+ }
1834
+ )
1835
+ ] });
1836
+ }
1837
+ var navigationMenuTriggerStyle = cva(
1838
+ "box-border flex items-center justify-center gap-1.5 h-10 px-2.5 xs:px-3 m-0 rounded-md text-foreground font-medium !text-[15px] leading-6 select-none no-underline hover:text-foreground data-[popup-open]:bg-black/[0.07] dark:data-[popup-open]:bg-white/[0.07] data-[popup-open]:text-foreground focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-ring focus-visible:relative"
1839
+ );
1840
+ var navigationMenuSubTriggerStyle = cva(
1841
+ "w-full text-left relative block rounded-md p-2.5 xs:p-3 no-underline text-inherit hover:bg-black/[0.07] dark:hover:bg-white/[0.07] hover:text-foreground active:bg-black/[0.11] dark:active:bg-white/[0.11] focus-visible:relative focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-ring data-[popup-open]:bg-black/[0.07] dark:data-[popup-open]:bg-white/[0.07] data-[popup-open]:text-foreground"
1842
+ );
1843
+ function NavigationMenu({
1844
+ className,
1845
+ children,
1846
+ side,
1847
+ sideOffset = 10,
1848
+ align,
1849
+ alignOffset,
1850
+ collisionPadding = { top: 5, bottom: 5, left: 20, right: 20 },
1851
+ collisionBoundary,
1852
+ arrow = false,
1853
+ positionMethod = "fixed",
1854
+ level = 2,
1855
+ shadowLevel = 2,
1856
+ ...props
1857
+ }) {
1858
+ return /* @__PURE__ */ jsxs(
1859
+ NavigationMenu$1.Root,
1860
+ {
1861
+ "data-slot": "navigation-menu",
1862
+ "data-level": level,
1863
+ className: cn("min-w-max rounded-md p-1 text-foreground", solidSurface(level, shadowLevel), className),
1864
+ ...props,
1865
+ children: [
1866
+ children,
1867
+ /* @__PURE__ */ jsx(
1868
+ NavigationMenuViewport,
1869
+ {
1870
+ side,
1871
+ sideOffset,
1872
+ align,
1873
+ alignOffset,
1874
+ collisionPadding,
1875
+ collisionBoundary,
1876
+ arrow,
1877
+ positionMethod
1878
+ }
1879
+ )
1880
+ ]
1881
+ }
1882
+ );
1883
+ }
1884
+ function NavigationMenuList({ className, ...props }) {
1885
+ return /* @__PURE__ */ jsx(NavigationMenu$1.List, { "data-slot": "navigation-menu-list", className: cn("relative flex", className), ...props });
1886
+ }
1887
+ function NavigationMenuItem({ className, ...props }) {
1888
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Item, { "data-slot": "navigation-menu-item", className: cn("relative", className), ...props });
1889
+ }
1890
+ function NavigationMenuTrigger({ className, children, ...props }) {
1891
+ return /* @__PURE__ */ jsxs(
1892
+ NavigationMenu$1.Trigger,
1893
+ {
1894
+ "data-slot": "navigation-menu-trigger",
1895
+ className: cn(navigationMenuTriggerStyle(), className),
1896
+ ...props,
1897
+ children: [
1898
+ children,
1899
+ /* @__PURE__ */ jsx(NavigationMenuIcon, {})
1900
+ ]
1901
+ }
1902
+ );
1903
+ }
1904
+ function NavigationMenuIcon({
1905
+ className,
1906
+ render = /* @__PURE__ */ jsx(ChevronDownIcon2, {}),
1907
+ ...props
1908
+ }) {
1909
+ return /* @__PURE__ */ jsx(
1910
+ NavigationMenu$1.Icon,
1911
+ {
1912
+ className: cn("transition-transform duration-200 ease-in-out data-[popup-open]:rotate-180", className),
1913
+ render,
1914
+ ...props
1915
+ }
1916
+ );
1917
+ }
1918
+ function NavigationMenuSubTrigger({
1919
+ className,
1920
+ children,
1921
+ ...props
1922
+ }) {
1923
+ return /* @__PURE__ */ jsxs(
1924
+ NavigationMenu$1.Trigger,
1925
+ {
1926
+ "data-slot": "navigation-menu-sub-trigger",
1927
+ className: cn(navigationMenuSubTriggerStyle(), className),
1928
+ ...props,
1929
+ children: [
1930
+ children,
1931
+ /* @__PURE__ */ jsx(
1932
+ NavigationMenu$1.Icon,
1933
+ {
1934
+ className: "absolute top-1/2 right-2.5 flex h-2.5 w-2.5 -translate-y-1/2 items-center justify-center transition-transform duration-200 ease-in-out data-[popup-open]:rotate-180",
1935
+ render: /* @__PURE__ */ jsx(ChevronRightIcon, {})
1936
+ }
1937
+ )
1938
+ ]
1939
+ }
1940
+ );
1941
+ }
1942
+ function NavigationMenuContent({ className, ...props }) {
1943
+ return /* @__PURE__ */ jsx(
1944
+ NavigationMenu$1.Content,
1945
+ {
1946
+ "data-slot": "navigation-menu-content",
1947
+ className: cn(
1948
+ "h-full w-[calc(100vw-2.5rem)] p-4 sm:w-max",
1949
+ // Transitions for opacity/transform/filter
1950
+ "transition-[opacity,transform,filter,scale,translate] duration-(--duration) ease-(--easing)",
1951
+ // Starting/ending opacity
1952
+ "data-ending-style:opacity-0 data-starting-style:opacity-0",
1953
+ // Direction-aware slide (starting)
1954
+ "data-starting-style:data-[activation-direction=left]:-translate-x-1/2",
1955
+ "data-starting-style:data-[activation-direction=right]:translate-x-1/2",
1956
+ // Direction-aware slide (ending)
1957
+ "data-ending-style:data-[activation-direction=left]:translate-x-1/2",
1958
+ "data-ending-style:data-[activation-direction=right]:-translate-x-1/2",
1959
+ // Blur effect during transitions
1960
+ "data-ending-style:blur-[4px] data-starting-style:blur-[4px]",
1961
+ // scale effect during transitions
1962
+ "data-ending-style:scale-97 data-starting-style:scale-97",
1963
+ // Motion reduce support
1964
+ "motion-reduce:transition-none",
1965
+ className
1966
+ ),
1967
+ ...props
1968
+ }
1969
+ );
1970
+ }
1971
+ function NavigationMenuLink({ className, standalone, ...props }) {
1972
+ return /* @__PURE__ */ jsx(
1973
+ NavigationMenu$1.Link,
1974
+ {
1975
+ "data-slot": "navigation-menu-link",
1976
+ className: cn(
1977
+ standalone ? navigationMenuTriggerStyle() : "block rounded-md p-2.5 xs:p-3 text-inherit no-underline duration-150 hover:text-foreground hover:duration-0 focus-visible:relative focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-1",
1978
+ className
1979
+ ),
1980
+ ...props
1981
+ }
1982
+ );
1983
+ }
1984
+ function NavigationMenuBackdrop({ ...props }) {
1985
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Backdrop, { "data-slot": "navigation-menu-backdrop", ...props });
1986
+ }
1987
+ function NavigationMenuPortal({ ...props }) {
1988
+ return /* @__PURE__ */ jsx(NavigationMenu$1.Portal, { "data-slot": "navigation-menu-portal", ...props });
1989
+ }
1990
+ function NavigationMenuArrow({ ...props }) {
1991
+ return /* @__PURE__ */ jsx(
1992
+ NavigationMenu$1.Arrow,
1993
+ {
1994
+ className: "flex transition-[left] duration-[var(--duration)] ease-[var(--easing)] data-[side=bottom]:top-[-8px] data-[side=left]:right-[-13px] data-[side=top]:bottom-[-8px] data-[side=right]:left-[-13px] data-[side=left]:rotate-90 data-[side=right]:-rotate-90 data-[side=top]:rotate-180",
1995
+ ...props,
1996
+ children: /* @__PURE__ */ jsx(ArrowSvg, {})
1997
+ }
1998
+ );
1999
+ }
2000
+ function NavigationMenuViewport({
2001
+ className,
2002
+ children,
2003
+ side,
2004
+ sideOffset,
2005
+ align,
2006
+ alignOffset,
2007
+ collisionPadding,
2008
+ collisionBoundary,
2009
+ arrow = false,
2010
+ positionMethod = "fixed",
2011
+ ...props
2012
+ }) {
2013
+ return /* @__PURE__ */ jsx(NavigationMenuPortal, { children: /* @__PURE__ */ jsx(
2014
+ NavigationMenu$1.Positioner,
2015
+ {
2016
+ "data-slot": "navigation-menu-positioner",
2017
+ side,
2018
+ sideOffset,
2019
+ align,
2020
+ alignOffset,
2021
+ collisionPadding,
2022
+ collisionBoundary,
2023
+ positionMethod,
2024
+ className: "z-50 box-border h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-(--duration) ease-(--easing) before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:-top-2.5 data-[side=left]:before:top-0 data-[side=right]:before:top-0 data-[side=bottom]:before:right-0 data-[side=left]:before:-right-2.5 data-[side=top]:before:right-0 data-[side=left]:before:bottom-0 data-[side=right]:before:bottom-0 data-[side=top]:before:-bottom-2.5 data-[side=bottom]:before:left-0 data-[side=right]:before:-left-2.5 data-[side=top]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=top]:before:h-2.5 data-[side=left]:before:w-2.5 data-[side=right]:before:w-2.5",
2025
+ style: validCssVars({ "--duration": "0.35s", "--easing": "cubic-bezier(0.22, 1, 0.36, 1)" }),
2026
+ children: /* @__PURE__ */ jsxs(
2027
+ NavigationMenu$1.Popup,
2028
+ {
2029
+ "data-slot": "navigation-menu-content",
2030
+ className: cn(
2031
+ "relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) overflow-hidden rounded-md text-foreground transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:duration-150",
2032
+ solidSurface(3, 3)
2033
+ ),
2034
+ children: [
2035
+ arrow ? /* @__PURE__ */ jsx(NavigationMenuArrow, {}) : null,
2036
+ /* @__PURE__ */ jsx(
2037
+ NavigationMenu$1.Viewport,
2038
+ {
2039
+ "data-slot": "navigation-menu-viewport",
2040
+ className: cn("relative h-full w-full overflow-hidden", className),
2041
+ ...props,
2042
+ children
2043
+ }
2044
+ )
2045
+ ]
2046
+ }
2047
+ )
2048
+ }
2049
+ ) });
2050
+ }
2051
+ function NavigationMenuSub({
2052
+ className,
2053
+ children,
2054
+ orientation = "vertical",
2055
+ side = "right",
2056
+ sideOffset = 24,
2057
+ align = "end",
2058
+ alignOffset = -24,
2059
+ arrow = false,
2060
+ ...props
2061
+ }) {
2062
+ return /* @__PURE__ */ jsxs(
2063
+ NavigationMenu$1.Root,
2064
+ {
2065
+ "data-slot": "navigation-menu-sub",
2066
+ className: cn("", className),
2067
+ orientation,
2068
+ ...props,
2069
+ children: [
2070
+ children,
2071
+ /* @__PURE__ */ jsx(NavigationMenuPortal, { children: /* @__PURE__ */ jsx(
2072
+ NavigationMenu$1.Positioner,
2073
+ {
2074
+ "data-slot": "navigation-menu-sub-positioner",
2075
+ sideOffset,
2076
+ alignOffset,
2077
+ align,
2078
+ side,
2079
+ className: "box-border h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-(--duration) ease-(--easing) before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:-top-2.5 data-[side=left]:before:top-0 data-[side=right]:before:top-0 data-[side=bottom]:before:right-0 data-[side=left]:before:-right-2.5 data-[side=top]:before:right-0 data-[side=left]:before:bottom-0 data-[side=right]:before:bottom-0 data-[side=top]:before:-bottom-2.5 data-[side=bottom]:before:left-0 data-[side=right]:before:-left-2.5 data-[side=top]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=top]:before:h-2.5 data-[side=left]:before:w-2.5 data-[side=right]:before:w-2.5",
2080
+ style: validCssVars({ "--duration": "0.35s", "--easing": "cubic-bezier(0.22, 1, 0.36, 1)" }),
2081
+ children: /* @__PURE__ */ jsxs(
2082
+ NavigationMenu$1.Popup,
2083
+ {
2084
+ "data-slot": "navigation-menu-sub-content",
2085
+ className: cn(
2086
+ "relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) overflow-hidden rounded-md text-foreground transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:duration-150",
2087
+ solidSurface(5, 5)
2088
+ ),
2089
+ children: [
2090
+ arrow ? /* @__PURE__ */ jsx(NavigationMenuArrow, {}) : null,
2091
+ /* @__PURE__ */ jsx(
2092
+ NavigationMenu$1.Viewport,
2093
+ {
2094
+ "data-slot": "navigation-menu-sub-viewport",
2095
+ className: "relative h-full w-full overflow-hidden"
2096
+ }
2097
+ )
2098
+ ]
2099
+ }
2100
+ )
2101
+ }
2102
+ ) })
2103
+ ]
2104
+ }
2105
+ );
2106
+ }
2107
+ function PasswordInput({ inputType = "password", ...props }) {
2108
+ const [visible, setVisible] = useState(false);
2109
+ const toggle = useCallback(() => setVisible((v) => !v), []);
2110
+ const eye = /* @__PURE__ */ jsx(
2111
+ "button",
2112
+ {
2113
+ type: "button",
2114
+ onClick: toggle,
2115
+ className: "pointer-events-auto cursor-pointer text-(--color-muted-foreground) hover:text-(--color-foreground)",
2116
+ "aria-label": visible ? "Hide password" : "Show password",
2117
+ tabIndex: -1,
2118
+ children: visible ? /* @__PURE__ */ jsx(EyeOffIcon, { className: "size-5" }) : /* @__PURE__ */ jsx(EyeIcon, { className: "size-5" })
2119
+ }
2120
+ );
2121
+ return /* @__PURE__ */ jsx(
2122
+ Input,
2123
+ {
2124
+ ...props,
2125
+ inputType: visible ? "text" : "password",
2126
+ rightAdornment: eye,
2127
+ autoComplete: inputType === "new-password" ? "new-password" : "current-password"
2128
+ }
2129
+ );
2130
+ }
2131
+ function EyeIcon(props) {
2132
+ return /* @__PURE__ */ jsxs(
2133
+ "svg",
2134
+ {
2135
+ "aria-hidden": "true",
2136
+ viewBox: "0 0 24 24",
2137
+ fill: "none",
2138
+ stroke: "currentColor",
2139
+ strokeWidth: "2",
2140
+ strokeLinecap: "round",
2141
+ strokeLinejoin: "round",
2142
+ ...props,
2143
+ children: [
2144
+ /* @__PURE__ */ jsx("path", { d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" }),
2145
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
2146
+ ]
2147
+ }
2148
+ );
2149
+ }
2150
+ function EyeOffIcon(props) {
2151
+ return /* @__PURE__ */ jsxs(
2152
+ "svg",
2153
+ {
2154
+ "aria-hidden": "true",
2155
+ viewBox: "0 0 24 24",
2156
+ fill: "none",
2157
+ stroke: "currentColor",
2158
+ strokeWidth: "2",
2159
+ strokeLinecap: "round",
2160
+ strokeLinejoin: "round",
2161
+ ...props,
2162
+ children: [
2163
+ /* @__PURE__ */ jsx("path", { d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }),
2164
+ /* @__PURE__ */ jsx("path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }),
2165
+ /* @__PURE__ */ jsx("path", { d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }),
2166
+ /* @__PURE__ */ jsx("path", { d: "m2 2 20 20" })
2167
+ ]
2168
+ }
2169
+ );
2170
+ }
2171
+ var rainbowButtonVariants = cva(
2172
+ cn(
2173
+ "relative cursor-pointer group transition-transform animate-rainbow",
2174
+ "inline-flex items-center justify-center gap-2 shrink-0",
2175
+ "rounded-sm outline-none focus-visible:ring-[3px] aria-invalid:border-destructive",
2176
+ "text-sm font-medium whitespace-nowrap",
2177
+ "disabled:pointer-events-none disabled:opacity-50",
2178
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0"
2179
+ ),
2180
+ {
2181
+ variants: {
2182
+ variant: {
2183
+ default: "border-0 bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))]",
2184
+ outline: "border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))]"
2185
+ },
2186
+ size: {
2187
+ default: "h-9 px-4 py-2",
2188
+ sm: "h-8 rounded-md px-3 text-xs",
2189
+ lg: "h-11 rounded-md px-8",
2190
+ icon: "size-9"
2191
+ }
2192
+ },
2193
+ defaultVariants: {
2194
+ variant: "default",
2195
+ size: "default"
2196
+ }
2197
+ }
2198
+ );
2199
+ function RainbowButton({ className, variant, size, asChild = false, ref, ...props }) {
2200
+ const Comp = asChild ? Slot : "button";
2201
+ return /* @__PURE__ */ jsx(Comp, { "data-slot": "button", className: cn(rainbowButtonVariants({ variant, size, className })), ref, ...props });
2202
+ }
2203
+ RainbowButton.displayName = "RainbowButton";
2204
+ function nearestIndex(steps, value) {
2205
+ return steps.reduce((best, s, i) => Math.abs(s - value) < Math.abs(steps[best] - value) ? i : best, 0);
2206
+ }
2207
+ function RangeSlider({ label, value, steps, ticks, valueLabel, onChange }) {
2208
+ const min = steps[0];
2209
+ const max = steps.at(-1) ?? min;
2210
+ const pct = (value - min) / (max - min) * 100;
2211
+ const index = nearestIndex(steps, value);
2212
+ const handleChange = useCallback(
2213
+ (event_) => onChange(steps[Number(event_.target.value)]),
2214
+ [onChange, steps]
2215
+ );
2216
+ return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
2217
+ /* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-baseline justify-between gap-2", children: [
2218
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-[15px] text-(--color-foreground)", children: label }),
2219
+ /* @__PURE__ */ jsx("p", { className: "font-bold font-numeric text-[20px] text-(--color-foreground) tabular-nums", children: valueLabel })
2220
+ ] }),
2221
+ /* @__PURE__ */ jsxs("div", { className: "relative", style: { height: 20 }, children: [
2222
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-1/2 h-1.5 -translate-y-1/2 rounded-full bg-(--color-border)" }),
2223
+ /* @__PURE__ */ jsx(
2224
+ "div",
2225
+ {
2226
+ className: "pointer-events-none absolute top-1/2 left-0 h-1.5 -translate-y-1/2 rounded-full bg-(--color-foreground)",
2227
+ style: { width: `${pct}%` }
2228
+ }
2229
+ ),
2230
+ /* @__PURE__ */ jsx(
2231
+ "input",
2232
+ {
2233
+ type: "range",
2234
+ min: 0,
2235
+ max: steps.length - 1,
2236
+ step: 1,
2237
+ value: index,
2238
+ onChange: handleChange,
2239
+ className: "peer absolute inset-0 z-10 h-full w-full cursor-pointer opacity-0",
2240
+ "aria-label": label,
2241
+ "aria-valuetext": valueLabel
2242
+ }
2243
+ ),
2244
+ /* @__PURE__ */ jsx(
2245
+ "div",
2246
+ {
2247
+ className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-(--color-foreground) peer-focus-visible:outline-2 peer-focus-visible:outline-(--color-foreground) peer-focus-visible:outline-offset-2",
2248
+ style: {
2249
+ left: `${pct}%`,
2250
+ width: 16,
2251
+ height: 16,
2252
+ boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
2253
+ }
2254
+ }
2255
+ )
2256
+ ] }),
2257
+ /* @__PURE__ */ jsx("div", { className: "relative mt-2", style: { height: 16 }, children: ticks.map((tick2, i) => {
2258
+ const tp = (tick2.value - min) / (max - min) * 100;
2259
+ const isFirst = i === 0;
2260
+ const isLast = i === ticks.length - 1;
2261
+ let left = `${tp}%`;
2262
+ if (isFirst) left = 0;
2263
+ else if (isLast) left = void 0;
2264
+ return /* @__PURE__ */ jsx(
2265
+ "span",
2266
+ {
2267
+ className: "absolute font-numeric text-(--color-muted-foreground) text-[11px] tabular-nums",
2268
+ style: {
2269
+ left,
2270
+ right: isLast ? 0 : void 0,
2271
+ transform: isFirst || isLast ? void 0 : "translateX(-50%)"
2272
+ },
2273
+ children: tick2.label
2274
+ },
2275
+ tick2.value
2276
+ );
2277
+ }) })
2278
+ ] });
2279
+ }
2280
+ var tick = 0;
2281
+ var listeners = /* @__PURE__ */ new Set();
2282
+ var timer = null;
2283
+ function subscribe(onChange) {
2284
+ listeners.add(onChange);
2285
+ if (timer === null)
2286
+ timer = setInterval(() => {
2287
+ tick += 1;
2288
+ for (const l of listeners) l();
2289
+ }, ROTATE_MS);
2290
+ return () => {
2291
+ listeners.delete(onChange);
2292
+ if (listeners.size === 0 && timer !== null) {
2293
+ clearInterval(timer);
2294
+ timer = null;
2295
+ }
2296
+ };
2297
+ }
2298
+ var getSnapshot = () => tick;
2299
+ var getServerSnapshot = () => 0;
2300
+ var ROTATE_MS = 4e3;
2301
+ function RollingBadge({ badges, className }) {
2302
+ const index = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) % badges.length;
2303
+ const badge = badges[index];
2304
+ if (badges.length === 0 || !badge) return null;
2305
+ return /* @__PURE__ */ jsx(
2306
+ motion.div,
2307
+ {
2308
+ layout: true,
2309
+ className: cn(
2310
+ "relative inline-flex h-8 items-center overflow-hidden rounded-full border border-(--color-border) bg-background px-3.5 shadow-sm",
2311
+ className
2312
+ ),
2313
+ children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "popLayout", children: /* @__PURE__ */ jsxs(
2314
+ motion.span,
2315
+ {
2316
+ layout: "position",
2317
+ initial: { y: "120%", opacity: 0 },
2318
+ animate: { y: "0%", opacity: 1 },
2319
+ exit: { y: "-120%", opacity: 0 },
2320
+ transition: {
2321
+ type: "spring",
2322
+ stiffness: 320,
2323
+ damping: 32
2324
+ },
2325
+ className: "flex items-center gap-1.5 whitespace-nowrap font-medium text-[12.5px]",
2326
+ children: [
2327
+ /* @__PURE__ */ jsx("span", { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true, children: badge.icon }),
2328
+ badge.label
2329
+ ]
2330
+ },
2331
+ index
2332
+ ) })
2333
+ }
2334
+ );
2335
+ }
2336
+ function SavingsBadge({ className, ...props }) {
2337
+ return /* @__PURE__ */ jsx(
2338
+ "span",
2339
+ {
2340
+ className: cn(
2341
+ "rounded-full bg-emerald-500/15 px-2.5 py-0.5 font-numeric font-semibold text-[11px] text-emerald-500 tabular-nums",
2342
+ className
2343
+ ),
2344
+ ...props
2345
+ }
2346
+ );
2347
+ }
2348
+ function ShineBorder({
2349
+ borderWidth = 1,
2350
+ duration = 14,
2351
+ shineColor = "#000000",
2352
+ className,
2353
+ style,
2354
+ ...props
2355
+ }) {
2356
+ return /* @__PURE__ */ jsx(
2357
+ "div",
2358
+ {
2359
+ style: validCssVars({
2360
+ "--border-width": `${borderWidth}px`,
2361
+ "--duration": `${duration}s`,
2362
+ backgroundImage: `radial-gradient(transparent,transparent, ${Array.isArray(shineColor) ? shineColor.join(",") : shineColor},transparent,transparent)`,
2363
+ backgroundSize: "300% 300%",
2364
+ mask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
2365
+ WebkitMask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
2366
+ WebkitMaskComposite: "xor",
2367
+ maskComposite: "exclude",
2368
+ padding: "var(--border-width)",
2369
+ ...style
2370
+ }),
2371
+ className: cn(
2372
+ "pointer-events-none absolute inset-0 size-full rounded-[inherit] will-change-[background-position] motion-safe:animate-shine",
2373
+ className
2374
+ ),
2375
+ ...props
2376
+ }
2377
+ );
2378
+ }
2379
+ var STAR_PATH = "M9.82531 0.843845C10.0553 0.215178 10.9446 0.215178 11.1746 0.843845L11.8618 2.72026C12.4006 4.19229 12.3916 6.39157 13.5 7.5C14.6084 8.60843 16.8077 8.59935 18.2797 9.13822L20.1561 9.82534C20.7858 10.0553 20.7858 10.9447 20.1561 11.1747L18.2797 11.8618C16.8077 12.4007 14.6084 12.3916 13.5 13.5C12.3916 14.6084 12.4006 16.8077 11.8618 18.2798L11.1746 20.1562C10.9446 20.7858 10.0553 20.7858 9.82531 20.1562L9.13819 18.2798C8.59932 16.8077 8.60843 14.6084 7.5 13.5C6.39157 12.3916 4.19225 12.4007 2.72023 11.8618L0.843814 11.1747C0.215148 10.9447 0.215148 10.0553 0.843814 9.82534L2.72023 9.13822C4.19225 8.59935 6.39157 8.60843 7.5 7.5C8.60843 6.39157 8.59932 4.19229 9.13819 2.72026L9.82531 0.843845Z";
2380
+ var DEFAULT_COLORS2 = {
2381
+ first: "var(--color-accent-brand)",
2382
+ second: "var(--color-accent-brand-soft)"
2383
+ };
2384
+ function SparkleStar({ x, y, color, delay, scale }) {
2385
+ return /* @__PURE__ */ jsx(
2386
+ motion.svg,
2387
+ {
2388
+ className: "pointer-events-none absolute z-20",
2389
+ initial: { opacity: 0, left: x, top: y },
2390
+ animate: {
2391
+ opacity: [0, 1, 0],
2392
+ scale: [0, scale, 0],
2393
+ rotate: [75, 120, 150]
2394
+ },
2395
+ transition: {
2396
+ duration: 0.8,
2397
+ repeat: Number.POSITIVE_INFINITY,
2398
+ delay
2399
+ },
2400
+ width: "21",
2401
+ height: "21",
2402
+ viewBox: "0 0 21 21",
2403
+ "aria-hidden": true,
2404
+ children: /* @__PURE__ */ jsx("path", { d: STAR_PATH, fill: color })
2405
+ }
2406
+ );
2407
+ }
2408
+ function SparklesText({ children, className, sparklesCount = 10, colors = DEFAULT_COLORS2 }) {
2409
+ const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
2410
+ const [sparkles, setSparkles] = useState([]);
2411
+ const { first, second } = colors;
2412
+ useEffect(() => {
2413
+ if (reducedMotion) {
2414
+ setSparkles([]);
2415
+ return;
2416
+ }
2417
+ const spawn = () => ({
2418
+ x: `${Math.random() * 100}%`,
2419
+ y: `${Math.random() * 100}%`,
2420
+ color: Math.random() > 0.5 ? first : second,
2421
+ delay: Math.random() * 2,
2422
+ scale: Math.random() + 0.3,
2423
+ expiresAt: performance.now() + (Math.random() * 10 + 5) * 1e3
2424
+ });
2425
+ setSparkles(Array.from({ length: sparklesCount }, spawn));
2426
+ const interval = setInterval(() => {
2427
+ setSparkles((current) => {
2428
+ const now = performance.now();
2429
+ if (!current.some((sparkle) => sparkle.expiresAt <= now)) return current;
2430
+ return current.map((sparkle) => sparkle.expiresAt <= now ? spawn() : sparkle);
2431
+ });
2432
+ }, 500);
2433
+ return () => clearInterval(interval);
2434
+ }, [first, second, sparklesCount, reducedMotion]);
2435
+ return /* @__PURE__ */ jsxs("span", { className: cn("relative inline-block", className), children: [
2436
+ sparkles.map((sparkle) => /* @__PURE__ */ jsx(SparkleStar, { ...sparkle }, `${sparkle.x}-${sparkle.y}-${sparkle.expiresAt}`)),
2437
+ children
2438
+ ] });
2439
+ }
2440
+ var PULL = 0.035;
2441
+ function pillTarget(activeIdx, hoverIdx, rects, pull) {
2442
+ const active = rects[activeIdx];
2443
+ if (!active) throw new Error(`No rect at index ${activeIdx}`);
2444
+ if (hoverIdx === null || hoverIdx === activeIdx) return active;
2445
+ const hover = rects[hoverIdx];
2446
+ if (!hover) return active;
2447
+ const activeRight = active.left + active.width;
2448
+ const hoverRight = hover.left + hover.width;
2449
+ const left = Math.min(active.left, active.left + (hover.left - active.left) * pull);
2450
+ const right = Math.max(activeRight, activeRight + (hoverRight - activeRight) * pull);
2451
+ return { left, width: right - left };
2452
+ }
2453
+ var labelBox = "flex items-center gap-2.5 px-5 py-1.5 font-semibold text-[13px]";
2454
+ var badgeBox = "font-bold text-(--color-accent-brand-soft) text-[11px] whitespace-nowrap";
2455
+ function Tabs({ tabs, value, onChange, label, className }) {
2456
+ const reduced = useReducedMotion();
2457
+ const pull = reduced ? 0 : PULL;
2458
+ const trackRef = useRef(null);
2459
+ const [rects, setRects] = useState([]);
2460
+ const [trackWidth, setTrackWidth] = useState(0);
2461
+ const [hovered, setHovered] = useState(null);
2462
+ const [ready, setReady] = useState(false);
2463
+ const foundIdx = tabs.findIndex((t) => t.id === value);
2464
+ const activeIdx = foundIdx === -1 ? 0 : foundIdx;
2465
+ const springConfig = reduced ? { stiffness: 700, damping: 60 } : { stiffness: 420, damping: 34, mass: 0.7 };
2466
+ const pillLeft = useSpring(0, springConfig);
2467
+ const pillWidth = useSpring(0, springConfig);
2468
+ const innerX = useTransform(pillLeft, (v) => -v);
2469
+ const measure = useCallback(() => {
2470
+ const track = trackRef.current;
2471
+ if (!track) return;
2472
+ setTrackWidth(track.offsetWidth);
2473
+ const btns = track.querySelectorAll("button[data-index]");
2474
+ setRects(
2475
+ Array.from(btns, (el) => ({
2476
+ left: el.offsetLeft,
2477
+ width: el.offsetWidth
2478
+ }))
2479
+ );
2480
+ }, []);
2481
+ useEffect(() => {
2482
+ measure();
2483
+ const track = trackRef.current;
2484
+ if (!track) return;
2485
+ const ro = new ResizeObserver(measure);
2486
+ ro.observe(track);
2487
+ return () => ro.disconnect();
2488
+ }, [measure]);
2489
+ useEffect(() => {
2490
+ if (rects.length !== tabs.length) return;
2491
+ const target = pillTarget(activeIdx, hovered, rects, pull);
2492
+ if (ready) {
2493
+ pillLeft.set(target.left);
2494
+ pillWidth.set(target.width);
2495
+ } else {
2496
+ pillLeft.jump(target.left);
2497
+ pillWidth.jump(target.width);
2498
+ setReady(true);
2499
+ }
2500
+ }, [rects, tabs.length, activeIdx, hovered, pull, ready, pillLeft, pillWidth]);
2501
+ const handleClick = useCallback(
2502
+ (e) => onChange(tabs[Number(e.currentTarget.dataset.index)].id),
2503
+ [onChange, tabs]
2504
+ );
2505
+ const handleEnter = useCallback((e) => setHovered(Number(e.currentTarget.dataset.index)), []);
2506
+ const handleLeave = useCallback(() => setHovered(null), []);
2507
+ return /* @__PURE__ */ jsx(
2508
+ "fieldset",
2509
+ {
2510
+ "aria-label": label,
2511
+ className: cn("inline-flex items-center rounded-full border border-(--color-border) bg-(--color-surface) p-1", className),
2512
+ children: /* @__PURE__ */ jsxs("div", { ref: trackRef, className: "relative inline-flex items-center", children: [
2513
+ tabs.map((tab, i) => /* @__PURE__ */ jsxs(
2514
+ "button",
2515
+ {
2516
+ type: "button",
2517
+ "data-index": i,
2518
+ onClick: handleClick,
2519
+ onMouseEnter: handleEnter,
2520
+ onMouseLeave: handleLeave,
2521
+ "aria-pressed": value === tab.id,
2522
+ className: cn(labelBox, "text-(--color-muted-foreground) hover:text-(--color-foreground)"),
2523
+ children: [
2524
+ tab.label,
2525
+ tab.badge ? /* @__PURE__ */ jsx("span", { className: badgeBox, children: tab.badge }) : null
2526
+ ]
2527
+ },
2528
+ tab.id
2529
+ )),
2530
+ /* @__PURE__ */ jsx(
2531
+ motion.div,
2532
+ {
2533
+ "aria-hidden": true,
2534
+ className: "pointer-events-none absolute inset-y-0 select-none overflow-hidden rounded-full bg-(--color-foreground)",
2535
+ style: { left: pillLeft, width: pillWidth, opacity: ready ? 1 : 0 },
2536
+ children: /* @__PURE__ */ jsx(motion.div, { className: "absolute inset-y-0 left-0 flex items-center", style: { width: trackWidth, x: innerX }, children: tabs.map((tab) => /* @__PURE__ */ jsxs("span", { className: cn(labelBox, "text-(--color-surface)"), children: [
2537
+ tab.label,
2538
+ tab.badge ? /* @__PURE__ */ jsx("span", { className: badgeBox, children: tab.badge }) : null
2539
+ ] }, tab.id)) })
2540
+ }
2541
+ )
2542
+ ] })
2543
+ }
2544
+ );
2545
+ }
2546
+ var ICON_LAYOUT = "w-8 p-0";
2547
+ var LABELED_LAYOUT = "gap-2 px-3 text-[13px]";
2548
+ function SunIcon() {
2549
+ return /* @__PURE__ */ jsxs(
2550
+ "svg",
2551
+ {
2552
+ width: 14,
2553
+ height: 14,
2554
+ viewBox: "0 0 24 24",
2555
+ fill: "none",
2556
+ stroke: "currentColor",
2557
+ strokeWidth: 2,
2558
+ strokeLinecap: "round",
2559
+ strokeLinejoin: "round",
2560
+ "aria-hidden": true,
2561
+ children: [
2562
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
2563
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "1" }),
2564
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "23", x2: "12", y2: "21" }),
2565
+ /* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "1", y2: "12" }),
2566
+ /* @__PURE__ */ jsx("line", { x1: "23", y1: "12", x2: "21", y2: "12" }),
2567
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "5", x2: "3.5", y2: "3.5" }),
2568
+ /* @__PURE__ */ jsx("line", { x1: "20.5", y1: "20.5", x2: "19", y2: "19" }),
2569
+ /* @__PURE__ */ jsx("line", { x1: "19", y1: "5", x2: "20.5", y2: "3.5" }),
2570
+ /* @__PURE__ */ jsx("line", { x1: "4.5", y1: "20.5", x2: "3", y2: "19" })
2571
+ ]
2572
+ }
2573
+ );
2574
+ }
2575
+ function MoonIcon() {
2576
+ return /* @__PURE__ */ jsx(
2577
+ "svg",
2578
+ {
2579
+ width: 14,
2580
+ height: 14,
2581
+ viewBox: "0 0 24 24",
2582
+ fill: "none",
2583
+ stroke: "currentColor",
2584
+ strokeWidth: 2,
2585
+ strokeLinecap: "round",
2586
+ strokeLinejoin: "round",
2587
+ "aria-hidden": true,
2588
+ children: /* @__PURE__ */ jsx("path", { d: "M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8z" })
2589
+ }
2590
+ );
2591
+ }
2592
+ function ThemeToggle({ theme, onToggle, showLabel = false }) {
2593
+ const size = showLabel ? "md" : "sm";
2594
+ const layoutClassName = showLabel ? LABELED_LAYOUT : ICON_LAYOUT;
2595
+ const isDark = theme === "dark";
2596
+ const label = isDark ? "Switch to light mode" : "Switch to dark mode";
2597
+ return /* @__PURE__ */ jsxs(
2598
+ Button,
2599
+ {
2600
+ variant: "filled",
2601
+ size,
2602
+ actionOrLink: onToggle,
2603
+ className: layoutClassName,
2604
+ "aria-label": label,
2605
+ children: [
2606
+ /* @__PURE__ */ jsx(ActionSwapRollIcon, { value: theme, className: "h-4 w-4", children: isDark ? /* @__PURE__ */ jsx(SunIcon, {}) : /* @__PURE__ */ jsx(MoonIcon, {}) }),
2607
+ showLabel ? /* @__PURE__ */ jsx(ActionSwapRollText, { value: theme, children: label }) : null
2608
+ ]
2609
+ }
2610
+ );
2611
+ }
2612
+ var BREAKPOINTS2 = [
2613
+ ["xs", 30],
2614
+ ["sm", 40],
2615
+ ["md", 50],
2616
+ ["lg", 64],
2617
+ ["xl", 80],
2618
+ ["2xl", 96]
2619
+ ];
2620
+ function getBreakpoint2() {
2621
+ let current = "base";
2622
+ for (const [name, rem] of BREAKPOINTS2) {
2623
+ if (globalThis.matchMedia(`(min-width: ${rem}rem)`).matches) current = name;
2624
+ }
2625
+ return current;
2626
+ }
2627
+ function onBreakpointChange2(listener) {
2628
+ const queries = BREAKPOINTS2.map(([, rem]) => globalThis.matchMedia(`(min-width: ${rem}rem)`));
2629
+ for (const query of queries) query.addEventListener("change", listener);
2630
+ return () => {
2631
+ for (const query of queries) query.removeEventListener("change", listener);
2632
+ };
2633
+ }
2634
+ function getBreakpointServer() {
2635
+ return "base";
2636
+ }
2637
+ function useBreakpoint() {
2638
+ const subscribe2 = useCallback(onBreakpointChange2, []);
2639
+ return useSyncExternalStore(subscribe2, getBreakpoint2, getBreakpointServer);
2640
+ }
2641
+
2642
+ export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, ActionSwapRollIcon, ActionSwapRollText, AnimatedBeam, ArrowLeft, ArrowRight, ArrowSvg, BREAKPOINTS2 as BREAKPOINTS, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChevronDownIcon2 as ChevronDownIcon, ChevronRightIcon, DiaTextReveal, EASE_OUT, EASE_OUT_CSS, ElevatedInput, FadeIn, FeatureCard, FlowDiamond, FlowNode, FlowPill, GlossyButton, grainient_default as Grainient, Highlighter, Input, JoinArrow, LiquidMetal, NavigationMenu, NavigationMenuArrow, NavigationMenuBackdrop, NavigationMenuContent, NavigationMenuIcon, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuPortal, NavigationMenuSub, NavigationMenuSubTrigger, NavigationMenuTrigger, NavigationMenuViewport, PasswordInput, RainbowButton, RangeSlider, RollingBadge, SPRING_SWAP, SavingsBadge, ShineBorder, SparklesText, SplitArrow, Stagger, StaggerItem, Tabs, ThemeToggle, TurnDown, cn, easeOut, easeOutBack, getBreakpoint2 as getBreakpoint, glossyButtonVariants, hasKey, navigationMenuSubTriggerStyle, navigationMenuTriggerStyle, noop, onBreakpointChange2 as onBreakpointChange, rainbowButtonVariants, solidSurface, useBreakpoint, validCssVars };
33
2643
  //# sourceMappingURL=index.mjs.map
34
2644
  //# sourceMappingURL=index.mjs.map