@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,2771 @@
1
+ import { useContentPage, ContentRenderer } from './chunk-EDLTUOIA.mjs';
2
+ import { ProseStyles } from './chunk-6VJT3SM4.mjs';
3
+ import { Input } from './chunk-34RX5P75.mjs';
4
+ import { PageHead } from './chunk-N5EC53MH.mjs';
5
+ import { Button } from './chunk-KHYXK7FG.mjs';
6
+ import { cn } from './chunk-R7G6TWIS.mjs';
7
+ import { useProduct } from './chunk-GCFLCO2Z.mjs';
8
+ import { useWebSDK, useWebSDKConfig } from './chunk-5JRJ57CL.mjs';
9
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
+ import { useState, useCallback, useEffect, useMemo } from 'react';
11
+ import { History, Search, ChevronLeft, ChevronRight } from 'lucide-react';
12
+
13
+ var LEGAL_DOCUMENTS = {
14
+ privacy: {
15
+ key: "privacy",
16
+ slug: "privacy-policy",
17
+ title: "Privacy Policy",
18
+ description: "How we collect, use, share and protect your personal information."
19
+ },
20
+ terms: {
21
+ key: "terms",
22
+ slug: "terms-of-service",
23
+ title: "Terms of Service",
24
+ description: "The terms that govern your use of the service."
25
+ },
26
+ cookies: {
27
+ key: "cookies",
28
+ slug: "cookie-policy",
29
+ title: "Cookie Policy",
30
+ description: "The cookies and similar technologies we use, and why."
31
+ },
32
+ refunds: {
33
+ key: "refunds",
34
+ slug: "refund-policy",
35
+ title: "Refund Policy",
36
+ description: "How cancellations and refunds work for paid plans."
37
+ },
38
+ aup: {
39
+ key: "aup",
40
+ slug: "acceptable-use-policy",
41
+ title: "Acceptable Use Policy",
42
+ description: "What you may and may not do with the service."
43
+ },
44
+ dpa: {
45
+ key: "dpa",
46
+ slug: "data-processing-addendum",
47
+ title: "Data Processing Addendum",
48
+ description: "Our obligations as a processor of personal data on your behalf."
49
+ },
50
+ "ai-terms": {
51
+ key: "ai-terms",
52
+ slug: "ai-product-terms",
53
+ title: "AI Product Terms",
54
+ description: "The terms that apply to AI features, including how your data is and is not used."
55
+ },
56
+ subprocessors: {
57
+ key: "subprocessors",
58
+ slug: "subprocessors",
59
+ title: "Subprocessors",
60
+ description: "The third parties that help us host, secure and support the service."
61
+ }
62
+ };
63
+ var LEGAL_DOCUMENT_KEYS = Object.keys(
64
+ LEGAL_DOCUMENTS
65
+ );
66
+ function findLegalDocument(keyOrSlug) {
67
+ if (Object.prototype.hasOwnProperty.call(LEGAL_DOCUMENTS, keyOrSlug)) {
68
+ return LEGAL_DOCUMENTS[keyOrSlug];
69
+ }
70
+ return Object.values(LEGAL_DOCUMENTS).find((doc) => doc.slug === keyOrSlug) ?? null;
71
+ }
72
+ var LEGAL_CONTENT_QUERY = `
73
+ query PublicLegalContentPage($slug: String!, $productId: String!) {
74
+ publicResolvedContentPage(slug: $slug, productId: $productId) {
75
+ title
76
+ slug
77
+ content
78
+ contentFormat
79
+ seoTitle
80
+ seoDescription
81
+ seoKeywords
82
+ lastUpdated
83
+ }
84
+ }
85
+ `;
86
+ async function fetchLegalContentPage(client, slug, productId) {
87
+ const result = await client.query(LEGAL_CONTENT_QUERY, { slug, productId }, { cache: false });
88
+ if (result.errors?.length) {
89
+ throw new Error(result.errors[0]?.message ?? "Unknown error");
90
+ }
91
+ return result.data?.publicResolvedContentPage ?? null;
92
+ }
93
+ async function fetchLegalContent(client, options) {
94
+ const docs = (options.documents ?? LEGAL_DOCUMENT_KEYS).map(
95
+ (key) => LEGAL_DOCUMENTS[key]
96
+ );
97
+ const entries = await Promise.all(
98
+ docs.map(
99
+ async (doc) => [
100
+ doc.slug,
101
+ await fetchLegalContentPage(client, doc.slug, options.productId)
102
+ ]
103
+ )
104
+ );
105
+ return Object.fromEntries(entries);
106
+ }
107
+ function splitLeadingHeading(content, format) {
108
+ if (format.toLowerCase() !== "markdown")
109
+ return { heading: null, body: content };
110
+ const match = /^\s*#[ \t]+([^\n]+?)[ \t#]*(?:\n|$)/.exec(content);
111
+ if (!match?.[1]) return { heading: null, body: content };
112
+ return {
113
+ heading: match[1].trim(),
114
+ body: content.slice(match[0].length).replace(/^\s+/, "")
115
+ };
116
+ }
117
+ function formatLegalDate(iso) {
118
+ if (!iso) return null;
119
+ const date = new Date(iso);
120
+ if (Number.isNaN(date.getTime())) return null;
121
+ return date.toLocaleDateString("en-US", {
122
+ year: "numeric",
123
+ month: "long",
124
+ day: "numeric",
125
+ timeZone: "UTC"
126
+ });
127
+ }
128
+ function LegalPage(props) {
129
+ const {
130
+ document: document2,
131
+ slug: slugProp,
132
+ initialContent,
133
+ fallbackTitle,
134
+ fallbackDescription,
135
+ productName,
136
+ canonicalUrl,
137
+ contactEmail,
138
+ className = ""
139
+ } = props;
140
+ const registered = document2 ? LEGAL_DOCUMENTS[document2] : slugProp ? findLegalDocument(slugProp) : null;
141
+ const slug = registered?.slug ?? slugProp ?? "";
142
+ const prefetched = initialContent !== void 0;
143
+ const { data: fetched, loading } = useContentPage(slug, {
144
+ resolve: true,
145
+ enabled: !prefetched && slug !== ""
146
+ });
147
+ const page = prefetched ? initialContent ?? null : fetched;
148
+ const isLoading = !prefetched && slug !== "" && loading;
149
+ const defaultTitle = fallbackTitle ?? registered?.title ?? "Legal";
150
+ const defaultDescription = fallbackDescription ?? registered?.description ?? "";
151
+ const { heading, body } = page ? splitLeadingHeading(page.content, page.contentFormat) : { heading: null, body: "" };
152
+ const title = page?.title || heading || defaultTitle;
153
+ const updated = formatLegalDate(page?.lastUpdated);
154
+ const unavailable = !isLoading && !page;
155
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
156
+ /* @__PURE__ */ jsx(ProseStyles, {}),
157
+ /* @__PURE__ */ jsx(
158
+ PageHead,
159
+ {
160
+ title: page?.seoTitle || title,
161
+ description: page?.seoDescription?.trim() || defaultDescription,
162
+ keywords: page?.seoKeywords ?? void 0,
163
+ productName,
164
+ url: canonicalUrl,
165
+ robots: unavailable ? "noindex, follow" : void 0
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsxs(
169
+ "article",
170
+ {
171
+ className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-24",
172
+ "aria-busy": isLoading,
173
+ children: [
174
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl font-bold tracking-tight text-foreground mb-3", children: title }),
175
+ updated && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mb-10", children: [
176
+ "Last updated:",
177
+ " ",
178
+ /* @__PURE__ */ jsx("time", { dateTime: page?.lastUpdated ?? void 0, children: updated })
179
+ ] }),
180
+ isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", "data-testid": "legal-page-loading", children: [
181
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 rounded bg-muted animate-pulse" }),
182
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-full rounded bg-muted animate-pulse" }),
183
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-5/6 rounded bg-muted animate-pulse" })
184
+ ] }) : page ? /* @__PURE__ */ jsx("div", { className: "boff-prose max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content: body, format: page.contentFormat }) }) : /* @__PURE__ */ jsxs(
185
+ "div",
186
+ {
187
+ role: "status",
188
+ className: "rounded-xl border border-border bg-muted/30 p-6",
189
+ children: [
190
+ /* @__PURE__ */ jsx("p", { className: "text-base text-foreground", children: "This document is not available right now." }),
191
+ contactEmail && /* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm text-muted-foreground", children: [
192
+ "For a copy, contact",
193
+ " ",
194
+ /* @__PURE__ */ jsx(
195
+ "a",
196
+ {
197
+ className: "text-primary underline",
198
+ href: `mailto:${contactEmail}`,
199
+ children: contactEmail
200
+ }
201
+ ),
202
+ "."
203
+ ] })
204
+ ]
205
+ }
206
+ )
207
+ ]
208
+ }
209
+ )
210
+ ] });
211
+ }
212
+ var PUBLIC_JOB_POSTING_FIELDS = (
213
+ /* GraphQL */
214
+ `
215
+ id
216
+ slug
217
+ title
218
+ department
219
+ location
220
+ employmentType
221
+ openings
222
+ description
223
+ overview
224
+ responsibilities
225
+ learnings
226
+ qualifications
227
+ rounds {
228
+ roundNumber
229
+ name
230
+ roundType
231
+ isRequired
232
+ description
233
+ }
234
+ `
235
+ );
236
+ var PUBLIC_JOB_POSTINGS_QUERY = (
237
+ /* GraphQL */
238
+ `
239
+ query PublicJobPostings($productId: ID, $limit: Int, $offset: Int) {
240
+ publicJobPostings(productId: $productId, limit: $limit, offset: $offset) {
241
+ ${PUBLIC_JOB_POSTING_FIELDS}
242
+ }
243
+ }
244
+ `
245
+ );
246
+ var PUBLIC_JOB_POSTING_QUERY = (
247
+ /* GraphQL */
248
+ `
249
+ query PublicJobPosting($slug: String!, $productId: ID) {
250
+ publicJobPosting(slug: $slug, productId: $productId) {
251
+ ${PUBLIC_JOB_POSTING_FIELDS}
252
+ }
253
+ }
254
+ `
255
+ );
256
+ var PUBLIC_JOB_POSTINGS_FOR_SUBMISSION_QUERY = (
257
+ /* GraphQL */
258
+ `
259
+ query PublicJobPostingsForSubmission(
260
+ $productId: ID
261
+ $limit: Int
262
+ $offset: Int
263
+ ) {
264
+ publicJobPostingsForSubmission(
265
+ productId: $productId
266
+ limit: $limit
267
+ offset: $offset
268
+ ) {
269
+ id
270
+ title
271
+ }
272
+ }
273
+ `
274
+ );
275
+ async function fetchPublicJobPostings(client, options) {
276
+ const result = await client.query(PUBLIC_JOB_POSTINGS_QUERY, {
277
+ productId: options?.productId,
278
+ limit: options?.limit ?? 50,
279
+ offset: options?.offset ?? 0
280
+ });
281
+ if (result.errors?.length) {
282
+ throw new Error(result.errors[0]?.message ?? "Unknown error");
283
+ }
284
+ return result.data?.publicJobPostings ?? [];
285
+ }
286
+ async function fetchPublicJobPosting(client, slug, options) {
287
+ const result = await client.query(PUBLIC_JOB_POSTING_QUERY, {
288
+ slug,
289
+ productId: options?.productId
290
+ });
291
+ if (result.errors?.length) {
292
+ throw new Error(result.errors[0]?.message ?? "Unknown error");
293
+ }
294
+ return result.data?.publicJobPosting ?? null;
295
+ }
296
+ async function fetchPublicJobPostingsForSubmission(client, options) {
297
+ const result = await client.query(PUBLIC_JOB_POSTINGS_FOR_SUBMISSION_QUERY, {
298
+ productId: options?.productId,
299
+ limit: options?.limit ?? 50,
300
+ offset: options?.offset ?? 0
301
+ });
302
+ if (result.errors?.length) {
303
+ throw new Error(result.errors[0]?.message ?? "Unknown error");
304
+ }
305
+ return result.data?.publicJobPostingsForSubmission ?? [];
306
+ }
307
+ function usePublicJobPostings(options) {
308
+ const client = useWebSDK();
309
+ const config = useWebSDKConfig();
310
+ const { product } = useProduct();
311
+ const resolvedProductId = options?.productId ?? product?.id ?? config.productId;
312
+ const [postings, setPostings] = useState([]);
313
+ const [loading, setLoading] = useState(true);
314
+ const [error, setError] = useState(null);
315
+ const fetchPostings = useCallback(async () => {
316
+ setLoading(true);
317
+ setError(null);
318
+ try {
319
+ const items = await fetchPublicJobPostings(client, {
320
+ productId: resolvedProductId,
321
+ limit: options?.limit,
322
+ offset: options?.offset
323
+ });
324
+ setPostings(items);
325
+ } catch (err) {
326
+ setError(
327
+ err instanceof Error ? err.message : "Failed to fetch job postings"
328
+ );
329
+ setPostings([]);
330
+ } finally {
331
+ setLoading(false);
332
+ }
333
+ }, [client, resolvedProductId, options?.limit, options?.offset]);
334
+ useEffect(() => {
335
+ fetchPostings();
336
+ }, [fetchPostings]);
337
+ return { postings, loading, error, refetch: fetchPostings };
338
+ }
339
+ function usePublicJobPostingsForSubmission(options) {
340
+ const client = useWebSDK();
341
+ const config = useWebSDKConfig();
342
+ const { product } = useProduct();
343
+ const resolvedProductId = options?.productId ?? product?.id ?? config.productId;
344
+ const [postings, setPostings] = useState([]);
345
+ const [loading, setLoading] = useState(true);
346
+ const [error, setError] = useState(null);
347
+ const fetchPostings = useCallback(async () => {
348
+ setLoading(true);
349
+ setError(null);
350
+ try {
351
+ const items = await fetchPublicJobPostingsForSubmission(client, {
352
+ productId: resolvedProductId,
353
+ limit: options?.limit,
354
+ offset: options?.offset
355
+ });
356
+ setPostings(items);
357
+ } catch (err) {
358
+ setError(
359
+ err instanceof Error ? err.message : "Failed to fetch job postings"
360
+ );
361
+ setPostings([]);
362
+ } finally {
363
+ setLoading(false);
364
+ }
365
+ }, [client, resolvedProductId, options?.limit, options?.offset]);
366
+ useEffect(() => {
367
+ fetchPostings();
368
+ }, [fetchPostings]);
369
+ return { postings, loading, error, refetch: fetchPostings };
370
+ }
371
+ function usePublicJobPosting(slug, options) {
372
+ const client = useWebSDK();
373
+ const config = useWebSDKConfig();
374
+ const { product } = useProduct();
375
+ const resolvedProductId = options?.productId ?? product?.id ?? config.productId;
376
+ const [posting, setPosting] = useState(null);
377
+ const [loading, setLoading] = useState(true);
378
+ const [error, setError] = useState(null);
379
+ const fetchPosting = useCallback(async () => {
380
+ if (!slug) {
381
+ setPosting(null);
382
+ setLoading(false);
383
+ return;
384
+ }
385
+ setLoading(true);
386
+ setError(null);
387
+ try {
388
+ const item = await fetchPublicJobPosting(client, slug, {
389
+ productId: resolvedProductId
390
+ });
391
+ setPosting(item);
392
+ } catch (err) {
393
+ setError(
394
+ err instanceof Error ? err.message : "Failed to fetch job posting"
395
+ );
396
+ setPosting(null);
397
+ } finally {
398
+ setLoading(false);
399
+ }
400
+ }, [client, resolvedProductId, slug]);
401
+ useEffect(() => {
402
+ fetchPosting();
403
+ }, [fetchPosting]);
404
+ return { posting, loading, error, refetch: fetchPosting };
405
+ }
406
+ var BLOG_POSTS_QUERY = `
407
+ query BlogPosts($productId: String!, $limit: Int, $offset: Int) {
408
+ publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
409
+ items {
410
+ id
411
+ title
412
+ slug
413
+ lastUpdated
414
+ tags
415
+ seoDescription
416
+ excerpt
417
+ thumbnail
418
+ author
419
+ publishedAt
420
+ readingTime
421
+ featured
422
+ category
423
+ }
424
+ total
425
+ hasMore
426
+ }
427
+ }
428
+ `;
429
+ var BLOG_POST_QUERY = `
430
+ query BlogPost($slug: String!, $productId: String) {
431
+ publicContentPage(slug: $slug, productId: $productId) {
432
+ id
433
+ title
434
+ slug
435
+ content
436
+ contentFormat
437
+ seoTitle
438
+ seoDescription
439
+ seoKeywords
440
+ lastUpdated
441
+ tags
442
+ excerpt
443
+ thumbnail
444
+ author
445
+ publishedAt
446
+ readingTime
447
+ featured
448
+ category
449
+ }
450
+ }
451
+ `;
452
+ function BlogCard({
453
+ post,
454
+ basePath = "/blog"
455
+ }) {
456
+ const date = post.publishedAt || post.lastUpdated;
457
+ const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
458
+ year: "numeric",
459
+ month: "long",
460
+ day: "numeric"
461
+ }) : "";
462
+ const [imgError, setImgError] = useState(false);
463
+ return /* @__PURE__ */ jsxs(
464
+ "a",
465
+ {
466
+ href: `${basePath}/${post.slug}`,
467
+ className: "group block bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
468
+ children: [
469
+ post.thumbnail && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsx(
470
+ "img",
471
+ {
472
+ src: post.thumbnail,
473
+ alt: post.title,
474
+ className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
475
+ loading: "lazy",
476
+ onError: () => setImgError(true)
477
+ }
478
+ ) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
479
+ "svg",
480
+ {
481
+ className: "w-12 h-12 text-muted-foreground/20",
482
+ fill: "none",
483
+ viewBox: "0 0 24 24",
484
+ stroke: "currentColor",
485
+ children: /* @__PURE__ */ jsx(
486
+ "path",
487
+ {
488
+ strokeLinecap: "round",
489
+ strokeLinejoin: "round",
490
+ strokeWidth: 1.5,
491
+ d: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
492
+ }
493
+ )
494
+ }
495
+ ) }),
496
+ /* @__PURE__ */ jsxs("div", { className: "p-5 sm:p-6", children: [
497
+ post.category && /* @__PURE__ */ jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: post.category }),
498
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: post.title }),
499
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
500
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
501
+ post.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: post.author }),
502
+ post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
503
+ formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
504
+ post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
505
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
506
+ /* @__PURE__ */ jsxs("span", { children: [
507
+ post.readingTime,
508
+ " min read"
509
+ ] })
510
+ ] })
511
+ ] })
512
+ ] })
513
+ ]
514
+ }
515
+ );
516
+ }
517
+ function BlogListPage(props) {
518
+ const {
519
+ productName,
520
+ heroTitle = "Blog",
521
+ heroSubtitle = "Latest updates, engineering insights, and product news",
522
+ blogPostBasePath = "/blog",
523
+ className = "",
524
+ seoTitle,
525
+ seoDescription,
526
+ seoKeywords
527
+ } = props;
528
+ const client = useWebSDK();
529
+ const config = useWebSDKConfig();
530
+ const { product } = useProduct();
531
+ const resolvedProductId = product?.id || config.productId;
532
+ const [posts, setPosts] = useState([]);
533
+ const [total, setTotal] = useState(0);
534
+ const [loading, setLoading] = useState(true);
535
+ const [error, setError] = useState(null);
536
+ const [offset, setOffset] = useState(0);
537
+ const limit = 12;
538
+ const fetchPosts = useCallback(async () => {
539
+ if (!resolvedProductId) return;
540
+ setLoading(true);
541
+ try {
542
+ const result = await client.query(BLOG_POSTS_QUERY, {
543
+ productId: resolvedProductId,
544
+ limit,
545
+ offset
546
+ });
547
+ if (result.errors?.length) {
548
+ setError(result.errors[0]?.message ?? "Failed to load posts");
549
+ return;
550
+ }
551
+ const blogPosts = (result.data?.publicContentPages?.items || []).filter(
552
+ (p) => p.tags?.includes("blog")
553
+ );
554
+ setPosts(blogPosts);
555
+ setTotal(result.data?.publicContentPages?.total || 0);
556
+ setError(null);
557
+ } catch {
558
+ setError("Failed to load blog posts");
559
+ } finally {
560
+ setLoading(false);
561
+ }
562
+ }, [client, resolvedProductId, offset]);
563
+ useEffect(() => {
564
+ fetchPosts();
565
+ }, [fetchPosts]);
566
+ const featuredPosts = posts.filter((p) => p.featured);
567
+ const regularPosts = posts.filter((p) => !p.featured);
568
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
569
+ seoTitle && /* @__PURE__ */ jsx(
570
+ PageHead,
571
+ {
572
+ title: seoTitle,
573
+ description: seoDescription || heroSubtitle,
574
+ productName,
575
+ keywords: seoKeywords,
576
+ url: typeof window !== "undefined" ? window.location.origin + window.location.pathname : void 0
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsx("section", { className: "py-16 sm:py-20 md:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
580
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground", children: heroTitle }),
581
+ /* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle })
582
+ ] }) }) }),
583
+ /* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
584
+ "div",
585
+ {
586
+ className: "bg-card border rounded-xl overflow-hidden animate-pulse",
587
+ children: [
588
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
589
+ /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-3", children: [
590
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
591
+ /* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-3/4" }),
592
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }),
593
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
594
+ ] })
595
+ ]
596
+ },
597
+ i
598
+ )) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) }) : posts.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No blog posts yet. Check back soon!" }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
599
+ featuredPosts.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 gap-6 sm:gap-8 mb-8", children: featuredPosts.map((post) => /* @__PURE__ */ jsx(
600
+ BlogCard,
601
+ {
602
+ post,
603
+ basePath: blogPostBasePath
604
+ },
605
+ post.id
606
+ )) }),
607
+ /* @__PURE__ */ jsx("div", { className: "grid md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8", children: regularPosts.map((post) => /* @__PURE__ */ jsx(
608
+ BlogCard,
609
+ {
610
+ post,
611
+ basePath: blogPostBasePath
612
+ },
613
+ post.id
614
+ )) }),
615
+ total > limit && /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4 mt-12", children: [
616
+ /* @__PURE__ */ jsx(
617
+ "button",
618
+ {
619
+ onClick: () => setOffset(Math.max(0, offset - limit)),
620
+ disabled: offset === 0,
621
+ className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
622
+ children: "Previous"
623
+ }
624
+ ),
625
+ /* @__PURE__ */ jsx(
626
+ "button",
627
+ {
628
+ onClick: () => setOffset(offset + limit),
629
+ disabled: offset + limit >= total,
630
+ className: "px-5 py-2.5 text-sm font-medium border rounded-lg disabled:opacity-40 hover:bg-muted transition-colors",
631
+ children: "Next"
632
+ }
633
+ )
634
+ ] })
635
+ ] }) }) })
636
+ ] });
637
+ }
638
+ function BlogPostPage(props) {
639
+ const {
640
+ productName,
641
+ blogListUrl = "/blog",
642
+ backLabel = "Back to Blog",
643
+ className = ""
644
+ } = props;
645
+ const client = useWebSDK();
646
+ const config = useWebSDKConfig();
647
+ const { product } = useProduct();
648
+ const resolvedProductId = product?.id || config.productId;
649
+ const [post, setPost] = useState(null);
650
+ const [loading, setLoading] = useState(true);
651
+ const [error, setError] = useState(null);
652
+ const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
653
+ useEffect(() => {
654
+ if (!slug || !resolvedProductId) return;
655
+ async function fetchPost() {
656
+ setLoading(true);
657
+ try {
658
+ const result = await client.query(BLOG_POST_QUERY, {
659
+ slug,
660
+ productId: resolvedProductId
661
+ });
662
+ if (result.errors?.length) {
663
+ setError(result.errors[0]?.message ?? "Failed to load post");
664
+ return;
665
+ }
666
+ setPost(result.data?.publicContentPage ?? null);
667
+ setError(null);
668
+ } catch {
669
+ setError("Failed to load blog post");
670
+ } finally {
671
+ setLoading(false);
672
+ }
673
+ }
674
+ fetchPost();
675
+ }, [client, slug, resolvedProductId]);
676
+ if (loading) {
677
+ return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
678
+ /* @__PURE__ */ jsx("div", { className: "h-8 bg-muted rounded w-2/3" }),
679
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/3" }),
680
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted rounded-xl" }),
681
+ /* @__PURE__ */ jsx("div", { className: "space-y-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }, i)) })
682
+ ] }) }) });
683
+ }
684
+ if (error || !post) {
685
+ return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-24 text-center", children: [
686
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold mb-4", children: "Post not found" }),
687
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-6", children: error || "This blog post doesn't exist or has been removed." }),
688
+ /* @__PURE__ */ jsxs(
689
+ "a",
690
+ {
691
+ href: blogListUrl,
692
+ className: "text-primary hover:underline font-medium",
693
+ children: [
694
+ "\u2190 ",
695
+ backLabel
696
+ ]
697
+ }
698
+ )
699
+ ] }) });
700
+ }
701
+ const date = post.publishedAt || post.lastUpdated;
702
+ const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
703
+ year: "numeric",
704
+ month: "long",
705
+ day: "numeric"
706
+ }) : "";
707
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
708
+ /* @__PURE__ */ jsx(ProseStyles, {}),
709
+ /* @__PURE__ */ jsx(
710
+ PageHead,
711
+ {
712
+ title: post.seoTitle || post.title,
713
+ description: post.seoDescription || post.excerpt || "",
714
+ productName,
715
+ keywords: post.seoKeywords || "",
716
+ image: post.thumbnail || void 0,
717
+ url: typeof window !== "undefined" ? window.location.origin + window.location.pathname : void 0
718
+ }
719
+ ),
720
+ /* @__PURE__ */ jsxs("article", { className: "max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-16 sm:py-20", children: [
721
+ /* @__PURE__ */ jsxs(
722
+ "a",
723
+ {
724
+ href: blogListUrl,
725
+ className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-8 transition-colors",
726
+ children: [
727
+ "\u2190 ",
728
+ backLabel
729
+ ]
730
+ }
731
+ ),
732
+ post.category && /* @__PURE__ */ jsx("span", { className: "inline-block text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-4", children: post.category }),
733
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4", children: post.title }),
734
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-sm text-muted-foreground mb-8", children: [
735
+ post.author && /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: post.author }),
736
+ post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
737
+ formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
738
+ post.readingTime && /* @__PURE__ */ jsxs(Fragment, { children: [
739
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
740
+ /* @__PURE__ */ jsxs("span", { children: [
741
+ post.readingTime,
742
+ " min read"
743
+ ] })
744
+ ] })
745
+ ] }),
746
+ post.thumbnail && /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] rounded-xl overflow-hidden mb-10", children: /* @__PURE__ */ jsx(
747
+ "img",
748
+ {
749
+ src: post.thumbnail,
750
+ alt: post.title,
751
+ className: "w-full h-full object-cover"
752
+ }
753
+ ) }),
754
+ /* @__PURE__ */ jsx("div", { className: "boff-prose max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content: post.content, format: post.contentFormat }) })
755
+ ] })
756
+ ] });
757
+ }
758
+ var CASE_STUDY_TAG = "case-study";
759
+ function hasCustomerSignOff(page) {
760
+ const signedAt = page.customerSignOff?.signedAt;
761
+ return typeof signedAt === "string" && !Number.isNaN(new Date(signedAt).getTime());
762
+ }
763
+ var ANIMATION_STYLES = `
764
+ @keyframes csFadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
765
+ @keyframes csFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
766
+ .cs-fade-up { animation: csFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) both; }
767
+ .cs-float { animation: csFloat 7s ease-in-out infinite; }
768
+ @media (prefers-reduced-motion: reduce) {
769
+ .cs-fade-up, .cs-float { animation: none !important; }
770
+ }
771
+ `;
772
+ function AnimationStyles() {
773
+ return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: ANIMATION_STYLES } });
774
+ }
775
+ var CASE_STUDIES_QUERY = `
776
+ query CaseStudies($productId: String!, $tag: String, $limit: Int, $offset: Int) {
777
+ publicContentPages(productId: $productId, tag: $tag, limit: $limit, offset: $offset) {
778
+ items {
779
+ id
780
+ title
781
+ slug
782
+ lastUpdated
783
+ tags
784
+ seoDescription
785
+ excerpt
786
+ thumbnail
787
+ author
788
+ publishedAt
789
+ readingTime
790
+ featured
791
+ category
792
+ customerSignOff {
793
+ signedAt
794
+ }
795
+ }
796
+ total
797
+ hasMore
798
+ }
799
+ }
800
+ `;
801
+ var CASE_STUDY_QUERY = `
802
+ query CaseStudy($slug: String!, $productId: String) {
803
+ publicContentPage(slug: $slug, productId: $productId) {
804
+ id
805
+ title
806
+ slug
807
+ content
808
+ contentFormat
809
+ seoTitle
810
+ seoDescription
811
+ seoKeywords
812
+ lastUpdated
813
+ tags
814
+ excerpt
815
+ thumbnail
816
+ author
817
+ publishedAt
818
+ readingTime
819
+ featured
820
+ category
821
+ customerSignOff {
822
+ signedAt
823
+ }
824
+ }
825
+ }
826
+ `;
827
+ function formatDate(value) {
828
+ if (!value) return "";
829
+ const d = new Date(value);
830
+ if (Number.isNaN(d.getTime())) return "";
831
+ return d.toLocaleDateString("en-US", {
832
+ year: "numeric",
833
+ month: "long",
834
+ day: "numeric"
835
+ });
836
+ }
837
+ function Thumbnail({
838
+ src,
839
+ alt,
840
+ className = ""
841
+ }) {
842
+ const [imgError, setImgError] = useState(false);
843
+ if (src && !imgError) {
844
+ return /* @__PURE__ */ jsx(
845
+ "img",
846
+ {
847
+ src,
848
+ alt,
849
+ className,
850
+ loading: "lazy",
851
+ onError: () => setImgError(true)
852
+ }
853
+ );
854
+ }
855
+ return /* @__PURE__ */ jsx(
856
+ "div",
857
+ {
858
+ className: `flex items-center justify-center bg-gradient-to-br from-muted/60 to-muted ${className}`,
859
+ "aria-hidden": "true",
860
+ children: /* @__PURE__ */ jsx(
861
+ "svg",
862
+ {
863
+ className: "w-12 h-12 text-muted-foreground/25",
864
+ fill: "none",
865
+ viewBox: "0 0 24 24",
866
+ stroke: "currentColor",
867
+ children: /* @__PURE__ */ jsx(
868
+ "path",
869
+ {
870
+ strokeLinecap: "round",
871
+ strokeLinejoin: "round",
872
+ strokeWidth: 1.5,
873
+ d: "M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
874
+ }
875
+ )
876
+ }
877
+ )
878
+ }
879
+ );
880
+ }
881
+ function MetaRow({
882
+ post,
883
+ className = ""
884
+ }) {
885
+ const formattedDate = formatDate(post.publishedAt || post.lastUpdated);
886
+ return /* @__PURE__ */ jsxs(
887
+ "div",
888
+ {
889
+ className: `flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground ${className}`,
890
+ children: [
891
+ post.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: post.author }),
892
+ post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
893
+ formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
894
+ post.readingTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
895
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
896
+ /* @__PURE__ */ jsxs("span", { children: [
897
+ post.readingTime,
898
+ " min read"
899
+ ] })
900
+ ] }) : null
901
+ ]
902
+ }
903
+ );
904
+ }
905
+ function FeaturedCard({
906
+ post,
907
+ basePath
908
+ }) {
909
+ return /* @__PURE__ */ jsxs(
910
+ "a",
911
+ {
912
+ href: `${basePath}/${post.slug}`,
913
+ className: "group relative grid md:grid-cols-2 gap-0 overflow-hidden rounded-2xl border bg-card shadow-sm transition-all duration-300 hover:-translate-y-1 hover:shadow-xl hover:border-primary/40",
914
+ children: [
915
+ /* @__PURE__ */ jsxs("div", { className: "relative aspect-[16/10] md:aspect-auto md:h-full overflow-hidden", children: [
916
+ /* @__PURE__ */ jsx(
917
+ Thumbnail,
918
+ {
919
+ src: post.thumbnail,
920
+ alt: post.title,
921
+ className: "w-full h-full min-h-[220px] object-cover transition-transform duration-500 group-hover:scale-[1.04]"
922
+ }
923
+ ),
924
+ /* @__PURE__ */ jsxs("span", { className: "absolute top-4 left-4 inline-flex items-center gap-1 rounded-full bg-primary px-2.5 py-1 text-xs font-semibold text-primary-foreground shadow-sm", children: [
925
+ /* @__PURE__ */ jsx(
926
+ "svg",
927
+ {
928
+ className: "h-3 w-3",
929
+ viewBox: "0 0 20 20",
930
+ fill: "currentColor",
931
+ "aria-hidden": "true",
932
+ children: /* @__PURE__ */ jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.286 3.957a1 1 0 00.95.69h4.162c.969 0 1.371 1.24.588 1.81l-3.368 2.447a1 1 0 00-.364 1.118l1.287 3.957c.3.921-.755 1.688-1.54 1.118l-3.367-2.447a1 1 0 00-1.176 0l-3.367 2.447c-.784.57-1.838-.197-1.539-1.118l1.286-3.957a1 1 0 00-.363-1.118L2.98 9.384c-.783-.57-.38-1.81.588-1.81h4.162a1 1 0 00.95-.69l1.286-3.957z" })
933
+ }
934
+ ),
935
+ "Featured"
936
+ ] })
937
+ ] }),
938
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col justify-center p-6 sm:p-8", children: [
939
+ post.category && /* @__PURE__ */ jsx("span", { className: "mb-3 inline-block w-fit rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary", children: post.category }),
940
+ /* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground transition-colors group-hover:text-primary line-clamp-3", children: post.title }),
941
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm sm:text-base text-muted-foreground line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
942
+ /* @__PURE__ */ jsx(MetaRow, { post, className: "mt-5" }),
943
+ /* @__PURE__ */ jsxs("span", { className: "mt-5 inline-flex items-center gap-1 text-sm font-semibold text-primary", children: [
944
+ "Read the story",
945
+ /* @__PURE__ */ jsx(
946
+ "svg",
947
+ {
948
+ className: "h-4 w-4 transition-transform duration-300 group-hover:translate-x-1",
949
+ viewBox: "0 0 20 20",
950
+ fill: "currentColor",
951
+ "aria-hidden": "true",
952
+ children: /* @__PURE__ */ jsx(
953
+ "path",
954
+ {
955
+ fillRule: "evenodd",
956
+ d: "M7.293 4.293a1 1 0 011.414 0l5 5a1 1 0 010 1.414l-5 5a1 1 0 01-1.414-1.414L11.586 10 7.293 5.707a1 1 0 010-1.414z",
957
+ clipRule: "evenodd"
958
+ }
959
+ )
960
+ }
961
+ )
962
+ ] })
963
+ ] })
964
+ ]
965
+ }
966
+ );
967
+ }
968
+ function CaseStudyCard({
969
+ post,
970
+ basePath = "/case-studies"
971
+ }) {
972
+ return /* @__PURE__ */ jsxs(
973
+ "a",
974
+ {
975
+ href: `${basePath}/${post.slug}`,
976
+ className: "group flex flex-col overflow-hidden rounded-xl border bg-card transition-all duration-300 hover:-translate-y-1 hover:shadow-lg hover:border-primary/40",
977
+ children: [
978
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden", children: /* @__PURE__ */ jsx(
979
+ Thumbnail,
980
+ {
981
+ src: post.thumbnail,
982
+ alt: post.title,
983
+ className: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
984
+ }
985
+ ) }),
986
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col p-5 sm:p-6", children: [
987
+ post.category && /* @__PURE__ */ jsx("span", { className: "mb-3 inline-block w-fit rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary", children: post.category }),
988
+ /* @__PURE__ */ jsx("h2", { className: "mb-2 text-lg font-semibold text-foreground transition-colors group-hover:text-primary line-clamp-2", children: post.title }),
989
+ /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground line-clamp-3", children: post.excerpt || post.seoDescription || "" }),
990
+ /* @__PURE__ */ jsx(MetaRow, { post, className: "mt-auto" })
991
+ ] })
992
+ ]
993
+ }
994
+ );
995
+ }
996
+ function EmptyState({
997
+ productLabel,
998
+ title,
999
+ subtitle,
1000
+ contactHref,
1001
+ contactLabel,
1002
+ exploreHref,
1003
+ exploreLabel
1004
+ }) {
1005
+ const highlights = [
1006
+ {
1007
+ title: "Real outcomes, real teams",
1008
+ body: `We're partnering with our earliest adopters right now. As they ship results with ${productLabel}, their stories will land here \u2014 measured and unembellished.`,
1009
+ icon: /* @__PURE__ */ jsx(
1010
+ "path",
1011
+ {
1012
+ strokeLinecap: "round",
1013
+ strokeLinejoin: "round",
1014
+ strokeWidth: 1.5,
1015
+ d: "M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"
1016
+ }
1017
+ )
1018
+ },
1019
+ {
1020
+ title: "See it on your use case",
1021
+ body: `Want to know how ${productLabel} would work for your team? We'll walk you through exactly what to expect \u2014 no pitch, just specifics.`,
1022
+ icon: /* @__PURE__ */ jsx(
1023
+ "path",
1024
+ {
1025
+ strokeLinecap: "round",
1026
+ strokeLinejoin: "round",
1027
+ strokeWidth: 1.5,
1028
+ d: "M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z M15 12a3 3 0 11-6 0 3 3 0 016 0z"
1029
+ }
1030
+ )
1031
+ },
1032
+ {
1033
+ title: "Be the first story",
1034
+ body: `Building something with ${productLabel} worth talking about? Tell us \u2014 the best early stories become the case studies featured on this page.`,
1035
+ icon: /* @__PURE__ */ jsx(
1036
+ "path",
1037
+ {
1038
+ strokeLinecap: "round",
1039
+ strokeLinejoin: "round",
1040
+ strokeWidth: 1.5,
1041
+ d: "M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.562.562 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.562.562 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"
1042
+ }
1043
+ )
1044
+ }
1045
+ ];
1046
+ return /* @__PURE__ */ jsxs("div", { className: "cs-fade-up mx-auto max-w-4xl", children: [
1047
+ /* @__PURE__ */ jsxs("div", { className: "relative overflow-hidden rounded-3xl border bg-card px-6 py-14 text-center sm:px-12 sm:py-16", children: [
1048
+ /* @__PURE__ */ jsx(
1049
+ "div",
1050
+ {
1051
+ className: "pointer-events-none absolute -top-24 -right-16 h-64 w-64 rounded-full bg-primary/10 blur-3xl",
1052
+ "aria-hidden": "true"
1053
+ }
1054
+ ),
1055
+ /* @__PURE__ */ jsx(
1056
+ "div",
1057
+ {
1058
+ className: "pointer-events-none absolute -bottom-24 -left-16 h-64 w-64 rounded-full bg-primary/5 blur-3xl",
1059
+ "aria-hidden": "true"
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1063
+ /* @__PURE__ */ jsx("div", { className: "cs-float mx-auto flex h-20 w-20 items-center justify-center rounded-2xl bg-primary/10 text-primary ring-1 ring-primary/20", children: /* @__PURE__ */ jsx(
1064
+ "svg",
1065
+ {
1066
+ className: "h-10 w-10",
1067
+ fill: "none",
1068
+ viewBox: "0 0 24 24",
1069
+ stroke: "currentColor",
1070
+ "aria-hidden": "true",
1071
+ children: /* @__PURE__ */ jsx(
1072
+ "path",
1073
+ {
1074
+ strokeLinecap: "round",
1075
+ strokeLinejoin: "round",
1076
+ strokeWidth: 1.5,
1077
+ d: "M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
1078
+ }
1079
+ )
1080
+ }
1081
+ ) }),
1082
+ /* @__PURE__ */ jsx("h2", { className: "mt-8 text-2xl font-bold tracking-tight text-foreground sm:text-3xl", children: title }),
1083
+ /* @__PURE__ */ jsx("p", { className: "mx-auto mt-4 max-w-2xl text-base leading-relaxed text-muted-foreground sm:text-lg", children: subtitle }),
1084
+ /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row", children: [
1085
+ /* @__PURE__ */ jsxs(
1086
+ "a",
1087
+ {
1088
+ href: contactHref,
1089
+ className: "inline-flex w-full items-center justify-center gap-2 rounded-lg bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground shadow-sm transition-all hover:opacity-90 hover:shadow-md sm:w-auto",
1090
+ children: [
1091
+ contactLabel,
1092
+ /* @__PURE__ */ jsx(
1093
+ "svg",
1094
+ {
1095
+ className: "h-4 w-4",
1096
+ viewBox: "0 0 20 20",
1097
+ fill: "currentColor",
1098
+ "aria-hidden": "true",
1099
+ children: /* @__PURE__ */ jsx(
1100
+ "path",
1101
+ {
1102
+ fillRule: "evenodd",
1103
+ d: "M7.293 4.293a1 1 0 011.414 0l5 5a1 1 0 010 1.414l-5 5a1 1 0 01-1.414-1.414L11.586 10 7.293 5.707a1 1 0 010-1.414z",
1104
+ clipRule: "evenodd"
1105
+ }
1106
+ )
1107
+ }
1108
+ )
1109
+ ]
1110
+ }
1111
+ ),
1112
+ /* @__PURE__ */ jsx(
1113
+ "a",
1114
+ {
1115
+ href: exploreHref,
1116
+ className: "inline-flex w-full items-center justify-center gap-2 rounded-lg border border-border bg-background px-6 py-3 text-sm font-semibold text-foreground transition-colors hover:bg-muted sm:w-auto",
1117
+ children: exploreLabel
1118
+ }
1119
+ )
1120
+ ] })
1121
+ ] })
1122
+ ] }),
1123
+ /* @__PURE__ */ jsx("div", { className: "mt-8 grid gap-4 sm:grid-cols-3", children: highlights.map((h) => /* @__PURE__ */ jsxs(
1124
+ "div",
1125
+ {
1126
+ className: "rounded-2xl border bg-card/60 p-5 text-left transition-colors hover:border-primary/30",
1127
+ children: [
1128
+ /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(
1129
+ "svg",
1130
+ {
1131
+ className: "h-5 w-5",
1132
+ fill: "none",
1133
+ viewBox: "0 0 24 24",
1134
+ stroke: "currentColor",
1135
+ "aria-hidden": "true",
1136
+ children: h.icon
1137
+ }
1138
+ ) }),
1139
+ /* @__PURE__ */ jsx("h3", { className: "mt-4 text-sm font-semibold text-foreground", children: h.title }),
1140
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: h.body })
1141
+ ]
1142
+ },
1143
+ h.title
1144
+ )) })
1145
+ ] });
1146
+ }
1147
+ function CaseStudiesListPage(props) {
1148
+ const {
1149
+ productName,
1150
+ eyebrow = "Customer Stories",
1151
+ heroTitle = "Case Studies",
1152
+ heroSubtitle = "Real-world stories of teams building with our platform.",
1153
+ caseStudyBasePath = "/case-studies",
1154
+ className = "",
1155
+ seoTitle,
1156
+ seoDescription,
1157
+ seoKeywords,
1158
+ contactHref = "/contact",
1159
+ contactLabel = "Get in touch",
1160
+ exploreHref = "/features",
1161
+ exploreLabel = "Explore the product",
1162
+ emptyTitle,
1163
+ emptySubtitle
1164
+ } = props;
1165
+ const client = useWebSDK();
1166
+ const config = useWebSDKConfig();
1167
+ const { product } = useProduct();
1168
+ const resolvedProductId = product?.id || config.productId;
1169
+ const productLabel = product?.name || productName || "our platform";
1170
+ const [posts, setPosts] = useState([]);
1171
+ const [total, setTotal] = useState(0);
1172
+ const [loading, setLoading] = useState(true);
1173
+ const [error, setError] = useState(null);
1174
+ const [offset, setOffset] = useState(0);
1175
+ const [activeCategory, setActiveCategory] = useState("All");
1176
+ const limit = 12;
1177
+ const fetchPosts = useCallback(async () => {
1178
+ if (!resolvedProductId) return;
1179
+ setLoading(true);
1180
+ try {
1181
+ const result = await client.query(CASE_STUDIES_QUERY, {
1182
+ productId: resolvedProductId,
1183
+ // Filter server-side: an unfiltered page of `limit` rows is mostly blog/legal pages, so
1184
+ // real case studies past it were never listed and the page fell back to the empty state.
1185
+ tag: CASE_STUDY_TAG,
1186
+ limit,
1187
+ offset
1188
+ });
1189
+ if (result.errors?.length) {
1190
+ setError(result.errors[0]?.message ?? "Failed to load case studies");
1191
+ setPosts([]);
1192
+ return;
1193
+ }
1194
+ const items = result.data?.publicContentPages?.items || [];
1195
+ const caseStudies = items.filter(
1196
+ (p) => p.tags?.includes(CASE_STUDY_TAG) && hasCustomerSignOff(p)
1197
+ );
1198
+ setPosts(caseStudies);
1199
+ const dropped = items.length - caseStudies.length;
1200
+ setTotal(
1201
+ Math.max(0, (result.data?.publicContentPages?.total || 0) - dropped)
1202
+ );
1203
+ setError(null);
1204
+ } catch {
1205
+ setError("load-failed");
1206
+ setPosts([]);
1207
+ } finally {
1208
+ setLoading(false);
1209
+ }
1210
+ }, [client, resolvedProductId, offset]);
1211
+ useEffect(() => {
1212
+ fetchPosts();
1213
+ }, [fetchPosts]);
1214
+ const categories = useMemo(() => {
1215
+ const set = /* @__PURE__ */ new Set();
1216
+ posts.forEach((p) => {
1217
+ if (p.category) set.add(p.category);
1218
+ });
1219
+ return ["All", ...Array.from(set)];
1220
+ }, [posts]);
1221
+ const visiblePosts = useMemo(() => {
1222
+ if (activeCategory === "All") return posts;
1223
+ return posts.filter((p) => p.category === activeCategory);
1224
+ }, [posts, activeCategory]);
1225
+ const featuredPosts = visiblePosts.filter((p) => p.featured);
1226
+ const regularPosts = visiblePosts.filter((p) => !p.featured);
1227
+ const hasContent = !loading && !error && posts.length > 0;
1228
+ const showEmpty = !loading && (error !== null || posts.length === 0);
1229
+ const resolvedEmptyTitle = emptyTitle ?? "Case studies are on the way";
1230
+ const resolvedEmptySubtitle = emptySubtitle ?? `${productLabel} is early in its journey, and we'd rather show you real, measurable results than filler. We're working closely with our first teams now \u2014 their stories will be published here soon. In the meantime, we'd love to show you what's possible.`;
1231
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, "data-cs": "case-studies-v2", children: [
1232
+ /* @__PURE__ */ jsx(ProseStyles, {}),
1233
+ /* @__PURE__ */ jsx(AnimationStyles, {}),
1234
+ seoTitle && /* @__PURE__ */ jsx(
1235
+ PageHead,
1236
+ {
1237
+ title: seoTitle,
1238
+ description: seoDescription || heroSubtitle,
1239
+ productName,
1240
+ keywords: seoKeywords
1241
+ }
1242
+ ),
1243
+ /* @__PURE__ */ jsxs("section", { className: "relative overflow-hidden", children: [
1244
+ /* @__PURE__ */ jsx(
1245
+ "div",
1246
+ {
1247
+ className: "pointer-events-none absolute inset-x-0 -top-32 mx-auto h-72 max-w-3xl rounded-full bg-primary/10 blur-3xl",
1248
+ "aria-hidden": "true"
1249
+ }
1250
+ ),
1251
+ /* @__PURE__ */ jsx("div", { className: "relative mx-auto max-w-7xl px-4 py-16 sm:px-6 sm:py-20 md:py-24 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl text-center", children: [
1252
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2 rounded-full border border-primary/20 bg-primary/10 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-primary", children: [
1253
+ /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-primary" }),
1254
+ eyebrow
1255
+ ] }),
1256
+ /* @__PURE__ */ jsx("h1", { className: "mt-5 text-3xl font-bold tracking-tight text-foreground sm:text-4xl md:text-5xl", children: heroTitle }),
1257
+ /* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle })
1258
+ ] }) })
1259
+ ] }),
1260
+ /* @__PURE__ */ jsx("section", { className: "pb-20 sm:pb-24", children: /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-7xl px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid gap-6 sm:gap-8 md:grid-cols-2 lg:grid-cols-3", children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsxs(
1261
+ "div",
1262
+ {
1263
+ className: "overflow-hidden rounded-xl border bg-card animate-pulse",
1264
+ children: [
1265
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
1266
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3 p-6", children: [
1267
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-1/4 rounded bg-muted" }),
1268
+ /* @__PURE__ */ jsx("div", { className: "h-6 w-3/4 rounded bg-muted" }),
1269
+ /* @__PURE__ */ jsx("div", { className: "h-4 rounded bg-muted" }),
1270
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-1/2 rounded bg-muted" })
1271
+ ] })
1272
+ ]
1273
+ },
1274
+ i
1275
+ )) }) : showEmpty ? /* @__PURE__ */ jsx(
1276
+ EmptyState,
1277
+ {
1278
+ productLabel,
1279
+ title: resolvedEmptyTitle,
1280
+ subtitle: resolvedEmptySubtitle,
1281
+ contactHref,
1282
+ contactLabel,
1283
+ exploreHref,
1284
+ exploreLabel
1285
+ }
1286
+ ) : hasContent ? /* @__PURE__ */ jsxs(Fragment, { children: [
1287
+ categories.length > 2 && /* @__PURE__ */ jsx("div", { className: "mb-10 flex flex-wrap justify-center gap-2", children: categories.map((cat) => /* @__PURE__ */ jsx(
1288
+ "button",
1289
+ {
1290
+ type: "button",
1291
+ onClick: () => setActiveCategory(cat),
1292
+ className: `rounded-full border px-4 py-1.5 text-sm font-medium transition-colors ${activeCategory === cat ? "border-primary bg-primary text-primary-foreground" : "border-border bg-background text-muted-foreground hover:border-primary/40 hover:text-foreground"}`,
1293
+ children: cat
1294
+ },
1295
+ cat
1296
+ )) }),
1297
+ featuredPosts.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-10 grid gap-6 sm:gap-8 lg:grid-cols-2", children: featuredPosts.map((post) => /* @__PURE__ */ jsx(
1298
+ FeaturedCard,
1299
+ {
1300
+ post,
1301
+ basePath: caseStudyBasePath
1302
+ },
1303
+ post.id
1304
+ )) }),
1305
+ regularPosts.length > 0 && /* @__PURE__ */ jsx("div", { className: "grid gap-6 sm:gap-8 md:grid-cols-2 lg:grid-cols-3", children: regularPosts.map((post) => /* @__PURE__ */ jsx(
1306
+ CaseStudyCard,
1307
+ {
1308
+ post,
1309
+ basePath: caseStudyBasePath
1310
+ },
1311
+ post.id
1312
+ )) }),
1313
+ activeCategory === "All" && total > limit && /* @__PURE__ */ jsxs("div", { className: "mt-14 flex justify-center gap-4", children: [
1314
+ /* @__PURE__ */ jsx(
1315
+ "button",
1316
+ {
1317
+ onClick: () => setOffset(Math.max(0, offset - limit)),
1318
+ disabled: offset === 0,
1319
+ className: "rounded-lg border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-muted disabled:opacity-40",
1320
+ children: "Previous"
1321
+ }
1322
+ ),
1323
+ /* @__PURE__ */ jsx(
1324
+ "button",
1325
+ {
1326
+ onClick: () => setOffset(offset + limit),
1327
+ disabled: offset + limit >= total,
1328
+ className: "rounded-lg border px-5 py-2.5 text-sm font-medium transition-colors hover:bg-muted disabled:opacity-40",
1329
+ children: "Next"
1330
+ }
1331
+ )
1332
+ ] }),
1333
+ /* @__PURE__ */ jsxs("div", { className: "mt-16 overflow-hidden rounded-2xl border bg-gradient-to-br from-primary/10 via-card to-card p-8 text-center sm:p-10", children: [
1334
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-foreground sm:text-2xl", children: "Want results like these?" }),
1335
+ /* @__PURE__ */ jsxs("p", { className: "mx-auto mt-2 max-w-xl text-sm text-muted-foreground sm:text-base", children: [
1336
+ "Tell us about your goals and we\u2019ll show you exactly how",
1337
+ " ",
1338
+ productLabel,
1339
+ " can help."
1340
+ ] }),
1341
+ /* @__PURE__ */ jsx(
1342
+ "a",
1343
+ {
1344
+ href: contactHref,
1345
+ className: "mt-6 inline-flex items-center justify-center gap-2 rounded-lg bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground shadow-sm transition-all hover:opacity-90 hover:shadow-md",
1346
+ children: contactLabel
1347
+ }
1348
+ )
1349
+ ] })
1350
+ ] }) : null }) })
1351
+ ] });
1352
+ }
1353
+ function CaseStudyPage(props) {
1354
+ const {
1355
+ productName,
1356
+ caseStudiesListUrl = "/case-studies",
1357
+ backLabel = "Back to Case Studies",
1358
+ contactHref = "/contact",
1359
+ contactLabel = "Get in touch",
1360
+ className = ""
1361
+ } = props;
1362
+ const client = useWebSDK();
1363
+ const config = useWebSDKConfig();
1364
+ const { product } = useProduct();
1365
+ const resolvedProductId = product?.id || config.productId;
1366
+ const productLabel = product?.name || productName || "our team";
1367
+ const [post, setPost] = useState(null);
1368
+ const [loading, setLoading] = useState(true);
1369
+ const [error, setError] = useState(null);
1370
+ const slug = typeof window !== "undefined" ? window.location.pathname.split("/").pop() || "" : "";
1371
+ useEffect(() => {
1372
+ if (!slug || !resolvedProductId) return;
1373
+ async function fetchPost() {
1374
+ setLoading(true);
1375
+ try {
1376
+ const result = await client.query(CASE_STUDY_QUERY, {
1377
+ slug,
1378
+ productId: resolvedProductId
1379
+ });
1380
+ if (result.errors?.length) {
1381
+ setError(result.errors[0]?.message ?? "Failed to load case study");
1382
+ return;
1383
+ }
1384
+ const page = result.data?.publicContentPage ?? null;
1385
+ setPost(page && hasCustomerSignOff(page) ? page : null);
1386
+ setError(null);
1387
+ } catch {
1388
+ setError("Failed to load case study");
1389
+ } finally {
1390
+ setLoading(false);
1391
+ }
1392
+ }
1393
+ fetchPost();
1394
+ }, [client, slug, resolvedProductId]);
1395
+ if (loading) {
1396
+ return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-4xl px-4 py-24 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-6", children: [
1397
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-2/3 rounded bg-muted" }),
1398
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-1/3 rounded bg-muted" }),
1399
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] rounded-xl bg-muted" }),
1400
+ /* @__PURE__ */ jsx("div", { className: "space-y-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx("div", { className: "h-4 rounded bg-muted" }, i)) })
1401
+ ] }) }) });
1402
+ }
1403
+ if (error || !post) {
1404
+ return /* @__PURE__ */ jsx("div", { className: `w-full ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl px-4 py-24 text-center sm:px-6 lg:px-8", children: [
1405
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-16 w-16 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(
1406
+ "svg",
1407
+ {
1408
+ className: "h-8 w-8",
1409
+ fill: "none",
1410
+ viewBox: "0 0 24 24",
1411
+ stroke: "currentColor",
1412
+ "aria-hidden": "true",
1413
+ children: /* @__PURE__ */ jsx(
1414
+ "path",
1415
+ {
1416
+ strokeLinecap: "round",
1417
+ strokeLinejoin: "round",
1418
+ strokeWidth: 1.5,
1419
+ d: "M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z"
1420
+ }
1421
+ )
1422
+ }
1423
+ ) }),
1424
+ /* @__PURE__ */ jsx("h1", { className: "mt-6 text-2xl font-bold text-foreground", children: "Case study not found" }),
1425
+ /* @__PURE__ */ jsxs("p", { className: "mx-auto mt-3 max-w-md text-muted-foreground", children: [
1426
+ "This story isn\u2019t available yet \u2014 but there\u2019s plenty more to explore, and we\u2019re always happy to talk through what ",
1427
+ productLabel,
1428
+ " can do."
1429
+ ] }),
1430
+ /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row", children: [
1431
+ /* @__PURE__ */ jsxs(
1432
+ "a",
1433
+ {
1434
+ href: caseStudiesListUrl,
1435
+ className: "inline-flex items-center justify-center rounded-lg border px-5 py-2.5 text-sm font-semibold text-foreground transition-colors hover:bg-muted",
1436
+ children: [
1437
+ "\u2190 ",
1438
+ backLabel
1439
+ ]
1440
+ }
1441
+ ),
1442
+ /* @__PURE__ */ jsx(
1443
+ "a",
1444
+ {
1445
+ href: contactHref,
1446
+ className: "inline-flex items-center justify-center rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground transition-all hover:opacity-90",
1447
+ children: contactLabel
1448
+ }
1449
+ )
1450
+ ] })
1451
+ ] }) });
1452
+ }
1453
+ const formattedDate = formatDate(post.publishedAt || post.lastUpdated);
1454
+ const approvedDate = formatDate(post.customerSignOff?.signedAt);
1455
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
1456
+ /* @__PURE__ */ jsx(ProseStyles, {}),
1457
+ /* @__PURE__ */ jsx(
1458
+ PageHead,
1459
+ {
1460
+ title: post.seoTitle || post.title,
1461
+ description: post.seoDescription || post.excerpt || "",
1462
+ productName,
1463
+ keywords: post.seoKeywords || ""
1464
+ }
1465
+ ),
1466
+ /* @__PURE__ */ jsxs("article", { className: "mx-auto max-w-4xl px-4 py-16 sm:px-6 sm:py-20 lg:px-8", children: [
1467
+ /* @__PURE__ */ jsxs(
1468
+ "a",
1469
+ {
1470
+ href: caseStudiesListUrl,
1471
+ className: "mb-8 inline-flex items-center gap-1 text-sm text-muted-foreground transition-colors hover:text-foreground",
1472
+ children: [
1473
+ "\u2190 ",
1474
+ backLabel
1475
+ ]
1476
+ }
1477
+ ),
1478
+ post.category && /* @__PURE__ */ jsx("span", { className: "mb-4 inline-block rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary", children: post.category }),
1479
+ /* @__PURE__ */ jsx("h1", { className: "mb-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl md:text-5xl", children: post.title }),
1480
+ /* @__PURE__ */ jsxs("div", { className: "mb-8 flex flex-wrap items-center gap-3 text-sm text-muted-foreground", children: [
1481
+ post.author && /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: post.author }),
1482
+ post.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
1483
+ formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
1484
+ post.readingTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
1485
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
1486
+ /* @__PURE__ */ jsxs("span", { children: [
1487
+ post.readingTime,
1488
+ " min read"
1489
+ ] })
1490
+ ] }) : null
1491
+ ] }),
1492
+ approvedDate && /* @__PURE__ */ jsxs(
1493
+ "p",
1494
+ {
1495
+ className: "-mt-4 mb-8 text-xs text-muted-foreground",
1496
+ "data-cs": "customer-signoff",
1497
+ children: [
1498
+ "Approved for publication by the customer on ",
1499
+ approvedDate
1500
+ ]
1501
+ }
1502
+ ),
1503
+ post.thumbnail && /* @__PURE__ */ jsx("div", { className: "mb-10 aspect-[16/9] overflow-hidden rounded-xl", children: /* @__PURE__ */ jsx(
1504
+ "img",
1505
+ {
1506
+ src: post.thumbnail,
1507
+ alt: post.title,
1508
+ className: "h-full w-full object-cover"
1509
+ }
1510
+ ) }),
1511
+ /* @__PURE__ */ jsx("div", { className: "boff-prose max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content: post.content, format: post.contentFormat }) }),
1512
+ /* @__PURE__ */ jsxs("div", { className: "mt-14 rounded-2xl border bg-gradient-to-br from-primary/10 via-card to-card p-8 text-center", children: [
1513
+ /* @__PURE__ */ jsxs("h2", { className: "text-xl font-bold text-foreground", children: [
1514
+ "Curious what ",
1515
+ productLabel,
1516
+ " could do for you?"
1517
+ ] }),
1518
+ /* @__PURE__ */ jsx("p", { className: "mx-auto mt-2 max-w-lg text-sm text-muted-foreground", children: "We\u2019re happy to walk you through it \u2014 no pressure, just a conversation about your goals." }),
1519
+ /* @__PURE__ */ jsx(
1520
+ "a",
1521
+ {
1522
+ href: contactHref,
1523
+ className: "mt-6 inline-flex items-center justify-center rounded-lg bg-primary px-6 py-3 text-sm font-semibold text-primary-foreground shadow-sm transition-all hover:opacity-90 hover:shadow-md",
1524
+ children: contactLabel
1525
+ }
1526
+ )
1527
+ ] })
1528
+ ] })
1529
+ ] });
1530
+ }
1531
+ var CHANGELOG_TAG = "changelog";
1532
+ var CHANGELOG_LIST_QUERY = `
1533
+ query ChangelogList($productId: String!, $limit: Int, $offset: Int) {
1534
+ publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
1535
+ items {
1536
+ id
1537
+ title
1538
+ slug
1539
+ lastUpdated
1540
+ tags
1541
+ excerpt
1542
+ seoDescription
1543
+ thumbnail
1544
+ author
1545
+ publishedAt
1546
+ readingTime
1547
+ featured
1548
+ category
1549
+ }
1550
+ total
1551
+ hasMore
1552
+ }
1553
+ }
1554
+ `;
1555
+ var CHANGELOG_ENTRY_QUERY = `
1556
+ query ChangelogEntry($slug: String!, $productId: String) {
1557
+ publicContentPage(slug: $slug, productId: $productId) {
1558
+ content
1559
+ contentFormat
1560
+ }
1561
+ }
1562
+ `;
1563
+ function formatDate2(value) {
1564
+ if (!value) return "";
1565
+ return new Date(value).toLocaleDateString("en-US", {
1566
+ year: "numeric",
1567
+ month: "long",
1568
+ day: "numeric"
1569
+ });
1570
+ }
1571
+ function sortByDateDesc(a, b) {
1572
+ const da = new Date(a.publishedAt || a.lastUpdated || 0).getTime();
1573
+ const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
1574
+ return db - da;
1575
+ }
1576
+ function normalize(value) {
1577
+ return value.toLowerCase().trim();
1578
+ }
1579
+ function paginate(items, page, pageSize) {
1580
+ const start = (page - 1) * pageSize;
1581
+ return items.slice(start, start + pageSize);
1582
+ }
1583
+ function parseEntryDate(date) {
1584
+ return new Date(date).getTime();
1585
+ }
1586
+ function useCmsChangelog() {
1587
+ const client = useWebSDK();
1588
+ const config = useWebSDKConfig();
1589
+ const { product } = useProduct();
1590
+ const resolvedProductId = product?.id || config.productId;
1591
+ const [entries, setEntries] = useState([]);
1592
+ const [loading, setLoading] = useState(true);
1593
+ const [error, setError] = useState(null);
1594
+ const fetchEntries = useCallback(async () => {
1595
+ if (!resolvedProductId) {
1596
+ setLoading(false);
1597
+ return;
1598
+ }
1599
+ setLoading(true);
1600
+ try {
1601
+ const listResult = await client.query(CHANGELOG_LIST_QUERY, {
1602
+ productId: resolvedProductId,
1603
+ limit: 50,
1604
+ offset: 0
1605
+ });
1606
+ if (listResult.errors?.length) {
1607
+ setError(listResult.errors[0]?.message ?? "Failed to load changelog");
1608
+ return;
1609
+ }
1610
+ const changelogItems = (listResult.data?.publicContentPages?.items || []).filter((p) => p.tags?.includes(CHANGELOG_TAG)).sort(sortByDateDesc);
1611
+ const resolved = await Promise.all(
1612
+ changelogItems.map(async (item) => {
1613
+ try {
1614
+ const detail = await client.query(CHANGELOG_ENTRY_QUERY, {
1615
+ slug: item.slug,
1616
+ productId: resolvedProductId
1617
+ });
1618
+ const page = detail.data?.publicContentPage;
1619
+ return {
1620
+ ...item,
1621
+ content: page?.content,
1622
+ contentFormat: page?.contentFormat
1623
+ };
1624
+ } catch {
1625
+ return { ...item };
1626
+ }
1627
+ })
1628
+ );
1629
+ setEntries(resolved);
1630
+ setError(null);
1631
+ } catch {
1632
+ setError("Failed to load changelog");
1633
+ } finally {
1634
+ setLoading(false);
1635
+ }
1636
+ }, [client, resolvedProductId]);
1637
+ useEffect(() => {
1638
+ fetchEntries();
1639
+ }, [fetchEntries]);
1640
+ return { entries, loading, error };
1641
+ }
1642
+ function CmsTimeline(props) {
1643
+ const { entries, loading, error } = props;
1644
+ if (loading) {
1645
+ return /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsx(
1646
+ "div",
1647
+ {
1648
+ className: "rounded-2xl border border-border/40 bg-card overflow-hidden animate-pulse",
1649
+ children: /* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8 space-y-4", children: [
1650
+ /* @__PURE__ */ jsx("div", { className: "h-3 bg-muted rounded w-1/3" }),
1651
+ /* @__PURE__ */ jsx("div", { className: "h-6 bg-muted rounded w-2/3" }),
1652
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded" }),
1653
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-5/6" })
1654
+ ] })
1655
+ },
1656
+ i
1657
+ )) });
1658
+ }
1659
+ if (error) {
1660
+ return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) });
1661
+ }
1662
+ if (entries.length === 0) {
1663
+ return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
1664
+ }
1665
+ return /* @__PURE__ */ jsx("div", { className: "max-w-3xl mx-auto space-y-12", children: entries.map((entry) => /* @__PURE__ */ jsxs(
1666
+ "article",
1667
+ {
1668
+ id: entry.slug,
1669
+ className: "rounded-2xl border border-border/40 bg-card overflow-hidden scroll-mt-24",
1670
+ children: [
1671
+ entry.thumbnail && /* @__PURE__ */ jsx(
1672
+ "img",
1673
+ {
1674
+ src: entry.thumbnail,
1675
+ alt: "",
1676
+ width: 1024,
1677
+ height: 576,
1678
+ loading: "lazy",
1679
+ decoding: "async",
1680
+ className: "w-full aspect-video object-cover border-b border-border/40"
1681
+ }
1682
+ ),
1683
+ /* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8", children: [
1684
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mb-2", children: [
1685
+ entry.publishedAt && /* @__PURE__ */ jsx("time", { dateTime: entry.publishedAt, children: formatDate2(entry.publishedAt || entry.lastUpdated) }),
1686
+ entry.author && /* @__PURE__ */ jsxs(Fragment, { children: [
1687
+ " \xB7 ",
1688
+ entry.author
1689
+ ] })
1690
+ ] }),
1691
+ /* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
1692
+ entry.content ? /* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm max-w-none", children: /* @__PURE__ */ jsx(
1693
+ ContentRenderer,
1694
+ {
1695
+ content: entry.content,
1696
+ format: entry.contentFormat
1697
+ }
1698
+ ) }) : entry.excerpt && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground leading-relaxed", children: entry.excerpt })
1699
+ ] })
1700
+ ]
1701
+ },
1702
+ entry.id
1703
+ )) });
1704
+ }
1705
+ function EntryContent({ content }) {
1706
+ if (typeof content === "string") {
1707
+ return /* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm max-w-none", children: /* @__PURE__ */ jsx(ContentRenderer, { content, format: "markdown" }) });
1708
+ }
1709
+ return /* @__PURE__ */ jsx("div", { className: "boff-prose boff-prose-sm max-w-none", children: content });
1710
+ }
1711
+ function EntriesTimeline(props) {
1712
+ const { entries, pageSize, productName } = props;
1713
+ const [query, setQuery] = useState("");
1714
+ const [selectedCategory, setSelectedCategory] = useState(null);
1715
+ const [page, setPage] = useState(1);
1716
+ const categories = useMemo(
1717
+ () => Array.from(new Set(entries.map((e) => e.category))).sort(),
1718
+ [entries]
1719
+ );
1720
+ const filtered = useMemo(() => {
1721
+ const normalized = normalize(query);
1722
+ return entries.filter((entry) => {
1723
+ if (selectedCategory && entry.category !== selectedCategory) {
1724
+ return false;
1725
+ }
1726
+ if (!normalized) return true;
1727
+ const haystack = [
1728
+ entry.title,
1729
+ entry.version,
1730
+ entry.category,
1731
+ ...entry.tags ?? [],
1732
+ typeof entry.content === "string" ? entry.content : ""
1733
+ ].join(" ").toLowerCase();
1734
+ return haystack.includes(normalized);
1735
+ }).sort((a, b) => parseEntryDate(b.date) - parseEntryDate(a.date));
1736
+ }, [entries, query, selectedCategory]);
1737
+ const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
1738
+ const safePage = Math.min(page, totalPages);
1739
+ const pageItems = paginate(filtered, safePage, pageSize);
1740
+ useEffect(() => {
1741
+ setPage(1);
1742
+ }, [query, selectedCategory]);
1743
+ if (entries.length === 0) {
1744
+ return /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No changelog entries yet. Check back soon!" }) });
1745
+ }
1746
+ return /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
1747
+ /* @__PURE__ */ jsxs("div", { className: "mb-8 space-y-4", children: [
1748
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1749
+ /* @__PURE__ */ jsx(
1750
+ Search,
1751
+ {
1752
+ className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground",
1753
+ "aria-hidden": "true"
1754
+ }
1755
+ ),
1756
+ /* @__PURE__ */ jsx(
1757
+ Input,
1758
+ {
1759
+ type: "search",
1760
+ placeholder: "Search releases, features, fixes\u2026",
1761
+ value: query,
1762
+ onChange: (e) => setQuery(e.target.value),
1763
+ className: "pl-9",
1764
+ "aria-label": "Search changelog"
1765
+ }
1766
+ )
1767
+ ] }),
1768
+ categories.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
1769
+ /* @__PURE__ */ jsx(
1770
+ "button",
1771
+ {
1772
+ type: "button",
1773
+ onClick: () => setSelectedCategory(null),
1774
+ className: cn(
1775
+ "px-3 py-1 rounded-full text-xs font-medium border transition-colors",
1776
+ selectedCategory === null ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
1777
+ ),
1778
+ children: "All"
1779
+ }
1780
+ ),
1781
+ categories.map((category) => /* @__PURE__ */ jsx(
1782
+ "button",
1783
+ {
1784
+ type: "button",
1785
+ onClick: () => setSelectedCategory(category),
1786
+ className: cn(
1787
+ "px-3 py-1 rounded-full text-xs font-medium border transition-colors",
1788
+ selectedCategory === category ? "bg-primary text-primary-foreground border-primary" : "bg-background text-muted-foreground border-border/60 hover:border-primary/40"
1789
+ ),
1790
+ children: category
1791
+ },
1792
+ category
1793
+ ))
1794
+ ] })
1795
+ ] }),
1796
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1797
+ /* @__PURE__ */ jsx(
1798
+ "div",
1799
+ {
1800
+ className: "absolute left-[1.125rem] top-3 bottom-3 w-px bg-border/60 hidden sm:block",
1801
+ "aria-hidden": "true"
1802
+ }
1803
+ ),
1804
+ /* @__PURE__ */ jsx("div", { className: "space-y-8", children: pageItems.map((entry) => /* @__PURE__ */ jsxs(
1805
+ "article",
1806
+ {
1807
+ className: "relative sm:pl-12",
1808
+ children: [
1809
+ /* @__PURE__ */ jsx(
1810
+ "div",
1811
+ {
1812
+ className: "hidden sm:flex absolute left-2 top-2 h-5 w-5 items-center justify-center rounded-full border-2 border-background bg-primary ring-1 ring-border/40",
1813
+ "aria-hidden": "true",
1814
+ children: /* @__PURE__ */ jsx("span", { className: "h-2 w-2 rounded-full bg-primary-foreground" })
1815
+ }
1816
+ ),
1817
+ /* @__PURE__ */ jsx("div", { className: "rounded-2xl border border-border/40 bg-card overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "p-6 sm:p-8", children: [
1818
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 mb-3", children: [
1819
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-md bg-primary/10 px-2 py-1 text-xs font-medium text-primary", children: entry.category }),
1820
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center rounded-md bg-muted px-2 py-1 text-xs font-mono font-medium text-muted-foreground", children: [
1821
+ "v",
1822
+ entry.version
1823
+ ] }),
1824
+ /* @__PURE__ */ jsx(
1825
+ "time",
1826
+ {
1827
+ className: "text-xs text-muted-foreground",
1828
+ dateTime: entry.date,
1829
+ children: formatDate2(entry.date)
1830
+ }
1831
+ )
1832
+ ] }),
1833
+ entry.tags && entry.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 mb-3", children: entry.tags.map((tag) => /* @__PURE__ */ jsx(
1834
+ "span",
1835
+ {
1836
+ className: "text-[10px] uppercase tracking-wide text-muted-foreground bg-background border border-border/40 px-1.5 py-0.5 rounded",
1837
+ children: tag
1838
+ },
1839
+ tag
1840
+ )) }),
1841
+ /* @__PURE__ */ jsx("h2", { className: "text-xl sm:text-2xl font-bold text-foreground mb-4", children: entry.title }),
1842
+ /* @__PURE__ */ jsx(EntryContent, { content: entry.content })
1843
+ ] }) })
1844
+ ]
1845
+ },
1846
+ `${entry.version}-${entry.date}`
1847
+ )) })
1848
+ ] }),
1849
+ pageItems.length === 0 && /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No entries match your filters." }) }),
1850
+ totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "mt-10 flex items-center justify-between", children: [
1851
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
1852
+ "Page ",
1853
+ safePage,
1854
+ " of ",
1855
+ totalPages,
1856
+ " \xB7 ",
1857
+ filtered.length,
1858
+ " entries"
1859
+ ] }),
1860
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1861
+ /* @__PURE__ */ jsx(
1862
+ Button,
1863
+ {
1864
+ variant: "outline",
1865
+ size: "sm",
1866
+ onClick: () => setPage((p) => Math.max(1, p - 1)),
1867
+ disabled: safePage <= 1,
1868
+ "aria-label": "Previous page",
1869
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
1870
+ }
1871
+ ),
1872
+ /* @__PURE__ */ jsx(
1873
+ Button,
1874
+ {
1875
+ variant: "outline",
1876
+ size: "sm",
1877
+ onClick: () => setPage((p) => Math.min(totalPages, p + 1)),
1878
+ disabled: safePage >= totalPages,
1879
+ "aria-label": "Next page",
1880
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
1881
+ }
1882
+ )
1883
+ ] })
1884
+ ] }),
1885
+ productName && pageItems.length > 0 && /* @__PURE__ */ jsx("script", { type: "application/ld+json", children: JSON.stringify({
1886
+ "@context": "https://schema.org",
1887
+ "@type": "ItemList",
1888
+ name: `${productName} Changelog`,
1889
+ itemListElement: pageItems.map((entry, index) => ({
1890
+ "@type": "ListItem",
1891
+ position: (safePage - 1) * pageSize + index + 1,
1892
+ name: entry.title,
1893
+ description: typeof entry.content === "string" ? entry.content.slice(0, 200) : void 0,
1894
+ datePublished: entry.date
1895
+ }))
1896
+ }) })
1897
+ ] });
1898
+ }
1899
+ function ChangelogPage(props) {
1900
+ const {
1901
+ productName,
1902
+ heroEyebrow = "What's new",
1903
+ heroTitle = "Changelog",
1904
+ heroSubtitle = "Platform updates, improvements, and announcements \u2014 newest first.",
1905
+ ctaTitle,
1906
+ ctaSubtitle,
1907
+ ctaHref,
1908
+ ctaLabel,
1909
+ className = "",
1910
+ seoTitle,
1911
+ seoDescription,
1912
+ seoKeywords,
1913
+ entries,
1914
+ pageSize = 10
1915
+ } = props;
1916
+ const { product } = useProduct();
1917
+ const resolvedProductName = productName || product?.name;
1918
+ const cms = useCmsChangelog();
1919
+ const showCta = Boolean(ctaHref && ctaLabel);
1920
+ const isPropDriven = entries != null;
1921
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
1922
+ /* @__PURE__ */ jsx(ProseStyles, {}),
1923
+ /* @__PURE__ */ jsx(
1924
+ PageHead,
1925
+ {
1926
+ title: seoTitle || heroTitle,
1927
+ description: seoDescription || heroSubtitle,
1928
+ productName: resolvedProductName,
1929
+ keywords: seoKeywords
1930
+ }
1931
+ ),
1932
+ /* @__PURE__ */ jsx("section", { className: "py-16 md:py-20 px-4 sm:px-6 lg:px-8 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
1933
+ /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-xs font-medium text-primary mb-6", children: [
1934
+ /* @__PURE__ */ jsx(History, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
1935
+ heroEyebrow
1936
+ ] }),
1937
+ /* @__PURE__ */ jsx("h1", { className: "text-4xl sm:text-5xl font-bold text-foreground mb-4", children: heroTitle }),
1938
+ /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground", children: heroSubtitle })
1939
+ ] }) }),
1940
+ /* @__PURE__ */ jsx("section", { className: "px-4 sm:px-6 lg:px-8 pb-20", children: isPropDriven ? /* @__PURE__ */ jsx(
1941
+ EntriesTimeline,
1942
+ {
1943
+ entries,
1944
+ pageSize,
1945
+ productName: resolvedProductName
1946
+ }
1947
+ ) : /* @__PURE__ */ jsx(
1948
+ CmsTimeline,
1949
+ {
1950
+ entries: cms.entries,
1951
+ loading: cms.loading,
1952
+ error: cms.error
1953
+ }
1954
+ ) }),
1955
+ showCta && /* @__PURE__ */ jsx("section", { className: "py-14 px-4 sm:px-6 lg:px-8 bg-primary/5 border-t border-border/40", children: /* @__PURE__ */ jsxs("div", { className: "max-w-2xl mx-auto text-center", children: [
1956
+ ctaTitle && /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-foreground mb-3", children: ctaTitle }),
1957
+ ctaSubtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-7", children: ctaSubtitle }),
1958
+ /* @__PURE__ */ jsx(
1959
+ "a",
1960
+ {
1961
+ href: ctaHref,
1962
+ className: "inline-flex items-center justify-center rounded-lg bg-primary px-6 py-3 text-sm font-medium text-primary-foreground hover:opacity-90 transition-opacity",
1963
+ children: ctaLabel
1964
+ }
1965
+ )
1966
+ ] }) })
1967
+ ] });
1968
+ }
1969
+
1970
+ // src/content/utils.ts
1971
+ function formatBytes(bytes) {
1972
+ if (bytes == null) return "";
1973
+ if (bytes < 1024) return `${bytes} B`;
1974
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
1975
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
1976
+ }
1977
+ function fileExt(file) {
1978
+ const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || "";
1979
+ const ext = name.split(".").pop();
1980
+ return ext && ext !== name ? ext.toUpperCase() : "FILE";
1981
+ }
1982
+ async function downloadFile(e, file) {
1983
+ e.preventDefault();
1984
+ const openInTab = () => window.open(file.fileUrl, "_blank", "noopener,noreferrer");
1985
+ const name = file.fileName || file.fileUrl.split("/").pop()?.split("?")[0] || file.title || "download";
1986
+ try {
1987
+ const res = await fetch(file.fileUrl, { mode: "cors" });
1988
+ if (!res.ok) {
1989
+ openInTab();
1990
+ return;
1991
+ }
1992
+ const blob = await res.blob();
1993
+ const objUrl = URL.createObjectURL(blob);
1994
+ const a = document.createElement("a");
1995
+ a.href = objUrl;
1996
+ a.download = name;
1997
+ document.body.appendChild(a);
1998
+ a.click();
1999
+ a.remove();
2000
+ URL.revokeObjectURL(objUrl);
2001
+ } catch {
2002
+ openInTab();
2003
+ }
2004
+ }
2005
+ var PRESS_KIT_QUERY = `
2006
+ query PublicPressKit($productId: String!, $limit: Int, $offset: Int) {
2007
+ publicPressKitAssets(productId: $productId, limit: $limit, offset: $offset) {
2008
+ items {
2009
+ id
2010
+ category
2011
+ title
2012
+ slug
2013
+ description
2014
+ fileUrl
2015
+ fileName
2016
+ fileSize
2017
+ mimeType
2018
+ thumbnailUrl
2019
+ version
2020
+ tags
2021
+ sortOrder
2022
+ updatedAt
2023
+ }
2024
+ total
2025
+ hasMore
2026
+ }
2027
+ }
2028
+ `;
2029
+ var PRESS_RELEASES_QUERY = `
2030
+ query PublicPressReleases($productId: String!, $limit: Int, $offset: Int) {
2031
+ publicContentPages(productId: $productId, limit: $limit, offset: $offset) {
2032
+ items {
2033
+ id
2034
+ title
2035
+ slug
2036
+ lastUpdated
2037
+ tags
2038
+ seoDescription
2039
+ excerpt
2040
+ thumbnail
2041
+ author
2042
+ publishedAt
2043
+ readingTime
2044
+ featured
2045
+ category
2046
+ }
2047
+ total
2048
+ hasMore
2049
+ }
2050
+ }
2051
+ `;
2052
+ var CATEGORY_ORDER = [
2053
+ "LOGO",
2054
+ "BANNER",
2055
+ "SCREENSHOT",
2056
+ "BRAND_GUIDE",
2057
+ "BROCHURE",
2058
+ "DOCUMENT",
2059
+ "PRESS_RELEASE"
2060
+ ];
2061
+ var CATEGORY_LABELS = {
2062
+ LOGO: "Logos",
2063
+ BANNER: "Banners",
2064
+ SCREENSHOT: "Screenshots",
2065
+ BRAND_GUIDE: "Brand Guides",
2066
+ BROCHURE: "Brochures",
2067
+ DOCUMENT: "Documents",
2068
+ PRESS_RELEASE: "Press Releases"
2069
+ };
2070
+ function isImageAsset(a) {
2071
+ return (a.mimeType || "").startsWith("image/");
2072
+ }
2073
+ function PressKitLightbox({
2074
+ asset,
2075
+ onClose
2076
+ }) {
2077
+ useEffect(() => {
2078
+ if (!asset) return;
2079
+ const onKey = (e) => {
2080
+ if (e.key === "Escape") onClose();
2081
+ };
2082
+ document.addEventListener("keydown", onKey);
2083
+ const prevOverflow = document.body.style.overflow;
2084
+ document.body.style.overflow = "hidden";
2085
+ return () => {
2086
+ document.removeEventListener("keydown", onKey);
2087
+ document.body.style.overflow = prevOverflow;
2088
+ };
2089
+ }, [asset, onClose]);
2090
+ if (!asset) return null;
2091
+ const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
2092
+ const size = formatBytes(asset.fileSize);
2093
+ return /* @__PURE__ */ jsx(
2094
+ "div",
2095
+ {
2096
+ role: "dialog",
2097
+ "aria-modal": "true",
2098
+ "aria-label": `${asset.title} preview`,
2099
+ onClick: onClose,
2100
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80 p-4 sm:p-8",
2101
+ children: /* @__PURE__ */ jsxs(
2102
+ "div",
2103
+ {
2104
+ onClick: (e) => e.stopPropagation(),
2105
+ className: "relative flex max-h-full w-full max-w-4xl flex-col overflow-hidden rounded-xl border bg-card shadow-2xl",
2106
+ children: [
2107
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4 border-b p-4", children: [
2108
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2109
+ /* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: asset.title }),
2110
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
2111
+ ext,
2112
+ size ? ` \xB7 ${size}` : ""
2113
+ ] })
2114
+ ] }),
2115
+ /* @__PURE__ */ jsx(
2116
+ "button",
2117
+ {
2118
+ type: "button",
2119
+ onClick: onClose,
2120
+ "aria-label": "Close preview",
2121
+ className: "shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
2122
+ children: /* @__PURE__ */ jsx(
2123
+ "svg",
2124
+ {
2125
+ className: "h-5 w-5",
2126
+ fill: "none",
2127
+ viewBox: "0 0 24 24",
2128
+ stroke: "currentColor",
2129
+ strokeWidth: 2,
2130
+ children: /* @__PURE__ */ jsx(
2131
+ "path",
2132
+ {
2133
+ strokeLinecap: "round",
2134
+ strokeLinejoin: "round",
2135
+ d: "M6 18L18 6M6 6l12 12"
2136
+ }
2137
+ )
2138
+ }
2139
+ )
2140
+ }
2141
+ )
2142
+ ] }),
2143
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center overflow-auto bg-muted/20 p-4", children: /* @__PURE__ */ jsx(
2144
+ "img",
2145
+ {
2146
+ src: asset.fileUrl,
2147
+ alt: asset.title,
2148
+ className: "max-h-[70vh] w-auto max-w-full object-contain"
2149
+ }
2150
+ ) }),
2151
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end border-t p-4", children: /* @__PURE__ */ jsxs(
2152
+ "a",
2153
+ {
2154
+ href: asset.fileUrl,
2155
+ target: "_blank",
2156
+ rel: "noopener noreferrer",
2157
+ download: true,
2158
+ onClick: (e) => {
2159
+ void downloadFile(e, asset);
2160
+ },
2161
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90",
2162
+ children: [
2163
+ /* @__PURE__ */ jsx(
2164
+ "svg",
2165
+ {
2166
+ className: "h-4 w-4",
2167
+ fill: "none",
2168
+ viewBox: "0 0 24 24",
2169
+ stroke: "currentColor",
2170
+ strokeWidth: 2,
2171
+ children: /* @__PURE__ */ jsx(
2172
+ "path",
2173
+ {
2174
+ strokeLinecap: "round",
2175
+ strokeLinejoin: "round",
2176
+ d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
2177
+ }
2178
+ )
2179
+ }
2180
+ ),
2181
+ "Download"
2182
+ ]
2183
+ }
2184
+ ) })
2185
+ ]
2186
+ }
2187
+ )
2188
+ }
2189
+ );
2190
+ }
2191
+ function AssetCard({
2192
+ asset,
2193
+ onPreview
2194
+ }) {
2195
+ const date = asset.updatedAt ? new Date(asset.updatedAt).toLocaleDateString("en-US", {
2196
+ year: "numeric",
2197
+ month: "short",
2198
+ day: "numeric"
2199
+ }) : "";
2200
+ const ext = (asset.mimeType || "file").split("/").pop()?.toUpperCase() || "FILE";
2201
+ const size = formatBytes(asset.fileSize);
2202
+ const [imgError, setImgError] = useState(false);
2203
+ const thumb = asset.thumbnailUrl && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsx(
2204
+ "img",
2205
+ {
2206
+ src: asset.thumbnailUrl,
2207
+ alt: asset.title,
2208
+ className: "w-full h-full object-contain group-hover:scale-105 transition-transform duration-300",
2209
+ loading: "lazy",
2210
+ onError: () => setImgError(true)
2211
+ }
2212
+ ) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
2213
+ "svg",
2214
+ {
2215
+ className: "w-12 h-12 text-muted-foreground/20",
2216
+ fill: "none",
2217
+ viewBox: "0 0 24 24",
2218
+ stroke: "currentColor",
2219
+ children: /* @__PURE__ */ jsx(
2220
+ "path",
2221
+ {
2222
+ strokeLinecap: "round",
2223
+ strokeLinejoin: "round",
2224
+ strokeWidth: 1.5,
2225
+ d: "M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"
2226
+ }
2227
+ )
2228
+ }
2229
+ ) });
2230
+ return /* @__PURE__ */ jsxs("div", { className: "group flex flex-col bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300", children: [
2231
+ onPreview && isImageAsset(asset) ? /* @__PURE__ */ jsx(
2232
+ "button",
2233
+ {
2234
+ type: "button",
2235
+ onClick: () => onPreview(asset),
2236
+ "aria-label": `Preview ${asset.title}`,
2237
+ className: "block w-full text-left cursor-zoom-in",
2238
+ children: thumb
2239
+ }
2240
+ ) : /* @__PURE__ */ jsx(
2241
+ "a",
2242
+ {
2243
+ href: asset.fileUrl,
2244
+ target: "_blank",
2245
+ rel: "noopener noreferrer",
2246
+ "aria-label": `Open ${asset.title}`,
2247
+ className: "block",
2248
+ children: thumb
2249
+ }
2250
+ ),
2251
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 p-5", children: [
2252
+ /* @__PURE__ */ jsx("span", { className: "inline-block self-start text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: CATEGORY_LABELS[asset.category] ?? asset.category }),
2253
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground mb-1 line-clamp-2", children: asset.title }),
2254
+ asset.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-3 line-clamp-2", children: asset.description }),
2255
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between pt-3", children: [
2256
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
2257
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: ext }),
2258
+ size && /* @__PURE__ */ jsxs(Fragment, { children: [
2259
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
2260
+ /* @__PURE__ */ jsx("span", { children: size })
2261
+ ] }),
2262
+ date && /* @__PURE__ */ jsxs(Fragment, { children: [
2263
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
2264
+ /* @__PURE__ */ jsx("span", { children: date })
2265
+ ] })
2266
+ ] }),
2267
+ /* @__PURE__ */ jsxs(
2268
+ "a",
2269
+ {
2270
+ href: asset.fileUrl,
2271
+ target: "_blank",
2272
+ rel: "noopener noreferrer",
2273
+ download: true,
2274
+ onClick: (e) => {
2275
+ void downloadFile(e, asset);
2276
+ },
2277
+ className: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline",
2278
+ children: [
2279
+ /* @__PURE__ */ jsx(
2280
+ "svg",
2281
+ {
2282
+ className: "w-4 h-4",
2283
+ fill: "none",
2284
+ viewBox: "0 0 24 24",
2285
+ stroke: "currentColor",
2286
+ strokeWidth: 2,
2287
+ children: /* @__PURE__ */ jsx(
2288
+ "path",
2289
+ {
2290
+ strokeLinecap: "round",
2291
+ strokeLinejoin: "round",
2292
+ d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
2293
+ }
2294
+ )
2295
+ }
2296
+ ),
2297
+ "Download"
2298
+ ]
2299
+ }
2300
+ )
2301
+ ] })
2302
+ ] })
2303
+ ] });
2304
+ }
2305
+ function PressReleaseCard({
2306
+ release,
2307
+ basePath
2308
+ }) {
2309
+ const date = release.publishedAt || release.lastUpdated;
2310
+ const formattedDate = date ? new Date(date).toLocaleDateString("en-US", {
2311
+ year: "numeric",
2312
+ month: "long",
2313
+ day: "numeric"
2314
+ }) : "";
2315
+ const [imgError, setImgError] = useState(false);
2316
+ return /* @__PURE__ */ jsxs(
2317
+ "a",
2318
+ {
2319
+ href: `${basePath}/${release.slug}`,
2320
+ className: "group flex flex-col bg-card border rounded-xl overflow-hidden hover:shadow-lg hover:border-primary/30 transition-all duration-300",
2321
+ children: [
2322
+ release.thumbnail && !imgError ? /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] overflow-hidden bg-muted/30", children: /* @__PURE__ */ jsx(
2323
+ "img",
2324
+ {
2325
+ src: release.thumbnail,
2326
+ alt: release.title,
2327
+ className: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300",
2328
+ loading: "lazy",
2329
+ onError: () => setImgError(true)
2330
+ }
2331
+ ) }) : /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted/50 flex items-center justify-center", children: /* @__PURE__ */ jsx(
2332
+ "svg",
2333
+ {
2334
+ className: "w-12 h-12 text-muted-foreground/20",
2335
+ fill: "none",
2336
+ viewBox: "0 0 24 24",
2337
+ stroke: "currentColor",
2338
+ children: /* @__PURE__ */ jsx(
2339
+ "path",
2340
+ {
2341
+ strokeLinecap: "round",
2342
+ strokeLinejoin: "round",
2343
+ strokeWidth: 1.5,
2344
+ d: "M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m-1 13a2 2 0 01-2-2V7m3 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z"
2345
+ }
2346
+ )
2347
+ }
2348
+ ) }),
2349
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 p-5 sm:p-6", children: [
2350
+ release.category && /* @__PURE__ */ jsx("span", { className: "inline-block self-start text-xs font-medium text-primary bg-primary/10 px-2.5 py-1 rounded-full mb-3", children: release.category }),
2351
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2 group-hover:text-primary transition-colors line-clamp-2", children: release.title }),
2352
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 line-clamp-3", children: release.excerpt || release.seoDescription || "" }),
2353
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center gap-3 text-xs text-muted-foreground", children: [
2354
+ release.author && /* @__PURE__ */ jsx("span", { className: "font-medium", children: release.author }),
2355
+ release.author && formattedDate && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
2356
+ formattedDate && /* @__PURE__ */ jsx("span", { children: formattedDate }),
2357
+ release.readingTime ? /* @__PURE__ */ jsxs(Fragment, { children: [
2358
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
2359
+ /* @__PURE__ */ jsxs("span", { children: [
2360
+ release.readingTime,
2361
+ " min read"
2362
+ ] })
2363
+ ] }) : null
2364
+ ] })
2365
+ ] })
2366
+ ]
2367
+ }
2368
+ );
2369
+ }
2370
+ function PressKitPage(props) {
2371
+ const {
2372
+ productName,
2373
+ heroTitle = "Press & Media Kit",
2374
+ heroSubtitle = "Official logos, brand assets, and media resources. Everything you need to write about us.",
2375
+ mediaContactEmail,
2376
+ brandKitUrl,
2377
+ className = "",
2378
+ seoTitle,
2379
+ seoDescription,
2380
+ seoKeywords,
2381
+ showPressReleases = true,
2382
+ pressReleaseBasePath = "/press",
2383
+ pressReleasesTitle = "Press Releases"
2384
+ } = props;
2385
+ const client = useWebSDK();
2386
+ const config = useWebSDKConfig();
2387
+ const { product } = useProduct();
2388
+ const resolvedProductId = product?.id || config.productId;
2389
+ const contactEmail = mediaContactEmail || product?.contactEmail || void 0;
2390
+ const [assets, setAssets] = useState([]);
2391
+ const [loading, setLoading] = useState(true);
2392
+ const [error, setError] = useState(null);
2393
+ const [activeCategory, setActiveCategory] = useState("ALL");
2394
+ const [releases, setReleases] = useState([]);
2395
+ const [releasesLoading, setReleasesLoading] = useState(true);
2396
+ const [preview, setPreview] = useState(null);
2397
+ const fetchAssets = useCallback(async () => {
2398
+ if (!resolvedProductId) {
2399
+ setLoading(false);
2400
+ return;
2401
+ }
2402
+ setLoading(true);
2403
+ try {
2404
+ const PAGE_SIZE = 100;
2405
+ const MAX_PAGES = 10;
2406
+ const all = [];
2407
+ let offset = 0;
2408
+ for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
2409
+ const result = await client.query(PRESS_KIT_QUERY, {
2410
+ productId: resolvedProductId,
2411
+ limit: PAGE_SIZE,
2412
+ offset
2413
+ });
2414
+ if (result.errors?.length) {
2415
+ setError(result.errors[0]?.message ?? "Failed to load press kit");
2416
+ return;
2417
+ }
2418
+ const page = result.data?.publicPressKitAssets;
2419
+ const items = page?.items || [];
2420
+ all.push(...items);
2421
+ if (!page?.hasMore || items.length === 0) break;
2422
+ offset += PAGE_SIZE;
2423
+ }
2424
+ setAssets(all);
2425
+ setError(null);
2426
+ } catch {
2427
+ setError("Failed to load press kit");
2428
+ } finally {
2429
+ setLoading(false);
2430
+ }
2431
+ }, [client, resolvedProductId]);
2432
+ useEffect(() => {
2433
+ fetchAssets();
2434
+ }, [fetchAssets]);
2435
+ const fetchReleases = useCallback(async () => {
2436
+ if (!resolvedProductId || !showPressReleases) {
2437
+ setReleasesLoading(false);
2438
+ return;
2439
+ }
2440
+ setReleasesLoading(true);
2441
+ try {
2442
+ const PAGE_SIZE = 100;
2443
+ const MAX_PAGES = 10;
2444
+ const all = [];
2445
+ let offset = 0;
2446
+ for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
2447
+ const result = await client.query(PRESS_RELEASES_QUERY, {
2448
+ productId: resolvedProductId,
2449
+ limit: PAGE_SIZE,
2450
+ offset
2451
+ });
2452
+ if (result.errors?.length) {
2453
+ setReleases([]);
2454
+ return;
2455
+ }
2456
+ const page = result.data?.publicContentPages;
2457
+ const items = page?.items || [];
2458
+ all.push(...items);
2459
+ if (!page?.hasMore || items.length === 0) break;
2460
+ offset += PAGE_SIZE;
2461
+ }
2462
+ const pressOnly = all.filter((p) => p.tags?.includes("press")).sort((a, b) => {
2463
+ const da = new Date(a.publishedAt || a.lastUpdated || 0).getTime();
2464
+ const db = new Date(b.publishedAt || b.lastUpdated || 0).getTime();
2465
+ return db - da;
2466
+ });
2467
+ setReleases(pressOnly);
2468
+ } catch {
2469
+ setReleases([]);
2470
+ } finally {
2471
+ setReleasesLoading(false);
2472
+ }
2473
+ }, [client, resolvedProductId, showPressReleases]);
2474
+ useEffect(() => {
2475
+ fetchReleases();
2476
+ }, [fetchReleases]);
2477
+ const presentCategories = CATEGORY_ORDER.filter(
2478
+ (c) => assets.some((a) => a.category === c)
2479
+ );
2480
+ const visibleAssets = activeCategory === "ALL" ? assets : assets.filter((a) => a.category === activeCategory);
2481
+ const grouped = (activeCategory === "ALL" ? presentCategories : [activeCategory]).map((cat) => ({
2482
+ cat,
2483
+ items: visibleAssets.filter((a) => a.category === cat).sort((a, b) => a.sortOrder - b.sortOrder)
2484
+ })).filter((g) => g.items.length > 0);
2485
+ return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
2486
+ seoTitle && /* @__PURE__ */ jsx(
2487
+ PageHead,
2488
+ {
2489
+ title: seoTitle,
2490
+ description: seoDescription || heroSubtitle,
2491
+ productName,
2492
+ keywords: seoKeywords
2493
+ }
2494
+ ),
2495
+ /* @__PURE__ */ jsx("section", { className: "py-16 sm:py-20 md:py-24", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-3xl mx-auto", children: [
2496
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl sm:text-4xl md:text-5xl font-bold tracking-tight text-foreground", children: heroTitle }),
2497
+ /* @__PURE__ */ jsx("p", { className: "mt-4 text-lg text-muted-foreground", children: heroSubtitle }),
2498
+ (brandKitUrl || contactEmail) && /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-wrap items-center justify-center gap-4", children: [
2499
+ brandKitUrl && /* @__PURE__ */ jsx(
2500
+ "a",
2501
+ {
2502
+ href: brandKitUrl,
2503
+ target: "_blank",
2504
+ rel: "noopener noreferrer",
2505
+ className: "inline-flex items-center gap-2 px-6 py-3 rounded-lg bg-primary text-primary-foreground font-medium hover:opacity-90 transition-opacity",
2506
+ children: "Download brand kit"
2507
+ }
2508
+ ),
2509
+ contactEmail && /* @__PURE__ */ jsx(
2510
+ "a",
2511
+ {
2512
+ href: `mailto:${contactEmail}`,
2513
+ className: "inline-flex items-center gap-2 px-6 py-3 rounded-lg border font-medium text-foreground hover:bg-muted transition-colors",
2514
+ children: "Media inquiries"
2515
+ }
2516
+ )
2517
+ ] })
2518
+ ] }) }) }),
2519
+ showPressReleases && (releasesLoading || releases.length > 0) && /* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsxs("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: [
2520
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground mb-6", children: pressReleasesTitle }),
2521
+ /* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: releasesLoading ? [1, 2, 3].map((i) => /* @__PURE__ */ jsxs(
2522
+ "div",
2523
+ {
2524
+ className: "bg-card border rounded-xl overflow-hidden animate-pulse",
2525
+ children: [
2526
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
2527
+ /* @__PURE__ */ jsxs("div", { className: "p-5 space-y-3", children: [
2528
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
2529
+ /* @__PURE__ */ jsx("div", { className: "h-5 bg-muted rounded w-3/4" }),
2530
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
2531
+ ] })
2532
+ ]
2533
+ },
2534
+ i
2535
+ )) : releases.map((r) => /* @__PURE__ */ jsx(
2536
+ PressReleaseCard,
2537
+ {
2538
+ release: r,
2539
+ basePath: pressReleaseBasePath
2540
+ },
2541
+ r.id
2542
+ )) })
2543
+ ] }) }),
2544
+ /* @__PURE__ */ jsx("section", { className: "pb-16 sm:pb-20", children: /* @__PURE__ */ jsx("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: loading ? /* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: [1, 2, 3, 4, 5, 6].map((i) => /* @__PURE__ */ jsxs(
2545
+ "div",
2546
+ {
2547
+ className: "bg-card border rounded-xl overflow-hidden animate-pulse",
2548
+ children: [
2549
+ /* @__PURE__ */ jsx("div", { className: "aspect-[16/9] bg-muted" }),
2550
+ /* @__PURE__ */ jsxs("div", { className: "p-5 space-y-3", children: [
2551
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/4" }),
2552
+ /* @__PURE__ */ jsx("div", { className: "h-5 bg-muted rounded w-3/4" }),
2553
+ /* @__PURE__ */ jsx("div", { className: "h-4 bg-muted rounded w-1/2" })
2554
+ ] })
2555
+ ]
2556
+ },
2557
+ i
2558
+ )) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: error }) }) : assets.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-12", children: /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
2559
+ "Press materials are coming soon. For media inquiries",
2560
+ contactEmail ? /* @__PURE__ */ jsxs(Fragment, { children: [
2561
+ ", contact ",
2562
+ /* @__PURE__ */ jsx(
2563
+ "a",
2564
+ {
2565
+ href: `mailto:${contactEmail}`,
2566
+ className: "text-primary underline underline-offset-4 hover:no-underline",
2567
+ children: contactEmail
2568
+ }
2569
+ )
2570
+ ] }) : " please reach out to our team",
2571
+ "."
2572
+ ] }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2573
+ presentCategories.length > 1 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 mb-10 justify-center", children: ["ALL", ...presentCategories].map((c) => {
2574
+ const active = activeCategory === c;
2575
+ return /* @__PURE__ */ jsx(
2576
+ "button",
2577
+ {
2578
+ type: "button",
2579
+ onClick: () => setActiveCategory(c),
2580
+ className: `px-4 py-2 rounded-full text-sm font-medium transition-colors ${active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`,
2581
+ children: c === "ALL" ? "All" : CATEGORY_LABELS[c] ?? c
2582
+ },
2583
+ c
2584
+ );
2585
+ }) }),
2586
+ grouped.map((group) => /* @__PURE__ */ jsxs("div", { className: "mb-12", children: [
2587
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground mb-5", children: CATEGORY_LABELS[group.cat] ?? group.cat }),
2588
+ /* @__PURE__ */ jsx("div", { className: "grid sm:grid-cols-2 lg:grid-cols-3 gap-6", children: group.items.map((a) => /* @__PURE__ */ jsx(AssetCard, { asset: a, onPreview: setPreview }, a.id)) })
2589
+ ] }, group.cat)),
2590
+ contactEmail && /* @__PURE__ */ jsxs("div", { className: "mt-8 border-t pt-10 text-center", children: [
2591
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground mb-2", children: "Media Contact" }),
2592
+ /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground", children: [
2593
+ "For interviews, partnerships, and press inquiries:",
2594
+ " ",
2595
+ /* @__PURE__ */ jsx(
2596
+ "a",
2597
+ {
2598
+ href: `mailto:${contactEmail}`,
2599
+ className: "text-primary underline underline-offset-4 hover:no-underline",
2600
+ children: contactEmail
2601
+ }
2602
+ )
2603
+ ] })
2604
+ ] })
2605
+ ] }) }) }),
2606
+ /* @__PURE__ */ jsx(PressKitLightbox, { asset: preview, onClose: () => setPreview(null) })
2607
+ ] });
2608
+ }
2609
+ var CONTRACTS_QUERY = `
2610
+ query PublicContracts($productId: String!, $limit: Int, $offset: Int) {
2611
+ publicPressKitAssets(productId: $productId, category: CONTRACT, limit: $limit, offset: $offset) {
2612
+ items {
2613
+ id
2614
+ title
2615
+ slug
2616
+ description
2617
+ fileUrl
2618
+ fileName
2619
+ fileSize
2620
+ mimeType
2621
+ version
2622
+ tags
2623
+ sortOrder
2624
+ updatedAt
2625
+ }
2626
+ hasMore
2627
+ }
2628
+ }
2629
+ `;
2630
+ function ContractsPage(props) {
2631
+ const {
2632
+ productName,
2633
+ heroTitle = "Contracts & Legal Agreements",
2634
+ heroSubtitle = "Download our standard legal agreements and policies.",
2635
+ className = "",
2636
+ seoTitle,
2637
+ seoDescription,
2638
+ seoKeywords
2639
+ } = props;
2640
+ const client = useWebSDK();
2641
+ const config = useWebSDKConfig();
2642
+ const { product } = useProduct();
2643
+ const resolvedProductId = product?.id || config.productId;
2644
+ const displayName = productName ?? product?.name ?? config.productId;
2645
+ const [contracts, setContracts] = useState([]);
2646
+ const [loading, setLoading] = useState(true);
2647
+ const [error, setError] = useState(null);
2648
+ const fetchContracts = useCallback(async () => {
2649
+ if (!resolvedProductId) {
2650
+ setLoading(false);
2651
+ return;
2652
+ }
2653
+ setLoading(true);
2654
+ try {
2655
+ const PAGE_SIZE = 100;
2656
+ const MAX_PAGES = 10;
2657
+ const all = [];
2658
+ let offset = 0;
2659
+ for (let pageNum = 0; pageNum < MAX_PAGES; pageNum++) {
2660
+ const result = await client.query(CONTRACTS_QUERY, {
2661
+ productId: resolvedProductId,
2662
+ limit: PAGE_SIZE,
2663
+ offset
2664
+ });
2665
+ if (result.errors?.length) {
2666
+ setError(result.errors[0]?.message ?? "Failed to load contracts");
2667
+ return;
2668
+ }
2669
+ const page = result.data?.publicPressKitAssets;
2670
+ const items = page?.items || [];
2671
+ all.push(...items);
2672
+ if (!page?.hasMore || items.length === 0) break;
2673
+ offset += PAGE_SIZE;
2674
+ }
2675
+ all.sort(
2676
+ (a, b) => a.sortOrder - b.sortOrder || a.title.localeCompare(b.title)
2677
+ );
2678
+ setContracts(all);
2679
+ setError(null);
2680
+ } catch {
2681
+ setError("Failed to load contracts");
2682
+ } finally {
2683
+ setLoading(false);
2684
+ }
2685
+ }, [client, resolvedProductId]);
2686
+ useEffect(() => {
2687
+ fetchContracts();
2688
+ }, [fetchContracts]);
2689
+ return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-background ${className}`, children: [
2690
+ /* @__PURE__ */ jsx(
2691
+ PageHead,
2692
+ {
2693
+ title: seoTitle || `Contracts \u2014 ${displayName}`,
2694
+ description: seoDescription || heroSubtitle,
2695
+ productName,
2696
+ keywords: seoKeywords
2697
+ }
2698
+ ),
2699
+ /* @__PURE__ */ jsx("section", { className: "border-b border-border bg-muted/30", children: /* @__PURE__ */ jsxs("div", { className: "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center", children: [
2700
+ /* @__PURE__ */ jsx("h1", { className: "text-4xl md:text-5xl font-bold text-foreground mb-4", children: heroTitle }),
2701
+ /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground max-w-2xl mx-auto", children: heroSubtitle })
2702
+ ] }) }),
2703
+ /* @__PURE__ */ jsx("section", { className: "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12", children: loading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-20", children: /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : error ? /* @__PURE__ */ jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error }) }) : contracts.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center py-16", children: /* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground", children: "No contracts are available yet." }) }) : /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border rounded-xl border border-border overflow-hidden bg-card", children: contracts.map((c) => {
2704
+ const ext = fileExt(c);
2705
+ const size = formatBytes(c.fileSize);
2706
+ return /* @__PURE__ */ jsxs(
2707
+ "li",
2708
+ {
2709
+ className: "flex items-center justify-between gap-4 p-5 hover:bg-muted/40 transition-colors",
2710
+ children: [
2711
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
2712
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
2713
+ /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground truncate", children: c.title }),
2714
+ c.version && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-primary bg-primary/10 px-2 py-0.5 rounded-full", children: c.version })
2715
+ ] }),
2716
+ c.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mt-1 line-clamp-2", children: c.description }),
2717
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground", children: [
2718
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: ext }),
2719
+ size && /* @__PURE__ */ jsxs(Fragment, { children: [
2720
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
2721
+ /* @__PURE__ */ jsx("span", { children: size })
2722
+ ] })
2723
+ ] })
2724
+ ] }),
2725
+ /* @__PURE__ */ jsxs(
2726
+ "a",
2727
+ {
2728
+ href: c.fileUrl,
2729
+ target: "_blank",
2730
+ rel: "noopener noreferrer",
2731
+ download: true,
2732
+ "aria-label": `Download ${c.title}`,
2733
+ onClick: (e) => {
2734
+ void downloadFile(e, c);
2735
+ },
2736
+ className: "flex-shrink-0 inline-flex items-center gap-1.5 text-sm font-medium text-primary-foreground bg-primary hover:opacity-90 px-4 py-2 rounded-lg transition-opacity",
2737
+ children: [
2738
+ /* @__PURE__ */ jsx(
2739
+ "svg",
2740
+ {
2741
+ className: "w-4 h-4",
2742
+ fill: "none",
2743
+ viewBox: "0 0 24 24",
2744
+ stroke: "currentColor",
2745
+ "aria-hidden": "true",
2746
+ children: /* @__PURE__ */ jsx(
2747
+ "path",
2748
+ {
2749
+ strokeLinecap: "round",
2750
+ strokeLinejoin: "round",
2751
+ strokeWidth: 2,
2752
+ d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
2753
+ }
2754
+ )
2755
+ }
2756
+ ),
2757
+ "Download"
2758
+ ]
2759
+ }
2760
+ )
2761
+ ]
2762
+ },
2763
+ c.id
2764
+ );
2765
+ }) }) })
2766
+ ] });
2767
+ }
2768
+
2769
+ export { BlogListPage, BlogPostPage, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ContractsPage, LEGAL_DOCUMENTS, LEGAL_DOCUMENT_KEYS, LegalPage, PressKitPage, fetchLegalContent, fetchLegalContentPage, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, findLegalDocument, formatLegalDate, hasCustomerSignOff, splitLeadingHeading, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission };
2770
+ //# sourceMappingURL=chunk-D2TW7MNC.mjs.map
2771
+ //# sourceMappingURL=chunk-D2TW7MNC.mjs.map