react-marketing-ui 0.0.3 → 0.0.5

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 (188) 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/footer-glow.d.cts +2 -0
  38. package/dist/footer-glow.d.ts +2 -0
  39. package/dist/footer-glow.d.ts.map +1 -0
  40. package/dist/footer-glow.js +110 -0
  41. package/dist/footer-glow.js.map +1 -0
  42. package/dist/footer-glow.mjs +108 -0
  43. package/dist/footer-glow.mjs.map +1 -0
  44. package/dist/glossy-button.js +1 -1
  45. package/dist/glossy-button.js.map +1 -1
  46. package/dist/glossy-button.mjs +82 -2
  47. package/dist/glossy-button.mjs.map +1 -1
  48. package/dist/grainient.js +1 -0
  49. package/dist/grainient.mjs +327 -2
  50. package/dist/grainient.mjs.map +1 -1
  51. package/dist/highlighter.js +1 -0
  52. package/dist/highlighter.mjs +122 -3
  53. package/dist/highlighter.mjs.map +1 -1
  54. package/dist/index.d.cts +1 -0
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +101 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/index.mjs +2741 -32
  60. package/dist/index.mjs.map +1 -1
  61. package/dist/input.js +1 -0
  62. package/dist/input.mjs +107 -2
  63. package/dist/input.mjs.map +1 -1
  64. package/dist/lib/breakpoints.js +1 -1
  65. package/dist/lib/breakpoints.js.map +1 -1
  66. package/dist/lib/breakpoints.mjs +34 -1
  67. package/dist/lib/breakpoints.mjs.map +1 -1
  68. package/dist/lib/cn.js +1 -1
  69. package/dist/lib/cn.js.map +1 -1
  70. package/dist/lib/cn.mjs +17 -1
  71. package/dist/lib/cn.mjs.map +1 -1
  72. package/dist/lib/ease.js +1 -0
  73. package/dist/lib/ease.mjs +9 -1
  74. package/dist/lib/ease.mjs.map +1 -1
  75. package/dist/lib/surface.js +1 -0
  76. package/dist/lib/surface.mjs +37 -1
  77. package/dist/lib/surface.mjs.map +1 -1
  78. package/dist/lib/use-media-query.js +1 -0
  79. package/dist/lib/use-media-query.mjs +16 -1
  80. package/dist/lib/use-media-query.mjs.map +1 -1
  81. package/dist/liquid-metal.js +1 -0
  82. package/dist/liquid-metal.mjs +40 -2
  83. package/dist/liquid-metal.mjs.map +1 -1
  84. package/dist/navigation-menu-icons.js +1 -1
  85. package/dist/navigation-menu-icons.js.map +1 -1
  86. package/dist/navigation-menu-icons.mjs +36 -1
  87. package/dist/navigation-menu-icons.mjs.map +1 -1
  88. package/dist/navigation-menu-styles.js +1 -1
  89. package/dist/navigation-menu-styles.js.map +1 -1
  90. package/dist/navigation-menu-styles.mjs +11 -1
  91. package/dist/navigation-menu-styles.mjs.map +1 -1
  92. package/dist/navigation-menu.js +1 -2
  93. package/dist/navigation-menu.js.map +1 -1
  94. package/dist/navigation-menu.mjs +350 -5
  95. package/dist/navigation-menu.mjs.map +1 -1
  96. package/dist/password-input.js +1 -0
  97. package/dist/password-input.mjs +171 -3
  98. package/dist/password-input.mjs.map +1 -1
  99. package/dist/rainbow-button.js +1 -0
  100. package/dist/rainbow-button.mjs +45 -2
  101. package/dist/rainbow-button.mjs.map +1 -1
  102. package/dist/range-slider.js +1 -0
  103. package/dist/range-slider.mjs +82 -1
  104. package/dist/range-slider.mjs.map +1 -1
  105. package/dist/rolling-badge.js +1 -0
  106. package/dist/rolling-badge.mjs +68 -2
  107. package/dist/rolling-badge.mjs.map +1 -1
  108. package/dist/savings-badge.js +1 -1
  109. package/dist/savings-badge.js.map +1 -1
  110. package/dist/savings-badge.mjs +22 -2
  111. package/dist/savings-badge.mjs.map +1 -1
  112. package/dist/shine-border.js +1 -0
  113. package/dist/shine-border.mjs +44 -2
  114. package/dist/shine-border.mjs.map +1 -1
  115. package/dist/sparkles-text.js +1 -0
  116. package/dist/sparkles-text.mjs +84 -3
  117. package/dist/sparkles-text.mjs.map +1 -1
  118. package/dist/tabs.js +1 -0
  119. package/dist/tabs.mjs +118 -2
  120. package/dist/tabs.mjs.map +1 -1
  121. package/dist/theme-toggle.js +1 -0
  122. package/dist/theme-toggle.mjs +248 -5
  123. package/dist/theme-toggle.mjs.map +1 -1
  124. package/package.json +12 -2
  125. package/dist/chunk-3SB6HUBA.mjs +0 -31
  126. package/dist/chunk-3SB6HUBA.mjs.map +0 -1
  127. package/dist/chunk-4PBVBXGY.mjs +0 -84
  128. package/dist/chunk-4PBVBXGY.mjs.map +0 -1
  129. package/dist/chunk-4VCFWVSJ.mjs +0 -42
  130. package/dist/chunk-4VCFWVSJ.mjs.map +0 -1
  131. package/dist/chunk-5QQAPGR2.mjs +0 -109
  132. package/dist/chunk-5QQAPGR2.mjs.map +0 -1
  133. package/dist/chunk-6MB4UKRX.mjs +0 -19
  134. package/dist/chunk-6MB4UKRX.mjs.map +0 -1
  135. package/dist/chunk-6T5LR34O.mjs +0 -45
  136. package/dist/chunk-6T5LR34O.mjs.map +0 -1
  137. package/dist/chunk-AYLCYDUM.mjs +0 -275
  138. package/dist/chunk-AYLCYDUM.mjs.map +0 -1
  139. package/dist/chunk-AYY7D2RJ.mjs +0 -112
  140. package/dist/chunk-AYY7D2RJ.mjs.map +0 -1
  141. package/dist/chunk-CTZEI2YS.mjs +0 -324
  142. package/dist/chunk-CTZEI2YS.mjs.map +0 -1
  143. package/dist/chunk-DA3I3Y5O.mjs +0 -71
  144. package/dist/chunk-DA3I3Y5O.mjs.map +0 -1
  145. package/dist/chunk-EYHT2EWJ.mjs +0 -18
  146. package/dist/chunk-EYHT2EWJ.mjs.map +0 -1
  147. package/dist/chunk-IHLGCS63.mjs +0 -36
  148. package/dist/chunk-IHLGCS63.mjs.map +0 -1
  149. package/dist/chunk-JVXJ6SFX.mjs +0 -38
  150. package/dist/chunk-JVXJ6SFX.mjs.map +0 -1
  151. package/dist/chunk-KBHYXLRG.mjs +0 -13
  152. package/dist/chunk-KBHYXLRG.mjs.map +0 -1
  153. package/dist/chunk-KMXUQYR3.mjs +0 -74
  154. package/dist/chunk-KMXUQYR3.mjs.map +0 -1
  155. package/dist/chunk-KNPOZ34H.mjs +0 -88
  156. package/dist/chunk-KNPOZ34H.mjs.map +0 -1
  157. package/dist/chunk-KRNWCJ4D.mjs +0 -219
  158. package/dist/chunk-KRNWCJ4D.mjs.map +0 -1
  159. package/dist/chunk-M5MESV26.mjs +0 -124
  160. package/dist/chunk-M5MESV26.mjs.map +0 -1
  161. package/dist/chunk-MJYBPJBA.mjs +0 -115
  162. package/dist/chunk-MJYBPJBA.mjs.map +0 -1
  163. package/dist/chunk-NNHPQ67J.mjs +0 -10
  164. package/dist/chunk-NNHPQ67J.mjs.map +0 -1
  165. package/dist/chunk-OCZFHVVD.mjs +0 -71
  166. package/dist/chunk-OCZFHVVD.mjs.map +0 -1
  167. package/dist/chunk-QAWSH567.mjs +0 -19
  168. package/dist/chunk-QAWSH567.mjs.map +0 -1
  169. package/dist/chunk-R2E2J42H.mjs +0 -38
  170. package/dist/chunk-R2E2J42H.mjs.map +0 -1
  171. package/dist/chunk-TPGLLSYV.mjs +0 -65
  172. package/dist/chunk-TPGLLSYV.mjs.map +0 -1
  173. package/dist/chunk-VJENJHXJ.mjs +0 -72
  174. package/dist/chunk-VJENJHXJ.mjs.map +0 -1
  175. package/dist/chunk-W22G7XHR.mjs +0 -104
  176. package/dist/chunk-W22G7XHR.mjs.map +0 -1
  177. package/dist/chunk-WDR5VPZJ.mjs +0 -79
  178. package/dist/chunk-WDR5VPZJ.mjs.map +0 -1
  179. package/dist/chunk-WLUGKBH7.mjs +0 -37
  180. package/dist/chunk-WLUGKBH7.mjs.map +0 -1
  181. package/dist/chunk-WYJYLDUA.mjs +0 -84
  182. package/dist/chunk-WYJYLDUA.mjs.map +0 -1
  183. package/dist/chunk-XZEDZVXT.mjs +0 -38
  184. package/dist/chunk-XZEDZVXT.mjs.map +0 -1
  185. package/dist/chunk-YKGP5JIL.mjs +0 -328
  186. package/dist/chunk-YKGP5JIL.mjs.map +0 -1
  187. package/dist/chunk-YM3U2OBE.mjs +0 -99
  188. package/dist/chunk-YM3U2OBE.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/feature-card.tsx"],"names":["twMerge","clsx","jsxs","jsx"],"mappings":";;;;;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACkBO,SAAS,YAAY,EAAE,IAAA,EAAM,OAAO,IAAA,EAAM,SAAA,EAAW,WAAU,EAAqB;AACzF,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,6HAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sHAAA,EACb,QAAA,kBAAAA,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA,CAAG,wDAAA,EAA0D,SAAA,IAAa,+BAA+B,CAAA;AAAA,YAEnH,QAAA,EAAA;AAAA;AAAA,SACH,EACF,CAAA;AAAA,wBACAD,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,wDAAA,EAA0D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BAC9EA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sEAAA,EAAwE,QAAA,EAAA,IAAA,EAAK;AAAA,SAAA,EAC5F;AAAA;AAAA;AAAA,GACF;AAEJ","file":"feature-card.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\nimport { cn } from '../lib/utils.js';\n\nexport type FeatureCardProps = {\n /** Icon rendered in the elevated top-left box. Pass any ReactNode (e.g. an\n * inlined SVG or an iconify <Icon icon={...} />). */\n icon: ReactNode;\n title: string;\n body: string;\n /** Icon colour class, e.g. `text-violet-500`. Defaults to the secondary foreground tone. */\n iconColor?: string;\n /** Extra classes merged onto the card root. */\n className?: string;\n};\n\n/**\n * Shared marketing feature card: a soft-filled panel with an elevated icon box\n * above a title + body. Used across the /security, /syncing, /web-access pages\n * and future copy pages.\n *\n * Geometry mirrors the design-system reference (p-6 → lg:p-8 → xl:p-10, icon box\n * size-10 → lg:size-12); the design tokens are mapped onto this library's own\n * variables so both themes stay in sync.\n */\nexport function FeatureCard({ icon, title, body, iconColor, className }: FeatureCardProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <div className=\"flex size-10 items-center justify-center rounded-[10px] bg-(--surface) shadow-(--shadow-sm) lg:size-12 lg:rounded-md\">\n <span\n className={cn('flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6', iconColor ?? 'text-(--foreground-secondary)')}\n >\n {icon}\n </span>\n </div>\n <div className=\"flex flex-col gap-2\">\n <h3 className=\"font-semibold text-[15px] text-foreground lg:text-base\">{title}</h3>\n <p className=\"text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm\">{body}</p>\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/feature-card.tsx"],"names":["twMerge","clsx","jsxs","jsx"],"mappings":";;;;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACkBO,SAAS,YAAY,EAAE,IAAA,EAAM,OAAO,IAAA,EAAM,SAAA,EAAW,WAAU,EAAqB;AACzF,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,6HAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sHAAA,EACb,QAAA,kBAAAA,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA,CAAG,wDAAA,EAA0D,SAAA,IAAa,+BAA+B,CAAA;AAAA,YAEnH,QAAA,EAAA;AAAA;AAAA,SACH,EACF,CAAA;AAAA,wBACAD,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,wDAAA,EAA0D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BAC9EA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sEAAA,EAAwE,QAAA,EAAA,IAAA,EAAK;AAAA,SAAA,EAC5F;AAAA;AAAA;AAAA,GACF;AAEJ","file":"feature-card.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\nimport { cn } from '../lib/utils.js';\n\nexport type FeatureCardProps = {\n /** Icon rendered in the elevated top-left box. Pass any ReactNode (e.g. an\n * inlined SVG or an iconify <Icon icon={...} />). */\n icon: ReactNode;\n title: string;\n body: string;\n /** Icon colour class, e.g. `text-violet-500`. Defaults to the secondary foreground tone. */\n iconColor?: string;\n /** Extra classes merged onto the card root. */\n className?: string;\n};\n\n/**\n * Shared marketing feature card: a soft-filled panel with an elevated icon box\n * above a title + body. Used across the /security, /syncing, /web-access pages\n * and future copy pages.\n *\n * Geometry mirrors the design-system reference (p-6 → lg:p-8 → xl:p-10, icon box\n * size-10 → lg:size-12); the design tokens are mapped onto this library's own\n * variables so both themes stay in sync.\n */\nexport function FeatureCard({ icon, title, body, iconColor, className }: FeatureCardProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <div className=\"flex size-10 items-center justify-center rounded-[10px] bg-(--surface) shadow-(--shadow-sm) lg:size-12 lg:rounded-md\">\n <span\n className={cn('flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6', iconColor ?? 'text-(--foreground-secondary)')}\n >\n {icon}\n </span>\n </div>\n <div className=\"flex flex-col gap-2\">\n <h3 className=\"font-semibold text-[15px] text-foreground lg:text-base\">{title}</h3>\n <p className=\"text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm\">{body}</p>\n </div>\n </div>\n );\n}\n"]}
