@burdenoff/website-sdk 2026.1101.1 → 2026.1101.2

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 (276) hide show
  1. package/README.md +42 -8
  2. package/dist/analytics/index.js +19 -69
  3. package/dist/analytics/index.js.map +1 -1
  4. package/dist/analytics/index.mjs +3 -69
  5. package/dist/analytics/index.mjs.map +1 -1
  6. package/dist/avatar-live/index.js +1 -0
  7. package/dist/avatar-live/index.js.map +1 -1
  8. package/dist/avatar-live/index.mjs +1 -0
  9. package/dist/avatar-live/index.mjs.map +1 -1
  10. package/dist/avatar-live-view/index.js +10 -30
  11. package/dist/avatar-live-view/index.js.map +1 -1
  12. package/dist/avatar-live-view/index.mjs +4 -24
  13. package/dist/avatar-live-view/index.mjs.map +1 -1
  14. package/dist/chunk-23H4JUL4.js +41 -0
  15. package/dist/chunk-23H4JUL4.js.map +1 -0
  16. package/dist/chunk-34RX5P75.mjs +25 -0
  17. package/dist/chunk-34RX5P75.mjs.map +1 -0
  18. package/dist/chunk-3LFFY7AZ.js +184 -0
  19. package/dist/chunk-3LFFY7AZ.js.map +1 -0
  20. package/dist/chunk-3X26GE4S.js +2794 -0
  21. package/dist/chunk-3X26GE4S.js.map +1 -0
  22. package/dist/chunk-45GCA4GG.js +85 -0
  23. package/dist/chunk-45GCA4GG.js.map +1 -0
  24. package/dist/chunk-4SAGVLHN.js +876 -0
  25. package/dist/chunk-4SAGVLHN.js.map +1 -0
  26. package/dist/chunk-4U6YAII5.js +218 -0
  27. package/dist/chunk-4U6YAII5.js.map +1 -0
  28. package/dist/chunk-5GMTBOO6.js +21 -0
  29. package/dist/chunk-5GMTBOO6.js.map +1 -0
  30. package/dist/chunk-5JRJ57CL.mjs +329 -0
  31. package/dist/chunk-5JRJ57CL.mjs.map +1 -0
  32. package/dist/chunk-6C2DKIC7.js +4 -0
  33. package/dist/chunk-6C2DKIC7.js.map +1 -0
  34. package/dist/chunk-6IBFBWC5.mjs +17 -0
  35. package/dist/chunk-6IBFBWC5.mjs.map +1 -0
  36. package/dist/chunk-6KY2ZRVI.js +116 -0
  37. package/dist/chunk-6KY2ZRVI.js.map +1 -0
  38. package/dist/chunk-6VJT3SM4.mjs +182 -0
  39. package/dist/chunk-6VJT3SM4.mjs.map +1 -0
  40. package/dist/chunk-6YZUFMK2.mjs +40 -0
  41. package/dist/chunk-6YZUFMK2.mjs.map +1 -0
  42. package/dist/chunk-7A6R7CGG.js +47 -0
  43. package/dist/chunk-7A6R7CGG.js.map +1 -0
  44. package/dist/chunk-7PWL4V2R.js +4 -0
  45. package/dist/chunk-7PWL4V2R.js.map +1 -0
  46. package/dist/chunk-AA33WDYS.js +161 -0
  47. package/dist/chunk-AA33WDYS.js.map +1 -0
  48. package/dist/chunk-AHRGFXV2.js +525 -0
  49. package/dist/chunk-AHRGFXV2.js.map +1 -0
  50. package/dist/chunk-B63XLDZH.mjs +109 -0
  51. package/dist/chunk-B63XLDZH.mjs.map +1 -0
  52. package/dist/chunk-BX2USEWF.mjs +35 -0
  53. package/dist/chunk-BX2USEWF.mjs.map +1 -0
  54. package/dist/chunk-BYSZT35R.js +150 -0
  55. package/dist/chunk-BYSZT35R.js.map +1 -0
  56. package/dist/chunk-C6OJIHNO.js +12 -0
  57. package/dist/chunk-C6OJIHNO.js.map +1 -0
  58. package/dist/chunk-COOELBX7.mjs +63 -0
  59. package/dist/chunk-COOELBX7.mjs.map +1 -0
  60. package/dist/chunk-D2TW7MNC.mjs +2771 -0
  61. package/dist/chunk-D2TW7MNC.mjs.map +1 -0
  62. package/dist/chunk-D5KEZ6V6.mjs +3 -0
  63. package/dist/chunk-D5KEZ6V6.mjs.map +1 -0
  64. package/dist/chunk-E3GUGJMY.js +46 -0
  65. package/dist/chunk-E3GUGJMY.js.map +1 -0
  66. package/dist/chunk-EBZ2HGJ2.mjs +52 -0
  67. package/dist/chunk-EBZ2HGJ2.mjs.map +1 -0
  68. package/dist/chunk-EDLTUOIA.mjs +210 -0
  69. package/dist/chunk-EDLTUOIA.mjs.map +1 -0
  70. package/dist/chunk-EJQSOT4X.js +4 -0
  71. package/dist/chunk-EJQSOT4X.js.map +1 -0
  72. package/dist/chunk-EUPFS6MZ.mjs +2019 -0
  73. package/dist/chunk-EUPFS6MZ.mjs.map +1 -0
  74. package/dist/chunk-F3XWDC3B.js +77 -0
  75. package/dist/chunk-F3XWDC3B.js.map +1 -0
  76. package/dist/chunk-FFADMVIK.mjs +5127 -0
  77. package/dist/chunk-FFADMVIK.mjs.map +1 -0
  78. package/dist/chunk-FJWS7BKT.mjs +3 -0
  79. package/dist/chunk-FJWS7BKT.mjs.map +1 -0
  80. package/dist/chunk-FJZJDUOR.mjs +3 -0
  81. package/dist/chunk-FJZJDUOR.mjs.map +1 -0
  82. package/dist/chunk-GCFLCO2Z.mjs +145 -0
  83. package/dist/chunk-GCFLCO2Z.mjs.map +1 -0
  84. package/dist/chunk-GEXC4LRP.js +61 -0
  85. package/dist/chunk-GEXC4LRP.js.map +1 -0
  86. package/dist/chunk-GTRAXQGC.mjs +3 -0
  87. package/dist/chunk-GTRAXQGC.mjs.map +1 -0
  88. package/dist/chunk-IKOIRUKW.js +270 -0
  89. package/dist/chunk-IKOIRUKW.js.map +1 -0
  90. package/dist/chunk-IXTWOPRN.js +45 -0
  91. package/dist/chunk-IXTWOPRN.js.map +1 -0
  92. package/dist/chunk-JDXOXGOK.js +547 -0
  93. package/dist/chunk-JDXOXGOK.js.map +1 -0
  94. package/dist/chunk-JSLDWYV7.mjs +558 -0
  95. package/dist/chunk-JSLDWYV7.mjs.map +1 -0
  96. package/dist/chunk-JXLSTVBK.js +336 -0
  97. package/dist/chunk-JXLSTVBK.js.map +1 -0
  98. package/dist/chunk-KHYXK7FG.mjs +49 -0
  99. package/dist/chunk-KHYXK7FG.mjs.map +1 -0
  100. package/dist/chunk-KSMBOWQQ.js +2034 -0
  101. package/dist/chunk-KSMBOWQQ.js.map +1 -0
  102. package/dist/chunk-KU2PXHGB.mjs +83 -0
  103. package/dist/chunk-KU2PXHGB.mjs.map +1 -0
  104. package/dist/chunk-KZANIV3S.mjs +37 -0
  105. package/dist/chunk-KZANIV3S.mjs.map +1 -0
  106. package/dist/chunk-L4BP6YOB.js +20 -0
  107. package/dist/chunk-L4BP6YOB.js.map +1 -0
  108. package/dist/chunk-MRKA2OAF.mjs +75 -0
  109. package/dist/chunk-MRKA2OAF.mjs.map +1 -0
  110. package/dist/chunk-N5EC53MH.mjs +80 -0
  111. package/dist/chunk-N5EC53MH.mjs.map +1 -0
  112. package/dist/chunk-NZANQGDM.mjs +34 -0
  113. package/dist/chunk-NZANQGDM.mjs.map +1 -0
  114. package/dist/chunk-O4GS3XPZ.js +10 -0
  115. package/dist/chunk-O4GS3XPZ.js.map +1 -0
  116. package/dist/chunk-O76QDGRM.js +5154 -0
  117. package/dist/chunk-O76QDGRM.js.map +1 -0
  118. package/dist/chunk-OYEUNZJY.js +114 -0
  119. package/dist/chunk-OYEUNZJY.js.map +1 -0
  120. package/dist/chunk-PHXAGQNB.js +74 -0
  121. package/dist/chunk-PHXAGQNB.js.map +1 -0
  122. package/dist/chunk-PIHHPP7J.mjs +16 -0
  123. package/dist/chunk-PIHHPP7J.mjs.map +1 -0
  124. package/dist/chunk-PXRHVVOU.mjs +499 -0
  125. package/dist/chunk-PXRHVVOU.mjs.map +1 -0
  126. package/dist/chunk-QMA6U6AU.js +36 -0
  127. package/dist/chunk-QMA6U6AU.js.map +1 -0
  128. package/dist/chunk-R6J7IULF.js +44 -0
  129. package/dist/chunk-R6J7IULF.js.map +1 -0
  130. package/dist/chunk-R7G6TWIS.mjs +10 -0
  131. package/dist/chunk-R7G6TWIS.mjs.map +1 -0
  132. package/dist/chunk-RUMGFI6L.mjs +544 -0
  133. package/dist/chunk-RUMGFI6L.mjs.map +1 -0
  134. package/dist/chunk-S54JWSJF.js +565 -0
  135. package/dist/chunk-S54JWSJF.js.map +1 -0
  136. package/dist/chunk-SK5UGG6A.js +2041 -0
  137. package/dist/chunk-SK5UGG6A.js.map +1 -0
  138. package/dist/chunk-SKIYDKIS.mjs +70 -0
  139. package/dist/chunk-SKIYDKIS.mjs.map +1 -0
  140. package/dist/chunk-SZNS5IK6.mjs +322 -0
  141. package/dist/chunk-SZNS5IK6.mjs.map +1 -0
  142. package/dist/chunk-T7JIPZAC.js +66 -0
  143. package/dist/chunk-T7JIPZAC.js.map +1 -0
  144. package/dist/chunk-TGYQHO2E.mjs +864 -0
  145. package/dist/chunk-TGYQHO2E.mjs.map +1 -0
  146. package/dist/chunk-TT3MHN42.mjs +8 -0
  147. package/dist/chunk-TT3MHN42.mjs.map +1 -0
  148. package/dist/chunk-UM55U65W.mjs +268 -0
  149. package/dist/chunk-UM55U65W.mjs.map +1 -0
  150. package/dist/chunk-UQ2HALUD.js +72 -0
  151. package/dist/chunk-UQ2HALUD.js.map +1 -0
  152. package/dist/chunk-UXWT7G77.js +82 -0
  153. package/dist/chunk-UXWT7G77.js.map +1 -0
  154. package/dist/chunk-VNS5WDWO.mjs +7 -0
  155. package/dist/chunk-VNS5WDWO.mjs.map +1 -0
  156. package/dist/chunk-VRWZLGR7.js +4 -0
  157. package/dist/chunk-VRWZLGR7.js.map +1 -0
  158. package/dist/chunk-VZLDSNH4.mjs +22 -0
  159. package/dist/chunk-VZLDSNH4.mjs.map +1 -0
  160. package/dist/chunk-W6P3YETJ.js +92 -0
  161. package/dist/chunk-W6P3YETJ.js.map +1 -0
  162. package/dist/chunk-WPKFFQCR.mjs +90 -0
  163. package/dist/chunk-WPKFFQCR.mjs.map +1 -0
  164. package/dist/chunk-WTVTI5TO.mjs +22 -0
  165. package/dist/chunk-WTVTI5TO.mjs.map +1 -0
  166. package/dist/chunk-XJOBZ4RJ.js +44 -0
  167. package/dist/chunk-XJOBZ4RJ.js.map +1 -0
  168. package/dist/chunk-XP2JDNDU.js +325 -0
  169. package/dist/chunk-XP2JDNDU.js.map +1 -0
  170. package/dist/chunk-Y4V5CEWD.mjs +112 -0
  171. package/dist/chunk-Y4V5CEWD.mjs.map +1 -0
  172. package/dist/chunk-YERN2UWM.js +116 -0
  173. package/dist/chunk-YERN2UWM.js.map +1 -0
  174. package/dist/chunk-ZKJQWFAA.mjs +114 -0
  175. package/dist/chunk-ZKJQWFAA.mjs.map +1 -0
  176. package/dist/chunk-ZOON3S3Y.mjs +138 -0
  177. package/dist/chunk-ZOON3S3Y.mjs.map +1 -0
  178. package/dist/chunk-ZP6QRAYC.mjs +2024 -0
  179. package/dist/chunk-ZP6QRAYC.mjs.map +1 -0
  180. package/dist/chunk-ZSTFX7FV.js +9 -0
  181. package/dist/chunk-ZSTFX7FV.js.map +1 -0
  182. package/dist/client/index.js +23 -331
  183. package/dist/client/index.js.map +1 -1
  184. package/dist/client/index.mjs +3 -330
  185. package/dist/client/index.mjs.map +1 -1
  186. package/dist/comparison/index.js +28 -111
  187. package/dist/comparison/index.js.map +1 -1
  188. package/dist/comparison/index.mjs +2 -107
  189. package/dist/comparison/index.mjs.map +1 -1
  190. package/dist/components/contact.js +21 -931
  191. package/dist/components/contact.js.map +1 -1
  192. package/dist/components/contact.mjs +12 -909
  193. package/dist/components/contact.mjs.map +1 -1
  194. package/dist/components/electron-download.js +12 -124
  195. package/dist/components/electron-download.js.map +1 -1
  196. package/dist/components/electron-download.mjs +4 -106
  197. package/dist/components/electron-download.mjs.map +1 -1
  198. package/dist/components/explore-cta.js +8 -112
  199. package/dist/components/explore-cta.js.map +1 -1
  200. package/dist/components/explore-cta.mjs +3 -114
  201. package/dist/components/explore-cta.mjs.map +1 -1
  202. package/dist/components/explore.js +62 -7833
  203. package/dist/components/explore.js.map +1 -1
  204. package/dist/components/explore.mjs +13 -7800
  205. package/dist/components/explore.mjs.map +1 -1
  206. package/dist/components/launch-countdown.js +8 -83
  207. package/dist/components/launch-countdown.js.map +1 -1
  208. package/dist/components/launch-countdown.mjs +3 -85
  209. package/dist/components/launch-countdown.mjs.map +1 -1
  210. package/dist/components/newsletter.js +20 -993
  211. package/dist/components/newsletter.js.map +1 -1
  212. package/dist/components/newsletter.mjs +11 -971
  213. package/dist/components/newsletter.mjs.map +1 -1
  214. package/dist/components/partners.js +24 -1302
  215. package/dist/components/partners.js.map +1 -1
  216. package/dist/components/partners.mjs +15 -1276
  217. package/dist/components/partners.mjs.map +1 -1
  218. package/dist/components/pricing.js +49 -1249
  219. package/dist/components/pricing.js.map +1 -1
  220. package/dist/components/pricing.mjs +8 -1226
  221. package/dist/components/pricing.mjs.map +1 -1
  222. package/dist/components/problems-solved.js +8 -150
  223. package/dist/components/problems-solved.js.map +1 -1
  224. package/dist/components/problems-solved.mjs +4 -133
  225. package/dist/components/problems-solved.mjs.map +1 -1
  226. package/dist/components/resource-links.js +8 -304
  227. package/dist/components/resource-links.js.map +1 -1
  228. package/dist/components/resource-links.mjs +5 -308
  229. package/dist/components/resource-links.mjs.map +1 -1
  230. package/dist/components/social-links.js +8 -343
  231. package/dist/components/social-links.js.map +1 -1
  232. package/dist/components/social-links.mjs +5 -347
  233. package/dist/components/social-links.mjs.map +1 -1
  234. package/dist/components/unsubscribe.js +10 -627
  235. package/dist/components/unsubscribe.js.map +1 -1
  236. package/dist/components/unsubscribe.mjs +6 -611
  237. package/dist/components/unsubscribe.mjs.map +1 -1
  238. package/dist/components/waitlist.js +21 -1001
  239. package/dist/components/waitlist.js.map +1 -1
  240. package/dist/components/waitlist.mjs +12 -982
  241. package/dist/components/waitlist.mjs.map +1 -1
  242. package/dist/components/website-switcher.js +12 -175
  243. package/dist/components/website-switcher.js.map +1 -1
  244. package/dist/components/website-switcher.mjs +4 -157
  245. package/dist/components/website-switcher.mjs.map +1 -1
  246. package/dist/content/index.js +118 -3616
  247. package/dist/content/index.js.map +1 -1
  248. package/dist/content/index.mjs +12 -3567
  249. package/dist/content/index.mjs.map +1 -1
  250. package/dist/hooks/index.js +37 -2321
  251. package/dist/hooks/index.js.map +1 -1
  252. package/dist/hooks/index.mjs +6 -2318
  253. package/dist/hooks/index.mjs.map +1 -1
  254. package/dist/index.d.mts +1 -1
  255. package/dist/index.d.ts +1 -1
  256. package/dist/index.js +4145 -20599
  257. package/dist/index.js.map +1 -1
  258. package/dist/index.mjs +3766 -20567
  259. package/dist/index.mjs.map +1 -1
  260. package/dist/product/index.js +20 -393
  261. package/dist/product/index.js.map +1 -1
  262. package/dist/product/index.mjs +5 -394
  263. package/dist/product/index.mjs.map +1 -1
  264. package/dist/seo/index.js +8 -76
  265. package/dist/seo/index.js.map +1 -1
  266. package/dist/seo/index.mjs +3 -78
  267. package/dist/seo/index.mjs.map +1 -1
  268. package/dist/store/index.js +51 -2650
  269. package/dist/store/index.js.map +1 -1
  270. package/dist/store/index.mjs +13 -2619
  271. package/dist/store/index.mjs.map +1 -1
  272. package/dist/utils/index.js +69 -134
  273. package/dist/utils/index.js.map +1 -1
  274. package/dist/utils/index.mjs +5 -122
  275. package/dist/utils/index.mjs.map +1 -1
  276. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/pricing-catalog.ts","../src/components/pricing.tsx"],"names":[],"mappings":"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","file":"chunk-TGYQHO2E.mjs","sourcesContent":["/**\n * Pure helpers that turn the billing catalog (`publicPlans`) into what the\n * pricing page shows: which product key to query, the display name of a\n * plan, which currencies a visitor can pick, and the price in that currency.\n *\n * Kept free of React so every rule here is unit-tested directly\n * (see `pricing-catalog.test.ts`).\n */\n\n// ============================================================================\n// Product key\n// ============================================================================\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/** True when `value` is shaped like a UUID (a product registry id, not a slug). */\nexport function isUuidLike(value: string): boolean {\n return UUID_PATTERN.test(value.trim());\n}\n\n/** A product as returned by `publicProduct` / `publicProducts`. */\nexport interface ProductKeyCandidate {\n id: string;\n slug: string;\n}\n\n/**\n * Thrown when the pricing page is given a product UUID that no public product\n * owns. `publicPlans(productId)` matches on the product SLUG (a plan's\n * `productID` is e.g. `\"bigconsole\"`), so a registry UUID silently returns an\n * empty list — the page must refuse it instead of rendering a blank grid.\n */\nexport class PricingProductKeyError extends Error {\n constructor(productId: string) {\n super(\n `PricingPage was given the product id \"${productId}\", which matches no public product. ` +\n `publicPlans(productId) expects the product slug (for example \"vibecontrols\"); pass product.slug.`,\n );\n this.name = \"PricingProductKeyError\";\n }\n}\n\n/**\n * Resolve the key `publicPlans` expects.\n *\n * - A slug is returned unchanged (trimmed).\n * - A UUID is mapped to its product's slug using `candidates` (the product\n * from `ProductProvider` and/or the `publicProducts` list).\n * - A UUID with no matching candidate returns `null`: the caller must look it\n * up or fail with {@link PricingProductKeyError}.\n */\nexport function resolvePricingProductKey(\n productId: string,\n candidates: ReadonlyArray<ProductKeyCandidate | null | undefined>,\n): string | null {\n const trimmed = productId.trim();\n if (!isUuidLike(trimmed)) return trimmed;\n const wanted = trimmed.toLowerCase();\n const match = candidates.find(\n (c): c is ProductKeyCandidate =>\n !!c && c.id.toLowerCase() === wanted && c.slug.trim().length > 0,\n );\n return match ? match.slug.trim() : null;\n}\n\n// ============================================================================\n// Plan names\n// ============================================================================\n\nconst PERIOD_SUFFIX =\n /\\s*[([]\\s*(monthly|month|annual|annually|yearly|year)\\s*[)\\]]\\s*$/i;\nconst PRODUCT_PREFIX = /^\\S.*?\\s[-–—]\\s+(?=\\S)/;\n\n/**\n * Catalog plan names carry the product and the billing period, e.g.\n * `\"VibeControls - Hobby (Monthly)\"`. The card already sits on the product's\n * own site and the period is chosen by the Monthly/Yearly toggle, so the\n * visitor sees `\"Hobby\"`.\n *\n * Only the FIRST `\" - \"` separates the product, so `\"Acme - Pro - Teams\"`\n * becomes `\"Pro - Teams\"`. A name that would end up empty is returned as is.\n */\nexport function cleanPlanDisplayName(name: string): string {\n const withoutPeriod = name.replace(PERIOD_SUFFIX, \"\").trim();\n const withoutProduct = withoutPeriod.replace(PRODUCT_PREFIX, \"\").trim();\n if (withoutProduct.length > 0) return withoutProduct;\n if (withoutPeriod.length > 0) return withoutPeriod;\n return name.trim();\n}\n\n// ============================================================================\n// Currencies\n// ============================================================================\n\n/** The price-bearing fields of a catalog plan. */\nexport interface PricedPlan {\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/**\n * The price of `plan` in `currency`, or `null` when the catalog has no price\n * for it. A free plan costs 0 in every currency.\n */\nexport function planPriceIn(plan: PricedPlan, currency: string): number | null {\n const code = currency.toUpperCase();\n if (plan.price === 0) return 0;\n if (plan.currency.toUpperCase() === code) return plan.price;\n const prices = plan.currencyPrices;\n if (!prices) return null;\n const direct = prices[code];\n if (isFiniteNumber(direct)) return direct;\n const key = Object.keys(prices).find((k) => k.toUpperCase() === code);\n const value = key === undefined ? undefined : prices[key];\n return isFiniteNumber(value) ? value : null;\n}\n\n/**\n * The currencies a visitor can switch to: those in which EVERY plan has a\n * price (free plans count as priced everywhere). A currency missing from a\n * single paid plan is left out, so switching never blanks a card. Sorted with\n * the catalog's base currency first, then alphabetically.\n */\nexport function availablePlanCurrencies(\n plans: ReadonlyArray<PricedPlan>,\n): string[] {\n if (plans.length === 0) return [];\n const all = new Set<string>();\n for (const plan of plans) {\n all.add(plan.currency.toUpperCase());\n for (const key of Object.keys(plan.currencyPrices ?? {})) {\n all.add(key.toUpperCase());\n }\n }\n const usable = [...all].filter((code) =>\n plans.every((plan) => planPriceIn(plan, code) !== null),\n );\n const base = plans.find((p) => p.price > 0)?.currency.toUpperCase();\n return usable.sort((a, b) => {\n if (a === base) return -1;\n if (b === base) return 1;\n return a.localeCompare(b);\n });\n}\n\nconst EURO_REGIONS = [\n \"AT\",\n \"BE\",\n \"CY\",\n \"DE\",\n \"EE\",\n \"ES\",\n \"FI\",\n \"FR\",\n \"GR\",\n \"HR\",\n \"IE\",\n \"IT\",\n \"LT\",\n \"LU\",\n \"LV\",\n \"MT\",\n \"NL\",\n \"PT\",\n \"SI\",\n \"SK\",\n];\n\n/** ISO 3166 region → ISO 4217 currency, for the currencies the catalog sells in. */\nconst REGION_CURRENCY: Readonly<Record<string, string>> = Object.freeze({\n AU: \"AUD\",\n BR: \"BRL\",\n CA: \"CAD\",\n CH: \"CHF\",\n CN: \"CNY\",\n DK: \"DKK\",\n GB: \"GBP\",\n HK: \"HKD\",\n IN: \"INR\",\n JP: \"JPY\",\n KR: \"KRW\",\n MX: \"MXN\",\n MY: \"MYR\",\n NO: \"NOK\",\n NZ: \"NZD\",\n PL: \"PLN\",\n SE: \"SEK\",\n SG: \"SGD\",\n TH: \"THB\",\n US: \"USD\",\n ...Object.fromEntries(EURO_REGIONS.map((r) => [r, \"EUR\"])),\n});\n\n/** Time zones that pin a region more reliably than the browser language. */\nconst TIME_ZONE_REGION: Readonly<Record<string, string>> = Object.freeze({\n \"Asia/Kolkata\": \"IN\",\n \"Asia/Calcutta\": \"IN\",\n});\n\n/** What the browser says about where the visitor is. */\nexport interface VisitorLocale {\n timeZone?: string | null;\n languages?: ReadonlyArray<string> | null;\n}\n\nfunction regionOfLanguage(tag: string): string | null {\n const parts = tag.replace(/_/g, \"-\").split(\"-\");\n for (const part of parts.slice(1)) {\n if (/^[A-Za-z]{2}$/.test(part)) return part.toUpperCase();\n }\n return null;\n}\n\n/**\n * The visitor's regional currency when the catalog sells in it, else `null`\n * (keep the base currency). The time zone wins over the browser language,\n * because many visitors browse with an `en-US` browser outside the US.\n */\nexport function detectRegionalCurrency(\n available: ReadonlyArray<string>,\n locale: VisitorLocale,\n): string | null {\n const sellable = new Set(available.map((c) => c.toUpperCase()));\n const regions: string[] = [];\n const tzRegion = locale.timeZone ? TIME_ZONE_REGION[locale.timeZone] : null;\n if (tzRegion) regions.push(tzRegion);\n for (const tag of locale.languages ?? []) {\n const region = regionOfLanguage(tag);\n if (region) regions.push(region);\n }\n for (const region of regions) {\n const currency = REGION_CURRENCY[region];\n if (currency && sellable.has(currency)) return currency;\n }\n return null;\n}\n\n/**\n * Format `amount` in `currency` the same way on the server (prerender) and in\n * every browser: a fixed `en-US` locale, no decimals for whole amounts.\n */\nexport function formatCatalogPrice(amount: number, currency: string): string {\n const code = currency.toUpperCase();\n const whole = amount % 1 === 0;\n try {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: code,\n minimumFractionDigits: whole ? 0 : 2,\n maximumFractionDigits: whole ? 0 : 2,\n }).format(amount);\n } catch {\n // An unknown ISO code makes Intl throw; show the code rather than nothing.\n return `${code} ${whole ? amount.toString() : amount.toFixed(2)}`;\n }\n}\n\n// ============================================================================\n// Billing cycle\n// ============================================================================\n\n/**\n * The cards shown for a billing cycle. Monthly shows the monthly plans;\n * yearly shows the yearly plans plus the free plan when the catalog has no\n * yearly free twin (free tiers are usually seeded once, as monthly), so the\n * free tier does not vanish when a visitor flips the toggle.\n */\nexport function plansForBillingCycle<\n T extends { duration: string; priceRaw: number },\n>(plans: ReadonlyArray<T>, cycle: \"monthly\" | \"yearly\"): T[] {\n if (cycle === \"monthly\") {\n return plans.filter((p) => p.duration === \"monthly\");\n }\n const yearly = plans.filter((p) => p.duration === \"yearly\");\n if (yearly.some((p) => p.priceRaw === 0)) return yearly;\n const free = plans.filter(\n (p) => p.duration === \"monthly\" && p.priceRaw === 0,\n );\n return [...free, ...yearly];\n}\n","/**\n * Pricing Component\n * GraphQL-powered pricing component with quota-based features and monthly/yearly toggle\n *\n * @example\n * ```tsx\n * import { PricingPage, PricingSection } from '@burdenoff/website-sdk/components/pricing'\n *\n * // Full page with hero\n * <PricingPage\n * productName=\"BigConsole\"\n * productId=\"bigconsole-123\"\n * appLoginUrl=\"https://app.bigconsole.com/login\"\n * contactUrl=\"/contact\"\n * fallbackFeatures={{\n * basic: ['Up to 5 dashboards', '10 data sources'],\n * professional: ['Unlimited dashboards', 'API access'],\n * enterprise: ['Everything in Professional', 'Dedicated support']\n * }}\n * />\n *\n * // Embeddable section\n * <PricingSection {...props} id=\"pricing\" className=\"bg-muted/30\" />\n * ```\n */\n\n\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport {\n PricingProductKeyError,\n availablePlanCurrencies,\n cleanPlanDisplayName,\n detectRegionalCurrency,\n formatCatalogPrice,\n isUuidLike,\n planPriceIn,\n plansForBillingCycle,\n resolvePricingProductKey,\n} from \"./pricing-catalog\";\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { useProduct } from \"../product/product-provider\";\nimport { PageHead } from \"../seo/page-head\";\nimport { Button } from \"../ui/button\";\n\nimport type { ProductKeyCandidate } from \"./pricing-catalog\";\n\n// Catalog helpers, re-exported so a product website can pin its own copy\n// (planMetadata keys, served plan names) to the same rules the page applies.\nexport {\n PricingProductKeyError,\n availablePlanCurrencies,\n cleanPlanDisplayName,\n isUuidLike,\n planPriceIn,\n resolvePricingProductKey,\n} from \"./pricing-catalog\";\n\n// ============================================================================\n// GRAPHQL QUERY\n// ============================================================================\n\nconst GET_PLANS_QUERY = `\n query GetPublicPlans($productId: String!) {\n publicPlans(productId: $productId) {\n id\n name\n price\n currency\n currencyPrices\n duration\n features {\n id\n quotaId\n context\n quota {\n id\n name\n limits\n }\n }\n isActive\n productID\n createdAt\n }\n }\n`;\n\n/**\n * Used only when a consumer passes a product UUID that the ProductProvider\n * cannot map to a slug (see `resolvePricingProductKey`).\n */\nconst PUBLIC_PRODUCT_KEYS_QUERY = `\n query PricingProductKeys {\n publicProducts(limit: 200) {\n items {\n id\n slug\n }\n }\n }\n`;\n\ninterface PublicProductKeysResponse {\n publicProducts?: { items?: ProductKeyCandidate[] | null } | null;\n}\n\n/** localStorage key remembering the visitor's currency choice. */\nconst CURRENCY_STORAGE_KEY = \"burdenoff.pricing.currency\";\n\nfunction readStoredCurrency(): string | null {\n try {\n if (typeof window === \"undefined\") return null;\n return window.localStorage.getItem(CURRENCY_STORAGE_KEY);\n } catch {\n return null;\n }\n}\n\nfunction storeCurrency(code: string): void {\n try {\n if (typeof window === \"undefined\") return;\n window.localStorage.setItem(CURRENCY_STORAGE_KEY, code);\n } catch {\n // Storage blocked (private window, disabled site data): the choice just\n // isn't remembered across visits.\n }\n}\n\nfunction readVisitorLocale(): {\n timeZone: string | null;\n languages: string[];\n} {\n let timeZone: string | null = null;\n try {\n timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? null;\n } catch {\n timeZone = null;\n }\n const languages =\n typeof navigator === \"undefined\"\n ? []\n : [...(navigator.languages ?? []), navigator.language].filter(\n (l): l is string => typeof l === \"string\" && l.length > 0,\n );\n return { timeZone, languages };\n}\n\n// ============================================================================\n// TYPES & INTERFACES\n// ============================================================================\n\ninterface PlanFeature {\n id: string;\n quotaId?: string | null;\n /**\n * Per-plan quantity for this quota (e.g. `{ quantity: 250, unit: 'profiles' }`).\n * This is the tier-specific value — `quota.limits` below is the SHARED\n * Quota row's value, fixed once at quota-creation time and identical for\n * every plan that links the same quota. See `transformFeatureToLabel`.\n */\n context?: unknown;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n}\n\ninterface GatewayPlan {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: PlanFeature[];\n isActive: boolean;\n productID?: string | null;\n createdAt: string;\n}\n\ninterface GetPlansResponse {\n publicPlans: GatewayPlan[];\n}\n\nexport interface PlanCard {\n id: string;\n name: string;\n price: number;\n currency: string;\n currencyPrices?: Record<string, number> | null;\n duration: string;\n features: Array<{\n id: string;\n quotaId?: string | null;\n context?: unknown;\n quota?: {\n id: string;\n name: string;\n limits?: unknown;\n } | null;\n }>;\n isActive: boolean;\n productID?: string | null;\n}\n\ninterface CurrencyConfig {\n code: string;\n symbol: string;\n position: \"prefix\" | \"suffix\";\n}\n\ninterface PlanMetadata {\n tier: \"basic\" | \"professional\" | \"enterprise\";\n displayName: string;\n defaultDescription: string;\n popular: boolean;\n ctaText: string;\n ctaType: \"signup\" | \"contact\";\n /**\n * Curated feature bullets for this specific plan. When provided, these win\n * over the tier-based `fallbackFeatures` and the raw quota list — letting a\n * consumer differentiate plans that share a tier keyword (e.g. Free vs Hobby,\n * Pro vs Team) with concise, accurate copy.\n */\n features?: string[];\n}\n\nexport interface PricingProps {\n /**\n * Product name (used in branding and SEO)\n */\n productName?: string;\n /**\n * Product ID for GraphQL query (falls back to WebSDKConfig.productId)\n */\n productId?: string;\n /**\n * App login URL for signup CTA\n */\n appLoginUrl: string;\n /**\n * Contact page URL for enterprise CTA\n * @default '/contact'\n */\n contactUrl?: string;\n /**\n * Supported currencies\n */\n currencies?: Record<string, CurrencyConfig>;\n /**\n * Billing interval display text\n */\n billingIntervals?: Record<string, string>;\n /**\n * Currency to show first (ISO 4217, e.g. \"INR\"). When omitted the page shows\n * the catalog's base currency until the browser reveals the visitor's\n * region, then switches to that region's currency if the catalog sells in it.\n */\n defaultCurrency?: string;\n /**\n * Show the currency picker when the catalog prices every plan in more than\n * one currency.\n * @default true\n */\n showCurrencySelector?: boolean;\n /**\n * Plan metadata (tier info, CTA text, etc.)\n */\n planMetadata?: Record<string, Partial<PlanMetadata>>;\n /**\n * Fallback features when API doesn't provide them or is unavailable\n */\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n };\n /**\n * Enable audience tabs (Individual / Enterprise).\n * When enabled, shows a two-level tab system.\n * @default false\n */\n showAudienceTabs?: boolean;\n /**\n * Enterprise plans to show when Enterprise tab is selected.\n * Each entry defines a static plan card (not fetched from API).\n */\n enterprisePlans?: Array<{\n name: string;\n subtitle: string;\n price: string;\n period: string;\n note?: string;\n button: string;\n buttonLink: string;\n popular: boolean;\n badge?: string;\n features: string[];\n }>;\n /**\n * Enterprise section heading\n * @default 'Enterprise Solutions'\n */\n enterpriseHeading?: string;\n /**\n * Enterprise section subtitle\n */\n enterpriseSubtitle?: string;\n /**\n * Hero section heading (for PricingPage)\n * @default 'Simple, Transparent Pricing'\n */\n heroHeading?: string;\n /**\n * Hero section subtitle (for PricingPage)\n * @default \"Choose the plan that's right for you. No hidden fees, no surprises.\"\n */\n heroSubtitle?: string;\n /**\n * Section heading (for PricingSection)\n * @default 'Pricing Plans'\n */\n sectionHeading?: string;\n /**\n * Section subtitle (for PricingSection)\n * @default 'Choose the perfect plan for your needs'\n */\n sectionSubtitle?: string;\n /**\n * Custom CSS class\n */\n className?: string;\n /**\n * Section ID for anchor links\n */\n id?: string;\n /**\n * SEO: Page title (optional, for PricingPage)\n */\n seoTitle?: string;\n /**\n * SEO: Page description (optional, for PricingPage)\n */\n seoDescription?: string;\n /**\n * SEO: Keywords (optional, for PricingPage)\n */\n seoKeywords?: string;\n /**\n * SEO: OG Image URL (optional, for PricingPage)\n */\n seoImage?: string;\n /**\n * SEO: Canonical URL (optional, for PricingPage)\n */\n seoUrl?: string;\n}\n\n// ============================================================================\n// SERVICE FUNCTIONS\n// ============================================================================\n\n/**\n * Format price for display. A consumer-supplied `currencies` entry wins;\n * every other ISO code is formatted by `Intl` with a fixed locale so the\n * prerendered HTML and the hydrated page agree.\n */\nfunction formatPrice(\n price: number,\n currencyCode: string = \"USD\",\n currencies?: Record<string, CurrencyConfig>,\n): string {\n const currency = currencies?.[currencyCode];\n if (!currency) {\n return formatCatalogPrice(price, currencyCode);\n }\n\n const formattedNumber = price % 1 === 0 ? price.toString() : price.toFixed(2);\n\n return currency.position === \"prefix\"\n ? `${currency.symbol}${formattedNumber}`\n : `${formattedNumber}${currency.symbol}`;\n}\n\n/**\n * Format billing interval for display\n */\nfunction formatInterval(\n duration: string,\n billingIntervals?: Record<string, string>,\n): string {\n const defaultIntervals: Record<string, string> = {\n monthly: \"/month\",\n yearly: \"/year\",\n };\n\n const intervals = billingIntervals || defaultIntervals;\n return intervals[duration] || `/${duration}`;\n}\n\n/**\n * Detect if a plan belongs to the enterprise audience based on name.\n * Plans with \"team\", \"business\", or \"enterprise\" in the name are enterprise.\n *\n * IMPORTANT: this heuristic only has somewhere to route matched plans TO when\n * `showAudienceTabs` is enabled (see `splitPlansByAudience` below) — the\n * separate \"Enterprise\" tab it feeds is only ever rendered in that mode.\n * Callers MUST gate on `showAudienceTabs` before using this, or a plan whose\n * name simply happens to contain \"business\"/\"team\" (a common self-serve tier\n * name, not necessarily a contact-sales tier) silently disappears from the\n * page with no error and no fallback rendering (found live on AssetHandler's\n * /pricing — BOFF-4854 — where a $999/mo \"Business\" self-serve plan was\n * completely invisible because the product renders without audience tabs).\n */\nfunction isEnterprisePlan(planName: string): boolean {\n const name = planName.toLowerCase();\n return (\n name.includes(\"team\") ||\n name.includes(\"business\") ||\n name.includes(\"enterprise\")\n );\n}\n\n/**\n * Decide whether a name-matched \"enterprise audience\" plan should actually be\n * routed to the Enterprise tab.\n *\n * The name heuristic (`isEnterprisePlan`) matches common self-serve tier names\n * like \"Business\" or \"Team\", not only contact-sales tiers. When a price is\n * available, we treat paid tiers as self-serve and keep them in the individual\n * grid; only $0 (custom/quote-based) name-matched plans go to the Enterprise\n * tab. Callers that omit `priceRaw` keep the legacy name-only behavior.\n */\nfunction isEnterpriseAudiencePlan<\n T extends { name: string; priceRaw?: number },\n>(plan: T): boolean {\n if (!isEnterprisePlan(plan.name)) {\n return false;\n }\n if (typeof plan.priceRaw === \"number\") {\n return plan.priceRaw === 0;\n }\n return true;\n}\n\n/**\n * Split the full active plan list into the individual (self-serve) grid vs.\n * the enterprise-audience-tab bucket.\n *\n * When `showAudienceTabs` is false (the default — @see `PricingProps.showAudienceTabs`),\n * there is no \"Enterprise\" tab for a name-matched plan to render under, so\n * every active plan must stay in the individual grid regardless of its name.\n *\n * When `showAudienceTabs` is true, only custom-priced (priceRaw === 0) plans\n * whose names contain \"team\"/\"business\"/\"enterprise\" are moved to the\n * Enterprise tab. Paid self-serve tiers with those same names (e.g.\n * \"$999/mo Business\") stay in the individual grid so they actually render —\n * this is the BOFF-5652 fix.\n *\n * Exported (pure, no React/hooks) so this exact branching can be unit-tested\n * without a DOM/render harness.\n */\nexport function splitPlansByAudience<\n T extends { name: string; priceRaw?: number },\n>(\n plans: T[],\n showAudienceTabs: boolean | undefined,\n): { individualPlans: T[]; enterprisePlans: T[] } {\n if (!showAudienceTabs) {\n return { individualPlans: plans, enterprisePlans: [] };\n }\n return {\n individualPlans: plans.filter((p) => !isEnterpriseAudiencePlan(p)),\n enterprisePlans: plans.filter((p) => isEnterpriseAudiencePlan(p)),\n };\n}\n\n/**\n * Resolve the final set of cards to show under the Enterprise audience tab.\n *\n * Historically this was a strict either/or: any API-fetched, name-matched\n * \"enterprise audience\" plan (see `isEnterprisePlan` — matches \"team\",\n * \"business\", or \"enterprise\" in the plan name) completely replaced the\n * consumer's static `enterprisePlans` prop, on the assumption that a product\n * either sells enterprise tiers self-serve through the billing catalog OR\n * lists them as static \"Contact Sales\" cards, never both.\n *\n * That assumption breaks for a product that self-serve-sells a mid tier\n * whose name happens to match the enterprise heuristic (e.g. a \"Business\"\n * plan sold through the catalog, $399/mo) while ALSO wanting a distinct,\n * uncatalogued, custom-priced \"Enterprise / Contact Sales\" tier above it\n * (sales-negotiated, not backed by a billing plan). Found live on\n * HousingVista's /pricing (BOFF-5007): the API's \"Business (Monthly/Yearly)\"\n * plans satisfied `hasApiEnterprisePlans`, so the static `enterprisePlans`\n * prop carrying the real \"Enterprise\" Contact-Sales card was silently\n * dropped in full — the tab showed Business but no Enterprise card at all.\n *\n * Fix: union the two sources instead of picking one. API plans always win a\n * same-name collision (case-insensitive) so a static entry can't shadow a\n * live catalog plan; anything in the static list that doesn't collide is\n * appended after the API cards. Only fall back to the single built-in\n * default card when NEITHER source has anything to show.\n *\n * Exported (pure, no React/hooks) so this merge/dedup logic can be\n * unit-tested without a DOM/render harness.\n */\nexport function resolveEnterprisePlans<T extends { name: string }>(\n apiEnterprisePlans: T[],\n staticEnterprisePlans: Array<{ name: string }> | undefined,\n defaultEnterpriseCard: { name: string },\n): Array<T | { name: string }> {\n const staticPlans = staticEnterprisePlans || [];\n\n if (apiEnterprisePlans.length === 0 && staticPlans.length === 0) {\n return [defaultEnterpriseCard];\n }\n\n const apiNames = new Set(apiEnterprisePlans.map((p) => p.name.toLowerCase()));\n const dedupedStaticPlans = staticPlans.filter(\n (p) => !apiNames.has(p.name.toLowerCase()),\n );\n\n return [...apiEnterprisePlans, ...dedupedStaticPlans];\n}\n\n/**\n * Detect plan tier from plan name\n */\nfunction detectPlanTier(\n planName: string,\n): \"basic\" | \"professional\" | \"enterprise\" | null {\n const name = planName.toLowerCase();\n\n if (\n name.includes(\"free\") ||\n name.includes(\"basic\") ||\n name.includes(\"starter\") ||\n name.includes(\"hobby\")\n ) {\n return \"basic\";\n } else if (\n name.includes(\"pro\") ||\n name.includes(\"professional\") ||\n name.includes(\"premium\") ||\n name.includes(\"team\")\n ) {\n return \"professional\";\n } else if (name.includes(\"enterprise\") || name.includes(\"business\")) {\n return \"enterprise\";\n }\n\n return null;\n}\n\n/**\n * Get features for a specific plan tier from fallback config\n */\nfunction getFallbackFeaturesForTier(\n tier: \"basic\" | \"professional\" | \"enterprise\",\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n return [...(fallbackFeatures?.[tier] || [])];\n}\n\n/**\n * Get metadata for a plan by name.\n *\n * `priceRaw` is used to disambiguate self-serve tiers from contact-sales\n * tiers that happen to share a name. A paid \"Business\" or \"Enterprise\" plan\n * is self-serve, so it gets a signup CTA and is treated as the professional\n * tier for fallback features/styling. Only $0 (custom/quote-based) plans with\n * enterprise-y names get the Enterprise contact-sales treatment.\n */\nfunction getMetadataForPlan(\n planName: string,\n priceRaw: number,\n planMetadata?: Record<string, Partial<PlanMetadata>>,\n): PlanMetadata {\n const normalizedName = planName.toLowerCase();\n const cleanName = cleanPlanDisplayName(planName);\n\n // Try exact match first — consumers can override any heuristic. Keys may be\n // the full catalog name (\"vibecontrols - pro (monthly)\") or the clean one (\"pro\").\n const meta =\n planMetadata?.[normalizedName] ?? planMetadata?.[cleanName.toLowerCase()];\n if (meta) {\n return {\n tier: meta.tier || \"basic\",\n displayName: meta.displayName || cleanName,\n defaultDescription: meta.defaultDescription || \"Choose this plan\",\n popular: meta.popular ?? false,\n ctaText: meta.ctaText || \"Get Started\",\n ctaType: meta.ctaType || \"signup\",\n features: meta.features,\n };\n }\n\n // Try tier detection\n const tier = detectPlanTier(planName);\n if (tier) {\n const isPaidEnterpriseName =\n tier === \"enterprise\" && typeof priceRaw === \"number\" && priceRaw > 0;\n if (isPaidEnterpriseName) {\n return {\n tier: \"professional\",\n displayName: cleanName,\n defaultDescription: \"Choose this plan\",\n popular: false,\n ctaText: \"Get Started\",\n ctaType: \"signup\",\n };\n }\n\n return {\n tier,\n displayName: cleanName,\n defaultDescription: \"Choose this plan\",\n popular: tier === \"professional\",\n ctaText: tier === \"enterprise\" ? \"Contact Sales\" : \"Get Started\",\n ctaType: tier === \"enterprise\" ? \"contact\" : \"signup\",\n };\n }\n\n // Fallback\n return {\n tier: \"basic\",\n displayName: cleanName,\n defaultDescription: \"Choose this plan\",\n popular: false,\n ctaText: \"Get Started\",\n ctaType: \"signup\",\n };\n}\n\n/**\n * Transform quota limits to a human-readable feature string\n */\n/**\n * Derive a human-readable label from a dotted quota name.\n * e.g. \"vibecontrols.workspaces.count\" → \"Workspaces\"\n * \"vibecontrols.storage.bytes\" → \"Storage\"\n */\nfunction humanizeQuotaName(name: string): string {\n const parts = name.split(\".\");\n // Use the second-to-last segment (the resource), or fall back to the last\n const resource =\n parts.length >= 3 ? parts[parts.length - 2]! : parts[parts.length - 1]!;\n // Capitalize and replace hyphens/underscores with spaces\n return resource\n .replace(/[-_]/g, \" \")\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Transform a plan feature (quota link) into a human-readable string.\n *\n * BOFF-4206: the per-PLAN quantity lives on the SubscriptionFeature's own\n * `context` (e.g. `{ quantity: 250, unit: 'profiles' }`) — `quota.limits` is\n * the SHARED Quota row's value, set once at quota-creation time and\n * IDENTICAL for every plan that links that quota. Reading `quota.limits`\n * here made every tier's card show the same numbers: live on TimeCampus's\n * /pricing, Starter/Growth/Business all rendered Free's \"1 Projects\" and \"2\n * Admin Seats\" instead of their real, higher, per-tier limits. Prefer the\n * per-feature `context.quantity`; fall back to `quota.limits.value` only\n * when a feature genuinely carries no context (legacy rows seeded before\n * this convention, or a quota linked without a context payload).\n *\n * Exported (pure, no React/hooks) so this exact precedence is unit-testable\n * without a DOM/render harness, matching `splitPlansByAudience` /\n * `resolveEnterprisePlans` above.\n */\nexport function transformFeatureToLabel(feature: {\n quotaId?: string | null;\n context?: unknown;\n quota?: { id: string; name: string; limits?: unknown } | null;\n}): string {\n const quota = feature.quota;\n if (!quota) return \"\";\n const { name, limits } = quota;\n\n const featureContext =\n feature.context && typeof feature.context === \"object\"\n ? (feature.context as Record<string, unknown>)\n : null;\n const limitsObj =\n limits && typeof limits === \"object\"\n ? (limits as Record<string, unknown>)\n : null;\n\n const value: number | undefined =\n typeof featureContext?.quantity === \"number\"\n ? featureContext.quantity\n : typeof limitsObj?.value === \"number\"\n ? limitsObj.value\n : undefined;\n const unit: string | undefined =\n (typeof featureContext?.unit === \"string\" && featureContext.unit) ||\n (typeof limitsObj?.unit === \"string\" && limitsObj.unit) ||\n undefined;\n const description: string | undefined =\n (typeof featureContext?.description === \"string\" &&\n featureContext.description) ||\n (typeof limitsObj?.description === \"string\" && limitsObj.description) ||\n undefined;\n const type = limitsObj?.type;\n\n // Use explicit description if provided\n if (description) {\n if (type === \"number\" && typeof value === \"number\") {\n return `${value.toLocaleString()} ${description}`;\n }\n return description;\n }\n\n // Use unit if provided\n if (unit) {\n if (typeof value === \"number\") {\n return `${value.toLocaleString()} ${unit}`;\n }\n return unit;\n }\n\n // Derive label from quota name\n const label = humanizeQuotaName(name);\n\n if (type === \"boolean\") {\n return label;\n }\n\n if (typeof value === \"number\") {\n return `${value.toLocaleString()} ${label}`;\n }\n\n return label;\n}\n\n/**\n * Extract display features from a plan's feature list\n */\nfunction extractDisplayFeatures(\n features: PlanFeature[],\n planName: string,\n fallbackFeatures?: {\n basic?: string[];\n professional?: string[];\n enterprise?: string[];\n },\n): string[] {\n // Prefer curated fallback features when available — they are concise\n // and differentiated per tier, unlike raw quota dumps\n const tier = detectPlanTier(planName);\n if (tier) {\n const tierFeatures = getFallbackFeaturesForTier(tier, fallbackFeatures);\n if (tierFeatures.length > 0) {\n return tierFeatures;\n }\n }\n\n // No fallback: transform quota features from API\n const quotaFeatures = features\n .filter((f) => f.quota)\n .map((f) => transformFeatureToLabel(f));\n\n if (quotaFeatures.length > 0) {\n return quotaFeatures;\n }\n\n return [];\n}\n\n// ============================================================================\n// UI CARD TYPE (internal)\n// ============================================================================\n\ninterface DisplayPlanCard {\n id: string;\n /** Display name (product prefix and period stripped, or planMetadata.displayName). */\n name: string;\n description: string;\n price: string;\n priceRaw: number;\n interval: string;\n duration: string;\n features: string[];\n popular: boolean;\n ctaText: string;\n ctaLink: string;\n tier: \"basic\" | \"professional\" | \"enterprise\" | null;\n}\n\n/**\n * Transform a GatewayPlan into a display card\n */\nfunction transformToDisplayCard(\n plan: GatewayPlan,\n props: PricingProps,\n currency: string | null,\n): DisplayPlanCard {\n const metadata = getMetadataForPlan(\n plan.name,\n plan.price,\n props.planMetadata,\n );\n\n // The selected currency only applies when the catalog prices this plan in\n // it; otherwise the card keeps the plan's own currency (never a blank).\n const selectedPrice = currency ? planPriceIn(plan, currency) : null;\n const formattedPrice =\n currency && selectedPrice !== null\n ? formatPrice(selectedPrice, currency.toUpperCase(), props.currencies)\n : formatPrice(plan.price, plan.currency, props.currencies);\n const interval = formatInterval(plan.duration, props.billingIntervals);\n\n // A curated per-plan list (via planMetadata) wins over the tier fallback and\n // the raw quota dump — this is how Free/Hobby and Pro/Team get distinct copy.\n const features =\n metadata.features && metadata.features.length > 0\n ? metadata.features\n : extractDisplayFeatures(\n plan.features,\n plan.name,\n props.fallbackFeatures,\n );\n\n const contactUrl = props.contactUrl || \"/contact\";\n const ctaLink =\n metadata.ctaType === \"contact\" ? contactUrl : props.appLoginUrl;\n // A $0 contact-sales plan (e.g. \"Enterprise\") is quote-based, not free.\n const isQuoteBased = metadata.ctaType === \"contact\" && plan.price === 0;\n\n return {\n id: plan.id,\n name: metadata.displayName,\n description: metadata.defaultDescription,\n price: isQuoteBased ? \"Custom\" : formattedPrice,\n priceRaw: plan.price,\n interval: isQuoteBased ? \"\" : interval,\n duration: plan.duration,\n features,\n popular: metadata.popular,\n ctaText: metadata.ctaText,\n ctaLink,\n tier: metadata.tier,\n };\n}\n\n// ============================================================================\n// REACT COMPONENTS\n// ============================================================================\n\n/**\n * Pricing Section Component - Embeddable\n */\nexport function PricingSection(props: PricingProps) {\n const {\n sectionHeading = \"Pricing Plans\",\n sectionSubtitle = \"Choose the perfect plan for your needs\",\n id,\n className = \"\",\n } = props;\n\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const { product: contextProduct } = useProduct();\n\n const requestedProductId = (props.productId || config.productId || \"\").trim();\n // A UUID the ProductProvider already knows is mapped to its slug without a\n // network call; anything else is resolved inside the effect below.\n const contextKey = resolvePricingProductKey(requestedProductId, [\n contextProduct,\n ]);\n const productKey = contextKey ?? requestedProductId;\n\n const [catalogPlans, setCatalogPlans] = useState<GatewayPlan[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [billingCycle, setBillingCycle] = useState<\"monthly\" | \"yearly\">(\n \"monthly\",\n );\n const [audience, setAudience] = useState<\"individual\" | \"enterprise\">(\n \"individual\",\n );\n const [selectedCurrency, setSelectedCurrency] = useState<string | null>(\n props.defaultCurrency ? props.defaultCurrency.toUpperCase() : null,\n );\n\n useEffect(() => {\n let cancelled = false;\n\n async function resolveKey(): Promise<string> {\n if (!productKey) {\n throw new Error(\n \"PricingPage needs a product slug: pass productId or set WebSDKConfig.productId.\",\n );\n }\n if (!isUuidLike(productKey)) return productKey;\n const response = await client.query<PublicProductKeysResponse>(\n PUBLIC_PRODUCT_KEYS_QUERY,\n );\n if (response.errors && response.errors.length > 0) {\n throw new Error(response.errors[0]!.message);\n }\n const resolved = resolvePricingProductKey(\n productKey,\n response.data?.publicProducts?.items ?? [],\n );\n if (!resolved) throw new PricingProductKeyError(productKey);\n return resolved;\n }\n\n async function loadPlans() {\n try {\n setLoading(true);\n\n const key = await resolveKey();\n if (cancelled) return;\n\n const response = await client.query<GetPlansResponse>(GET_PLANS_QUERY, {\n productId: key,\n });\n\n if (cancelled) return;\n\n if (response.errors && response.errors.length > 0) {\n throw new Error(response.errors[0]!.message);\n }\n\n if (!response.data?.publicPlans) {\n throw new Error(\"No plans data received\");\n }\n\n // Server already filters by productId — keep the active plans.\n const active = response.data.publicPlans.filter(\n (plan) => plan.isActive,\n );\n if (active.length === 0) {\n // An empty catalog is a misconfiguration (wrong key, unseeded\n // product), never a valid page: say so instead of an empty grid.\n throw new Error(\n `publicPlans returned no active plans for product \"${key}\".`,\n );\n }\n\n setCatalogPlans(active);\n setError(null);\n } catch (err) {\n if (cancelled) return;\n console.error(\"Failed to load plans:\", err);\n setCatalogPlans([]);\n setError(\"Unable to load pricing information. Please try again later.\");\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n loadPlans();\n\n return () => {\n cancelled = true;\n };\n }, [client, productKey]);\n\n const currencyOptions = useMemo(\n () => availablePlanCurrencies(catalogPlans),\n [catalogPlans],\n );\n\n // Pick the visitor's currency once the catalog is known: a remembered\n // choice first, else the regional currency. Runs after hydration so the\n // prerendered HTML (base currency) and the first client render agree.\n useEffect(() => {\n if (selectedCurrency || currencyOptions.length < 2) return;\n const stored = readStoredCurrency()?.toUpperCase();\n if (stored && currencyOptions.includes(stored)) {\n setSelectedCurrency(stored);\n return;\n }\n const regional = detectRegionalCurrency(\n currencyOptions,\n readVisitorLocale(),\n );\n if (regional) setSelectedCurrency(regional);\n }, [currencyOptions, selectedCurrency]);\n\n const activeCurrency =\n selectedCurrency && currencyOptions.includes(selectedCurrency)\n ? selectedCurrency\n : (currencyOptions[0] ?? null);\n\n const allPlans: DisplayPlanCard[] = catalogPlans\n .map((plan) => transformToDisplayCard(plan, props, activeCurrency))\n .sort((a, b) => {\n // Quote-based (Custom) cards go last; the rest ascend by price.\n const aCustom = a.price === \"Custom\" ? 1 : 0;\n const bCustom = b.price === \"Custom\" ? 1 : 0;\n return aCustom - bCustom || a.priceRaw - b.priceRaw;\n });\n\n const showCurrencySelector =\n props.showCurrencySelector !== false && currencyOptions.length > 1;\n\n // Split plans by audience (individual vs enterprise) based on plan name —\n // ONLY when the two-tab layout is actually enabled (see\n // `splitPlansByAudience`'s doc comment for why this must be gated).\n const {\n individualPlans: individualAllPlans,\n enterprisePlans: enterpriseApiPlans,\n } = splitPlansByAudience(allPlans, props.showAudienceTabs);\n\n // Filter individual plans by billing cycle\n const individualPlans = plansForBillingCycle(\n individualAllPlans,\n billingCycle,\n );\n\n // Enterprise plans from API (show all — no billing cycle filter since enterprise is typically monthly)\n const enterpriseCards: DisplayPlanCard[] = enterpriseApiPlans.map((p) => {\n // Mark $0 enterprise plans as \"Custom\" pricing with Contact Sales CTA\n if (p.priceRaw === 0 && p.name.toLowerCase().includes(\"enterprise\")) {\n return {\n ...p,\n price: \"Custom\",\n interval: \"\",\n ctaText: \"Contact Sales\",\n ctaLink: props.contactUrl || \"/contact\",\n };\n }\n return p;\n });\n\n // Merge API-fetched enterprise-audience plans (name-matched \"team\"/\n // \"business\"/\"enterprise\") with any statically-configured enterprisePlans\n // — see `resolveEnterprisePlans` for why this must be a union, not an\n // either/or, and only fall back to the built-in default when both are empty.\n const defaultEnterpriseCard: Record<string, unknown> & { name: string } = {\n name: \"Enterprise\",\n subtitle: \"For organizations that need more\",\n description: \"For organizations that need more\",\n price: \"Custom\",\n period: \"\",\n interval: \"\",\n button: \"Contact Sales\",\n buttonLink: props.contactUrl || \"/contact\",\n ctaText: \"Contact Sales\",\n ctaLink: props.contactUrl || \"/contact\",\n popular: false,\n features: props.fallbackFeatures?.enterprise || [\n \"Unlimited everything\",\n \"SSO & SAML\",\n \"Audit logs\",\n \"Dedicated support\",\n \"Self-hosted option\",\n ],\n };\n const resolvedEnterprisePlans = resolveEnterprisePlans(\n enterpriseCards,\n props.enterprisePlans as unknown as Array<{ name: string }> | undefined,\n defaultEnterpriseCard,\n ) as unknown as Record<string, unknown>[];\n\n // Determine which plans to show based on audience\n const plans =\n props.showAudienceTabs && audience === \"enterprise\"\n ? [] // Enterprise uses separate rendering\n : individualPlans;\n\n if (loading) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n {sectionHeading ? (\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n ) : (\n // Visually hidden but DOM-present heading so axe's heading-order\n // rule still sees an h2 between the consumer's hero h1 and the\n // h3 plan-card titles. See `getMetadataForPlan` for why a falsy\n // sectionHeading is the canonical \"no visible heading\" signal.\n <h2 className=\"sr-only\">Pricing</h2>\n )}\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg\">\n Loading pricing information...\n </p>\n </div>\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8\">\n {[1, 2, 3].map((i) => (\n <div\n key={i}\n className=\"bg-card border rounded-lg p-6 animate-pulse\"\n >\n <div className=\"h-6 bg-muted rounded w-1/2 mb-4\"></div>\n <div className=\"h-4 bg-muted rounded w-3/4 mb-6\"></div>\n <div className=\"h-10 bg-muted rounded w-1/3 mb-6\"></div>\n <div className=\"space-y-3 mb-6\">\n {[1, 2, 3, 4].map((j) => (\n <div key={j} className=\"h-4 bg-muted rounded\"></div>\n ))}\n </div>\n <div className=\"h-10 bg-muted rounded\"></div>\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n }\n\n if (error && plans.length === 0) {\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center\">\n {sectionHeading ? (\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-4\">\n {sectionHeading}\n </h2>\n ) : (\n <h2 className=\"sr-only\">Pricing</h2>\n )}\n <p className=\"text-muted-foreground mb-8\">{error}</p>\n <Button onClick={() => window.location.reload()}>Retry</Button>\n </div>\n </div>\n </section>\n );\n }\n\n return (\n <section id={id} className={`py-12 sm:py-16 md:py-20 ${className}`}>\n <div className=\"container mx-auto px-4 sm:px-6\">\n <div className=\"text-center mb-8 sm:mb-12\">\n {sectionHeading ? (\n <h2 className=\"text-2xl sm:text-3xl md:text-4xl font-bold mb-3 sm:mb-4\">\n {sectionHeading}\n </h2>\n ) : (\n <h2 className=\"sr-only\">Pricing</h2>\n )}\n <p className=\"text-muted-foreground text-sm sm:text-base md:text-lg mb-6\">\n {sectionSubtitle}\n </p>\n\n {/* Audience Toggle (Individual / Enterprise) */}\n {props.showAudienceTabs && (\n <div className=\"flex justify-center mb-4\">\n <div className=\"inline-flex items-center bg-muted p-1.5 rounded-xl\">\n <button\n type=\"button\"\n onClick={() => setAudience(\"individual\")}\n className={`px-6 sm:px-8 py-2.5 rounded-lg text-sm font-semibold transition-all ${\n audience === \"individual\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Individual\n </button>\n <button\n type=\"button\"\n onClick={() => setAudience(\"enterprise\")}\n className={`px-6 sm:px-8 py-2.5 rounded-lg text-sm font-semibold transition-all ${\n audience === \"enterprise\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Enterprise\n </button>\n </div>\n </div>\n )}\n\n {/* Billing Cycle Toggle — only for Individual */}\n {(audience === \"individual\" || !props.showAudienceTabs) && (\n <div className=\"flex justify-center\">\n <div className=\"inline-flex items-center bg-muted/60 p-1.5 rounded-xl\">\n <button\n type=\"button\"\n onClick={() => setBillingCycle(\"monthly\")}\n className={`px-5 sm:px-6 py-2 rounded-lg text-sm font-medium transition-all ${\n billingCycle === \"monthly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Monthly\n </button>\n <button\n type=\"button\"\n onClick={() => setBillingCycle(\"yearly\")}\n className={`px-5 sm:px-6 py-2 rounded-lg text-sm font-medium transition-all ${\n billingCycle === \"yearly\"\n ? \"bg-background shadow-sm text-foreground\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Yearly\n </button>\n </div>\n </div>\n )}\n\n {showCurrencySelector && (\n <div className=\"flex justify-center mt-4\">\n <label className=\"inline-flex items-center gap-2 text-sm text-muted-foreground\">\n <span>Currency</span>\n <select\n value={activeCurrency ?? \"\"}\n onChange={(event) => {\n const code = event.target.value;\n setSelectedCurrency(code);\n storeCurrency(code);\n }}\n className=\"h-9 rounded-md border border-input bg-background px-3 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n data-testid=\"pricing-currency-select\"\n >\n {currencyOptions.map((code) => (\n <option key={code} value={code}>\n {code}\n </option>\n ))}\n </select>\n </label>\n </div>\n )}\n </div>\n\n {/* Enterprise Intro — only when Enterprise is selected */}\n {props.showAudienceTabs && audience === \"enterprise\" && (\n <div className=\"mx-auto max-w-3xl text-center mb-8\">\n <h3 className=\"text-xl sm:text-2xl font-bold text-foreground\">\n {props.enterpriseHeading || \"Enterprise Solutions\"}\n </h3>\n <p className=\"mt-3 text-muted-foreground\">\n {props.enterpriseSubtitle ||\n \"Built for teams, agencies, and organizations that need advanced collaboration, security, support, and scale.\"}\n </p>\n </div>\n )}\n\n <div className=\"grid md:grid-cols-3 gap-6 sm:gap-8 max-w-6xl mx-auto items-stretch\">\n {props.showAudienceTabs && audience === \"enterprise\"\n ? /* Enterprise cards — from API, static prop, or built-in default */\n resolvedEnterprisePlans.map((ep) => {\n // Normalize fields — API uses description/ctaText/ctaLink/interval, static prop uses subtitle/button/buttonLink/period\n const subtitle = (ep.subtitle ||\n ep.description ||\n \"\") as string;\n const btnText = (ep.button ||\n ep.ctaText ||\n \"Get Started\") as string;\n const btnLink = (ep.buttonLink ||\n ep.ctaLink ||\n props.appLoginUrl) as string;\n const period = (ep.period || ep.interval || \"\") as string;\n const note = (ep.note || \"\") as string;\n const badge = (ep.badge || \"\") as string;\n const isPopular = ep.popular as boolean;\n const features = (ep.features || []) as string[];\n const price = String(ep.price);\n\n return (\n <div\n key={ep.name as string}\n className={`bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${\n isPopular\n ? \"border-2 border-primary shadow-xl ring-1 ring-primary/20\"\n : \"border hover:shadow-lg hover:border-primary/50\"\n }`}\n >\n <div className=\"text-center mb-6\">\n {isPopular && badge && (\n <span className=\"inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3\">\n {badge}\n </span>\n )}\n <h3 className=\"text-xl sm:text-2xl font-bold mb-2\">\n {ep.name as string}\n </h3>\n <p className=\"text-muted-foreground text-sm\">\n {subtitle}\n </p>\n </div>\n\n <div className=\"text-center mb-2\">\n {price === \"Custom\" ? (\n <p className=\"text-3xl sm:text-4xl font-bold\">Custom</p>\n ) : (\n <p className=\"flex items-baseline justify-center gap-1\">\n <span className=\"text-4xl sm:text-5xl font-extrabold\">\n {price}\n </span>\n <span className=\"text-muted-foreground text-lg\">\n {period}\n </span>\n </p>\n )}\n {note && (\n <p className=\"mt-2 text-sm font-medium text-primary\">\n {note}\n </p>\n )}\n </div>\n\n <ul className=\"space-y-3 mb-8 mt-6 flex-1\">\n {features.map((feature) => (\n <li\n key={feature}\n className=\"text-sm flex items-start gap-2\"\n >\n <span className=\"text-primary mt-0.5 flex-shrink-0\">\n &#10003;\n </span>\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n\n {btnLink.startsWith(\"/\") ? (\n <Button\n className=\"w-full h-11\"\n variant={isPopular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={btnLink}\n onClick={() =>\n window.scrollTo({ top: 0, behavior: \"smooth\" })\n }\n >\n {btnText}\n </a>\n </Button>\n ) : (\n <Button\n className=\"w-full h-11\"\n variant={isPopular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={btnLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {btnText}\n </a>\n </Button>\n )}\n </div>\n );\n })\n : /* Individual API-fetched cards */\n plans.map((plan) => (\n <div\n key={plan.id}\n className={`bg-card rounded-xl p-6 sm:p-8 transition-all duration-300 flex flex-col ${\n plan.popular\n ? \"border-2 border-primary shadow-xl ring-1 ring-primary/20\"\n : \"border hover:shadow-lg hover:border-primary/50\"\n }`}\n >\n <div className=\"text-center mb-6\">\n {plan.popular && (\n <span className=\"inline-block bg-primary text-primary-foreground px-4 py-1 rounded-full text-xs font-semibold mb-3\">\n Most Popular\n </span>\n )}\n <h3 className=\"text-xl sm:text-2xl font-bold mb-2\">\n {plan.name}\n </h3>\n <p className=\"text-muted-foreground text-sm\">\n {plan.description}\n </p>\n </div>\n\n {/* The amount sits in a <p> on purpose: product sites build\n /pricing.md (their llms.txt corpus) with an extractor that\n keeps only h1-h6/p/li/blockquote/figcaption/dt/dd text, so\n a price in a bare <div>/<span> vanished from it (BOFF-7178). */}\n <div className=\"text-center mb-8\">\n {plan.price === \"Custom\" ? (\n <p className=\"text-3xl sm:text-4xl font-bold\">Custom</p>\n ) : (\n <p className=\"flex items-baseline justify-center gap-1\">\n <span className=\"text-4xl sm:text-5xl font-bold\">\n {plan.price}\n </span>\n <span className=\"text-muted-foreground text-lg\">\n {plan.interval}\n </span>\n </p>\n )}\n </div>\n\n <ul className=\"space-y-3 mb-8 flex-1\">\n {plan.features.map((feature, index) => (\n <li\n key={index}\n className=\"text-sm flex items-start gap-2\"\n >\n <span className=\"text-primary mt-0.5 flex-shrink-0\">\n &#10003;\n </span>\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n\n {plan.ctaLink.startsWith(\"/\") ? (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n onClick={() =>\n window.scrollTo({ top: 0, behavior: \"smooth\" })\n }\n >\n {plan.ctaText}\n </a>\n </Button>\n ) : (\n <Button\n className=\"w-full h-11\"\n variant={plan.popular ? \"default\" : \"outline\"}\n size=\"lg\"\n asChild\n >\n <a\n href={plan.ctaLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {plan.ctaText}\n </a>\n </Button>\n )}\n </div>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n/**\n * Pricing Page Component - Full Page with Hero\n */\nexport function PricingPage(props: PricingProps) {\n const {\n productName,\n heroHeading = \"Simple, Transparent Pricing\",\n heroSubtitle = \"Choose the plan that's right for you. No hidden fees, no surprises.\",\n seoTitle,\n seoDescription,\n seoKeywords,\n seoImage,\n seoUrl,\n } = props;\n\n return (\n <div className=\"w-full\">\n {/* SEO Meta Tags */}\n {seoTitle && (\n <PageHead\n title={seoTitle}\n description={seoDescription || heroSubtitle}\n productName={productName}\n keywords={seoKeywords}\n image={seoImage}\n url={seoUrl}\n />\n )}\n\n {/* Hero Section */}\n <section className=\"bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"text-center max-w-3xl mx-auto\">\n <h1 className=\"text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6\">\n {heroHeading}\n </h1>\n <p className=\"text-lg sm:text-xl text-muted-foreground leading-relaxed\">\n {heroSubtitle}\n </p>\n </div>\n </div>\n </section>\n\n {/* Pricing Section */}\n <PricingSection {...props} />\n </div>\n );\n}\n"]}
