@burdenoff/website-sdk 2026.1101.1 → 2026.1101.3

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