@@ -1,4 +1,36 @@
1
- export { FeatureCard } from './chunk-3SB6HUBA.mjs';
2
- import './chunk-QAWSH567.mjs';
1
+ "use client";
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+ function FeatureCard({ icon, title, body, iconColor, className }) {
10
+ return /* @__PURE__ */ jsxs(
11
+ "div",
12
+ {
13
+ className: cn(
14
+ "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",
15
+ className
16
+ ),
17
+ children: [
18
+ /* @__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(
19
+ "span",
20
+ {
21
+ className: cn("flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6", iconColor ?? "text-(--foreground-secondary)"),
22
+ children: icon
23
+ }
24
+ ) }),
25
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
26
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-[15px] text-foreground lg:text-base", children: title }),
27
+ /* @__PURE__ */ jsx("p", { className: "text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm", children: body })
28
+ ] })
29
+ ]
30
+ }
31
+ );
32
+ }
33
+
34
+ export { FeatureCard };
3
35
  //# sourceMappingURL=feature-card.mjs.map
4
36
  //# sourceMappingURL=feature-card.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"feature-card.mjs"}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/feature-card.tsx"],"names":[],"mappings":";;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACkBO,SAAS,YAAY,EAAE,IAAA,EAAM,OAAO,IAAA,EAAM,SAAA,EAAW,WAAU,EAAqB;AACzF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,6HAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sHAAA,EACb,QAAA,kBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA,CAAG,wDAAA,EAA0D,SAAA,IAAa,+BAA+B,CAAA;AAAA,YAEnH,QAAA,EAAA;AAAA;AAAA,SACH,EACF,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,wDAAA,EAA0D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BAC9E,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sEAAA,EAAwE,QAAA,EAAA,IAAA,EAAK;AAAA,SAAA,EAC5F;AAAA;AAAA;AAAA,GACF;AAEJ","file":"feature-card.mjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\nimport { cn } from '../lib/utils.js';\n\nexport type FeatureCardProps = {\n /** Icon rendered in the elevated top-left box. Pass any ReactNode (e.g. an\n * inlined SVG or an iconify <Icon icon={...} />). */\n icon: ReactNode;\n title: string;\n body: string;\n /** Icon colour class, e.g. `text-violet-500`. Defaults to the secondary foreground tone. */\n iconColor?: string;\n /** Extra classes merged onto the card root. */\n className?: string;\n};\n\n/**\n * Shared marketing feature card: a soft-filled panel with an elevated icon box\n * above a title + body. Used across the /security, /syncing, /web-access pages\n * and future copy pages.\n *\n * Geometry mirrors the design-system reference (p-6 → lg:p-8 → xl:p-10, icon box\n * size-10 → lg:size-12); the design tokens are mapped onto this library's own\n * variables so both themes stay in sync.\n */\nexport function FeatureCard({ icon, title, body, iconColor, className }: FeatureCardProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <div className=\"flex size-10 items-center justify-center rounded-[10px] bg-(--surface) shadow-(--shadow-sm) lg:size-12 lg:rounded-md\">\n <span\n className={cn('flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6', iconColor ?? 'text-(--foreground-secondary)')}\n >\n {icon}\n </span>\n </div>\n <div className=\"flex flex-col gap-2\">\n <h3 className=\"font-semibold text-[15px] text-foreground lg:text-base\">{title}</h3>\n <p className=\"text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm\">{body}</p>\n </div>\n </div>\n );\n}\n"]}
@@ -1,10 +1,10 @@
1
+ "use client";
1
2
  'use strict';
2
3
 
3
4
  var clsx = require('clsx');
4
5
  var tailwindMerge = require('tailwind-merge');
5
6
  var jsxRuntime = require('react/jsx-runtime');
6
7
 