@@ -0,0 +1,8 @@
1
+ // src/components/explore-fill.ts
2
+ function fill(template, values) {
3
+ return template.replace(/\{(\w+)\}/g, (match, key) => values[key] ?? match);
4
+ }
5
+
6
+ export { fill };
7
+ //# sourceMappingURL=chunk-TT3MHN42.mjs.map
8
+ //# sourceMappingURL=chunk-TT3MHN42.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/explore-fill.ts"],"names":[],"mappings":";AAMO,SAAS,IAAA,CAAK,UAAkB,MAAA,EAAwC;AAC7E,EAAA,OAAO,QAAA,CAAS,QAAQ,YAAA,EAAc,CAAC,OAAO,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA,IAAK,KAAK,CAAA;AAC5E","file":"chunk-TT3MHN42.mjs","sourcesContent":["/**\n * Substitute `{product}` and friends without pulling in a formatting library.\n *\n * A module of its own so the live avatar's view, which is loaded on its own (see `explore-avatar-live.tsx`), can use\n * it without carrying `explore-i18n.ts`, the panel's strings. `explore-i18n.ts` re-exports it.\n */\nexport function fill(template: string, values: Record<string, string>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key) => values[key] ?? match);\n}\n"]}
@@ -0,0 +1,268 @@
1
+ import { PageHead } from './chunk-N5EC53MH.mjs';
2
+ import { Button } from './chunk-KHYXK7FG.mjs';
3
+ import { useWebSDK, useWebSDKConfig } from './chunk-5JRJ57CL.mjs';
4
+ import { useState, useEffect } from 'react';
5
+ import { toast } from 'sonner';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var UNSUBSCRIBE_MUTATION = (
9
+ /* GraphQL */
10
+ `
11
+ mutation PublicUnsubscribeByToken($token: String!) {
12
+ publicUnsubscribeByToken(token: $token)
13
+ }
14
+ `
15
+ );
16
+ function UnsubscribePage({
17
+ productName,
18
+ className = "",
19
+ seoTitle = "Unsubscribe from Newsletter",
20
+ seoDescription = "Manage your newsletter subscription preferences.",
21
+ resubscribeUrl,
22
+ successMessage = "You have been successfully unsubscribed from our newsletter.",
23
+ errorMessage = "Something went wrong. Please try again or contact support."
24
+ }) {
25
+ const client = useWebSDK();
26
+ const config = useWebSDKConfig();
27
+ const displayName = productName ?? config.productId;
28
+ const [state, setState] = useState("loading");
29
+ const [error, setError] = useState("");
30
+ const [token, setToken] = useState("");
31
+ const [successCopy, setSuccessCopy] = useState(successMessage);
32
+ useEffect(() => {
33
+ const params = new URLSearchParams(window.location.search);
34
+ const t = params.get("token");
35
+ if (t) {
36
+ setToken(t);
37
+ setState("confirming");
38
+ } else {
39
+ setState("invalid");
40
+ }
41
+ }, []);
42
+ const handleUnsubscribe = async () => {
43
+ if (!token) return;
44
+ setState("processing");
45
+ try {
46
+ const result = await client.mutate(UNSUBSCRIBE_MUTATION, { token });
47
+ if (result.errors?.length) {
48
+ const errMsg = result.errors[0]?.message ?? errorMessage;
49
+ const code = result.errors[0]?.extensions?.code;
50
+ if (code === "ALREADY_UNSUBSCRIBED") {
51
+ toast.info("You are already unsubscribed from this newsletter.");
52
+ setSuccessCopy("You were already unsubscribed from this newsletter.");
53
+ setState("success");
54
+ return;
55
+ } else if (code === "UNSUBSCRIBE_TOKEN_EXPIRED") {
56
+ setError(
57
+ "This unsubscribe link has expired. Please contact support."
58
+ );
59
+ } else if (code === "INVALID_UNSUBSCRIBE_TOKEN") {
60
+ setState("invalid");
61
+ return;
62
+ } else {
63
+ setError(errMsg);
64
+ }
65
+ setState("error");
66
+ return;
67
+ }
68
+ if (result.data?.publicUnsubscribeByToken) {
69
+ setSuccessCopy(successMessage);
70
+ setState("success");
71
+ toast.success("Successfully unsubscribed");
72
+ } else {
73
+ setError(errorMessage);
74
+ setState("error");
75
+ }
76
+ } catch {
77
+ setError(errorMessage);
78
+ setState("error");
79
+ }
80
+ };
81
+ return /* @__PURE__ */ jsxs(
82
+ "div",
83
+ {
84
+ className,
85
+ style: {
86
+ minHeight: "60vh",
87
+ display: "flex",
88
+ alignItems: "center",
89
+ justifyContent: "center",
90
+ padding: "6rem 1rem 4rem"
91
+ },
92
+ children: [
93
+ /* @__PURE__ */ jsx(PageHead, { title: seoTitle, description: seoDescription }),
94
+ /* @__PURE__ */ jsxs("div", { className: "max-w-md w-full text-center", children: [
95
+ state === "loading" && /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
96
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-48 bg-muted rounded mx-auto mb-4" }),
97
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-64 bg-muted rounded mx-auto" })
98
+ ] }),
99
+ state === "confirming" && /* @__PURE__ */ jsxs("div", { children: [
100
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center", children: /* @__PURE__ */ jsx(
101
+ "svg",
102
+ {
103
+ className: "w-8 h-8 text-amber-600 dark:text-amber-400",
104
+ fill: "none",
105
+ viewBox: "0 0 24 24",
106
+ stroke: "currentColor",
107
+ strokeWidth: 2,
108
+ children: /* @__PURE__ */ jsx(
109
+ "path",
110
+ {
111
+ strokeLinecap: "round",
112
+ strokeLinejoin: "round",
113
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"
114
+ }
115
+ )
116
+ }
117
+ ) }),
118
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Unsubscribe from Newsletter" }),
119
+ /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground mb-8", children: [
120
+ "Are you sure you want to unsubscribe from ",
121
+ displayName,
122
+ " ",
123
+ "newsletter? You will no longer receive updates and news from us."
124
+ ] }),
125
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-3 justify-center", children: [
126
+ /* @__PURE__ */ jsx(
127
+ Button,
128
+ {
129
+ onClick: handleUnsubscribe,
130
+ variant: "destructive",
131
+ className: "px-8",
132
+ children: "Yes, Unsubscribe"
133
+ }
134
+ ),
135
+ resubscribeUrl && /* @__PURE__ */ jsx(
136
+ Button,
137
+ {
138
+ variant: "outline",
139
+ onClick: () => {
140
+ window.location.href = resubscribeUrl;
141
+ },
142
+ className: "px-8",
143
+ children: "Cancel"
144
+ }
145
+ )
146
+ ] })
147
+ ] }),
148
+ state === "processing" && /* @__PURE__ */ jsxs("div", { children: [
149
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsxs(
150
+ "svg",
151
+ {
152
+ className: "w-8 h-8 text-muted-foreground animate-spin",
153
+ fill: "none",
154
+ viewBox: "0 0 24 24",
155
+ children: [
156
+ /* @__PURE__ */ jsx(
157
+ "circle",
158
+ {
159
+ className: "opacity-25",
160
+ cx: "12",
161
+ cy: "12",
162
+ r: "10",
163
+ stroke: "currentColor",
164
+ strokeWidth: "4"
165
+ }
166
+ ),
167
+ /* @__PURE__ */ jsx(
168
+ "path",
169
+ {
170
+ className: "opacity-75",
171
+ fill: "currentColor",
172
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
173
+ }
174
+ )
175
+ ]
176
+ }
177
+ ) }),
178
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Unsubscribing..." }),
179
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Please wait while we process your request." })
180
+ ] }),
181
+ state === "success" && /* @__PURE__ */ jsxs("div", { children: [
182
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center", children: /* @__PURE__ */ jsx(
183
+ "svg",
184
+ {
185
+ className: "w-8 h-8 text-green-600 dark:text-green-400",
186
+ fill: "none",
187
+ viewBox: "0 0 24 24",
188
+ stroke: "currentColor",
189
+ strokeWidth: 2,
190
+ children: /* @__PURE__ */ jsx(
191
+ "path",
192
+ {
193
+ strokeLinecap: "round",
194
+ strokeLinejoin: "round",
195
+ d: "M5 13l4 4L19 7"
196
+ }
197
+ )
198
+ }
199
+ ) }),
200
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Successfully Unsubscribed" }),
201
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-8", children: successCopy }),
202
+ resubscribeUrl && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
203
+ "Changed your mind?",
204
+ " ",
205
+ /* @__PURE__ */ jsx(
206
+ "a",
207
+ {
208
+ href: resubscribeUrl,
209
+ className: "text-primary underline hover:no-underline",
210
+ children: "Resubscribe"
211
+ }
212
+ )
213
+ ] })
214
+ ] }),
215
+ state === "error" && /* @__PURE__ */ jsxs("div", { children: [
216
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center", children: /* @__PURE__ */ jsx(
217
+ "svg",
218
+ {
219
+ className: "w-8 h-8 text-red-600 dark:text-red-400",
220
+ fill: "none",
221
+ viewBox: "0 0 24 24",
222
+ stroke: "currentColor",
223
+ strokeWidth: 2,
224
+ children: /* @__PURE__ */ jsx(
225
+ "path",
226
+ {
227
+ strokeLinecap: "round",
228
+ strokeLinejoin: "round",
229
+ d: "M6 18L18 6M6 6l12 12"
230
+ }
231
+ )
232
+ }
233
+ ) }),
234
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Unsubscribe Failed" }),
235
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-8", children: error }),
236
+ /* @__PURE__ */ jsx(Button, { onClick: () => setState("confirming"), variant: "outline", children: "Try Again" })
237
+ ] }),
238
+ state === "invalid" && /* @__PURE__ */ jsxs("div", { children: [
239
+ /* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-6 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center", children: /* @__PURE__ */ jsx(
240
+ "svg",
241
+ {
242
+ className: "w-8 h-8 text-gray-400",
243
+ fill: "none",
244
+ viewBox: "0 0 24 24",
245
+ stroke: "currentColor",
246
+ strokeWidth: 2,
247
+ children: /* @__PURE__ */ jsx(
248
+ "path",
249
+ {
250
+ strokeLinecap: "round",
251
+ strokeLinejoin: "round",
252
+ d: "M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
253
+ }
254
+ )
255
+ }
256
+ ) }),
257
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground mb-3", children: "Invalid Unsubscribe Link" }),
258
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "This unsubscribe link is invalid or missing. If you want to unsubscribe, please use the link from your newsletter email." })
259
+ ] })
260
+ ] })
261
+ ]
262
+ }
263
+ );
264
+ }
265
+
266
+ export { UnsubscribePage };
267
+ //# sourceMappingURL=chunk-UM55U65W.mjs.map
268
+ //# sourceMappingURL=chunk-UM55U65W.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/unsubscribe.tsx"],"names":[],"mappings":"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","file":"chunk-UM55U65W.mjs","sourcesContent":["\"use client\";\n\nimport { useState, useEffect } from \"react\";\n\nimport { toast } from \"sonner\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { PageHead } from \"../seo/page-head\";\nimport { Button } from \"../ui/button\";\n\n// ============================================================================\n// GRAPHQL MUTATION\n// ============================================================================\n\nconst UNSUBSCRIBE_MUTATION = /* GraphQL */ `\n mutation PublicUnsubscribeByToken($token: String!) {\n publicUnsubscribeByToken(token: $token)\n }\n`;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface UnsubscribePageProps {\n productName?: string;\n className?: string;\n seoTitle?: string;\n seoDescription?: string;\n resubscribeUrl?: string;\n successMessage?: string;\n errorMessage?: string;\n}\n\ntype UnsubscribeState =\n \"loading\" | \"confirming\" | \"processing\" | \"success\" | \"error\" | \"invalid\";\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function UnsubscribePage({\n productName,\n className = \"\",\n seoTitle = \"Unsubscribe from Newsletter\",\n seoDescription = \"Manage your newsletter subscription preferences.\",\n resubscribeUrl,\n successMessage = \"You have been successfully unsubscribed from our newsletter.\",\n errorMessage = \"Something went wrong. Please try again or contact support.\",\n}: UnsubscribePageProps) {\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const displayName = productName ?? config.productId;\n\n const [state, setState] = useState<UnsubscribeState>(\"loading\");\n const [error, setError] = useState<string>(\"\");\n const [token, setToken] = useState<string>(\"\");\n const [successCopy, setSuccessCopy] = useState<string>(successMessage);\n\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const t = params.get(\"token\");\n if (t) {\n setToken(t);\n setState(\"confirming\");\n } else {\n setState(\"invalid\");\n }\n }, []);\n\n const handleUnsubscribe = async () => {\n if (!token) return;\n\n setState(\"processing\");\n\n try {\n const result = await client.mutate<{\n publicUnsubscribeByToken: boolean;\n }>(UNSUBSCRIBE_MUTATION, { token });\n\n if (result.errors?.length) {\n const errMsg = result.errors[0]?.message ?? errorMessage;\n const code = (result.errors[0] as { extensions?: { code?: string } })\n ?.extensions?.code;\n\n if (code === \"ALREADY_UNSUBSCRIBED\") {\n toast.info(\"You are already unsubscribed from this newsletter.\");\n setSuccessCopy(\"You were already unsubscribed from this newsletter.\");\n setState(\"success\");\n return;\n } else if (code === \"UNSUBSCRIBE_TOKEN_EXPIRED\") {\n setError(\n \"This unsubscribe link has expired. Please contact support.\",\n );\n } else if (code === \"INVALID_UNSUBSCRIBE_TOKEN\") {\n setState(\"invalid\");\n return;\n } else {\n setError(errMsg);\n }\n setState(\"error\");\n return;\n }\n\n if (result.data?.publicUnsubscribeByToken) {\n setSuccessCopy(successMessage);\n setState(\"success\");\n toast.success(\"Successfully unsubscribed\");\n } else {\n setError(errorMessage);\n setState(\"error\");\n }\n } catch {\n setError(errorMessage);\n setState(\"error\");\n }\n };\n\n return (\n <div\n className={className}\n style={{\n minHeight: \"60vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"6rem 1rem 4rem\",\n }}\n >\n <PageHead title={seoTitle} description={seoDescription} />\n\n <div className=\"max-w-md w-full text-center\">\n {/* Loading */}\n {state === \"loading\" && (\n <div className=\"animate-pulse\">\n <div className=\"h-8 w-48 bg-muted rounded mx-auto mb-4\" />\n <div className=\"h-4 w-64 bg-muted rounded mx-auto\" />\n </div>\n )}\n\n {/* Confirm */}\n {state === \"confirming\" && (\n <div>\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-amber-600 dark:text-amber-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-foreground mb-3\">\n Unsubscribe from Newsletter\n </h1>\n <p className=\"text-muted-foreground mb-8\">\n Are you sure you want to unsubscribe from {displayName}{\" \"}\n newsletter? You will no longer receive updates and news from us.\n </p>\n <div className=\"flex flex-col sm:flex-row gap-3 justify-center\">\n <Button\n onClick={handleUnsubscribe}\n variant=\"destructive\"\n className=\"px-8\"\n >\n Yes, Unsubscribe\n </Button>\n {resubscribeUrl && (\n <Button\n variant=\"outline\"\n onClick={() => {\n window.location.href = resubscribeUrl;\n }}\n className=\"px-8\"\n >\n Cancel\n </Button>\n )}\n </div>\n </div>\n )}\n\n {/* Processing */}\n {state === \"processing\" && (\n <div>\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-muted flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-muted-foreground animate-spin\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-foreground mb-3\">\n Unsubscribing...\n </h1>\n <p className=\"text-muted-foreground\">\n Please wait while we process your request.\n </p>\n </div>\n )}\n\n {/* Success */}\n {state === \"success\" && (\n <div>\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-green-100 dark:bg-green-900/30 flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-green-600 dark:text-green-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-foreground mb-3\">\n Successfully Unsubscribed\n </h1>\n <p className=\"text-muted-foreground mb-8\">{successCopy}</p>\n {resubscribeUrl && (\n <p className=\"text-sm text-muted-foreground\">\n Changed your mind?{\" \"}\n <a\n href={resubscribeUrl}\n className=\"text-primary underline hover:no-underline\"\n >\n Resubscribe\n </a>\n </p>\n )}\n </div>\n )}\n\n {/* Error */}\n {state === \"error\" && (\n <div>\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-foreground mb-3\">\n Unsubscribe Failed\n </h1>\n <p className=\"text-muted-foreground mb-8\">{error}</p>\n <Button onClick={() => setState(\"confirming\")} variant=\"outline\">\n Try Again\n </Button>\n </div>\n )}\n\n {/* Invalid / No Token */}\n {state === \"invalid\" && (\n <div>\n <div className=\"w-16 h-16 mx-auto mb-6 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center\">\n <svg\n className=\"w-8 h-8 text-gray-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-foreground mb-3\">\n Invalid Unsubscribe Link\n </h1>\n <p className=\"text-muted-foreground\">\n This unsubscribe link is invalid or missing. If you want to\n unsubscribe, please use the link from your newsletter email.\n </p>\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var chunkC6OJIHNO_js = require('./chunk-C6OJIHNO.js');
4
+ var React = require('react');
5
+ var reactSlot = require('@radix-ui/react-slot');
6
+ var classVarianceAuthority = require('class-variance-authority');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+
29
+ var buttonVariants = classVarianceAuthority.cva(
30
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
31
+ {
32
+ variants: {
33
+ variant: {
34
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
35
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
36
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
37
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
38
+ ghost: "hover:bg-accent hover:text-accent-foreground",
39
+ link: "text-primary underline-offset-4 hover:underline"
40
+ },
41
+ size: {
42
+ default: "h-9 px-4 py-2",
43
+ sm: "h-8 rounded-md px-3 text-xs",
44
+ lg: "h-10 rounded-md px-8",
45
+ icon: "h-9 w-9"
46
+ }
47
+ },
48
+ defaultVariants: {
49
+ variant: "default",
50
+ size: "default"
51
+ }
52
+ }
53
+ );
54
+ var Button = React__namespace.forwardRef(
55
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
56
+ const Comp = asChild ? reactSlot.Slot : "button";
57
+ return /* @__PURE__ */ jsxRuntime.jsx(
58
+ Comp,
59
+ {
60
+ className: chunkC6OJIHNO_js.cn(buttonVariants({ variant, size, className })),
61
+ ref,
62
+ ...props
63
+ }
64
+ );
65
+ }
66
+ );
67
+ Button.displayName = "Button";
68
+
69
+ exports.Button = Button;
70
+ exports.buttonVariants = buttonVariants;
71
+ //# sourceMappingURL=chunk-UQ2HALUD.js.map
72
+ //# sourceMappingURL=chunk-UQ2HALUD.js.map