7
- // src/lib/utils.ts
8
8
  function cn(...inputs) {
9
9
  return tailwindMerge.twMerge(clsx.clsx(inputs));
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/flowchart-parts.tsx"],"names":["twMerge","clsx","jsx","jsxs"],"mappings":";;;;;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACCA,IAAM,gBAAA,GACJ,6HAAA;AAEF,IAAM,iBAAA,GACJ,0HAAA;AAEF,IAAM,gBAAA,GACJ,2HAAA;AAGF,IAAM,eAAA,GACJ,kNAAA;AAOK,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,SAAA,EAAU,EAAoB;AAChE,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EACxD,QAAA,EAAA;AAAA,oBAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qCAAA,EAAsC,CAAA;AAAA,oBACtDA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,iBAAA,EAAmB,CAAA;AAAA,IACnC,wBAAQA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,eAAA,EAAkB,iBAAM,CAAA,GAAU;AAAA,GAAA,EAC9D,CAAA;AAEJ;AAKO,SAAS,SAAA,CAAU,EAAE,KAAA,EAAO,SAAA,EAAU,EAAmB;AAC9D,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EACxD,QAAA,EAAA;AAAA,oBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qCAAA,EAAsC,CAAA;AAAA,oBACtDA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,gBAAA,EAAkB,CAAA;AAAA,IAClC,wBAAQA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,eAAA,EAAkB,iBAAM,CAAA,GAAU;AAAA,GAAA,EAC9D,CAAA;AAEJ;AAKO,SAAS,QAAA,CAAS,EAAE,SAAA,EAAU,EAAkB;AACrD,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,cAAA,EAAgB,SAAS,CAAA,EAC1C,QAAA,EAAA;AAAA,oBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,8EAAA,EAA+E,CAAA;AAAA,oBAC/FA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,gBAAA,EAAkB;AAAA,GAAA,EACrC,CAAA;AAEJ;AAKO,SAAS,UAAA,CAAW,EAAE,SAAA,EAAW,UAAA,EAAY,WAAU,EAAoB;AAChF,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA,EAC3C,QAAA,EAAA;AAAA,oBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,6EAAA,EAA8E,CAAA;AAAA,oBAC9FA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uFAAA,EAAwF,CAAA;AAAA,oBACxGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iFAAA,EAAkF,CAAA;AAAA,oBAClGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iFAAA,EAAkF,CAAA;AAAA,oBAClGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+HAAA,EAAgI,CAAA;AAAA,oBAChJA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+HAAA,EAAgI,CAAA;AAAA,IAC/I,4BACCA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iKAAA,EACb,qBACH,CAAA,GACE,IAAA;AAAA,IACH,6BACCA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kKAAA,EACb,sBACH,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AAKO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAU,EAAmB;AACvD,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA,EAC3C,QAAA,EAAA;AAAA,oBAAAA,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uFAAA,EAAwF,CAAA;AAAA,oBACxGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChGA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6HAAA,EAA8H;AAAA,GAAA,EAChJ,CAAA;AAEJ;AAkBO,SAAS,QAAA,CAAS,EAAE,IAAA,EAAM,SAAA,EAAW,OAAO,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,SAAA,EAAU,EAAkB;AAClG,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,mFAAA,EAAqF,SAAS,CAAA,EAC/G,QAAA,EAAA;AAAA,oBAAAC,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,IAAA,mBACCD,cAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,kEAAkE,SAAA,IAAa,cAAc,CAAA,EAC7G,QAAA,EAAA,IAAA,EACH,CAAA,GACE,IAAA;AAAA,sBACJC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iDAAA,EACb,QAAA,EAAA;AAAA,0BAAAD,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uEAAA,EAAyE,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UAC3F,sBACCA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qGAAA,EACb,eACH,CAAA,GACE;AAAA,SAAA,EACN,CAAA;AAAA,QACC,uBAAOA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,+EAAA,EAAiF,gBAAK,CAAA,GAAO;AAAA,OAAA,EACpH;AAAA,KAAA,EACF,CAAA;AAAA,IACC,2BAAWA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAQ,UAAS,CAAA,GAAS;AAAA,GAAA,EACvD,CAAA;AAEJ;AAKO,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,SAAA,EAAU,EAAkB;AAC5D,EAAA,uBACEA,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,sIAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,kBAAAA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wDAAA,EAA0D,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA,GAC/E;AAEJ;AAKO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,GAAA,EAAK,WAAU,EAAqB;AACvE,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,wDAAA,EAA0D,SAAS,CAAA,EACpF,QAAA,EAAA;AAAA,oBAAAA,cAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sFAAA,EAAuF,CAAA;AAAA,oBACtGC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2JAAA,EACb,QAAA,EAAA;AAAA,sBAAAD,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wEAAA,EAA0E,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MAC5F,sBAAMA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sDAAA,EAAwD,eAAI,CAAA,GAAO;AAAA,KAAA,EACzF;AAAA,GAAA,EACF,CAAA;AAEJ","file":"flowchart-parts.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../lib/utils.js';\n\n// ── Non-exported helpers ──────────────────────────────────────────────────────\n\n/** Downward chevron (rotated square, two borders) placed at the end of a line. */\nconst downChevronClass =\n '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)';\n\nconst rightChevronClass =\n '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)';\n\nconst leftChevronClass =\n '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)';\n\n/** Micro label chip that masks the line it sits on. */\nconst microLabelClass =\n '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)';\n\n// ── Exports ───────────────────────────────────────────────────────────────────\n\ntype ArrowRightProps = { label?: string; className?: string };\n\n/** Horizontal connector (left → right) between two snake cells. */\nexport function ArrowRight({ label, className }: ArrowRightProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={rightChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype ArrowLeftProps = { label?: string; className?: string };\n\n/** Horizontal connector (right → left) between two snake cells. */\nexport function ArrowLeft({ label, className }: ArrowLeftProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={leftChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype TurnDownProps = { className?: string };\n\n/** Short vertical connector used when the snake drops to the next row. */\nexport function TurnDown({ className }: TurnDownProps) {\n return (\n <div className={cn('relative h-4', className)}>\n <span className=\"absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className={downChevronClass} />\n </div>\n );\n}\n\ntype SplitArrowProps = { leftLabel?: string; rightLabel?: string; className?: string };\n\n/** One-to-two branch connector: spine down, horizontal arm, drops at 25% / 75%. */\nexport function SplitArrow({ leftLabel, rightLabel, className }: SplitArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n <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)\" />\n {leftLabel ? (\n <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)\">\n {leftLabel}\n </span>\n ) : null}\n {rightLabel ? (\n <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)\">\n {rightLabel}\n </span>\n ) : null}\n </div>\n );\n}\n\ntype JoinArrowProps = { className?: string };\n\n/** Two-to-one join connector: risers at 25% / 75%, horizontal arm, spine down. */\nexport function JoinArrow({ className }: JoinArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n </div>\n );\n}\n\ntype FlowNodeProps = {\n icon?: ReactNode;\n /**\n * Accepted for API compatibility with the site's icon-based version; the icon is now a\n * caller-supplied ReactNode that carries its own sizing/color classes, so this is unused.\n */\n iconClass?: string;\n chipClass?: string;\n title: string;\n body?: string;\n tag?: string;\n children?: ReactNode;\n className?: string;\n};\n\n/** A compact rounded node: icon chip, one-line title, one-line sub, optional children. */\nexport function FlowNode({ icon, chipClass, title, body, tag, children, className }: FlowNodeProps) {\n return (\n <div className={cn('flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5', className)}>\n <div className=\"flex items-start gap-2\">\n {icon ? (\n <div className={cn('flex size-7 shrink-0 items-center justify-center rounded-[8px]', chipClass ?? 'bg-(--muted)')}>\n {icon}\n </div>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-1.5 gap-y-0.5\">\n <p className=\"font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]\">{title}</p>\n {tag ? (\n <span className=\"rounded-full border border-(--border) px-1.5 py-px font-mono text-[8.5px] text-(--foreground-muted)\">\n {tag}\n </span>\n ) : null}\n </div>\n {body ? <p className=\"mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]\">{body}</p> : null}\n </div>\n </div>\n {children ? <div className=\"mt-2\">{children}</div> : null}\n </div>\n );\n}\n\ntype FlowPillProps = { title: string; className?: string };\n\n/** A start/end pill: centered, fits content, sits on the flowchart spine. */\nexport function FlowPill({ title, className }: FlowPillProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <p className=\"text-[12px] font-semibold leading-snug text-foreground\">{title}</p>\n </div>\n );\n}\n\ntype FlowDiamondProps = { label: string; sub?: string; className?: string };\n\n/** A compact decision diamond (clip-path, straight text inside). */\nexport function FlowDiamond({ label, sub, className }: FlowDiamondProps) {\n return (\n <div className={cn('relative h-14 w-36 justify-self-center sm:h-16 sm:w-44', className)}>\n <div className=\"absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]\" />\n <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%)]\">\n <p className=\"text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]\">{label}</p>\n {sub ? <p className=\"text-[8.5px] leading-tight text-(--foreground-muted)\">{sub}</p> : null}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/flowchart-parts.tsx"],"names":["twMerge","clsx","jsx","jsxs"],"mappings":"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","file":"flowchart-parts.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../lib/utils.js';\n\n// ── Non-exported helpers ──────────────────────────────────────────────────────\n\n/** Downward chevron (rotated square, two borders) placed at the end of a line. */\nconst downChevronClass =\n '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)';\n\nconst rightChevronClass =\n '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)';\n\nconst leftChevronClass =\n '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)';\n\n/** Micro label chip that masks the line it sits on. */\nconst microLabelClass =\n '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)';\n\n// ── Exports ───────────────────────────────────────────────────────────────────\n\ntype ArrowRightProps = { label?: string; className?: string };\n\n/** Horizontal connector (left → right) between two snake cells. */\nexport function ArrowRight({ label, className }: ArrowRightProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={rightChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype ArrowLeftProps = { label?: string; className?: string };\n\n/** Horizontal connector (right → left) between two snake cells. */\nexport function ArrowLeft({ label, className }: ArrowLeftProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={leftChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype TurnDownProps = { className?: string };\n\n/** Short vertical connector used when the snake drops to the next row. */\nexport function TurnDown({ className }: TurnDownProps) {\n return (\n <div className={cn('relative h-4', className)}>\n <span className=\"absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className={downChevronClass} />\n </div>\n );\n}\n\ntype SplitArrowProps = { leftLabel?: string; rightLabel?: string; className?: string };\n\n/** One-to-two branch connector: spine down, horizontal arm, drops at 25% / 75%. */\nexport function SplitArrow({ leftLabel, rightLabel, className }: SplitArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n <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)\" />\n {leftLabel ? (\n <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)\">\n {leftLabel}\n </span>\n ) : null}\n {rightLabel ? (\n <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)\">\n {rightLabel}\n </span>\n ) : null}\n </div>\n );\n}\n\ntype JoinArrowProps = { className?: string };\n\n/** Two-to-one join connector: risers at 25% / 75%, horizontal arm, spine down. */\nexport function JoinArrow({ className }: JoinArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n </div>\n );\n}\n\ntype FlowNodeProps = {\n icon?: ReactNode;\n /**\n * Accepted for API compatibility with the site's icon-based version; the icon is now a\n * caller-supplied ReactNode that carries its own sizing/color classes, so this is unused.\n */\n iconClass?: string;\n chipClass?: string;\n title: string;\n body?: string;\n tag?: string;\n children?: ReactNode;\n className?: string;\n};\n\n/** A compact rounded node: icon chip, one-line title, one-line sub, optional children. */\nexport function FlowNode({ icon, chipClass, title, body, tag, children, className }: FlowNodeProps) {\n return (\n <div className={cn('flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5', className)}>\n <div className=\"flex items-start gap-2\">\n {icon ? (\n <div className={cn('flex size-7 shrink-0 items-center justify-center rounded-[8px]', chipClass ?? 'bg-(--muted)')}>\n {icon}\n </div>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-1.5 gap-y-0.5\">\n <p className=\"font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]\">{title}</p>\n {tag ? (\n <span className=\"rounded-full border border-(--border) px-1.5 py-px font-mono text-[8.5px] text-(--foreground-muted)\">\n {tag}\n </span>\n ) : null}\n </div>\n {body ? <p className=\"mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]\">{body}</p> : null}\n </div>\n </div>\n {children ? <div className=\"mt-2\">{children}</div> : null}\n </div>\n );\n}\n\ntype FlowPillProps = { title: string; className?: string };\n\n/** A start/end pill: centered, fits content, sits on the flowchart spine. */\nexport function FlowPill({ title, className }: FlowPillProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <p className=\"text-[12px] font-semibold leading-snug text-foreground\">{title}</p>\n </div>\n );\n}\n\ntype FlowDiamondProps = { label: string; sub?: string; className?: string };\n\n/** A compact decision diamond (clip-path, straight text inside). */\nexport function FlowDiamond({ label, sub, className }: FlowDiamondProps) {\n return (\n <div className={cn('relative h-14 w-36 justify-self-center sm:h-16 sm:w-44', className)}>\n <div className=\"absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]\" />\n <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%)]\">\n <p className=\"text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]\">{label}</p>\n {sub ? <p className=\"text-[8.5px] leading-tight text-(--foreground-muted)\">{sub}</p> : null}\n </div>\n </div>\n );\n}\n"]}
@@ -1,4 +1,93 @@
1
- export { ArrowLeft, ArrowRight, FlowDiamond, FlowNode, FlowPill, JoinArrow, SplitArrow, TurnDown } from './chunk-KNPOZ34H.mjs';
2
- import './chunk-QAWSH567.mjs';
1
+ "use client";
2
+ import { clsx } from 'clsx';
3
+ import { twMerge } from 'tailwind-merge';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function cn(...inputs) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+ 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)";
10
+ 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)";
11
+ 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)";
12
+ 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)";
13
+ function ArrowRight({ label, className }) {
14
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
15
+ /* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
16
+ /* @__PURE__ */ jsx("span", { className: rightChevronClass }),
17
+ label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
18
+ ] });
19
+ }
20
+ function ArrowLeft({ label, className }) {
21
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
22
+ /* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
23
+ /* @__PURE__ */ jsx("span", { className: leftChevronClass }),
24
+ label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
25
+ ] });
26
+ }
27
+ function TurnDown({ className }) {
28
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-4", className), children: [
29
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)" }),
30
+ /* @__PURE__ */ jsx("span", { className: downChevronClass })
31
+ ] });
32
+ }
33
+ function SplitArrow({ leftLabel, rightLabel, className }) {
34
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
35
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
36
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
37
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
38
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
39
+ /* @__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)" }),
40
+ /* @__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)" }),
41
+ 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,
42
+ 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
43
+ ] });
44
+ }
45
+ function JoinArrow({ className }) {
46
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
47
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
48
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
49
+ /* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
50
+ /* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
51
+ /* @__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)" })
52
+ ] });
53
+ }
54
+ function FlowNode({ icon, chipClass, title, body, tag, children, className }) {
55
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5", className), children: [
56
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
57
+ icon ? /* @__PURE__ */ jsx("div", { className: cn("flex size-7 shrink-0 items-center justify-center rounded-[8px]", chipClass ?? "bg-(--muted)"), children: icon }) : null,
58
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
59
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-1.5 gap-y-0.5", children: [
60
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]", children: title }),
61
+ 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
62
+ ] }),
63
+ body ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]", children: body }) : null
64
+ ] })
65
+ ] }),
66
+ children ? /* @__PURE__ */ jsx("div", { className: "mt-2", children }) : null
67
+ ] });
68
+ }
69
+ function FlowPill({ title, className }) {
70
+ return /* @__PURE__ */ jsx(
71
+ "div",
72
+ {
73
+ className: cn(
74
+ "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",
75
+ className
76
+ ),
77
+ children: /* @__PURE__ */ jsx("p", { className: "text-[12px] font-semibold leading-snug text-foreground", children: title })
78
+ }
79
+ );
80
+ }
81
+ function FlowDiamond({ label, sub, className }) {
82
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative h-14 w-36 justify-self-center sm:h-16 sm:w-44", className), children: [
83
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]" }),
84
+ /* @__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: [
85
+ /* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]", children: label }),
86
+ sub ? /* @__PURE__ */ jsx("p", { className: "text-[8.5px] leading-tight text-(--foreground-muted)", children: sub }) : null
87
+ ] })
88
+ ] });
89
+ }
90
+
91
+ export { ArrowLeft, ArrowRight, FlowDiamond, FlowNode, FlowPill, JoinArrow, SplitArrow, TurnDown };
3
92
  //# sourceMappingURL=flowchart-parts.mjs.map
4
93
  //# sourceMappingURL=flowchart-parts.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"flowchart-parts.mjs"}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/flowchart-parts.tsx"],"names":[],"mappings":";;;;AAIO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACCA,IAAM,gBAAA,GACJ,6HAAA;AAEF,IAAM,iBAAA,GACJ,0HAAA;AAEF,IAAM,gBAAA,GACJ,2HAAA;AAGF,IAAM,eAAA,GACJ,kNAAA;AAOK,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,SAAA,EAAU,EAAoB;AAChE,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EACxD,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qCAAA,EAAsC,CAAA;AAAA,oBACtD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,iBAAA,EAAmB,CAAA;AAAA,IACnC,wBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,eAAA,EAAkB,iBAAM,CAAA,GAAU;AAAA,GAAA,EAC9D,CAAA;AAEJ;AAKO,SAAS,SAAA,CAAU,EAAE,KAAA,EAAO,SAAA,EAAU,EAAmB;AAC9D,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA,EACxD,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qCAAA,EAAsC,CAAA;AAAA,oBACtD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,gBAAA,EAAkB,CAAA;AAAA,IAClC,wBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,eAAA,EAAkB,iBAAM,CAAA,GAAU;AAAA,GAAA,EAC9D,CAAA;AAEJ;AAKO,SAAS,QAAA,CAAS,EAAE,SAAA,EAAU,EAAkB;AACrD,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,cAAA,EAAgB,SAAS,CAAA,EAC1C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,8EAAA,EAA+E,CAAA;AAAA,oBAC/F,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,gBAAA,EAAkB;AAAA,GAAA,EACrC,CAAA;AAEJ;AAKO,SAAS,UAAA,CAAW,EAAE,SAAA,EAAW,UAAA,EAAY,WAAU,EAAoB;AAChF,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA,EAC3C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,6EAAA,EAA8E,CAAA;AAAA,oBAC9F,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uFAAA,EAAwF,CAAA;AAAA,oBACxG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iFAAA,EAAkF,CAAA;AAAA,oBAClG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iFAAA,EAAkF,CAAA;AAAA,oBAClG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+HAAA,EAAgI,CAAA;AAAA,oBAChJ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+HAAA,EAAgI,CAAA;AAAA,IAC/I,4BACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iKAAA,EACb,qBACH,CAAA,GACE,IAAA;AAAA,IACH,6BACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kKAAA,EACb,sBACH,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AAKO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAU,EAAmB;AACvD,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,eAAA,EAAiB,SAAS,CAAA,EAC3C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uFAAA,EAAwF,CAAA;AAAA,oBACxG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+EAAA,EAAgF,CAAA;AAAA,oBAChG,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6HAAA,EAA8H;AAAA,GAAA,EAChJ,CAAA;AAEJ;AAkBO,SAAS,QAAA,CAAS,EAAE,IAAA,EAAM,SAAA,EAAW,OAAO,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,SAAA,EAAU,EAAkB;AAClG,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,mFAAA,EAAqF,SAAS,CAAA,EAC/G,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,IAAA,mBACC,GAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,kEAAkE,SAAA,IAAa,cAAc,CAAA,EAC7G,QAAA,EAAA,IAAA,EACH,CAAA,GACE,IAAA;AAAA,sBACJ,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iDAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uEAAA,EAAyE,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UAC3F,sBACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qGAAA,EACb,eACH,CAAA,GACE;AAAA,SAAA,EACN,CAAA;AAAA,QACC,uBAAO,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,+EAAA,EAAiF,gBAAK,CAAA,GAAO;AAAA,OAAA,EACpH;AAAA,KAAA,EACF,CAAA;AAAA,IACC,2BAAW,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EAAQ,UAAS,CAAA,GAAS;AAAA,GAAA,EACvD,CAAA;AAEJ;AAKO,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,SAAA,EAAU,EAAkB;AAC5D,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,sIAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wDAAA,EAA0D,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA,GAC/E;AAEJ;AAKO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,GAAA,EAAK,WAAU,EAAqB;AACvE,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,wDAAA,EAA0D,SAAS,CAAA,EACpF,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sFAAA,EAAuF,CAAA;AAAA,oBACtG,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2JAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wEAAA,EAA0E,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MAC5F,sBAAM,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sDAAA,EAAwD,eAAI,CAAA,GAAO;AAAA,KAAA,EACzF;AAAA,GAAA,EACF,CAAA;AAEJ","file":"flowchart-parts.mjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport type { CSSProperties } from 'react';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * A style object that may carry CSS custom properties (CSS variables)\n * such as `--duration`. React's `CSSProperties` intentionally drops\n * its index signature, so custom properties are not accepted without help.\n */\nexport type CSSPropertiesWithVars = CSSProperties & Record<`--${string}`, string | number>;\n\n/**\n * Builds a {@link CSSProperties} value that also allows CSS custom properties,\n * so `style` props can be written without an `as React.CSSProperties` cast while\n * still type-checking both the known style keys and the custom-property values.\n *\n * @example\n * <div style={validCssVars({ '--duration': '0.35s', color: 'red' })} />\n */\nexport function validCssVars(style: CSSPropertiesWithVars): CSSProperties {\n return style;\n}\n\n/**\n * Narrows a union to the member(s) that declare `key` — a type-guard\n * replacement for the `in` operator's discriminated-union narrowing.\n */\nexport function hasKey<K extends PropertyKey>(key: K, obj: unknown): obj is Record<K, unknown> {\n return obj !== null && typeof obj === 'object' && Object.hasOwn(obj, key);\n}\n\nexport function noop(): void {\n // intentional no-op\n}\n","import type { ReactNode } from 'react';\n\nimport { cn } from '../lib/utils.js';\n\n// ── Non-exported helpers ──────────────────────────────────────────────────────\n\n/** Downward chevron (rotated square, two borders) placed at the end of a line. */\nconst downChevronClass =\n '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)';\n\nconst rightChevronClass =\n '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)';\n\nconst leftChevronClass =\n '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)';\n\n/** Micro label chip that masks the line it sits on. */\nconst microLabelClass =\n '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)';\n\n// ── Exports ───────────────────────────────────────────────────────────────────\n\ntype ArrowRightProps = { label?: string; className?: string };\n\n/** Horizontal connector (left → right) between two snake cells. */\nexport function ArrowRight({ label, className }: ArrowRightProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={rightChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype ArrowLeftProps = { label?: string; className?: string };\n\n/** Horizontal connector (right → left) between two snake cells. */\nexport function ArrowLeft({ label, className }: ArrowLeftProps) {\n return (\n <div className={cn('relative flex items-center', className)}>\n <span className=\"h-px w-full bg-(--foreground-muted)\" />\n <span className={leftChevronClass} />\n {label ? <span className={microLabelClass}>{label}</span> : null}\n </div>\n );\n}\n\ntype TurnDownProps = { className?: string };\n\n/** Short vertical connector used when the snake drops to the next row. */\nexport function TurnDown({ className }: TurnDownProps) {\n return (\n <div className={cn('relative h-4', className)}>\n <span className=\"absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className={downChevronClass} />\n </div>\n );\n}\n\ntype SplitArrowProps = { leftLabel?: string; rightLabel?: string; className?: string };\n\n/** One-to-two branch connector: spine down, horizontal arm, drops at 25% / 75%. */\nexport function SplitArrow({ leftLabel, rightLabel, className }: SplitArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n <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)\" />\n {leftLabel ? (\n <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)\">\n {leftLabel}\n </span>\n ) : null}\n {rightLabel ? (\n <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)\">\n {rightLabel}\n </span>\n ) : null}\n </div>\n );\n}\n\ntype JoinArrowProps = { className?: string };\n\n/** Two-to-one join connector: risers at 25% / 75%, horizontal arm, spine down. */\nexport function JoinArrow({ className }: JoinArrowProps) {\n return (\n <div className={cn('relative h-12', className)}>\n <span className=\"absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)\" />\n <span className=\"absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)\" />\n <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)\" />\n </div>\n );\n}\n\ntype FlowNodeProps = {\n icon?: ReactNode;\n /**\n * Accepted for API compatibility with the site's icon-based version; the icon is now a\n * caller-supplied ReactNode that carries its own sizing/color classes, so this is unused.\n */\n iconClass?: string;\n chipClass?: string;\n title: string;\n body?: string;\n tag?: string;\n children?: ReactNode;\n className?: string;\n};\n\n/** A compact rounded node: icon chip, one-line title, one-line sub, optional children. */\nexport function FlowNode({ icon, chipClass, title, body, tag, children, className }: FlowNodeProps) {\n return (\n <div className={cn('flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5', className)}>\n <div className=\"flex items-start gap-2\">\n {icon ? (\n <div className={cn('flex size-7 shrink-0 items-center justify-center rounded-[8px]', chipClass ?? 'bg-(--muted)')}>\n {icon}\n </div>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-1.5 gap-y-0.5\">\n <p className=\"font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]\">{title}</p>\n {tag ? (\n <span className=\"rounded-full border border-(--border) px-1.5 py-px font-mono text-[8.5px] text-(--foreground-muted)\">\n {tag}\n </span>\n ) : null}\n </div>\n {body ? <p className=\"mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]\">{body}</p> : null}\n </div>\n </div>\n {children ? <div className=\"mt-2\">{children}</div> : null}\n </div>\n );\n}\n\ntype FlowPillProps = { title: string; className?: string };\n\n/** A start/end pill: centered, fits content, sits on the flowchart spine. */\nexport function FlowPill({ title, className }: FlowPillProps) {\n return (\n <div\n className={cn(\n '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',\n className,\n )}\n >\n <p className=\"text-[12px] font-semibold leading-snug text-foreground\">{title}</p>\n </div>\n );\n}\n\ntype FlowDiamondProps = { label: string; sub?: string; className?: string };\n\n/** A compact decision diamond (clip-path, straight text inside). */\nexport function FlowDiamond({ label, sub, className }: FlowDiamondProps) {\n return (\n <div className={cn('relative h-14 w-36 justify-self-center sm:h-16 sm:w-44', className)}>\n <div className=\"absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]\" />\n <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%)]\">\n <p className=\"text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]\">{label}</p>\n {sub ? <p className=\"text-[8.5px] leading-tight text-(--foreground-muted)\">{sub}</p> : null}\n </div>\n </div>\n );\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export default function FooterGlow(): import("react").JSX.Element;
2
+ //# sourceMappingURL=footer-glow.d.ts.map
@@ -0,0 +1,2 @@
1
+ export default function FooterGlow(): import("react").JSX.Element;
2
+ //# sourceMappingURL=footer-glow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer-glow.d.ts","sourceRoot":"","sources":["../../src/components/footer-glow.tsx"],"names":[],"mappings":"AAwEA,MAAM,CAAC,OAAO,UAAU,UAAU,gCAmGjC"}
@@ -0,0 +1,110 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var framerMotion = require('framer-motion');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ var VB_W = 1270;
9
+ var VB_H = 600;
10
+ var BAND_TOP = 0;
11
+ var OVERHANG = "0.5rem";
12
+ var OVERSHOOT = 60;
13
+ var BAND_X = -OVERSHOOT;
14
+ var BAND_W = VB_W + OVERSHOOT * 2;
15
+ var BAND_H = VB_H + OVERSHOOT;
16
+ var HUES = [188, 210, 232, 250, 262, 285, 308, 330, 350];
17
+ var ARCH_RX = VB_W * 1.35;
18
+ var FADE_STOPS = [
19
+ { offset: 0, opacity: 1 },
20
+ { offset: 0.62, opacity: 1 },
21
+ { offset: 0.81, opacity: 0.8 },
22
+ { offset: 0.93, opacity: 0.35 },
23
+ { offset: 1, opacity: 0 }
24
+ ];
25
+ var MAX_OPACITY = 0.85;
26
+ function FadeStops() {
27
+ return FADE_STOPS.map(({ offset, opacity }) => /* @__PURE__ */ jsxRuntime.jsx("stop", { offset, style: { stopColor: "#fff", stopOpacity: opacity } }, offset));
28
+ }
29
+ function FooterGlow() {
30
+ const ref = react.useRef(null);
31
+ const reduce = framerMotion.useReducedMotion();
32
+ const uid = react.useId();
33
+ const hueId = `footer-glow-hue-${uid}`;
34
+ const flatFadeId = `footer-glow-fade-flat-${uid}`;
35
+ const archFadeId = `footer-glow-fade-arch-${uid}`;
36
+ const flatMaskId = `footer-glow-mask-flat-${uid}`;
37
+ const archMaskId = `footer-glow-mask-arch-${uid}`;
38
+ const { scrollYProgress } = framerMotion.useScroll({ target: ref, offset: ["start end", "start center"] });
39
+ const y = framerMotion.useTransform(scrollYProgress, [0, 0.7, 1], ["55%", "5%", "2%"]);
40
+ const opacity = framerMotion.useTransform(scrollYProgress, [0, 0.65], [0, MAX_OPACITY]);
41
+ return /* @__PURE__ */ jsxRuntime.jsx(
42
+ "div",
43
+ {
44
+ ref,
45
+ "aria-hidden": "true",
46
+ className: "pointer-events-none absolute inset-x-0 bottom-0 overflow-hidden",
47
+ style: { height: `calc(100% + ${OVERHANG})` },
48
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
49
+ framerMotion.motion.svg,
50
+ {
51
+ viewBox: `0 0 ${VB_W} ${VB_H}`,
52
+ preserveAspectRatio: "none",
53
+ className: "h-full w-full",
54
+ overflow: "visible",
55
+ style: reduce ? { opacity: MAX_OPACITY } : { y, opacity },
56
+ children: [
57
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
58
+ /* @__PURE__ */ jsxRuntime.jsx("linearGradient", { id: hueId, x1: "0", y1: "0", x2: "1", y2: "0", children: HUES.map((hue, i) => /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: i / (HUES.length - 1), style: { stopColor: `hsl(${hue} 95% 55%)` } }, hue)) }),
59
+ /* @__PURE__ */ jsxRuntime.jsx("linearGradient", { id: flatFadeId, gradientUnits: "userSpaceOnUse", x1: "0", y1: VB_H, x2: "0", y2: BAND_TOP, children: /* @__PURE__ */ jsxRuntime.jsx(FadeStops, {}) }),
60
+ /* @__PURE__ */ jsxRuntime.jsx(
61
+ "radialGradient",
62
+ {
63
+ id: archFadeId,
64
+ gradientUnits: "userSpaceOnUse",
65
+ cx: VB_W / 2,
66
+ cy: VB_H,
67
+ r: VB_H - BAND_TOP,
68
+ gradientTransform: `translate(${VB_W / 2} 0) scale(${ARCH_RX / (VB_H - BAND_TOP)} 1) translate(${-VB_W / 2} 0)`,
69
+ children: /* @__PURE__ */ jsxRuntime.jsx(FadeStops, {})
70
+ }
71
+ ),
72
+ [
73
+ { id: flatMaskId, fill: flatFadeId },
74
+ { id: archMaskId, fill: archFadeId }
75
+ ].map(({ id, fill }) => /* @__PURE__ */ jsxRuntime.jsx("mask", { id, maskUnits: "userSpaceOnUse", x: BAND_X, y: "0", width: BAND_W, height: BAND_H, children: /* @__PURE__ */ jsxRuntime.jsx("rect", { x: BAND_X, y: "0", width: BAND_W, height: BAND_H, fill: `url(#${fill})` }) }, id))
76
+ ] }),
77
+ /* @__PURE__ */ jsxRuntime.jsx(
78
+ "rect",
79
+ {
80
+ x: BAND_X,
81
+ y: "0",
82
+ width: BAND_W,
83
+ height: BAND_H,
84
+ fill: `url(#${hueId})`,
85
+ mask: `url(#${flatMaskId})`,
86
+ className: "md:hidden"
87
+ }
88
+ ),
89
+ /* @__PURE__ */ jsxRuntime.jsx(
90
+ "rect",
91
+ {
92
+ x: BAND_X,
93
+ y: "0",
94
+ width: BAND_W,
95
+ height: BAND_H,
96
+ fill: `url(#${hueId})`,
97
+ mask: `url(#${archMaskId})`,
98
+ className: "hidden md:block"
99
+ }
100
+ )
101
+ ]
102
+ }
103
+ )
104
+ }
105
+ );
106
+ }
107
+
108
+ module.exports = FooterGlow;
109
+ //# sourceMappingURL=footer-glow.js.map
110
+ //# sourceMappingURL=footer-glow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/footer-glow.tsx"],"names":["jsx","useRef","useReducedMotion","useId","useScroll","useTransform","jsxs","motion"],"mappings":"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","file":"footer-glow.js","sourcesContent":["'use client';\n\nimport { motion, useReducedMotion, useScroll, useTransform } from 'framer-motion';\nimport { useId, useRef } from 'react';\n\n/**\n * Blurred brand glow behind the footer card — inspired by the Lovable footer.\n * A single full-bleed band carries a horizontal hue sweep (cyan → blue → brand\n * violet → pink) and is masked so it fades out towards the top: on wide screens\n * a very wide ellipse anchored to the bottom edge gives a shallow arch (solid to\n * the corners at the base, cresting in the middle); below `md` the same ramp runs\n * straight up, because at narrow widths the arch has no room to read as a curve\n * and just looks like a lopsided top edge. The wash reads as one even sheet of\n * colour with no bar seams and no hard cut against `overflow-hidden`. It fades +\n * rises into place as the footer scrolls into view (scroll-linked, not a\n * one-shot), and stays static when the user prefers reduced motion.\n *\n * Both masks are always in the markup and CSS picks between them, so the static\n * export is correct at every width without a JS width branch.\n */\n\nconst VB_W = 1270;\nconst VB_H = 600;\n// The band's top: the vertical fade reaches full transparency at the very top of\n// the layer, which itself overhangs the footer (see OVERHANG) — so the glow dies\n// out in open air above the footer rather than against a clipped edge.\nconst BAND_TOP = 0;\n// How far the glow layer reaches above the footer's top edge, into the CTA\n// section. Only the faint tail of the fade lands up there.\nconst OVERHANG = '0.5rem';\n// Overshoot — the band runs past the viewBox on the sides and below so the\n// colour stays full-bleed to the footer's edges even while the scroll transform\n// nudges it downwards.\nconst OVERSHOOT = 60;\nconst BAND_X = -OVERSHOOT;\nconst BAND_W = VB_W + OVERSHOOT * 2;\nconst BAND_H = VB_H + OVERSHOOT;\n\n// Hue sweep across the width. Saturation + lightness are constant so no column\n// reads brighter than its neighbours; only the hue moves.\nconst HUES = [188, 210, 232, 250, 262 /* centre — brand violet */, 285, 308, 330, 350];\n\n// Arch curvature, as a multiple of the band width: the horizontal radius of the\n// fade's ellipse. Larger = flatter. At 1.35 the outer edges give out ~7% of the\n// footer's height below the centre — a shallow crown, not a dome. The bottom\n// corners stay well inside the solid core, so the base is still edge-to-edge.\nconst ARCH_RX = VB_W * 1.35;\n\n// Alpha ramp from the solid base outwards (bottom → top, or centre-bottom → rim\n// of the ellipse for the arched variant). Solid through the lower two thirds,\n// then a tight falloff — holding full opacity that long is what keeps the band\n// reading as a defined sheet of colour instead of a diffuse haze. The ellipse's\n// rim lands exactly on BAND_TOP along the centre line, so both variants agree\n// down the middle; the arch only differs by the sides reaching zero sooner.\nconst FADE_STOPS = [\n { offset: 0, opacity: 1 },\n { offset: 0.62, opacity: 1 },\n { offset: 0.81, opacity: 0.8 },\n { offset: 0.93, opacity: 0.35 },\n { offset: 1, opacity: 0 },\n];\n\n// Peak wash opacity. The glow sits *behind* the opaque card (footer on top), so\n// only the part above the card shows — it can carry rich, saturated colour.\nconst MAX_OPACITY = 0.85;\n\nfunction FadeStops() {\n return FADE_STOPS.map(({ offset, opacity }) => (\n <stop key={offset} offset={offset} style={{ stopColor: '#fff', stopOpacity: opacity }} />\n ));\n}\n\nexport default function FooterGlow() {\n const ref = useRef<HTMLDivElement>(null);\n const reduce = useReducedMotion();\n const uid = useId();\n const hueId = `footer-glow-hue-${uid}`;\n const flatFadeId = `footer-glow-fade-flat-${uid}`;\n const archFadeId = `footer-glow-fade-arch-${uid}`;\n const flatMaskId = `footer-glow-mask-flat-${uid}`;\n const archMaskId = `footer-glow-mask-arch-${uid}`;\n\n // Progress runs 0 → 1 as the layer's top edge travels from the bottom of the\n // viewport to its middle. Deliberately viewport-relative rather than tied to\n // the footer's own height: the footer is several screens tall once the link\n // columns stack, and anchoring the end to it ('end end') meant the glow only\n // finished rising at the very bottom of the page on a phone. Half a viewport\n // of travel puts it in place early and behaves the same at every width.\n const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'start center'] });\n\n const y = useTransform(scrollYProgress, [0, 0.7, 1], ['55%', '5%', '2%']);\n const opacity = useTransform(scrollYProgress, [0, 0.65], [0, MAX_OPACITY]);\n\n // Full-bleed background layer, anchored to the footer's bottom and one overhang\n // taller than it, so the band scales with the footer while spilling above its\n // top edge. It clips itself rather than relying on the footer: that keeps the\n // sides and the scroll-transformed bottom contained (no stray page overflow)\n // while leaving the top free. `pointer-events-none` keeps the CTA above it\n // clickable through the spill.\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-x-0 bottom-0 overflow-hidden\"\n style={{ height: `calc(100% + ${OVERHANG})` }}\n >\n <motion.svg\n viewBox={`0 0 ${VB_W} ${VB_H}`}\n preserveAspectRatio=\"none\"\n className=\"h-full w-full\"\n overflow=\"visible\"\n style={reduce ? { opacity: MAX_OPACITY } : { y, opacity }}\n >\n <defs>\n <linearGradient id={hueId} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">\n {HUES.map((hue, i) => (\n <stop key={hue} offset={i / (HUES.length - 1)} style={{ stopColor: `hsl(${hue} 95% 55%)` }} />\n ))}\n </linearGradient>\n\n {/* Flat variant — a straight bottom-to-top ramp. */}\n <linearGradient id={flatFadeId} gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1={VB_H} x2=\"0\" y2={BAND_TOP}>\n <FadeStops />\n </linearGradient>\n\n {/* Arched variant — a circle of radius (VB_H - BAND_TOP) centred on the\n bottom edge, stretched horizontally into a very wide ellipse; that\n stretch is the arch. Both use userSpaceOnUse so the geometry is\n absolute, independent of the rect's bounding box (which overshoots\n the viewBox on three sides). */}\n <radialGradient\n id={archFadeId}\n gradientUnits=\"userSpaceOnUse\"\n cx={VB_W / 2}\n cy={VB_H}\n r={VB_H - BAND_TOP}\n gradientTransform={`translate(${VB_W / 2} 0) scale(${ARCH_RX / (VB_H - BAND_TOP)} 1) translate(${-VB_W / 2} 0)`}\n >\n <FadeStops />\n </radialGradient>\n\n {[\n { id: flatMaskId, fill: flatFadeId },\n { id: archMaskId, fill: archFadeId },\n ].map(({ id, fill }) => (\n <mask key={id} id={id} maskUnits=\"userSpaceOnUse\" x={BAND_X} y=\"0\" width={BAND_W} height={BAND_H}>\n <rect x={BAND_X} y=\"0\" width={BAND_W} height={BAND_H} fill={`url(#${fill})`} />\n </mask>\n ))}\n </defs>\n <rect\n x={BAND_X}\n y=\"0\"\n width={BAND_W}\n height={BAND_H}\n fill={`url(#${hueId})`}\n mask={`url(#${flatMaskId})`}\n className=\"md:hidden\"\n />\n <rect\n x={BAND_X}\n y=\"0\"\n width={BAND_W}\n height={BAND_H}\n fill={`url(#${hueId})`}\n mask={`url(#${archMaskId})`}\n className=\"hidden md:block\"\n />\n </motion.svg>\n </div>\n );\n}\n"]}
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import { useReducedMotion, useScroll, useTransform, motion } from 'framer-motion';
3
+ import { useRef, useId } from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ var VB_W = 1270;
7
+ var VB_H = 600;
8
+ var BAND_TOP = 0;
9
+ var OVERHANG = "0.5rem";
10
+ var OVERSHOOT = 60;
11
+ var BAND_X = -OVERSHOOT;
12
+ var BAND_W = VB_W + OVERSHOOT * 2;
13
+ var BAND_H = VB_H + OVERSHOOT;
14
+ var HUES = [188, 210, 232, 250, 262, 285, 308, 330, 350];
15
+ var ARCH_RX = VB_W * 1.35;
16
+ var FADE_STOPS = [
17
+ { offset: 0, opacity: 1 },
18
+ { offset: 0.62, opacity: 1 },
19
+ { offset: 0.81, opacity: 0.8 },
20
+ { offset: 0.93, opacity: 0.35 },
21
+ { offset: 1, opacity: 0 }
22
+ ];
23
+ var MAX_OPACITY = 0.85;
24
+ function FadeStops() {
25
+ return FADE_STOPS.map(({ offset, opacity }) => /* @__PURE__ */ jsx("stop", { offset, style: { stopColor: "#fff", stopOpacity: opacity } }, offset));
26
+ }
27
+ function FooterGlow() {
28
+ const ref = useRef(null);
29
+ const reduce = useReducedMotion();
30
+ const uid = useId();
31
+ const hueId = `footer-glow-hue-${uid}`;
32
+ const flatFadeId = `footer-glow-fade-flat-${uid}`;
33
+ const archFadeId = `footer-glow-fade-arch-${uid}`;
34
+ const flatMaskId = `footer-glow-mask-flat-${uid}`;
35
+ const archMaskId = `footer-glow-mask-arch-${uid}`;
36
+ const { scrollYProgress } = useScroll({ target: ref, offset: ["start end", "start center"] });
37
+ const y = useTransform(scrollYProgress, [0, 0.7, 1], ["55%", "5%", "2%"]);
38
+ const opacity = useTransform(scrollYProgress, [0, 0.65], [0, MAX_OPACITY]);
39
+ return /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ ref,
43
+ "aria-hidden": "true",
44
+ className: "pointer-events-none absolute inset-x-0 bottom-0 overflow-hidden",
45
+ style: { height: `calc(100% + ${OVERHANG})` },
46
+ children: /* @__PURE__ */ jsxs(
47
+ motion.svg,
48
+ {
49
+ viewBox: `0 0 ${VB_W} ${VB_H}`,
50
+ preserveAspectRatio: "none",
51
+ className: "h-full w-full",
52
+ overflow: "visible",
53
+ style: reduce ? { opacity: MAX_OPACITY } : { y, opacity },
54
+ children: [
55
+ /* @__PURE__ */ jsxs("defs", { children: [
56
+ /* @__PURE__ */ jsx("linearGradient", { id: hueId, x1: "0", y1: "0", x2: "1", y2: "0", children: HUES.map((hue, i) => /* @__PURE__ */ jsx("stop", { offset: i / (HUES.length - 1), style: { stopColor: `hsl(${hue} 95% 55%)` } }, hue)) }),
57
+ /* @__PURE__ */ jsx("linearGradient", { id: flatFadeId, gradientUnits: "userSpaceOnUse", x1: "0", y1: VB_H, x2: "0", y2: BAND_TOP, children: /* @__PURE__ */ jsx(FadeStops, {}) }),
58
+ /* @__PURE__ */ jsx(
59
+ "radialGradient",
60
+ {
61
+ id: archFadeId,
62
+ gradientUnits: "userSpaceOnUse",
63
+ cx: VB_W / 2,
64
+ cy: VB_H,
65
+ r: VB_H - BAND_TOP,
66
+ gradientTransform: `translate(${VB_W / 2} 0) scale(${ARCH_RX / (VB_H - BAND_TOP)} 1) translate(${-VB_W / 2} 0)`,
67
+ children: /* @__PURE__ */ jsx(FadeStops, {})
68
+ }
69
+ ),
70
+ [
71
+ { id: flatMaskId, fill: flatFadeId },
72
+ { id: archMaskId, fill: archFadeId }
73
+ ].map(({ id, fill }) => /* @__PURE__ */ jsx("mask", { id, maskUnits: "userSpaceOnUse", x: BAND_X, y: "0", width: BAND_W, height: BAND_H, children: /* @__PURE__ */ jsx("rect", { x: BAND_X, y: "0", width: BAND_W, height: BAND_H, fill: `url(#${fill})` }) }, id))
74
+ ] }),
75
+ /* @__PURE__ */ jsx(
76
+ "rect",
77
+ {
78
+ x: BAND_X,
79
+ y: "0",
80
+ width: BAND_W,
81
+ height: BAND_H,
82
+ fill: `url(#${hueId})`,
83
+ mask: `url(#${flatMaskId})`,
84
+ className: "md:hidden"
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx(
88
+ "rect",
89
+ {
90
+ x: BAND_X,
91
+ y: "0",
92
+ width: BAND_W,
93
+ height: BAND_H,
94
+ fill: `url(#${hueId})`,
95
+ mask: `url(#${archMaskId})`,
96
+ className: "hidden md:block"
97
+ }
98
+ )
99
+ ]
100
+ }
101
+ )
102
+ }
103
+ );
104
+ }
105
+
106
+ export { FooterGlow as default };
107
+ //# sourceMappingURL=footer-glow.mjs.map
108
+ //# sourceMappingURL=footer-glow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/footer-glow.tsx"],"names":[],"mappings":"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","file":"footer-glow.mjs","sourcesContent":["'use client';\n\nimport { motion, useReducedMotion, useScroll, useTransform } from 'framer-motion';\nimport { useId, useRef } from 'react';\n\n/**\n * Blurred brand glow behind the footer card — inspired by the Lovable footer.\n * A single full-bleed band carries a horizontal hue sweep (cyan → blue → brand\n * violet → pink) and is masked so it fades out towards the top: on wide screens\n * a very wide ellipse anchored to the bottom edge gives a shallow arch (solid to\n * the corners at the base, cresting in the middle); below `md` the same ramp runs\n * straight up, because at narrow widths the arch has no room to read as a curve\n * and just looks like a lopsided top edge. The wash reads as one even sheet of\n * colour with no bar seams and no hard cut against `overflow-hidden`. It fades +\n * rises into place as the footer scrolls into view (scroll-linked, not a\n * one-shot), and stays static when the user prefers reduced motion.\n *\n * Both masks are always in the markup and CSS picks between them, so the static\n * export is correct at every width without a JS width branch.\n */\n\nconst VB_W = 1270;\nconst VB_H = 600;\n// The band's top: the vertical fade reaches full transparency at the very top of\n// the layer, which itself overhangs the footer (see OVERHANG) — so the glow dies\n// out in open air above the footer rather than against a clipped edge.\nconst BAND_TOP = 0;\n// How far the glow layer reaches above the footer's top edge, into the CTA\n// section. Only the faint tail of the fade lands up there.\nconst OVERHANG = '0.5rem';\n// Overshoot — the band runs past the viewBox on the sides and below so the\n// colour stays full-bleed to the footer's edges even while the scroll transform\n// nudges it downwards.\nconst OVERSHOOT = 60;\nconst BAND_X = -OVERSHOOT;\nconst BAND_W = VB_W + OVERSHOOT * 2;\nconst BAND_H = VB_H + OVERSHOOT;\n\n// Hue sweep across the width. Saturation + lightness are constant so no column\n// reads brighter than its neighbours; only the hue moves.\nconst HUES = [188, 210, 232, 250, 262 /* centre — brand violet */, 285, 308, 330, 350];\n\n// Arch curvature, as a multiple of the band width: the horizontal radius of the\n// fade's ellipse. Larger = flatter. At 1.35 the outer edges give out ~7% of the\n// footer's height below the centre — a shallow crown, not a dome. The bottom\n// corners stay well inside the solid core, so the base is still edge-to-edge.\nconst ARCH_RX = VB_W * 1.35;\n\n// Alpha ramp from the solid base outwards (bottom → top, or centre-bottom → rim\n// of the ellipse for the arched variant). Solid through the lower two thirds,\n// then a tight falloff — holding full opacity that long is what keeps the band\n// reading as a defined sheet of colour instead of a diffuse haze. The ellipse's\n// rim lands exactly on BAND_TOP along the centre line, so both variants agree\n// down the middle; the arch only differs by the sides reaching zero sooner.\nconst FADE_STOPS = [\n { offset: 0, opacity: 1 },\n { offset: 0.62, opacity: 1 },\n { offset: 0.81, opacity: 0.8 },\n { offset: 0.93, opacity: 0.35 },\n { offset: 1, opacity: 0 },\n];\n\n// Peak wash opacity. The glow sits *behind* the opaque card (footer on top), so\n// only the part above the card shows — it can carry rich, saturated colour.\nconst MAX_OPACITY = 0.85;\n\nfunction FadeStops() {\n return FADE_STOPS.map(({ offset, opacity }) => (\n <stop key={offset} offset={offset} style={{ stopColor: '#fff', stopOpacity: opacity }} />\n ));\n}\n\nexport default function FooterGlow() {\n const ref = useRef<HTMLDivElement>(null);\n const reduce = useReducedMotion();\n const uid = useId();\n const hueId = `footer-glow-hue-${uid}`;\n const flatFadeId = `footer-glow-fade-flat-${uid}`;\n const archFadeId = `footer-glow-fade-arch-${uid}`;\n const flatMaskId = `footer-glow-mask-flat-${uid}`;\n const archMaskId = `footer-glow-mask-arch-${uid}`;\n\n // Progress runs 0 → 1 as the layer's top edge travels from the bottom of the\n // viewport to its middle. Deliberately viewport-relative rather than tied to\n // the footer's own height: the footer is several screens tall once the link\n // columns stack, and anchoring the end to it ('end end') meant the glow only\n // finished rising at the very bottom of the page on a phone. Half a viewport\n // of travel puts it in place early and behaves the same at every width.\n const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'start center'] });\n\n const y = useTransform(scrollYProgress, [0, 0.7, 1], ['55%', '5%', '2%']);\n const opacity = useTransform(scrollYProgress, [0, 0.65], [0, MAX_OPACITY]);\n\n // Full-bleed background layer, anchored to the footer's bottom and one overhang\n // taller than it, so the band scales with the footer while spilling above its\n // top edge. It clips itself rather than relying on the footer: that keeps the\n // sides and the scroll-transformed bottom contained (no stray page overflow)\n // while leaving the top free. `pointer-events-none` keeps the CTA above it\n // clickable through the spill.\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-x-0 bottom-0 overflow-hidden\"\n style={{ height: `calc(100% + ${OVERHANG})` }}\n >\n <motion.svg\n viewBox={`0 0 ${VB_W} ${VB_H}`}\n preserveAspectRatio=\"none\"\n className=\"h-full w-full\"\n overflow=\"visible\"\n style={reduce ? { opacity: MAX_OPACITY } : { y, opacity }}\n >\n <defs>\n <linearGradient id={hueId} x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">\n {HUES.map((hue, i) => (\n <stop key={hue} offset={i / (HUES.length - 1)} style={{ stopColor: `hsl(${hue} 95% 55%)` }} />\n ))}\n </linearGradient>\n\n {/* Flat variant — a straight bottom-to-top ramp. */}\n <linearGradient id={flatFadeId} gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1={VB_H} x2=\"0\" y2={BAND_TOP}>\n <FadeStops />\n </linearGradient>\n\n {/* Arched variant — a circle of radius (VB_H - BAND_TOP) centred on the\n bottom edge, stretched horizontally into a very wide ellipse; that\n stretch is the arch. Both use userSpaceOnUse so the geometry is\n absolute, independent of the rect's bounding box (which overshoots\n the viewBox on three sides). */}\n <radialGradient\n id={archFadeId}\n gradientUnits=\"userSpaceOnUse\"\n cx={VB_W / 2}\n cy={VB_H}\n r={VB_H - BAND_TOP}\n gradientTransform={`translate(${VB_W / 2} 0) scale(${ARCH_RX / (VB_H - BAND_TOP)} 1) translate(${-VB_W / 2} 0)`}\n >\n <FadeStops />\n </radialGradient>\n\n {[\n { id: flatMaskId, fill: flatFadeId },\n { id: archMaskId, fill: archFadeId },\n ].map(({ id, fill }) => (\n <mask key={id} id={id} maskUnits=\"userSpaceOnUse\" x={BAND_X} y=\"0\" width={BAND_W} height={BAND_H}>\n <rect x={BAND_X} y=\"0\" width={BAND_W} height={BAND_H} fill={`url(#${fill})`} />\n </mask>\n ))}\n </defs>\n <rect\n x={BAND_X}\n y=\"0\"\n width={BAND_W}\n height={BAND_H}\n fill={`url(#${hueId})`}\n mask={`url(#${flatMaskId})`}\n className=\"md:hidden\"\n />\n <rect\n x={BAND_X}\n y=\"0\"\n width={BAND_W}\n height={BAND_H}\n fill={`url(#${hueId})`}\n mask={`url(#${archMaskId})`}\n className=\"hidden md:block\"\n />\n </motion.svg>\n </div>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  'use strict';
2
3
 
3
4
  var classVarianceAuthority = require('class-variance-authority');
@@ -5,7 +6,6 @@ var clsx = require('clsx');
5
6
  var tailwindMerge = require('tailwind-merge');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
 
8
- // src/components/glossy-button.tsx
9
9
  function cn(...inputs) {
10
10
  return tailwindMerge.twMerge(clsx.clsx(inputs));
11
11
  }