@burdenoff/website-sdk 0.0.0-dev

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 (119) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +357 -0
  3. package/dist/analytics/index.d.mts +27 -0
  4. package/dist/analytics/index.d.ts +27 -0
  5. package/dist/analytics/index.js +36 -0
  6. package/dist/analytics/index.js.map +1 -0
  7. package/dist/analytics/index.mjs +34 -0
  8. package/dist/analytics/index.mjs.map +1 -0
  9. package/dist/client/index.d.mts +29 -0
  10. package/dist/client/index.d.ts +29 -0
  11. package/dist/client/index.js +261 -0
  12. package/dist/client/index.js.map +1 -0
  13. package/dist/client/index.mjs +255 -0
  14. package/dist/client/index.mjs.map +1 -0
  15. package/dist/components/contact.d.mts +144 -0
  16. package/dist/components/contact.d.ts +144 -0
  17. package/dist/components/contact.js +806 -0
  18. package/dist/components/contact.js.map +1 -0
  19. package/dist/components/contact.mjs +780 -0
  20. package/dist/components/contact.mjs.map +1 -0
  21. package/dist/components/electron-download.d.mts +32 -0
  22. package/dist/components/electron-download.d.ts +32 -0
  23. package/dist/components/electron-download.js +131 -0
  24. package/dist/components/electron-download.js.map +1 -0
  25. package/dist/components/electron-download.mjs +108 -0
  26. package/dist/components/electron-download.mjs.map +1 -0
  27. package/dist/components/launch-countdown.d.mts +15 -0
  28. package/dist/components/launch-countdown.d.ts +15 -0
  29. package/dist/components/launch-countdown.js +89 -0
  30. package/dist/components/launch-countdown.js.map +1 -0
  31. package/dist/components/launch-countdown.mjs +87 -0
  32. package/dist/components/launch-countdown.mjs.map +1 -0
  33. package/dist/components/newsletter.d.mts +155 -0
  34. package/dist/components/newsletter.d.ts +155 -0
  35. package/dist/components/newsletter.js +880 -0
  36. package/dist/components/newsletter.js.map +1 -0
  37. package/dist/components/newsletter.mjs +854 -0
  38. package/dist/components/newsletter.mjs.map +1 -0
  39. package/dist/components/partners.d.mts +88 -0
  40. package/dist/components/partners.d.ts +88 -0
  41. package/dist/components/partners.js +1169 -0
  42. package/dist/components/partners.js.map +1 -0
  43. package/dist/components/partners.mjs +1143 -0
  44. package/dist/components/partners.mjs.map +1 -0
  45. package/dist/components/pricing.d.mts +194 -0
  46. package/dist/components/pricing.d.ts +194 -0
  47. package/dist/components/pricing.js +813 -0
  48. package/dist/components/pricing.js.map +1 -0
  49. package/dist/components/pricing.mjs +791 -0
  50. package/dist/components/pricing.mjs.map +1 -0
  51. package/dist/components/problems-solved.d.mts +37 -0
  52. package/dist/components/problems-solved.d.ts +37 -0
  53. package/dist/components/problems-solved.js +157 -0
  54. package/dist/components/problems-solved.js.map +1 -0
  55. package/dist/components/problems-solved.mjs +135 -0
  56. package/dist/components/problems-solved.mjs.map +1 -0
  57. package/dist/components/resource-links.d.mts +28 -0
  58. package/dist/components/resource-links.d.ts +28 -0
  59. package/dist/components/resource-links.js +229 -0
  60. package/dist/components/resource-links.js.map +1 -0
  61. package/dist/components/resource-links.mjs +227 -0
  62. package/dist/components/resource-links.mjs.map +1 -0
  63. package/dist/components/social-links.d.mts +37 -0
  64. package/dist/components/social-links.d.ts +37 -0
  65. package/dist/components/social-links.js +268 -0
  66. package/dist/components/social-links.js.map +1 -0
  67. package/dist/components/social-links.mjs +266 -0
  68. package/dist/components/social-links.mjs.map +1 -0
  69. package/dist/components/unsubscribe.d.mts +14 -0
  70. package/dist/components/unsubscribe.d.ts +14 -0
  71. package/dist/components/unsubscribe.js +538 -0
  72. package/dist/components/unsubscribe.js.map +1 -0
  73. package/dist/components/unsubscribe.mjs +517 -0
  74. package/dist/components/unsubscribe.mjs.map +1 -0
  75. package/dist/components/waitlist.d.mts +70 -0
  76. package/dist/components/waitlist.d.ts +70 -0
  77. package/dist/components/waitlist.js +864 -0
  78. package/dist/components/waitlist.js.map +1 -0
  79. package/dist/components/waitlist.mjs +841 -0
  80. package/dist/components/waitlist.mjs.map +1 -0
  81. package/dist/components/website-switcher.d.mts +27 -0
  82. package/dist/components/website-switcher.d.ts +27 -0
  83. package/dist/components/website-switcher.js +168 -0
  84. package/dist/components/website-switcher.js.map +1 -0
  85. package/dist/components/website-switcher.mjs +146 -0
  86. package/dist/components/website-switcher.mjs.map +1 -0
  87. package/dist/content/index.d.mts +247 -0
  88. package/dist/content/index.d.ts +247 -0
  89. package/dist/content/index.js +2458 -0
  90. package/dist/content/index.js.map +1 -0
  91. package/dist/content/index.mjs +2428 -0
  92. package/dist/content/index.mjs.map +1 -0
  93. package/dist/index.d.mts +72 -0
  94. package/dist/index.d.ts +72 -0
  95. package/dist/index.js +6273 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/index.mjs +6204 -0
  98. package/dist/index.mjs.map +1 -0
  99. package/dist/product/index.d.mts +94 -0
  100. package/dist/product/index.d.ts +94 -0
  101. package/dist/product/index.js +282 -0
  102. package/dist/product/index.js.map +1 -0
  103. package/dist/product/index.mjs +278 -0
  104. package/dist/product/index.mjs.map +1 -0
  105. package/dist/provider-D7Rij9UM.d.mts +86 -0
  106. package/dist/provider-D7Rij9UM.d.ts +86 -0
  107. package/dist/seo/index.d.mts +64 -0
  108. package/dist/seo/index.d.ts +64 -0
  109. package/dist/seo/index.js +61 -0
  110. package/dist/seo/index.js.map +1 -0
  111. package/dist/seo/index.mjs +59 -0
  112. package/dist/seo/index.mjs.map +1 -0
  113. package/dist/utils/index.d.mts +21 -0
  114. package/dist/utils/index.d.ts +21 -0
  115. package/dist/utils/index.js +12 -0
  116. package/dist/utils/index.js.map +1 -0
  117. package/dist/utils/index.mjs +10 -0
  118. package/dist/utils/index.mjs.map +1 -0
  119. package/package.json +168 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/security.ts","../../src/client/graphql-client.ts","../../src/client/provider.tsx","../../src/product/product-provider.tsx","../../src/seo/page-head.tsx","../../src/utils/cn.ts","../../src/ui/button.tsx","../../src/ui/input.tsx","../../src/ui/label.tsx","../../src/ui/select.tsx","../../src/ui/textarea.tsx","../../src/components/contact.tsx","../../src/content/content-provider.tsx","../../src/components/partners.tsx"],"names":["createContext","useContext","Helmet","jsx","twMerge","clsx","cva","React","Slot","React2","React3","LabelPrimitive","React4","React5","useRef","useState","toast","jsxs","Mail","Phone","MapPin","Clock","ReCAPTCHA","Fragment","Send","FileText","Download","useEffect"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAM,iCAAiB,IAAI,GAAA,CAAI,CAAC,WAAA,EAAa,WAAA,EAAa,KAAK,CAAC,CAAA;AAChE,IAAM,gBAAA,uBAAuB,GAAA,CAAI;AAAA,EAC/B,eAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,sBAAA;AAAA,EACA,iBAAA;AAAA,EACA,sBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAEM,SAAS,mBAAmB,KAAA,EAAuB;AACxD,EAAA,IAAI,GAAA;AAEJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,IAAI,KAAK,CAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,QAAA,EAAU;AAC7B,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEA,EAAA,IACE,GAAA,CAAI,aAAa,OAAA,IACjB,cAAA,CAAe,IAAI,GAAA,CAAI,QAAA,CAAS,WAAA,EAAa,CAAA,EAC7C;AACA,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEA,EAAA,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAC1E;AAEO,SAAS,gBACd,OAAA,EACoC;AACpC,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AAErB,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,MAAA;AAAA,MACtB,CAAC,CAAC,GAAG,CAAA,KAAM,CAAC,gBAAA,CAAiB,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa;AAAA;AACpD,GACF;AACF;;;ACZO,IAAM,aAAA,GAAN,MAAM,aAAA,CAAa;AAAA,EAUxB,YAAY,MAAA,EAA4B;AATxC,IAAA,aAAA,CAAA,IAAA,EAAQ,QAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,YAAA,sBAAiB,GAAA,EAGvB,CAAA;AACF,IAAA,aAAA,CAAA,IAAA,EAAQ,UAAA,sBAAe,GAAA,EAA+C,CAAA;AAKpE,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,MAAA;AAAA,MACH,UAAA,EAAY,kBAAA,CAAmB,MAAA,CAAO,UAAU,CAAA;AAAA,MAChD,OAAA,EAAS,eAAA,CAAgB,MAAA,CAAO,OAAO;AAAA,KACzC;AAAA,EACF;AAAA,EAEA,SAAA,GAAgC;AAC9B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,CACJ,KAAA,EACA,SAAA,EAC6B;AAC7B,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAW,CAAA;AAGpD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAI,KAAK,GAAA,EAAI,GAAI,MAAA,CAAO,EAAA,GAAK,cAAa,SAAA,EAAW;AACnD,QAAA,OAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AACA,MAAA,IAAA,CAAK,UAAA,CAAW,OAAO,QAAQ,CAAA;AAAA,IACjC;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAW,KAAA,EAAO,SAAS,CAAA,CAC7C,IAAA,CAAK,CAAC,MAAA,KAAW;AAEhB,MAAA,IAAI,MAAA,CAAO,IAAA,IAAQ,CAAC,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzC,QAAA,IAAI,IAAA,CAAK,UAAA,CAAW,IAAA,IAAQ,aAAA,CAAa,iBAAA,EAAmB;AAC1D,UAAA,MAAM,cAAc,IAAA,CAAK,UAAA,CAAW,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AAClD,UAAA,IAAI,WAAA,EAAa;AACf,YAAA,IAAA,CAAK,UAAA,CAAW,OAAO,WAAW,CAAA;AAAA,UACpC;AAAA,QACF;AACA,QAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAA,EAAU,EAAE,IAAA,EAAM,QAAQ,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,EAAG,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,QAAQ,CAAA;AAAA,IAC/B,CAAC,CAAA;AAEH,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,QAAA,EAAU,OAAO,CAAA;AACnC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,QAAA,EACA,SAAA,EAC6B;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,QAAA,EAAU,SAAS,CAAA;AAAA,EAC5C;AAAA,EAEA,MAAc,OAAA,CACZ,KAAA,EACA,SAAA,EAC6B;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,OAAO,UAAA,EAAY;AAAA,QACnD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,cAAA,EAAgB,KAAK,MAAA,CAAO,SAAA;AAAA,UAC5B,GAAG,KAAK,MAAA,CAAO;AAAA,SACjB;AAAA,QACA,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,WAAW;AAAA,OAC1C,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,OAAA,CAAQ,KAAA;AAAA,UACN,iCAAA;AAAA,UACA,QAAA,CAAS,MAAA;AAAA,UACT,QAAA,CAAS;AAAA,SACX;AACA,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ;AAAA,YACN;AAAA,cACE,SAAS,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA,CAAA;AAAA,cACxD,YAAY,EAAE,IAAA,EAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AAAG;AAChD;AACF,SACF;AAAA,MACF;AAEA,MAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,IAC9B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA;AAAA,QACN,wBAAA;AAAA,QACA,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,OAC3C;AACA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ;AAAA,UACN;AAAA,YACE,OAAA,EAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAAA,YAClD,UAAA,EAAY,EAAE,IAAA,EAAM,eAAA;AAAgB;AACtC;AACF,OACF;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAtHE,aAAA,CAPW,aAAA,EAOI,WAAA,EAAY,CAAA,GAAI,EAAA,GAAK,GAAA,CAAA;AAAA;AACpC,aAAA,CARW,eAQI,mBAAA,EAAoB,GAAA,CAAA;AC7BrC,IAAM,aAAA,GAAgBA,oBAAmC,IAAI,CAAA;AAyCtD,SAAS,SAAA,GAA0B;AACxC,EAAA,MAAM,MAAA,GAASC,iBAAW,aAAa,CAAA;AACvC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AACA,EAAA,OAAO,MAAA;AACT;AAMO,SAAS,eAAA,GAAsC;AACpD,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,OAAO,OAAO,SAAA,EAAU;AAC1B;AC6EA,IAAM,iBAAiBD,mBAAAA,CAAmC;AAAA,EACxD,OAAA,EAAS,IAAA;AAAA,EACT,OAAA,EAAS,IAAA;AAAA,EACT,KAAA,EAAO,IAAA;AAAA,EACP,WAAA,EAAa,KAAA;AAAA,EACb,SAAS,MAAM;AAAA,EAAC;AAClB,CAAC,CAAA;AA4GM,SAAS,UAAA,GAAkC;AAChD,EAAA,OAAOC,iBAAW,cAAc,CAAA;AAClC;ACtMO,SAAS,QAAA,CAAS;AAAA,EACvB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,GAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,GAAS,8EAAA;AAAA,EACT,MAAA,GAAS,OAAA;AAAA,EACT,aAAA;AAAA,EACA,UAAA,GAAa,SAAA;AAAA,EACb,cAAA;AAAA,EACA;AACF,CAAA,EAAkB;AAChB,EAAA,MAAM,SAAA,GACJ,WAAA,IAAe,CAAC,KAAA,CAAM,QAAA,CAAS,WAAW,CAAA,GACtC,CAAA,EAAG,KAAK,CAAA,GAAA,EAAM,WAAW,CAAA,CAAA,GACzB,KAAA;AAEN,EAAA,MAAM,eACJ,KAAA,IAAS,CAAC,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA,IAAK,GAAA,GAClC,CAAA,EAAG,GAAA,CAAI,QAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,EAAG,KAAK,CAAA,CAAA,GACjC,KAAA;AAGN,EAAA,MAAM,mBAAA,GAAsD,cAAA,GACxD,KAAA,CAAM,OAAA,CAAQ,cAAc,IAC1B,cAAA,GACA,CAAC,cAAc,CAAA,GACjB,EAAC;AAEL,EAAA,uCACGC,uBAAA,EAAA,EAEC,QAAA,EAAA;AAAA,oBAAAC,cAAAA,CAAC,WAAO,QAAA,EAAA,SAAA,EAAU,CAAA;AAAA,oBAClBA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,SAAS,SAAA,EAAW,CAAA;AAAA,IACtC,+BAAeA,cAAAA,CAAC,UAAK,IAAA,EAAK,aAAA,EAAc,SAAS,WAAA,EAAa,CAAA;AAAA,IAC9D,4BAAYA,cAAAA,CAAC,UAAK,IAAA,EAAK,UAAA,EAAW,SAAS,QAAA,EAAU,CAAA;AAAA,oBACtDA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,QAAA,EAAS,SAAQ,wCAAA,EAAyC,CAAA;AAAA,oBACrEA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,QAAA,EAAS,SAAS,MAAA,EAAQ,CAAA;AAAA,IAGpC,uBAAOA,cAAAA,CAAC,UAAK,GAAA,EAAI,WAAA,EAAY,MAAM,GAAA,EAAK,CAAA;AAAA,IAGxC,2BAAWA,cAAAA,CAAC,UAAK,GAAA,EAAI,MAAA,EAAO,MAAM,OAAA,EAAS,CAAA;AAAA,oBAG5CA,cAAAA,CAAC,MAAA,EAAA,EAAK,QAAA,EAAS,SAAA,EAAU,SAAQ,SAAA,EAAU,CAAA;AAAA,oBAC3CA,cAAAA,CAAC,MAAA,EAAA,EAAK,QAAA,EAAS,UAAA,EAAW,SAAS,SAAA,EAAW,CAAA;AAAA,IAC7C,+BAAeA,cAAAA,CAAC,UAAK,QAAA,EAAS,gBAAA,EAAiB,SAAS,WAAA,EAAa,CAAA;AAAA,IACrE,gCAAgBA,cAAAA,CAAC,UAAK,QAAA,EAAS,UAAA,EAAW,SAAS,YAAA,EAAc,CAAA;AAAA,IACjE,uBAAOA,cAAAA,CAAC,UAAK,QAAA,EAAS,QAAA,EAAS,SAAS,GAAA,EAAK,CAAA;AAAA,oBAC9CA,cAAAA,CAAC,MAAA,EAAA,EAAK,QAAA,EAAS,WAAA,EAAY,SAAS,MAAA,EAAQ,CAAA;AAAA,IAC3C,+BAAeA,cAAAA,CAAC,UAAK,QAAA,EAAS,cAAA,EAAe,SAAS,WAAA,EAAa,CAAA;AAAA,oBAGpEA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,cAAA,EAAe,SAAQ,qBAAA,EAAsB,CAAA;AAAA,oBACxDA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,eAAA,EAAgB,SAAS,SAAA,EAAW,CAAA;AAAA,IAC9C,+BAAeA,cAAAA,CAAC,UAAK,IAAA,EAAK,qBAAA,EAAsB,SAAS,WAAA,EAAa,CAAA;AAAA,IACtE,gCAAgBA,cAAAA,CAAC,UAAK,IAAA,EAAK,eAAA,EAAgB,SAAS,YAAA,EAAc,CAAA;AAAA,IAClE,iCAAiBA,cAAAA,CAAC,UAAK,IAAA,EAAK,iBAAA,EAAkB,SAAS,aAAA,EAAe,CAAA;AAAA,oBAGvEA,cAAAA,CAAC,MAAA,EAAA,EAAK,IAAA,EAAK,aAAA,EAAc,SAAS,UAAA,EAAY,CAAA;AAAA,IAG7C,oBAAoB,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,qBAC9BA,cAAAA,CAAC,QAAA,EAAA,EAA2B,IAAA,EAAK,qBAAA,EAC9B,eAAK,SAAA,CAAU,IAAI,KADT,CAAA,GAAA,EAAM,KAAK,EAExB,CACD,CAAA;AAAA,IAGA,cAAA,EAAgB,GAAA,CAAI,CAAC,IAAA,EAAM,0BAC1BA,cAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QAEE,GAAI,KAAK,IAAA,GAAO,EAAE,MAAM,IAAA,CAAK,IAAA,KAAS,EAAC;AAAA,QACvC,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,QACpD,SAAS,IAAA,CAAK;AAAA,OAAA;AAAA,MAHT,QAAQ,KAAK,CAAA;AAAA,KAKrB;AAAA,GAAA,EACH,CAAA;AAEJ;ACjIO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAOC,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACdA,IAAM,cAAA,GAAiBC,0BAAA;AAAA,EACrB,uSAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EACE,+DAAA;AAAA,QACF,WAAA,EACE,8EAAA;AAAA,QACF,OAAA,EACE,0FAAA;AAAA,QACF,SAAA,EACE,wEAAA;AAAA,QACF,KAAA,EAAO,8CAAA;AAAA,QACP,IAAA,EAAM;AAAA,OACR;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,eAAA;AAAA,QACT,EAAA,EAAI,6BAAA;AAAA,QACJ,EAAA,EAAI,sBAAA;AAAA,QACJ,IAAA,EAAM;AAAA;AACR,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM;AAAA;AACR;AAEJ,CAAA;AASA,IAAM,MAAA,GAAeC,gBAAA,CAAA,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,UAAU,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAChE,IAAA,MAAM,IAAA,GAAO,UAAUC,cAAA,GAAO,QAAA;AAC9B,IAAA,uBACEL,cAAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,GAAG,cAAA,CAAe,EAAE,SAAS,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA;AAAA,QAC1D,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF,CAAA;AACA,MAAA,CAAO,WAAA,GAAc,QAAA;ACpDrB,IAAM,KAAA,GAAcM,gBAAA,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,MAAM,GAAG,KAAA,IAAS,GAAA,KAAQ;AACtC,IAAA,uBACEN,cAAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,yWAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,GAAA;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF,CAAA;AACA,KAAA,CAAM,WAAA,GAAc,OAAA;ACZpB,IAAM,aAAA,GAAgBG,0BAAAA;AAAA,EACpB;AACF,CAAA;AAEA,IAAM,KAAA,GAAcI,4BAIlB,CAAC,EAAE,WAAW,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1BP,cAAAA;AAAA,EAAgBQ,yBAAA,CAAA,IAAA;AAAA,EAAf;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,aAAA,EAAc,EAAG,SAAS,CAAA;AAAA,IACvC,GAAG;AAAA;AACN,CACD,CAAA;AACD,KAAA,CAAM,cAA6BA,yBAAA,CAAA,IAAA,CAAK,WAAA;ACjBxC,IAAM,MAAA,GAAeC,4BAGnB,CAAC,EAAE,WAAW,QAAA,EAAU,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC5C,EAAA,uBACET,cAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,sWAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOA,CAAA,+PAAA,CAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,GAAA;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ,CAAC,CAAA;AACD,MAAA,CAAO,WAAA,GAAc,QAAA;ACzBrB,IAAM,QAAA,GAAiBU,4BAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AAClC,EAAA,uBACEV,cAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,2QAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,GAAA;AAAA,MACC,GAAG;AAAA;AAAA,GACN;AAEJ,CAAC,CAAA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA;AC8KvB,IAAM,+BAAA;AAAA;AAAA,EAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAatD,eAAe,iBAAA,CACb,MAAA,EACA,IAAA,EACA,SAAA,EACiD;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAKzB,+BAAA,EAAiC;AAAA,MAClC,KAAA,EAAO;AAAA,QACL,MAAM,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,CAAA,EAAI,KAAK,QAAQ,CAAA,CAAA;AAAA,QACxC,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,WAAA,EAAY;AAAA,QACrC,OAAA,EAAS,KAAK,OAAA,IAAW,KAAA,CAAA;AAAA,QACzB,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMA,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA,QACnD,GAAI,KAAK,cAAA,GAAiB,EAAE,gBAAgB,IAAA,CAAK,cAAA,KAAmB;AAAC;AACvE,KACD,CAAA;AAED,IAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAQ;AACzB,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,CAAC,GAAG,OAAA,IAAW,wBAAA;AAC9C,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,QAAA,EAAS;AAAA,IAC7C;AAEA,IAAA,MAAM,QAAA,GAAW,OAAO,IAAA,EAAM,oBAAA;AAC9B,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,OAAA,EAAS,SAAS,OAAA,IAAW;AAAA,OAC/B;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,OAAA,EAAS,UAAU,OAAA,IAAW;AAAA,KAChC;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,kCAAkC,KAAK,CAAA;AACrD,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AACF;AAMA,SAAS,mBAAA,CACP,IAAA,EACA,WAAA,EACA,KAAA,EACQ;AACR,EAAA,OAAO,KAAK,OAAA,CAAQ,gBAAA,EAAkB,WAAW,CAAA,CAAE,OAAA,CAAQ,YAAY,KAAK,CAAA;AAC9E;AAMO,SAAS,WAAA,CAAY;AAAA,EAC1B,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA,GAAe,sCAAA;AAAA,EACf,SAAA,GAAY,cAAA;AAAA,EACZ,eAAA,GAAkB,8HAAA;AAAA,EAClB,YAAA,GAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOf,aAAa,EAAC;AAAA,EACd,aAAA,GAAgB,UAAA;AAAA,EAChB,mBAAA,GAAsB,mBAAA;AAAA,EACtB,gBAAA,GAAmB,IAAA;AAAA,EACnB,iBAAA,GAAoB;AAAA,IAClB;AAAA,MACE,KAAA,EAAO,iBAAA;AAAA,MACP,WAAA,EACE,uEAAA;AAAA,MACF,UAAA,EAAY,eAAA;AAAA,MACZ,UAAA,EAAY,UAAU,YAAY,CAAA;AAAA,KACpC;AAAA,IACA;AAAA,MACE,KAAA,EAAO,mBAAA;AAAA,MACP,WAAA,EACE,qEAAA;AAAA,MACF,UAAA,EAAY,aAAA;AAAA,MACZ,UAAA,EAAY,UAAU,YAAY,CAAA;AAAA,KACpC;AAAA,IACA;AAAA,MACE,KAAA,EAAO,aAAA;AAAA,MACP,WAAA,EACE,2EAAA;AAAA,MACF,UAAA,EAAY,iBAAA;AAAA,MACZ,UAAA,EAAY,UAAU,YAAY,CAAA;AAAA;AACpC,GACF;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,UAAA,EAAW;AAC/B,EAAA,MAAM,iBAAA,GAAoB,OAAA,EAAS,EAAA,IAAM,MAAA,CAAO,SAAA;AAChD,EAAA,MAAM,WAAA,GAAc,WAAA,IAAe,OAAA,EAAS,IAAA,IAAQ,MAAA,CAAO,SAAA;AAI3D,EAAA,MAAM,yBAAA,GACJ,gBAAA,IACA,OAAA,EAAS,gBAAA,IACT,OAAO,gBAAA,IACP,EAAA;AAEF,EAAA,MAAM,YAAA,GAAeW,aAAkB,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIC,eAAS,KAAK,CAAA;AACtD,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,eAAuB,MAAM,CAAA;AAErE,EAAA,MAAM,YAAA,GAAe,OAAO,CAAA,KAAwC;AAClE,IAAA,CAAA,CAAE,cAAA,EAAe;AAGjB,IAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,OAAA,EAAS,QAAA,EAAS,IAAK,EAAA;AAE3D,IAAA,IAAI,yBAAA,IAA6B,CAAC,cAAA,EAAgB;AAChD,MAAAC,YAAA,CAAM,MAAM,4CAA4C,CAAA;AACxD,MAAA;AAAA,IACF;AAEA,IAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,IAAA,eAAA,CAAgB,MAAM,CAAA;AAGtB,IAAA,MAAM,OAAO,CAAA,CAAE,aAAA;AAEf,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,IAAI,QAAA,CAAS,IAAI,CAAA;AAKlC,MAAA,MAAM,YAAA,GAAe,WAAW,MAAA,GAAS,CAAA;AACzC,MAAA,MAAM,WAAA,GAAc,gBACd,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,IAAuB,EAAA,EAAI,MAAK,GACzD,EAAA;AACJ,MAAA,IAAI,YAAA,IAAgB,gBAAA,IAAoB,CAAC,WAAA,EAAa;AASpD,QAAAA,YAAA,CAAM,MAAM,0BAA0B,CAAA;AACtC,QAAA,eAAA,CAAgB,KAAK,CAAA;AACrB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAA,GAA+B;AAAA,QACnC,SAAA,EAAW,QAAA,CAAS,GAAA,CAAI,WAAW,CAAA;AAAA,QACnC,QAAA,EAAU,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA;AAAA,QACjC,KAAA,EAAO,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA;AAAA,QAC3B,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AAAA,QAC/B,UAAU,WAAA,IAAe,KAAA,CAAA;AAAA,QACzB,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AAAA,QAC/B,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AAAA,QAC/B;AAAA,OACF;AAEA,MAAA,MAAM,SAAS,MAAM,iBAAA;AAAA,QACnB,MAAA;AAAA,QACA,WAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,eAAA,CAAgB,SAAS,CAAA;AACzB,QAAAA,YAAA,CAAM,OAAA;AAAA,UACJ,MAAA,CAAO,OAAA,IACL,CAAA,yBAAA,EAA4B,WAAW,CAAA,wCAAA;AAAA,SAC3C;AAGA,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,IAAA,CAAK,KAAA,EAAM;AAAA,QACb;AAEA,QAAA,YAAA,CAAa,SAAS,KAAA,EAAM;AAAA,MAC9B,CAAA,MAAO;AACL,QAAA,eAAA,CAAgB,OAAO,CAAA;AACvB,QAAAA,YAAA,CAAM,KAAA;AAAA,UACJ,OAAO,OAAA,IAAW;AAAA,SACpB;AACA,QAAA,YAAA,CAAa,SAAS,KAAA,EAAM;AAAA,MAC9B;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,KAAK,CAAA;AAC7C,MAAA,eAAA,CAAgB,OAAO,CAAA;AACvB,MAAAA,YAAA,CAAM,MAAM,iDAAiD,CAAA;AAC7D,MAAA,YAAA,CAAa,SAAS,KAAA,EAAM;AAAA,IAC9B,CAAA,SAAE;AACA,MAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,IACvB;AAAA,EACF,CAAA;AAEA,EAAA,uBACEC,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,QAAA,EACZ,QAAA,EAAA;AAAA,IAAA,GAAA,oBACCd,cAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,KAAA,EACE,GAAA,CAAI,KAAA,IAAS,CAAA,QAAA,EAAW,WAAW,CAAA,6BAAA,CAAA;AAAA,QAErC,WAAA,EACE,IAAI,WAAA,IACJ,CAAA,wJAAA,CAAA;AAAA,QAEF,WAAA,EAAa,WAAA;AAAA,QACb,UACE,GAAA,CAAI,QAAA,IACJ,CAAA,QAAA,EAAW,WAAA,CAAY,aAAa,CAAA,+FAAA,CAAA;AAAA,QAEtC,KAAA,EAAO,IAAI,KAAA,IAAS,uBAAA;AAAA,QACpB,KAAK,GAAA,CAAI;AAAA;AAAA,KACX;AAAA,oBAKFA,cAAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,SAAA,EACE,YAAA,KAAiB,CAAA,GACb,gBAAA,GACA,+EAAA;AAAA,QAGN,QAAA,kBAAAA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0CACb,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+BAAA,EACZ,QAAA,EAAA;AAAA,UAAA,YAAA,KAAiB,CAAA,mBAChBd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qCAAA,EACX,QAAA,EAAA,SAAA,EACH,CAAA,mBAEAA,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,2DACX,QAAA,EAAA,SAAA,EACH,CAAA;AAAA,0BAEFA,eAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4DACV,QAAA,EAAA,mBAAA,CAAoB,eAAA,EAAiB,WAAA,EAAa,YAAY,CAAA,EACjE;AAAA,SAAA,EACF,CAAA,EACF;AAAA;AAAA,KACF;AAAA,oBAGAA,cAAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,oCACjB,QAAA,kBAAAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAA,EACb,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8DAAA,EAEb,QAAA,EAAA;AAAA,sBAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EACb,QAAA,EAAA;AAAA,wBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,qBAAA,EAE3D,CAAA;AAAA,wBAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACb,QAAA,EAAA;AAAA,0BAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yCAAA,EACb,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAAC,SAAI,SAAA,EAAU,iGAAA,EACb,0BAAAA,cAAAA,CAACe,gBAAA,EAAA,EAAK,SAAA,EAAU,oCAAA,EAAqC,CAAA,EACvD,CAAA;AAAA,4BACAD,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yCAAA,EAA0C,QAAA,EAAA,OAAA,EAExD,CAAA;AAAA,8BACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wDACV,QAAA,EAAA,YAAA,EACH;AAAA,aAAA,EACF;AAAA,WAAA,EACF,CAAA;AAAA,UAEC,YAAA,oBACCc,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yCAAA,EACb,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAAC,SAAI,SAAA,EAAU,iGAAA,EACb,0BAAAA,cAAAA,CAACgB,iBAAA,EAAA,EAAM,SAAA,EAAU,oCAAA,EAAqC,CAAA,EACxD,CAAA;AAAA,4BACAF,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yCAAA,EAA0C,QAAA,EAAA,OAAA,EAExD,CAAA;AAAA,8BACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8CACV,QAAA,EAAA,YAAA,EACH;AAAA,aAAA,EACF;AAAA,WAAA,EACF,CAAA;AAAA,0BAGFc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yCAAA,EACb,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAAC,SAAI,SAAA,EAAU,iGAAA,EACb,0BAAAA,cAAAA,CAACiB,kBAAA,EAAA,EAAO,SAAA,EAAU,oCAAA,EAAqC,CAAA,EACzD,CAAA;AAAA,4BACAH,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yCAAA,EAA0C,QAAA,EAAA,QAAA,EAExD,CAAA;AAAA,8BACAc,eAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4DAAA,EACV,QAAA,EAAA;AAAA,gBAAA,aAAA,CAAc,KAAA;AAAA,gCACfd,eAAC,IAAA,EAAA,EAAG,CAAA;AAAA,gBACH,aAAA,CAAc,KAAA;AAAA,gCACfA,eAAC,IAAA,EAAA,EAAG,CAAA;AAAA,gBACH,aAAA,CAAc,KAAA;AAAA,gCACfA,eAAC,IAAA,EAAA,EAAG,CAAA;AAAA,gBACH,aAAA,CAAc;AAAA,eAAA,EACjB;AAAA,aAAA,EACF;AAAA,WAAA,EACF,CAAA;AAAA,0BAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yCAAA,EACb,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAAC,SAAI,SAAA,EAAU,iGAAA,EACb,0BAAAA,cAAAA,CAACkB,iBAAA,EAAA,EAAM,SAAA,EAAU,oCAAA,EAAqC,CAAA,EACxD,CAAA;AAAA,4BACAJ,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yCAAA,EAA0C,QAAA,EAAA,eAAA,EAExD,CAAA;AAAA,8BACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8CACV,QAAA,EAAA,YAAA,EACH;AAAA,aAAA,EACF;AAAA,WAAA,EACF;AAAA,SAAA,EACF;AAAA,OAAA,EACF,CAAA;AAAA,sBAGAA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCACb,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACb,QAAA,EAAA;AAAA,wBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EAA6C,QAAA,EAAA,mBAAA,EAE3D,CAAA;AAAA,wBAEAc,eAAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,QAAA,EAAU,YAAA;AAAA,YACV,SAAA,EAAU,wBAAA;AAAA,YAEV,QAAA,EAAA;AAAA,8BAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EACb,QAAA,EAAA;AAAA,gCAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,kCAAAd,cAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,OAAA,EAAQ,WAAA;AAAA,sBACR,SAAA,EAAU,sBAAA;AAAA,sBACX,QAAA,EAAA;AAAA;AAAA,mBAED;AAAA,kCACAA,cAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,EAAA,EAAG,WAAA;AAAA,sBACH,IAAA,EAAK,WAAA;AAAA,sBACL,QAAA,EAAQ,IAAA;AAAA,sBACR,WAAA,EAAY,MAAA;AAAA,sBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,iBAAA,EACF,CAAA;AAAA,gCAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,kCAAAd,cAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,OAAA,EAAQ,UAAA;AAAA,sBACR,SAAA,EAAU,sBAAA;AAAA,sBACX,QAAA,EAAA;AAAA;AAAA,mBAED;AAAA,kCACAA,cAAAA;AAAA,oBAAC,KAAA;AAAA,oBAAA;AAAA,sBACC,EAAA,EAAG,UAAA;AAAA,sBACH,IAAA,EAAK,UAAA;AAAA,sBACL,QAAA,EAAQ,IAAA;AAAA,sBACR,WAAA,EAAY,KAAA;AAAA,sBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,iBAAA,EACF;AAAA,eAAA,EACF,CAAA;AAAA,8BAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,eAAC,KAAA,EAAA,EAAM,OAAA,EAAQ,OAAA,EAAQ,SAAA,EAAU,wBAAuB,QAAA,EAAA,SAAA,EAExD,CAAA;AAAA,gCACAA,cAAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,OAAA;AAAA,oBACH,IAAA,EAAK,OAAA;AAAA,oBACL,IAAA,EAAK,OAAA;AAAA,oBACL,QAAA,EAAQ,IAAA;AAAA,oBACR,WAAA,EAAY,kBAAA;AAAA,oBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,eAAA,EACF,CAAA;AAAA,8BAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,eAAC,KAAA,EAAA,EAAM,OAAA,EAAQ,SAAA,EAAU,SAAA,EAAU,wBAAuB,QAAA,EAAA,SAAA,EAE1D,CAAA;AAAA,gCACAA,cAAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,SAAA;AAAA,oBACH,IAAA,EAAK,SAAA;AAAA,oBACL,WAAA,EAAY,WAAA;AAAA,oBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,eAAA,EACF,CAAA;AAAA,cAEC,WAAW,MAAA,GAAS,CAAA,oBACnBc,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,WAAA,EACb,QAAA,EAAA;AAAA,gCAAAA,eAAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,OAAA,EAAQ,UAAA;AAAA,oBACR,SAAA,EAAU,sBAAA;AAAA,oBAET,QAAA,EAAA;AAAA,sBAAA,aAAA;AAAA,sBACA,mBAAmB,IAAA,GAAO;AAAA;AAAA;AAAA,iBAC7B;AAAA,gCACAA,eAAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,UAAA;AAAA,oBACH,IAAA,EAAK,UAAA;AAAA,oBACL,QAAA,EAAU,gBAAA;AAAA,oBACV,YAAA,EAAa,EAAA;AAAA,oBACb,SAAA,EAAU,sBAAA;AAAA,oBAgBV,QAAA,EAAA;AAAA,sCAAAd,eAAC,QAAA,EAAA,EAAO,KAAA,EAAM,EAAA,EAAG,QAAA,EAAU,kBACxB,QAAA,EAAA,mBAAA,EACH,CAAA;AAAA,sBACC,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,qBACfA,cAAAA,CAAC,QAAA,EAAA,EAAqB,KAAA,EAAO,CAAA,CAAE,KAAA,EAC5B,QAAA,EAAA,CAAA,CAAE,KAAA,EAAA,EADQ,CAAA,CAAE,KAEf,CACD;AAAA;AAAA;AAAA;AACH,eAAA,EACF,CAAA;AAAA,8BAGFc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,eAAC,KAAA,EAAA,EAAM,OAAA,EAAQ,SAAA,EAAU,SAAA,EAAU,wBAAuB,QAAA,EAAA,WAAA,EAE1D,CAAA;AAAA,gCACAA,cAAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,SAAA;AAAA,oBACH,IAAA,EAAK,SAAA;AAAA,oBACL,QAAA,EAAQ,IAAA;AAAA,oBACR,WAAA,EAAY,sBAAA;AAAA,oBACZ,SAAA,EAAU;AAAA;AAAA;AACZ,eAAA,EACF,CAAA;AAAA,8BAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,eAAC,KAAA,EAAA,EAAM,OAAA,EAAQ,SAAA,EAAU,SAAA,EAAU,wBAAuB,QAAA,EAAA,WAAA,EAE1D,CAAA;AAAA,gCACAA,cAAAA;AAAA,kBAAC,QAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,SAAA;AAAA,oBACH,IAAA,EAAK,SAAA;AAAA,oBACL,QAAA,EAAQ,IAAA;AAAA,oBACR,WAAA,EAAY,kCAAA;AAAA,oBACZ,IAAA,EAAM,CAAA;AAAA,oBACN,SAAA,EAAU;AAAA;AAAA;AACZ,eAAA,EACF,CAAA;AAAA,8BAEAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACZ,QAAA,EAAA;AAAA,gBAAA,yBAAA,oBACCd,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCACb,QAAA,kBAAAA,cAAAA;AAAA,kBAACmB,0BAAA;AAAA,kBAAA;AAAA,oBACC,GAAA,EAAK,YAAA;AAAA,oBACL,OAAA,EAAS;AAAA;AAAA,iBACX,EACF,CAAA;AAAA,gCAGFnB,cAAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,IAAA,EAAK,QAAA;AAAA,oBACL,IAAA,EAAK,IAAA;AAAA,oBACL,QAAA,EAAU,YAAA;AAAA,oBACV,SAAA,EAAU,gCAAA;AAAA,oBAET,QAAA,EAAA,YAAA,GACC,YAAA,mBAEAc,eAAAA,CAAAM,mBAAA,EAAA,EAAE,QAAA,EAAA;AAAA,sBAAA,eAAA;AAAA,sCACapB,cAAAA,CAACqB,gBAAA,EAAA,EAAK,SAAA,EAAU,cAAA,EAAe;AAAA,qBAAA,EAC9C;AAAA;AAAA;AAEJ,eAAA,EACF,CAAA;AAAA,cAEC,iBAAiB,SAAA,oBAChBP,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,+EAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,kCAAA,EAAmC,QAAA,EAAA,4BAAA,EAEhD,CAAA;AAAA,gCACAc,eAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,yBAAA,EAA0B,QAAA,EAAA;AAAA,kBAAA,2BAAA;AAAA,kBACX,WAAA;AAAA,kBAAY;AAAA,iBAAA,EAExC;AAAA,eAAA,EACF,CAAA;AAAA,cAGD,iBAAiB,OAAA,oBAChBA,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yEAAA,EACb,QAAA,EAAA;AAAA,gCAAAd,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,kCAAA,EAAmC,QAAA,EAAA,wBAAA,EAEhD,CAAA;AAAA,gCACAc,eAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,yBAAA,EAA0B,QAAA,EAAA;AAAA,kBAAA,kDAAA;AAAA,kBACY,GAAA;AAAA,kBAChD;AAAA,iBAAA,EACH;AAAA,eAAA,EACF;AAAA;AAAA;AAAA;AAEJ,OAAA,EACF,CAAA,EACF;AAAA,KAAA,EACF,GACF,CAAA,EACF,CAAA;AAAA,IAGC,iBAAA,CAAkB,MAAA,GAAS,CAAA,oBAC1Bd,cAAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,8CAAA,EACjB,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wCAAA,EACb,QAAA,EAAA;AAAA,sBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,0DAAA,EAA2D,QAAA,EAAA,sBAAA,EAEzE,CAAA;AAAA,sBAEAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qEAAA,EACZ,4BAAkB,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,qBAC9Bc,eAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,kDAAA;AAAA,UAEV,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yCAAA,EACX,iBAAO,KAAA,EACV,CAAA;AAAA,4BACAA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,iEAAA,EACV,QAAA,EAAA,mBAAA;AAAA,cACC,MAAA,CAAO,WAAA;AAAA,cACP,WAAA;AAAA,cACA;AAAA,aACF,EACF,CAAA;AAAA,4BACAA,cAAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,OAAA,EAAQ,SAAA;AAAA,gBACR,OAAA,EAAO,IAAA;AAAA,gBACP,SAAA,EAAU,sBAAA;AAAA,gBAEV,0BAAAA,cAAAA,CAAC,GAAA,EAAA,EAAE,MAAM,MAAA,CAAO,UAAA,EAAa,iBAAO,UAAA,EAAW;AAAA;AAAA;AACjD;AAAA,SAAA;AAAA,QAnBK;AAAA,OAqBR,CAAA,EACH;AAAA,KAAA,EACF,CAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;AC5fA,SAAS,eAAe,EAAA,EAAoB;AAC1C,EAAA,IAAI,IAAA,GAAO,EAAA;AAEX,EAAA,IAAA,GAAO,IAAA,CACJ,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA,CACrB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CACpB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA;AAGvB,EAAA,IAAA,GAAO,KAAK,OAAA,CAAQ,0BAAA,EAA4B,CAAC,EAAA,EAAI,OAAO,IAAA,KAAS;AACnE,IAAA,OAAO,CAAA,WAAA,EAAc,IAAA,CAAK,IAAA,EAAM,CAAA,aAAA,CAAA;AAAA,EAClC,CAAC,CAAA;AAED,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,iBAAiB,CAAA;AAGnD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,iBAAA,EAAmB,aAAa,CAAA;AACpD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,aAAa,CAAA;AACnD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,aAAa,CAAA;AAClD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,cAAA,EAAgB,aAAa,CAAA;AACjD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,EAAe,aAAa,CAAA;AAChD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,aAAa,CAAA;AAG/C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,oBAAA,EAAsB,8BAA8B,CAAA;AACxE,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,qBAAqB,CAAA;AAC3D,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,aAAa,CAAA;AAG/C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA;AAAA,IACV,0BAAA;AAAA,IACA;AAAA,GACF;AAGA,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,6BAA6B,CAAA;AAGlE,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,uBAAA,EAAyB,CAAC,KAAA,KAAU;AACtD,IAAA,MAAM,QAAQ,KAAA,CACX,KAAA,CAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAS,CAAA,IAAA,EAAO,IAAA,CAAK,QAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,KAAA,CAAO,CAAA,CACnD,KAAK,EAAE,CAAA;AACV,IAAA,OAAO,OAAO,KAAK,CAAA,KAAA,CAAA;AAAA,EACrB,CAAC,CAAA;AAED,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,+BAAA,EAAiC,CAAC,KAAA,KAAU;AAC9D,IAAA,MAAM,QAAQ,KAAA,CACX,KAAA,CAAM,IAAI,CAAA,CACV,IAAI,CAAC,IAAA,KAAS,CAAA,IAAA,EAAO,IAAA,CAAK,QAAQ,SAAA,EAAW,EAAE,CAAC,CAAA,KAAA,CAAO,CAAA,CACvD,KAAK,EAAE,CAAA;AACV,IAAA,OAAO,OAAO,KAAK,CAAA,KAAA,CAAA;AAAA,EACrB,CAAC,CAAA;AAGD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAQ,CAAA;AAGvC,EAAA,IAAA,GAAO,KACJ,KAAA,CAAM,OAAO,CAAA,CACb,GAAA,CAAI,CAAC,KAAA,KAAU;AACd,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAI,CAAC,SAAS,OAAO,EAAA;AACrB,IAAA,IAAI,oCAAA,CAAqC,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,OAAA;AAC/D,IAAA,OAAO,CAAA,GAAA,EAAM,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,QAAQ,CAAC,CAAA,IAAA,CAAA;AAAA,EAC/C,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AAEZ,EAAA,OAAO,IAAA;AACT;AAcO,SAAS,eAAA,CAAgB;AAAA,EAC9B,OAAA;AAAA,EACA,MAAA,GAAS,UAAA;AAAA,EACT;AACF,CAAA,EAIG;AACD,EAAA,IAAI,WAAW,UAAA,EAAY;AACzB,IAAA,uBACEA,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA;AAAA,QACA,uBAAA,EAAyB,EAAE,MAAA,EAAQ,cAAA,CAAe,OAAO,CAAA;AAAE;AAAA,KAC7D;AAAA,EAEJ;AAEA,EAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,IAAA,uBACEA,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA;AAAA,QACA,uBAAA,EAAyB,EAAE,MAAA,EAAQ,OAAA;AAAQ;AAAA,KAC7C;AAAA,EAEJ;AAGA,EAAA,uBACEA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EACH,0BAAAA,cAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,YAAY,UAAA,EAAY,UAAA,EAAY,SAAA,EAAU,EACzD,mBACH,CAAA,EACF,CAAA;AAEJ;ACjOA,IAAM,qBAAA,GAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAmB9B,IAAM,uBAAA,GAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAyBhC,SAAS,eAAe,KAAA,EAA0C;AAChE,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,IAAS,CAAA,EAAG,OAAO,EAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAA,EAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AACpC,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,IAAI,CAAA,GAAI,KAAA;AACR,EAAA,OAAO,CAAA,IAAK,IAAA,IAAQ,CAAA,GAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACxC,IAAA,CAAA,IAAK,IAAA;AACL,IAAA,CAAA,EAAA;AAAA,EACF;AACA,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,OAAA,CAAQ,CAAA,IAAK,EAAA,IAAM,CAAA,KAAM,CAAA,GAAI,CAAA,GAAI,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAC7D;AAQA,eAAe,gBAAA,CACb,GACA,GAAA,EACe;AACf,EAAA,CAAA,CAAE,cAAA,EAAe;AACjB,EAAA,MAAM,OACJ,GAAA,CAAI,QAAA,IACJ,GAAA,CAAI,OAAA,CAAQ,MAAM,GAAG,CAAA,CAAE,GAAA,EAAI,EAAG,MAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAC1C,IAAI,KAAA,IACJ,kBAAA;AACF,EAAA,MAAM,YAAY,MAChB,MAAA,CAAO,KAAK,GAAA,CAAI,OAAA,EAAS,UAAU,qBAAqB,CAAA;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,CAAI,SAAS,EAAE,IAAA,EAAM,QAAQ,CAAA;AACrD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,SAAA,EAAU;AACV,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACpC,IAAA,CAAA,CAAE,IAAA,GAAO,MAAA;AACT,IAAA,CAAA,CAAE,QAAA,GAAW,IAAA;AACb,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,CAAC,CAAA;AAC3B,IAAA,CAAA,CAAE,KAAA,EAAM;AACR,IAAA,CAAA,CAAE,MAAA,EAAO;AACT,IAAA,GAAA,CAAI,gBAAgB,MAAM,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA,SAAA,EAAU;AAAA,EACZ;AACF;AAMA,SAAS,WAAA,CAAY;AAAA,EACnB,KAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,uBACEA,eAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,+DACjB,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CAAA,EACb,QAAA,EAAA;AAAA,oBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,oEAAA,EACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,IACC,4BACCA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8DACV,QAAA,EAAA,QAAA,EACH;AAAA,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;AAYO,SAAS,mBAAA,CAAoB,SAAiB,MAAA,EAAyB;AAC5E,EAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,mCAAA,EAAqC,EAAE,CAAA;AAAA,EAChE;AAKA,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,sBAAA,EAAwB,EAAE,CAAA;AACnD;AAEA,SAAS,qBAAA,CAAsB;AAAA,EAC7B;AACF,CAAA,EAEG;AAKD,EAAA,uBACEA,cAAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,kBACjB,QAAA,kBAAAA,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW;AAAA,QACT,wBAAA;AAAA;AAAA,QAEA,gFAAA;AAAA,QACA,iFAAA;AAAA,QACA,6DAAA;AAAA,QACA,6DAAA;AAAA;AAAA,QAEA,kDAAA;AAAA,QACA,2DAAA;AAAA,QACA,8DAAA;AAAA,QACA,wBAAA;AAAA,QACA,eAAA;AAAA,QACA,2JAAA;AAAA,QACA,kCAAA;AAAA;AAAA,QAEA,qDAAA;AAAA,QACA,eAAA;AAAA,QACA,+GAAA;AAAA,QACA,wGAAA;AAAA,QACA,sGAAA;AAAA,QACA;AAAA,OACF,CAAE,KAAK,GAAG,CAAA;AAAA,MAET,QAAA,EAAA,IAAA,CAAK,2BACJA,cAAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAS,mBAAA,CAAoB,IAAA,CAAK,OAAA,EAAS,KAAK,aAAa,CAAA;AAAA,UAC7D,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAKE,KAAK,aAAA,KAAkB,UAAA,IAAc,KAAK,aAAA,KAAkB,MAAA,GACxD,KAAK,aAAA,GACL;AAAA;AAAA;AAAA;AAER;AAAA,GAEJ,EACF,CAAA;AAEJ;AAEA,SAAS,mBAAA,CAAoB,EAAE,GAAA,EAAI,EAA6B;AAC9D,EAAA,MAAM,SAAA,GAAY,cAAA,CAAe,GAAA,CAAI,QAAQ,CAAA;AAC7C,EAAA,MAAM,GAAA,GAAM,IAAI,QAAA,EAAU,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,IAAO,WAAA,EAAY;AACxD,EAAA,uBACEc,eAAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,6GAAA,EACjB,QAAA,EAAA;AAAA,oBAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACb,QAAA,EAAA;AAAA,sBAAAd,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EACb,QAAA,kBAAAA,cAAAA,CAACsB,oBAAA,EAAA,EAAS,IAAA,EAAM,EAAA,EAAI,SAAA,EAAU,uBAAA,EAAwB,CAAA,EACxD,CAAA;AAAA,sBACAR,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,wBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,wCAAA,EACX,cAAI,KAAA,EACP,CAAA;AAAA,QACC,IAAI,OAAA,oBACHc,eAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,sCAAA,EAAuC,QAAA,EAAA;AAAA,UAAA,UAAA;AAAA,UACzC,GAAA,CAAI;AAAA,SAAA,EACf;AAAA,OAAA,EAEJ;AAAA,KAAA,EACF,CAAA;AAAA,IACC,GAAA,CAAI,+BACHd,cAAAA,CAAC,OAAE,SAAA,EAAU,4CAAA,EACV,cAAI,WAAA,EACP,CAAA;AAAA,oBAEFc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gFAAA,EACb,QAAA,EAAA;AAAA,sBAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uDAAA,EACZ,QAAA,EAAA;AAAA,QAAA,GAAA,oBAAOd,cAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,GAAA,EAAI,CAAA;AAAA,QAClB,SAAA,oBACCc,eAAAA,CAAAM,mBAAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAApB,cAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAW,IAAA,EAAC,QAAA,EAAA,MAAA,EAAC,CAAA;AAAA,0BACnBA,cAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,SAAA,EAAU;AAAA,SAAA,EACnB;AAAA,OAAA,EAEJ,CAAA;AAAA,sBACAc,eAAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,MAAM,GAAA,CAAI,OAAA;AAAA,UACV,QAAA,EAAU,IAAI,QAAA,IAAY,MAAA;AAAA,UAC1B,SAAS,CAAC,CAAA,KAAM,KAAK,gBAAA,CAAiB,GAAG,GAAG,CAAA;AAAA,UAC5C,SAAA,EAAU,iKAAA;AAAA,UAEV,QAAA,EAAA;AAAA,4BAAAd,cAAAA,CAACuB,oBAAA,EAAA,EAAS,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,YAAE;AAAA;AAAA;AAAA;AAExB,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;AAEA,SAAS,uBAAA,CAAwB;AAAA,EAC/B,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,uBACEvB,eAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,8BACjB,QAAA,kBAAAc,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,eAAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,2BAAA,EAChB,QAAA,EAAA;AAAA,sBAAAd,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qDAAA,EACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,MACC,4BACCA,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,2CACV,QAAA,EAAA,QAAA,EACH;AAAA,KAAA,EAEJ,CAAA;AAAA,oBACAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sDAAA,EACZ,eAAK,GAAA,CAAI,CAAC,GAAA,qBACTA,eAAC,mBAAA,EAAA,EAAiC,GAAA,EAAA,EAAR,GAAA,CAAI,EAAc,CAC7C,CAAA,EACH;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;AAMA,IAAM,wBAAA,GAA4C;AAAA,EAChD,KAAA,EAAO,aAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAEO,SAAS,aAAa,KAAA,EAA0B;AACrD,EAAA,MAAM;AAAA,IACJ,WAAA,EAAa,eAAA;AAAA,IACb,SAAA,GAAY,iBAAA;AAAA,IACZ,YAAA;AAAA,IAEA,UAAA,GAAa,SAAA;AAAA,IACb,WAAA;AAAA,IAEA,YAAA,GAAe,SAAA;AAAA,IACf,cAAA,GAAiB,mBAAA;AAAA,IACjB,iBAAA;AAAA,IAEA,eAAA,GAAkB,IAAA;AAAA,IAClB,eAAA;AAAA,IACA,SAAA,GAAY,kBAAA;AAAA,IACZ,YAAA;AAAA,IAEA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA;AAAA,IACA,iBAAA;AAAA,IAEA,QAAA;AAAA,IACA,cAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAEJ,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,SAAS,eAAA,EAAgB;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,UAAA,EAAW;AAE/B,EAAA,MAAM,iBAAA,GACJ,OAAA,EAAS,EAAA,IAAM,MAAA,EAAQ,aAAa,eAAA,IAAmB,EAAA;AACzD,EAAA,MAAM,mBAAA,GACJ,eAAA,IAAmB,OAAA,EAAS,IAAA,IAAQ,QAAQ,SAAA,IAAa,UAAA;AAE3D,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIY,eAEpC,IAAI,CAAA;AACN,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIA,cAAAA,CAA4B,EAAE,CAAA;AACtD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIA,eAAkB,IAAI,CAAA;AAIpD,EAAAY,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,iBAAA,EAAmB;AAKjC,MAAA,cAAA,CAAe,IAAI,CAAA;AACnB,MAAA,OAAA,CAAQ,EAAE,CAAA;AACV,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,UAAA,CAAW,IAAI,CAAA;AAEf,IAAA,KAAK,QAAQ,UAAA,CAAW;AAAA,MACtB,MAAA,CAAO,MAOJ,qBAAA,EAAuB,EAAE,WAAW,iBAAA,EAAmB,KAAA,EAAO,IAAI,CAAA;AAAA,MACrE,MAAA,CAAO,KAAA;AAAA,QACL,uBAAA;AAAA,QACA,EAAE,SAAA,EAAW,iBAAA,EAAmB,KAAA,EAAO,EAAA;AAAG;AAC5C,KACD,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,aAAA,EAAe,UAAU,CAAA,KAAM;AACvC,MAAA,IAAI,SAAA,EAAW;AAKf,MAAA,IAAI,aAAA,CAAc,WAAW,UAAA,EAAY;AACvC,QAAA,cAAA,CAAe,IAAI,CAAA;AAAA,MACrB,CAAA,MAAA,IAAW,aAAA,CAAc,MAAA,KAAW,WAAA,EAAa;AAK/C,QAAA,MAAM,QACJ,aAAA,CAAc,KAAA,CAAM,IAAA,EAAM,kBAAA,EAAoB,SAAS,EAAC;AAC1D,QAAA,MAAM,QAAiC,WAAA,GACnC,KAAA,CAAM,KAAK,CAAC,CAAA,KAAmB,EAAE,IAAA,KAAS,WAAW,CAAA,GACrD,KAAA,CAAM,KAAK,CAAC,CAAA,KAAmB,EAAE,IAAA,EAAM,QAAA,CAAS,UAAU,CAAC,CAAA;AAC/D,QAAA,cAAA,CAAe,SAAS,IAAI,CAAA;AAAA,MAC9B;AAIA,MAAA,IAAI,UAAA,CAAW,WAAW,UAAA,EAAY;AACpC,QAAA,OAAA,CAAQ,EAAE,CAAA;AAAA,MACZ,CAAA,MAAA,IAAW,UAAA,CAAW,MAAA,KAAW,WAAA,EAAa;AAC5C,QAAA,MAAM,QACJ,UAAA,CAAW,KAAA,CAAM,IAAA,EAAM,oBAAA,EAAsB,SAAS,EAAC;AACzD,QAAA,MAAM,WAAW,KAAA,CACd,MAAA;AAAA,UACC,CAAC,CAAA,KACC,CAAA,CAAE,QAAA,KAAa,UAAA,IACf,CAAA,CAAE,IAAA,EAAM,QAAA,CAAS,YAAY,CAAA,IAC7B,CAAC,CAAC,CAAA,CAAE;AAAA,SACR,CACC,IAAA;AAAA,UACC,CAAC,CAAA,EAAoB,CAAA,KACnB,CAAA,CAAE,YAAY,CAAA,CAAE;AAAA,SACpB;AACF,QAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAClB;AAEA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB,CAAC,CAAA;AAED,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,GAAG,CAAC,MAAA,EAAQ,mBAAmB,WAAA,EAAa,UAAA,EAAY,YAAY,CAAC,CAAA;AAUrE,EAAA,IAAI,iBAAA;AACJ,EAAA,IAAI,oBAAoB,KAAA,EAAO;AAC7B,IAAA,iBAAA,GAAoB,EAAC;AAAA,EACvB,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,eAAe,CAAA,EAAG;AACzC,IAAA,iBAAA,GACE,eAAA,CAAgB,MAAA,GAAS,CAAA,GAAI,eAAA,GAAkB,CAAC,wBAAwB,CAAA;AAAA,EAC5E,CAAA,MAAO;AACL,IAAA,iBAAA,GAAoB,CAAC,mBAAmB,wBAAwB,CAAA;AAAA,EAClE;AAEA,EAAA,uBACEV,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EACH,QAAA,EAAA;AAAA,oBAAAd,cAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,QAAA,IAAY,CAAA,EAAG,SAAS,WAAM,mBAAmB,CAAA,CAAA;AAAA,QACxD,WAAA,EACE,cAAA,IACA,YAAA,IACA,CAAA,SAAA,EAAY,mBAAmB,CAAA,mBAAA,CAAA;AAAA,QAEjC,QAAA,EAAU;AAAA;AAAA,KACZ;AAAA,oBAEAA,cAAAA,CAAC,WAAA,EAAA,EAAY,KAAA,EAAO,SAAA,EAAW,UAAU,YAAA,EAAc,CAAA;AAAA,IAEtD,CAAC,OAAA,IAAW,WAAA,oBAAeA,cAAAA,CAAC,qBAAA,EAAA,EAAsB,MAAM,WAAA,EAAa,CAAA;AAAA,IAErE,CAAC,OAAA,IAAW,IAAA,CAAK,MAAA,GAAS,qBACzBA,cAAAA;AAAA,MAAC,uBAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,cAAA;AAAA,QACP,QAAA,EAAU,iBAAA;AAAA,QACV;AAAA;AAAA,KACF;AAAA,IAGD,mCACCA,cAAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAa,mBAAA;AAAA,QACb,SAAA,EAAW,SAAA;AAAA,QAIX,YAAA,EAAc,CAAA;AAAA,QACd,eAAA,EACE,YAAA,IACA,CAAA,2DAAA,EAA8D,mBAAmB,CAAA,kBAAA,CAAA;AAAA,QAEnF,YAAA;AAAA,QACA,YAAA;AAAA,QACA,aAAA;AAAA,QACA,YAAA;AAAA,QACA,gBAAA;AAAA,QACA,iBAAA;AAAA,QAIA,UAAA,EAAY,iBAAA;AAAA,QACZ,aAAA,EAAc,kBAAA;AAAA,QACd,gBAAA,EAAkB,kBAAkB,MAAA,GAAS;AAAA;AAAA;AAC/C,GAAA,EAEJ,CAAA;AAEJ","file":"partners.js","sourcesContent":["const LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst RESERVED_HEADERS = new Set([\n \"authorization\",\n \"cookie\",\n \"x-actor-id\",\n \"x-actor-type\",\n \"x-consent-granted-by\",\n \"x-consent-scope\",\n \"x-consent-granted-at\",\n \"x-consent-expires-at\",\n]);\n\nexport function validateGatewayUrl(value: string): string {\n let url: URL;\n\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Gateway URL must be a valid absolute URL\");\n }\n\n if (url.protocol === \"https:\") {\n return url.toString();\n }\n\n if (\n url.protocol === \"http:\" &&\n LOOPBACK_HOSTS.has(url.hostname.toLowerCase())\n ) {\n return url.toString();\n }\n\n throw new Error(\"Gateway URL must use HTTPS unless it targets localhost\");\n}\n\nexport function sanitizeHeaders(\n headers?: Record<string, string>,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n\n return Object.fromEntries(\n Object.entries(headers).filter(\n ([key]) => !RESERVED_HEADERS.has(key.toLowerCase()),\n ),\n );\n}\n","/**\n * Lightweight GraphQL client for the Burdenoff Web SDK.\n * Uses native fetch - zero external dependencies.\n * All calls are unauthenticated (public gateway operations only).\n */\n\nimport { sanitizeHeaders, validateGatewayUrl } from \"./security\";\n\nexport interface WebSDKClientConfig {\n /** Global public gateway URL (e.g. \"https://api.burdenoff.com/global/graphql\") */\n gatewayUrl: string;\n /** Platform product ID for scoping operations */\n productId: string;\n /** Product slug (used for public product queries) */\n productSlug?: string;\n /** reCAPTCHA site key (if not fetched from product config) */\n recaptchaSiteKey?: string;\n /** Rybbit analytics site ID */\n rybbitSiteId?: string;\n /** Custom headers to include in all requests */\n headers?: Record<string, string>;\n}\n\nexport interface GraphQLResponse<T = Record<string, unknown>> {\n data?: T;\n errors?: Array<{\n message: string;\n locations?: Array<{ line: number; column: number }>;\n path?: Array<string | number>;\n extensions?: Record<string, unknown>;\n }>;\n}\n\nexport class WebSDKClient {\n private config: WebSDKClientConfig;\n private queryCache = new Map<\n string,\n { data: GraphQLResponse<unknown>; ts: number }\n >();\n private inflight = new Map<string, Promise<GraphQLResponse<unknown>>>();\n private static CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n private static MAX_CACHE_ENTRIES = 100;\n\n constructor(config: WebSDKClientConfig) {\n this.config = {\n ...config,\n gatewayUrl: validateGatewayUrl(config.gatewayUrl),\n headers: sanitizeHeaders(config.headers),\n };\n }\n\n getConfig(): WebSDKClientConfig {\n return this.config;\n }\n\n /**\n * Execute a GraphQL query (with deduplication and caching)\n */\n async query<T = Record<string, unknown>>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n const cacheKey = JSON.stringify({ query, variables });\n\n // Return cached response if still valid, evict if expired\n const cached = this.queryCache.get(cacheKey);\n if (cached) {\n if (Date.now() - cached.ts < WebSDKClient.CACHE_TTL) {\n return cached.data as GraphQLResponse<T>;\n }\n this.queryCache.delete(cacheKey);\n }\n\n // Deduplicate: if same query is already in-flight, reuse the promise\n const existing = this.inflight.get(cacheKey);\n if (existing) {\n return existing as Promise<GraphQLResponse<T>>;\n }\n\n const promise = this.request<T>(query, variables)\n .then((result) => {\n // Cache successful responses only\n if (result.data && !result.errors?.length) {\n if (this.queryCache.size >= WebSDKClient.MAX_CACHE_ENTRIES) {\n const oldestEntry = this.queryCache.keys().next().value;\n if (oldestEntry) {\n this.queryCache.delete(oldestEntry);\n }\n }\n this.queryCache.set(cacheKey, { data: result, ts: Date.now() });\n }\n return result;\n })\n .finally(() => {\n this.inflight.delete(cacheKey);\n });\n\n this.inflight.set(cacheKey, promise);\n return promise;\n }\n\n /**\n * Execute a GraphQL mutation\n */\n async mutate<T = Record<string, unknown>>(\n mutation: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n return this.request<T>(mutation, variables);\n }\n\n private async request<T>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<GraphQLResponse<T>> {\n try {\n const response = await fetch(this.config.gatewayUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-product-id\": this.config.productId,\n ...this.config.headers,\n },\n body: JSON.stringify({ query, variables }),\n });\n\n if (!response.ok) {\n console.error(\n \"[WebSDK] GraphQL request failed\",\n response.status,\n response.statusText,\n );\n return {\n errors: [\n {\n message: `HTTP ${response.status}: ${response.statusText}`,\n extensions: { code: `HTTP_${response.status}` },\n },\n ],\n };\n }\n\n return (await response.json()) as GraphQLResponse<T>;\n } catch (error) {\n console.error(\n \"[WebSDK] Network error\",\n error instanceof Error ? error.message : \"unknown error\",\n );\n return {\n errors: [\n {\n message: error instanceof Error ? error.message : \"Network error\",\n extensions: { code: \"NETWORK_ERROR\" },\n },\n ],\n };\n }\n }\n}\n","/**\n * React context provider for the Web SDK client.\n * Wraps the application with WebSDKClient configuration.\n */\n\"use client\";\n\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { resolveGatewayUrl } from \"./gateway-resolver\";\nimport { WebSDKClient, type WebSDKClientConfig } from \"./graphql-client\";\n\nconst WebSDKContext = createContext<WebSDKClient | null>(null);\n\nexport interface WebSDKProviderProps {\n /** SDK client configuration */\n config: WebSDKClientConfig;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the WebSDKClient available to all child components.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={{\n * gatewayUrl: \"https://api.burdenoff.com/global/graphql\",\n * productId: \"your-product-id\",\n * productSlug: \"your-product\",\n * }}>\n * <App />\n * </WebSDKProvider>\n * ```\n */\nexport function WebSDKProvider({ config, children }: WebSDKProviderProps) {\n const client = useMemo(() => {\n const resolvedConfig = {\n ...config,\n gatewayUrl: resolveGatewayUrl(config.gatewayUrl),\n };\n return new WebSDKClient(resolvedConfig);\n }, [config]);\n\n return (\n <WebSDKContext.Provider value={client}>{children}</WebSDKContext.Provider>\n );\n}\n\n/**\n * Hook to access the WebSDKClient instance.\n * Must be used within a WebSDKProvider.\n */\nexport function useWebSDK(): WebSDKClient {\n const client = useContext(WebSDKContext);\n if (!client) {\n throw new Error(\"useWebSDK must be used within a WebSDKProvider\");\n }\n return client;\n}\n\n/**\n * Hook to access the SDK configuration.\n * Useful for components that need config values like productId, recaptchaSiteKey, etc.\n */\nexport function useWebSDKConfig(): WebSDKClientConfig {\n const client = useWebSDK();\n return client.getConfig();\n}\n","/**\n * Product Provider\n *\n * React context and hooks for accessing product metadata from the global tenant service.\n * Fetches product info (name, logo, SEO, contact, reCAPTCHA key, etc.) on mount\n * and provides it to all child components.\n */\n\"use client\";\n\nimport {\n createContext,\n useContext,\n useState,\n useLayoutEffect,\n useCallback,\n useMemo,\n} from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ProductData {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n status: string;\n logoUrl?: string | null;\n website?: string | null;\n appUrl?: string | null;\n docsUrl?: string | null;\n contactEmail?: string | null;\n supportEmail?: string | null;\n contactPhone?: string | null;\n contactAddress?: string | null;\n seoTitle?: string | null;\n seoDescription?: string | null;\n seoKeywords?: string | null;\n ogImage?: string | null;\n socialLinks?: Record<string, string> | null;\n /**\n * Resource links for the website footer \"Resources\" column\n * (JSON: { docs, community, careers, team, companies, ... }).\n * Same shape as socialLinks. Free-form keys; the ResourceLinks\n * component renders known keys and silently ignores the rest.\n * Backed by Product.resourceLinks on the backend (global-tenant-svc).\n */\n resourceLinks?: Record<string, string> | null;\n recaptchaSiteKey?: string | null;\n rybbitSiteId?: string | null;\n notificationEmail?: string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface ProductProviderProps {\n /** Child components */\n children: ReactNode;\n /** Optional fallback product data (used while loading) */\n fallback?: Partial<ProductData>;\n}\n\n// ============================================================================\n// GraphQL Query\n// ============================================================================\n\n/**\n * Body of fields requested for every product fetch — shared by the primary\n * query and the legacy-backend fallback below. Kept as a string fragment\n * (not a real GraphQL `fragment` block) so we can append/strip\n * `resourceLinks` without touching anything else.\n */\nconst PRODUCT_FIELDS_BASE = `\n id\n name\n slug\n description\n status\n logoUrl\n website\n appUrl\n docsUrl\n contactEmail\n supportEmail\n contactPhone\n contactAddress\n seoTitle\n seoDescription\n seoKeywords\n ogImage\n socialLinks\n recaptchaSiteKey\n rybbitSiteId\n notificationEmail\n metadata\n`;\n\n/**\n * Primary query — includes the recently-added `resourceLinks` field.\n * Backends that have run the corresponding `global-tenant-svc` migration\n * (PR #64) expose this field; older ones don't, in which case\n * GraphQL validation rejects the whole query with\n * `Cannot query field \"resourceLinks\" on type \"PublicProduct\"`. The fetch\n * helper detects that specific error and transparently retries the\n * fallback below, so the SDK works on both pre- and post-migration\n * deployments without consumer-side gating.\n */\nconst PUBLIC_PRODUCT_QUERY = `\n query PublicProduct($slug: String!) {\n publicProduct(slug: $slug) {\n ${PRODUCT_FIELDS_BASE}\n resourceLinks\n }\n }\n`;\n\n/**\n * Fallback query for older backend deployments. Identical to the primary\n * minus `resourceLinks`. Consumers see `product.resourceLinks === undefined`\n * and any consumer (e.g. `<ResourceLinks/>`) falls through to prop / default\n * resolution paths.\n */\nconst PUBLIC_PRODUCT_QUERY_FALLBACK = `\n query PublicProductFallback($slug: String!) {\n publicProduct(slug: $slug) {\n ${PRODUCT_FIELDS_BASE}\n }\n }\n`;\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface ProductContextValue {\n product: ProductData | null;\n loading: boolean;\n error: string | null;\n hasProvider: boolean;\n refetch: () => void;\n}\n\nconst ProductContext = createContext<ProductContextValue>({\n product: null,\n loading: true,\n error: null,\n hasProvider: false,\n refetch: () => {},\n});\n\n// ============================================================================\n// Provider\n// ============================================================================\n\n/**\n * ProductProvider fetches and provides product metadata to child components.\n * Uses the product slug from WebSDKConfig to fetch from the public API.\n *\n * @example\n * ```tsx\n * <WebSDKProvider config={sdkConfig}>\n * <ProductProvider>\n * <App />\n * </ProductProvider>\n * </WebSDKProvider>\n * ```\n */\nexport function ProductProvider({ children, fallback }: ProductProviderProps) {\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const [product, setProduct] = useState<ProductData | null>(\n fallback ? (fallback as ProductData) : null,\n );\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const fetchProduct = useCallback(async () => {\n if (!config.productSlug) {\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n let result = await client.query<{ publicProduct: ProductData | null }>(\n PUBLIC_PRODUCT_QUERY,\n { slug: config.productSlug },\n );\n\n // Backwards-compat fallback: if the backend's `publicProduct` schema\n // doesn't yet expose `resourceLinks` (deployed before\n // `global-tenant-svc` PR #64), the primary query fails validation\n // with a \"Cannot query field …\" error and `result.data` is null.\n // Retry the fallback query that omits `resourceLinks`; consumers\n // gracefully see `product.resourceLinks === undefined` and fall\n // through their own resolution paths.\n const schemaMissingResourceLinks = result.errors?.some((e) =>\n /Cannot query field [\"']?resourceLinks[\"']?/i.test(e?.message ?? \"\"),\n );\n if (schemaMissingResourceLinks) {\n result = await client.query<{ publicProduct: ProductData | null }>(\n PUBLIC_PRODUCT_QUERY_FALLBACK,\n { slug: config.productSlug },\n );\n }\n\n if (result.errors?.length) {\n setError(result.errors[0]?.message ?? \"Unknown error\");\n } else if (result.data?.publicProduct) {\n setProduct(result.data.publicProduct);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to fetch product\");\n } finally {\n setLoading(false);\n }\n }, [client, config.productSlug]);\n\n // Use useLayoutEffect for earliest possible fetch after commit (before paint).\n // Runs when slug or client changes. Client-side query cache + dedup ensures\n // no duplicate network requests even if React StrictMode fires this twice.\n useLayoutEffect(() => {\n fetchProduct();\n }, [fetchProduct]);\n\n const value = useMemo(\n () => ({\n product,\n loading,\n error,\n hasProvider: true,\n refetch: fetchProduct,\n }),\n [product, loading, error, fetchProduct],\n );\n\n return (\n <ProductContext.Provider value={value}>{children}</ProductContext.Provider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Hook to access the current product data.\n *\n * @example\n * ```tsx\n * const { product, loading } = useProduct();\n * if (loading) return <Loading />;\n * return <h1>{product?.name}</h1>;\n * ```\n */\nexport function useProduct(): ProductContextValue {\n return useContext(ProductContext);\n}\n\n/**\n * Hook to get product-specific configuration.\n * Merges SDK config with fetched product data.\n * Useful for getting reCAPTCHA keys, analytics IDs, etc.\n *\n * @example\n * ```tsx\n * const { recaptchaSiteKey, rybbitSiteId } = useProductConfig();\n * ```\n */\nexport function useProductConfig(): {\n recaptchaSiteKey: string | null;\n rybbitSiteId: string | null;\n contactEmail: string | null;\n supportEmail: string | null;\n notificationEmail: string | null;\n productName: string | null;\n logoUrl: string | null;\n} {\n const { product } = useProduct();\n const config = useWebSDKConfig();\n\n return {\n // Prefer product-level config, fall back to SDK config\n recaptchaSiteKey:\n product?.recaptchaSiteKey ?? config.recaptchaSiteKey ?? null,\n rybbitSiteId: product?.rybbitSiteId ?? config.rybbitSiteId ?? null,\n contactEmail: product?.contactEmail ?? null,\n supportEmail: product?.supportEmail ?? null,\n notificationEmail:\n product?.notificationEmail ?? product?.contactEmail ?? null,\n productName: product?.name ?? null,\n logoUrl: product?.logoUrl ?? null,\n };\n}\n","/**\n * PageHead Component\n * Manages dynamic meta tags for SEO optimization on a per-page basis.\n * Supports JSON-LD structured data, Open Graph, Twitter Cards, favicons, and robots directives.\n *\n * @example\n * ```tsx\n * <PageHead\n * title=\"About Us\"\n * description=\"Learn about our mission and team\"\n * productName=\"MyProduct\"\n * keywords=\"about, team, mission\"\n * image=\"/og-about.png\"\n * url=\"https://myproduct.com/about\"\n * favicon=\"/favicon.ico\"\n * robots=\"index, follow\"\n * locale=\"en_US\"\n * twitterHandle=\"@burdenoff\"\n * themeColor=\"#1a1a2e\"\n * structuredData={{\n * \"@context\": \"https://schema.org\",\n * \"@type\": \"WebPage\",\n * name: \"About Us\",\n * }}\n * />\n * ```\n */\n\nimport { Helmet } from \"react-helmet-async\";\n\nexport interface PageHeadProps {\n /** Page title */\n title: string;\n /** Meta description */\n description?: string;\n /** Product/brand name (appended to title) */\n productName?: string;\n /** SEO keywords */\n keywords?: string;\n /** Open Graph image URL */\n image?: string;\n /** Page canonical URL */\n url?: string;\n /** Favicon URL */\n favicon?: string;\n /** Robots directive (e.g., \"index, follow\") */\n robots?: string;\n /** Open Graph locale (e.g., \"en_US\") */\n locale?: string;\n /** Twitter handle (e.g., \"@burdenoff\") */\n twitterHandle?: string;\n /** Theme color for mobile browsers */\n themeColor?: string;\n /** JSON-LD structured data objects */\n structuredData?: Record<string, unknown> | Array<Record<string, unknown>>;\n /** Additional meta tags */\n additionalMeta?: Array<{\n name?: string;\n property?: string;\n content: string;\n }>;\n}\n\nexport function PageHead({\n title,\n description,\n productName,\n keywords,\n image,\n url,\n favicon,\n robots = \"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\",\n locale = \"en_US\",\n twitterHandle,\n themeColor = \"#000000\",\n structuredData,\n additionalMeta,\n}: PageHeadProps) {\n const fullTitle =\n productName && !title.includes(productName)\n ? `${title} | ${productName}`\n : title;\n\n const fullImageUrl =\n image && !image.startsWith(\"http\") && url\n ? `${url.replace(/\\/$/, \"\")}${image}`\n : image;\n\n // Normalize structured data to an array\n const structuredDataItems: Array<Record<string, unknown>> = structuredData\n ? Array.isArray(structuredData)\n ? structuredData\n : [structuredData]\n : [];\n\n return (\n <Helmet>\n {/* Primary Meta Tags */}\n <title>{fullTitle}</title>\n <meta name=\"title\" content={fullTitle} />\n {description && <meta name=\"description\" content={description} />}\n {keywords && <meta name=\"keywords\" content={keywords} />}\n <meta name=\"author\" content=\"Burdenoff Consultancy Services Pvt Ltd\" />\n <meta name=\"robots\" content={robots} />\n\n {/* Canonical URL */}\n {url && <link rel=\"canonical\" href={url} />}\n\n {/* Favicon */}\n {favicon && <link rel=\"icon\" href={favicon} />}\n\n {/* Open Graph / Facebook */}\n <meta property=\"og:type\" content=\"website\" />\n <meta property=\"og:title\" content={fullTitle} />\n {description && <meta property=\"og:description\" content={description} />}\n {fullImageUrl && <meta property=\"og:image\" content={fullImageUrl} />}\n {url && <meta property=\"og:url\" content={url} />}\n <meta property=\"og:locale\" content={locale} />\n {productName && <meta property=\"og:site_name\" content={productName} />}\n\n {/* Twitter Card */}\n <meta name=\"twitter:card\" content=\"summary_large_image\" />\n <meta name=\"twitter:title\" content={fullTitle} />\n {description && <meta name=\"twitter:description\" content={description} />}\n {fullImageUrl && <meta name=\"twitter:image\" content={fullImageUrl} />}\n {twitterHandle && <meta name=\"twitter:creator\" content={twitterHandle} />}\n\n {/* Theme Color */}\n <meta name=\"theme-color\" content={themeColor} />\n\n {/* JSON-LD Structured Data */}\n {structuredDataItems.map((data, index) => (\n <script key={`ld-${index}`} type=\"application/ld+json\">\n {JSON.stringify(data)}\n </script>\n ))}\n\n {/* Additional Meta Tags */}\n {additionalMeta?.map((meta, index) => (\n <meta\n key={`meta-${index}`}\n {...(meta.name ? { name: meta.name } : {})}\n {...(meta.property ? { property: meta.property } : {})}\n content={meta.content}\n />\n ))}\n </Helmet>\n );\n}\n","/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx and tailwind-merge for optimal class handling\n */\n\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge multiple class names intelligently\n * - Handles conditional classes via clsx\n * - Deduplicates and resolves Tailwind conflicts via tailwind-merge\n *\n * @example\n * ```ts\n * cn('px-4 py-2', 'bg-blue-500', { 'text-white': isActive })\n * // => 'px-4 py-2 bg-blue-500 text-white' (if isActive is true)\n * ```\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../utils/cn\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2\",\n sm: \"h-8 rounded-md px-3 text-xs\",\n lg: \"h-10 rounded-md px-8\",\n icon: \"h-9 w-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps\n extends\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import * as React from \"react\";\n\nimport { cn } from \"../utils/cn\";\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<\"input\">>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport { Input };\n","import * as React from \"react\";\n\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../utils/cn\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","import * as React from \"react\";\n\nimport { cn } from \"../utils/cn\";\n\n/** Native `<select>` wrapper matching the `Input` design tokens. */\nconst Select = React.forwardRef<\n HTMLSelectElement,\n React.ComponentProps<\"select\">\n>(({ className, children, ...props }, ref) => {\n return (\n <select\n className={cn(\n \"flex h-9 w-full appearance-none rounded-md border border-input bg-transparent bg-[length:1rem_1rem] bg-[right_0.75rem_center] bg-no-repeat px-3 py-1 pr-8 text-base shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n // Inline SVG chevron: SVG inside a `background-image: url(data:…)`\n // does NOT inherit `currentColor` from the host element (the SVG is\n // its own document with no parent CSS context), so the stroke is\n // hardcoded to a muted slate-400 (#94a3b8). Matches the muted\n // foreground token visually in both light and dark themes well\n // enough for a passive chevron — addresses #9 review feedback.\n \"bg-[url(\\\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>\\\")]\",\n className,\n )}\n ref={ref}\n {...props}\n >\n {children}\n </select>\n );\n});\nSelect.displayName = \"Select\";\n\nexport { Select };\n","import * as React from \"react\";\n\nimport { cn } from \"../utils/cn\";\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<\"textarea\">\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n \"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n});\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea };\n","/**\n * Contact Page Component\n * Complete contact page with form submission via GraphQL, reCAPTCHA validation,\n * contact information display, and additional contact options.\n * Uses the WebSDKClient provider for API calls.\n *\n * @example\n * ```tsx\n * import { ContactPage } from '@burdenoff/website-sdk/components/contact'\n *\n * <ContactPage\n * productName=\"MyProduct\"\n * recaptchaSiteKey=\"your-recaptcha-key\"\n * contactEmail=\"contact@myproduct.com\"\n * contactPhone=\"+1-234-567-8900\"\n * officeAddress={{\n * line1: \"123 Main St\",\n * line2: \"Suite 100\",\n * line3: \"City, State 12345\",\n * country: \"USA\"\n * }}\n * />\n * ```\n */\n\n\"use client\";\n\nimport { useState, useRef } from \"react\";\n\nimport { Mail, MapPin, Phone, Clock, Send } from \"lucide-react\";\nimport ReCAPTCHA from \"react-google-recaptcha\";\nimport { toast } from \"sonner\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { useProduct } from \"../product/product-provider\";\nimport { PageHead } from \"../seo/page-head\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Label } from \"../ui/label\";\nimport { Select } from \"../ui/select\";\nimport { Textarea } from \"../ui/textarea\";\n\nimport type { WebSDKClient } from \"../client/graphql-client\";\n\n// ============================================================================\n// TYPES & INTERFACES\n// ============================================================================\n\ninterface OfficeAddress {\n line1: string;\n line2: string;\n line3: string;\n country: string;\n}\n\ninterface ContactOption {\n title: string;\n description: string;\n buttonText: string;\n buttonLink: string;\n}\n\n/**\n * One entry in the contact-form Category dropdown. Each product website\n * supplies its own allow-list via the `categories` prop so the\n * vocabulary stays product-appropriate (e.g. VibeControls uses\n * `plugin-developer`, a manufacturing site uses `dealer`). The backend\n * accepts whatever `value` string is sent and persists it directly.\n *\n * `value` flows to the backend; `label` is what the user sees.\n */\nexport interface ContactCategory {\n /** Stored on the server. Short, kebab-case is conventional. */\n value: string;\n /** Human-readable label shown in the dropdown. */\n label: string;\n}\n\n/**\n * Conservative starter category list — Burdenoff-generic vocabulary\n * (General / Sales / Support / Partnership / Press / Careers / Security).\n *\n * **Not** applied by default: pass it explicitly to opt in:\n *\n * ```tsx\n * <ContactPage\n * …\n * categories={DEFAULT_CONTACT_CATEGORIES}\n * />\n * ```\n *\n * The component default for `categories` is `[]` (no dropdown) so this\n * SDK release is backward-compatible with existing consumers that\n * don't yet know about the field — see the prop docs.\n */\nexport const DEFAULT_CONTACT_CATEGORIES: ContactCategory[] = [\n { value: \"general\", label: \"General enquiry\" },\n { value: \"sales\", label: \"Sales\" },\n { value: \"support\", label: \"Support\" },\n { value: \"partnership\", label: \"Partnership\" },\n { value: \"press\", label: \"Press / media\" },\n { value: \"careers\", label: \"Careers\" },\n { value: \"security\", label: \"Security disclosure\" },\n];\n\ninterface ContactFormData {\n firstName: string;\n lastName: string;\n email: string;\n company?: string;\n category?: string;\n subject: string;\n message: string;\n recaptchaToken: string;\n}\n\ntype SubmitStatus = \"idle\" | \"success\" | \"error\";\n\nexport interface ContactPageProps {\n /** Product name. Falls back to SDK config productId if not provided. */\n productName?: string;\n /** reCAPTCHA site key (optional, falls back to SDK config) */\n recaptchaSiteKey?: string;\n /** Contact email */\n contactEmail: string;\n /** Contact phone number */\n contactPhone: string;\n /** Office address */\n officeAddress: OfficeAddress;\n /** Response time message */\n responseTime?: string;\n /** Hero title */\n heroTitle?: string;\n /** Hero description */\n heroDescription?: string;\n /**\n * Heading level for the hero title. Defaults to `1` (a full page hero,\n * `<h1>`). Pass `2` when embedding ContactPage inside another page that\n * already owns the page `<h1>` (e.g. `PartnersPage`) — renders a compact\n * `<h2>` section header instead of a competing hero, keeping one `<h1>`\n * per page for SEO and a clean visual hierarchy.\n */\n headingLevel?: 1 | 2;\n /** Additional contact options */\n additionalOptions?: ContactOption[];\n /**\n * Inquiry-type dropdown allow-list. **Defaults to `[]`** — the\n * dropdown does not render unless the consumer explicitly opts in.\n *\n * Two ways to opt in:\n *\n * ```tsx\n * // 1. Provide a product-specific list\n * <ContactPage categories={[{ value: 'sales', label: 'Sales' }, …]} />\n *\n * // 2. Or use the conservative SDK starter list\n * <ContactPage categories={DEFAULT_CONTACT_CATEGORIES} />\n * ```\n *\n * Default is intentionally empty (not `DEFAULT_CONTACT_CATEGORIES`)\n * to keep this SDK release backward-compatible with existing\n * consumers that don't yet wire `categories` — they get zero\n * behavior change.\n *\n * Typed `readonly` because the component never mutates the array;\n * lets product sites pass an `as const`-frozen config without an\n * extra `[...spread]` at the call site.\n */\n categories?: readonly ContactCategory[];\n /** Label shown above the category dropdown. */\n categoryLabel?: string;\n /** Placeholder text for the unselected state of the dropdown. */\n categoryPlaceholder?: string;\n /**\n * Whether selecting a category is required to submit. Defaults to\n * `true` — the whole point of the dropdown is routing, so users\n * self-triage instead of pushing that work onto support.\n */\n categoryRequired?: boolean;\n /** SEO metadata */\n seo?: {\n title?: string;\n description?: string;\n keywords?: string;\n image?: string;\n url?: string;\n };\n}\n\n// ============================================================================\n// GRAPHQL MUTATION\n// ============================================================================\n\nconst SUBMIT_CONTACT_INQUIRY_MUTATION = /* GraphQL */ `\n mutation SubmitContactInquiry($input: SubmitContactInquiryInput!) {\n submitContactInquiry(input: $input) {\n success\n message\n }\n }\n`;\n\n// ============================================================================\n// API SERVICE\n// ============================================================================\n\nasync function submitContactForm(\n client: WebSDKClient,\n data: ContactFormData,\n productId: string,\n): Promise<{ success: boolean; message?: string }> {\n try {\n const result = await client.mutate<{\n submitContactInquiry: {\n success: boolean;\n message: string;\n };\n }>(SUBMIT_CONTACT_INQUIRY_MUTATION, {\n input: {\n name: `${data.firstName} ${data.lastName}`,\n email: data.email.trim().toLowerCase(),\n company: data.company || undefined,\n subject: data.subject,\n message: data.message,\n productId,\n // Send `category` only when the user actually picked one. Older\n // backend deployments without the `category` field in the\n // `SubmitContactInquiryInput` schema would reject any unknown\n // field; spreading conditionally keeps the SDK forward-\n // compatible.\n ...(data.category ? { category: data.category } : {}),\n ...(data.recaptchaToken ? { recaptchaToken: data.recaptchaToken } : {}),\n },\n });\n\n if (result.errors?.length) {\n const errorMsg = result.errors[0]?.message ?? \"Failed to send message\";\n return { success: false, message: errorMsg };\n }\n\n const response = result.data?.submitContactInquiry;\n if (response?.success) {\n return {\n success: true,\n message: response.message || \"Message sent successfully!\",\n };\n }\n\n return {\n success: false,\n message: response?.message || \"Failed to send message\",\n };\n } catch (error) {\n console.error(\"Contact form submission error:\", error);\n return {\n success: false,\n message: \"Network error. Please try again.\",\n };\n }\n}\n\n// ============================================================================\n// HELPER\n// ============================================================================\n\nfunction replacePlaceholders(\n text: string,\n productName: string,\n email: string,\n): string {\n return text.replace(/{productName}/g, productName).replace(/{email}/g, email);\n}\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport function ContactPage({\n productName,\n recaptchaSiteKey,\n contactEmail,\n contactPhone,\n officeAddress,\n responseTime = \"We typically respond within 24 hours\",\n heroTitle = \"Get in Touch\",\n heroDescription = \"Have questions about {productName}? We're here to help. Reach out to our team and we'll get back to you as soon as possible.\",\n headingLevel = 1,\n // Backward-compatibility: default to `[]` so existing consumers\n // (fluidgrids/burdenoff/algoshred websites) that don't pass\n // `categories` continue to render with NO dropdown — same behavior\n // they had before this SDK version. To opt in, pass an explicit\n // `categories={…}` array (or the exported `DEFAULT_CONTACT_CATEGORIES`\n // constant for the sane Burdenoff-generic vocabulary).\n categories = [],\n categoryLabel = \"Category\",\n categoryPlaceholder = \"Select a category\",\n categoryRequired = true,\n additionalOptions = [\n {\n title: \"Sales Inquiries\",\n description:\n \"Ready to see {productName} in action? Our sales team is here to help.\",\n buttonText: \"Contact Sales\",\n buttonLink: `mailto:${contactEmail}`,\n },\n {\n title: \"Technical Support\",\n description:\n \"Need help with your {productName} setup? Our support team is ready.\",\n buttonText: \"Get Support\",\n buttonLink: `mailto:${contactEmail}`,\n },\n {\n title: \"Partnership\",\n description:\n \"Interested in partnering with {productName}? Let's explore opportunities.\",\n buttonText: \"Partner With Us\",\n buttonLink: `mailto:${contactEmail}`,\n },\n ],\n seo,\n}: ContactPageProps) {\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const { product } = useProduct();\n const resolvedProductId = product?.id || config.productId;\n const displayName = productName ?? product?.name ?? config.productId;\n // Resolution order: explicit prop → product CMS (publicProduct.recaptchaSiteKey)\n // → SDK config/env. Lets the key be managed per-product in the CMS without\n // any env wiring on the consuming site.\n const effectiveRecaptchaSiteKey =\n recaptchaSiteKey ??\n product?.recaptchaSiteKey ??\n config.recaptchaSiteKey ??\n \"\";\n\n const recaptchaRef = useRef<ReCAPTCHA>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitStatus, setSubmitStatus] = useState<SubmitStatus>(\"idle\");\n\n const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n\n // Get reCAPTCHA token (skip validation when no site key is configured)\n const recaptchaToken = recaptchaRef.current?.getValue() ?? \"\";\n\n if (effectiveRecaptchaSiteKey && !recaptchaToken) {\n toast.error(\"Please complete the reCAPTCHA verification\");\n return;\n }\n\n setIsSubmitting(true);\n setSubmitStatus(\"idle\");\n\n // Store form reference before async operations\n const form = e.currentTarget;\n\n try {\n const formData = new FormData(form);\n\n // Category is rendered only when `categories` is non-empty. Read\n // it conditionally so an opt-out site (`categories={[]}`) never\n // sends an empty-string `category` on the wire.\n const showCategory = categories.length > 0;\n const rawCategory = showCategory\n ? ((formData.get(\"category\") as string | null) ?? \"\").trim()\n : \"\";\n if (showCategory && categoryRequired && !rawCategory) {\n // Belt-and-braces validation. Browsers already enforce the\n // `required` attribute, but the form-data path runs even when\n // the native check is bypassed by a custom client.\n //\n // Message is hardcoded (not derived from `categoryPlaceholder`)\n // so a placeholder like \"Department type\" doesn't produce\n // ungrammatical output like \"Please department type\" —\n // addresses #9 review feedback.\n toast.error(\"Please select a category\");\n setIsSubmitting(false);\n return;\n }\n\n const contactData: ContactFormData = {\n firstName: formData.get(\"firstName\") as string,\n lastName: formData.get(\"lastName\") as string,\n email: formData.get(\"email\") as string,\n company: formData.get(\"company\") as string,\n category: rawCategory || undefined,\n subject: formData.get(\"subject\") as string,\n message: formData.get(\"message\") as string,\n recaptchaToken,\n };\n\n const result = await submitContactForm(\n client,\n contactData,\n resolvedProductId,\n );\n\n if (result.success) {\n setSubmitStatus(\"success\");\n toast.success(\n result.message ??\n `Thank you for contacting ${displayName}. We'll get back to you within 24 hours.`,\n );\n\n // Reset form\n if (form) {\n form.reset();\n }\n // Reset reCAPTCHA\n recaptchaRef.current?.reset();\n } else {\n setSubmitStatus(\"error\");\n toast.error(\n result.message ?? \"Failed to send message. Please try again.\",\n );\n recaptchaRef.current?.reset();\n }\n } catch (error) {\n console.error(\"Error submitting form:\", error);\n setSubmitStatus(\"error\");\n toast.error(\"Failed to send message. Please try again later.\");\n recaptchaRef.current?.reset();\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <div className=\"w-full\">\n {seo && (\n <PageHead\n title={\n seo.title ?? `Contact ${displayName} - Get in Touch With Our Team`\n }\n description={\n seo.description ??\n `Ready to transform your business? Contact our team for sales inquiries, technical support, or partnership opportunities. We're here to help you succeed.`\n }\n productName={displayName}\n keywords={\n seo.keywords ??\n `contact ${displayName.toLowerCase()}, sales inquiries, customer support, technical support, partnership opportunities, get in touch`\n }\n image={seo.image ?? \"/og-image-contact.png\"}\n url={seo.url}\n />\n )}\n\n {/* Hero Section — full page hero (h1) by default; compact section\n header (h2) when embedded in a page that already owns the <h1>. */}\n <section\n className={\n headingLevel === 2\n ? \"py-12 md:py-16\"\n : \"bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24\"\n }\n >\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"text-center max-w-3xl mx-auto\">\n {headingLevel === 2 ? (\n <h2 className=\"text-2xl md:text-3xl font-bold mb-3\">\n {heroTitle}\n </h2>\n ) : (\n <h1 className=\"text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6\">\n {heroTitle}\n </h1>\n )}\n <p className=\"text-lg sm:text-xl text-muted-foreground leading-relaxed\">\n {replacePlaceholders(heroDescription, displayName, contactEmail)}\n </p>\n </div>\n </div>\n </section>\n\n {/* Contact Form and Info */}\n <section className=\"py-12 sm:py-16 md:py-20 lg:py-24\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <div className=\"grid sm:grid-cols-1 lg:grid-cols-3 gap-8 sm:gap-10 lg:gap-12\">\n {/* Contact Information */}\n <div className=\"lg:col-span-1 order-2 lg:order-1\">\n <h2 className=\"text-xl sm:text-2xl font-bold mb-4 sm:mb-6\">\n Contact Information\n </h2>\n\n <div className=\"space-y-4 sm:space-y-6\">\n <div className=\"flex items-start space-x-3 sm:space-x-4\">\n <div className=\"w-8 h-8 sm:w-10 sm:h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0\">\n <Mail className=\"h-4 w-4 sm:h-5 sm:w-5 text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold mb-1 text-sm sm:text-base\">\n Email\n </h3>\n <p className=\"text-muted-foreground text-sm sm:text-base break-all\">\n {contactEmail}\n </p>\n </div>\n </div>\n\n {contactPhone && (\n <div className=\"flex items-start space-x-3 sm:space-x-4\">\n <div className=\"w-8 h-8 sm:w-10 sm:h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0\">\n <Phone className=\"h-4 w-4 sm:h-5 sm:w-5 text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold mb-1 text-sm sm:text-base\">\n Phone\n </h3>\n <p className=\"text-muted-foreground text-sm sm:text-base\">\n {contactPhone}\n </p>\n </div>\n </div>\n )}\n\n <div className=\"flex items-start space-x-3 sm:space-x-4\">\n <div className=\"w-8 h-8 sm:w-10 sm:h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0\">\n <MapPin className=\"h-4 w-4 sm:h-5 sm:w-5 text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold mb-1 text-sm sm:text-base\">\n Office\n </h3>\n <p className=\"text-muted-foreground text-sm sm:text-base leading-relaxed\">\n {officeAddress.line1}\n <br />\n {officeAddress.line2}\n <br />\n {officeAddress.line3}\n <br />\n {officeAddress.country}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-start space-x-3 sm:space-x-4\">\n <div className=\"w-8 h-8 sm:w-10 sm:h-10 bg-primary/10 rounded-lg flex items-center justify-center flex-shrink-0\">\n <Clock className=\"h-4 w-4 sm:h-5 sm:w-5 text-primary\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold mb-1 text-sm sm:text-base\">\n Response Time\n </h3>\n <p className=\"text-muted-foreground text-sm sm:text-base\">\n {responseTime}\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Contact Form */}\n <div className=\"lg:col-span-2 order-1 lg:order-2\">\n <div className=\"bg-card border rounded-lg p-4 sm:p-6 md:p-8\">\n <h2 className=\"text-xl sm:text-2xl font-bold mb-4 sm:mb-6\">\n Send us a Message\n </h2>\n\n <form\n onSubmit={handleSubmit}\n className=\"space-y-4 sm:space-y-6\"\n >\n <div className=\"grid sm:grid-cols-2 gap-4 sm:gap-6\">\n <div className=\"space-y-2\">\n <Label\n htmlFor=\"firstName\"\n className=\"text-sm sm:text-base\"\n >\n First Name *\n </Label>\n <Input\n id=\"firstName\"\n name=\"firstName\"\n required\n placeholder=\"John\"\n className=\"text-sm sm:text-base\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label\n htmlFor=\"lastName\"\n className=\"text-sm sm:text-base\"\n >\n Last Name *\n </Label>\n <Input\n id=\"lastName\"\n name=\"lastName\"\n required\n placeholder=\"Doe\"\n className=\"text-sm sm:text-base\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\" className=\"text-sm sm:text-base\">\n Email *\n </Label>\n <Input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n placeholder=\"john@company.com\"\n className=\"text-sm sm:text-base\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"company\" className=\"text-sm sm:text-base\">\n Company\n </Label>\n <Input\n id=\"company\"\n name=\"company\"\n placeholder=\"Acme Inc.\"\n className=\"text-sm sm:text-base\"\n />\n </div>\n\n {categories.length > 0 && (\n <div className=\"space-y-2\">\n <Label\n htmlFor=\"category\"\n className=\"text-sm sm:text-base\"\n >\n {categoryLabel}\n {categoryRequired ? \" *\" : \"\"}\n </Label>\n <Select\n id=\"category\"\n name=\"category\"\n required={categoryRequired}\n defaultValue=\"\"\n className=\"text-sm sm:text-base\"\n >\n {/*\n * `disabled` is tied to `categoryRequired` on\n * purpose. When required, the placeholder is\n * locked out so the native form-validation can\n * enforce that the user picks a real value;\n * when optional, leaving it enabled lets the\n * user clear an accidental selection back to\n * the empty / uncategorized state (otherwise\n * an optional dropdown becomes effectively\n * sticky after any click). The form-submit\n * handler treats `category === ''` as\n * `undefined` on the wire so unselected\n * submissions don't carry a category at all.\n */}\n <option value=\"\" disabled={categoryRequired}>\n {categoryPlaceholder}\n </option>\n {categories.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </Select>\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"subject\" className=\"text-sm sm:text-base\">\n Subject *\n </Label>\n <Input\n id=\"subject\"\n name=\"subject\"\n required\n placeholder=\"How can we help you?\"\n className=\"text-sm sm:text-base\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"message\" className=\"text-sm sm:text-base\">\n Message *\n </Label>\n <Textarea\n id=\"message\"\n name=\"message\"\n required\n placeholder=\"Tell us more about your needs...\"\n rows={5}\n className=\"text-sm sm:text-base min-h-[120px] sm:min-h-[150px] resize-y\"\n />\n </div>\n\n <div className=\"space-y-4\">\n {effectiveRecaptchaSiteKey && (\n <div className=\"flex justify-center sm:justify-start\">\n <ReCAPTCHA\n ref={recaptchaRef}\n sitekey={effectiveRecaptchaSiteKey}\n />\n </div>\n )}\n\n <Button\n type=\"submit\"\n size=\"lg\"\n disabled={isSubmitting}\n className=\"w-full sm:w-auto min-w-[200px]\"\n >\n {isSubmitting ? (\n \"Sending...\"\n ) : (\n <>\n Send Message <Send className=\"ml-2 h-4 w-4\" />\n </>\n )}\n </Button>\n </div>\n\n {submitStatus === \"success\" && (\n <div className=\"p-3 sm:p-4 bg-green-50 border border-green-200 rounded-lg text-green-800 mt-4\">\n <p className=\"font-medium text-sm sm:text-base\">\n Message sent successfully!\n </p>\n <p className=\"text-xs sm:text-sm mt-1\">\n Thank you for contacting {displayName}. We&apos;ll get\n back to you within 24 hours.\n </p>\n </div>\n )}\n\n {submitStatus === \"error\" && (\n <div className=\"p-3 sm:p-4 bg-red-50 border border-red-200 rounded-lg text-red-800 mt-4\">\n <p className=\"font-medium text-sm sm:text-base\">\n Failed to send message\n </p>\n <p className=\"text-xs sm:text-sm mt-1\">\n Please try again later or contact us directly at{\" \"}\n {contactEmail}\n </p>\n </div>\n )}\n </form>\n </div>\n </div>\n </div>\n </div>\n </section>\n\n {/* Additional Contact Options — hidden when additionalOptions is empty */}\n {additionalOptions.length > 0 && (\n <section className=\"py-12 sm:py-16 md:py-20 lg:py-24 bg-muted/30\">\n <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n <h2 className=\"text-2xl sm:text-3xl font-bold text-center mb-8 sm:mb-12\">\n More Ways to Connect\n </h2>\n\n <div className=\"grid sm:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8 max-w-5xl mx-auto\">\n {additionalOptions.map((option, index) => (\n <div\n key={index}\n className=\"text-center p-4 sm:p-6 bg-card border rounded-lg\"\n >\n <h3 className=\"font-semibold text-base sm:text-lg mb-2\">\n {option.title}\n </h3>\n <p className=\"text-muted-foreground text-sm sm:text-base mb-4 leading-relaxed\">\n {replacePlaceholders(\n option.description,\n displayName,\n contactEmail,\n )}\n </p>\n <Button\n variant=\"outline\"\n asChild\n className=\"text-sm sm:text-base\"\n >\n <a href={option.buttonLink}>{option.buttonText}</a>\n </Button>\n </div>\n ))}\n </div>\n </div>\n </section>\n )}\n </div>\n );\n}\n","/**\n * Content Provider\n *\n * React hooks for fetching public content pages from the global tenant service.\n * Content pages include privacy policies, terms of service, blogs, changelogs, etc.\n */\n\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\n\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { useProduct } from \"../product/product-provider\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ContentPageData {\n id: string;\n title: string;\n slug: string;\n content: string;\n contentFormat: string;\n seoTitle?: string | null;\n seoDescription?: string | null;\n seoKeywords?: string | null;\n lastUpdated: string;\n version: number;\n tags?: string[];\n excerpt?: string | null;\n thumbnail?: string | null;\n author?: string | null;\n publishedAt?: string | null;\n readingTime?: number | null;\n featured?: boolean;\n category?: string | null;\n}\n\nexport interface ContentPageListItem {\n id: string;\n title: string;\n slug: string;\n lastUpdated: string;\n tags?: string[];\n excerpt?: string | null;\n thumbnail?: string | null;\n author?: string | null;\n publishedAt?: string | null;\n readingTime?: number | null;\n featured?: boolean;\n category?: string | null;\n seoDescription?: string | null;\n}\n\nexport interface ContentPageListData {\n items: ContentPageListItem[];\n total: number;\n hasMore: boolean;\n}\n\nexport interface UseContentPageOptions {\n /** Whether to use template variable replacement (resolvedContentPage) */\n resolve?: boolean;\n}\n\n// ============================================================================\n// GraphQL Queries\n// ============================================================================\n\nconst PUBLIC_CONTENT_PAGE_QUERY = `\n query PublicContentPage($slug: String!, $productId: String) {\n publicContentPage(slug: $slug, productId: $productId) {\n id\n title\n slug\n content\n contentFormat\n seoTitle\n seoDescription\n seoKeywords\n lastUpdated\n version\n excerpt\n thumbnail\n author\n publishedAt\n readingTime\n featured\n category\n }\n }\n`;\n\nconst PUBLIC_RESOLVED_CONTENT_PAGE_QUERY = `\n query PublicResolvedContentPage($slug: String!, $productId: String!) {\n publicResolvedContentPage(slug: $slug, productId: $productId) {\n id\n title\n slug\n content\n contentFormat\n seoTitle\n seoDescription\n seoKeywords\n lastUpdated\n version\n excerpt\n thumbnail\n author\n publishedAt\n readingTime\n featured\n category\n }\n }\n`;\n\nconst PUBLIC_CONTENT_PAGES_QUERY = `\n query PublicContentPages($productId: String!, $limit: Int, $offset: Int) {\n publicContentPages(productId: $productId, limit: $limit, offset: $offset) {\n items {\n id\n title\n slug\n lastUpdated\n tags\n seoDescription\n excerpt\n thumbnail\n author\n publishedAt\n readingTime\n featured\n category\n }\n total\n hasMore\n }\n }\n`;\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Hook to fetch a single public content page by slug.\n *\n * @example\n * ```tsx\n * const { data, loading, error } = useContentPage('privacy-policy');\n * ```\n */\nexport function useContentPage(\n slug: string,\n options?: UseContentPageOptions,\n): {\n data: ContentPageData | null;\n loading: boolean;\n error: string | null;\n refetch: () => void;\n} {\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const { product } = useProduct();\n const resolvedProductId = product?.id || config.productId;\n const [data, setData] = useState<ContentPageData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchPage = useCallback(async () => {\n if (!resolvedProductId) return; // Wait for product to load\n\n setLoading(true);\n setError(null);\n\n try {\n const query = options?.resolve\n ? PUBLIC_RESOLVED_CONTENT_PAGE_QUERY\n : PUBLIC_CONTENT_PAGE_QUERY;\n\n const queryName = options?.resolve\n ? \"publicResolvedContentPage\"\n : \"publicContentPage\";\n\n const result = await client.query<Record<string, ContentPageData | null>>(\n query,\n {\n slug,\n productId: resolvedProductId,\n },\n );\n\n if (result.errors?.length) {\n setError(result.errors[0]?.message ?? \"Unknown error\");\n setData(null);\n } else {\n setData(result.data?.[queryName] ?? null);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to fetch content\");\n setData(null);\n } finally {\n setLoading(false);\n }\n }, [client, resolvedProductId, slug, options?.resolve]);\n\n useEffect(() => {\n fetchPage();\n }, [fetchPage]);\n\n return { data, loading, error, refetch: fetchPage };\n}\n\n/**\n * Hook to fetch a list of public content pages for the current product.\n *\n * @example\n * ```tsx\n * const { data, loading } = useContentPages({ limit: 10 });\n * ```\n */\nexport function useContentPages(options?: {\n limit?: number;\n offset?: number;\n}): {\n data: ContentPageListData | null;\n loading: boolean;\n error: string | null;\n refetch: () => void;\n} {\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const [data, setData] = useState<ContentPageListData | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchPages = useCallback(async () => {\n setLoading(true);\n setError(null);\n\n try {\n const result = await client.query<{\n publicContentPages: ContentPageListData;\n }>(PUBLIC_CONTENT_PAGES_QUERY, {\n productId: config.productId,\n limit: options?.limit ?? 50,\n offset: options?.offset ?? 0,\n });\n\n if (result.errors?.length) {\n setError(result.errors[0]?.message ?? \"Unknown error\");\n setData(null);\n } else {\n setData(result.data?.publicContentPages ?? null);\n }\n } catch (err) {\n setError(\n err instanceof Error ? err.message : \"Failed to fetch content pages\",\n );\n setData(null);\n } finally {\n setLoading(false);\n }\n }, [client, config.productId, options?.limit, options?.offset]);\n\n useEffect(() => {\n fetchPages();\n }, [fetchPages]);\n\n return { data, loading, error, refetch: fetchPages };\n}\n\n/**\n * Minimal, dependency-free Markdown → HTML renderer.\n *\n * HTML entities are escaped first so raw user content cannot inject markup\n * (the output is fed to dangerouslySetInnerHTML). Mirrors the admin content\n * editor's preview renderer so authored content looks the same everywhere.\n */\nfunction renderMarkdown(md: string): string {\n let html = md;\n\n html = html\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n\n // Fenced code blocks\n html = html.replace(/```(\\w*)\\n([\\s\\S]*?)```/g, (_m, _lang, code) => {\n return `<pre><code>${code.trim()}</code></pre>`;\n });\n // Inline code\n html = html.replace(/`([^`]+)`/g, \"<code>$1</code>\");\n\n // Headings\n html = html.replace(/^###### (.+)$/gm, \"<h6>$1</h6>\");\n html = html.replace(/^##### (.+)$/gm, \"<h5>$1</h5>\");\n html = html.replace(/^#### (.+)$/gm, \"<h4>$1</h4>\");\n html = html.replace(/^### (.+)$/gm, \"<h3>$1</h3>\");\n html = html.replace(/^## (.+)$/gm, \"<h2>$1</h2>\");\n html = html.replace(/^# (.+)$/gm, \"<h1>$1</h1>\");\n\n // Bold / italic\n html = html.replace(/\\*\\*\\*(.+?)\\*\\*\\*/g, \"<strong><em>$1</em></strong>\");\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\");\n html = html.replace(/\\*(.+?)\\*/g, \"<em>$1</em>\");\n\n // Links\n html = html.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\">$1</a>',\n );\n\n // Blockquotes (entities already escaped → match &gt;)\n html = html.replace(/^&gt; (.+)$/gm, \"<blockquote>$1</blockquote>\");\n\n // Unordered lists\n html = html.replace(/(^- .+$(\\n^- .+$)*)/gm, (block) => {\n const items = block\n .split(\"\\n\")\n .map((line) => `<li>${line.replace(/^- /, \"\")}</li>`)\n .join(\"\");\n return `<ul>${items}</ul>`;\n });\n // Ordered lists\n html = html.replace(/(^\\d+\\. .+$(\\n^\\d+\\. .+$)*)/gm, (block) => {\n const items = block\n .split(\"\\n\")\n .map((line) => `<li>${line.replace(/^\\d+\\. /, \"\")}</li>`)\n .join(\"\");\n return `<ol>${items}</ol>`;\n });\n\n // Horizontal rule\n html = html.replace(/^---$/gm, \"<hr />\");\n\n // Paragraphs\n html = html\n .split(/\\n\\n+/)\n .map((block) => {\n const trimmed = block.trim();\n if (!trimmed) return \"\";\n if (/^<(h[1-6]|ul|ol|pre|blockquote|hr)/.test(trimmed)) return trimmed;\n return `<p>${trimmed.replace(/\\n/g, \"<br />\")}</p>`;\n })\n .join(\"\\n\");\n\n return html;\n}\n\n/**\n * Content renderer component.\n *\n * - `markdown` (default): converts to HTML via {@link renderMarkdown}\n * - `html`: rendered as-is (assumed already sanitized upstream)\n * - anything else: plain-text fallback\n *\n * @example\n * ```tsx\n * <ContentRenderer content={page.content} format={page.contentFormat} />\n * ```\n */\nexport function ContentRenderer({\n content,\n format = \"markdown\",\n className,\n}: {\n content: string;\n format?: string;\n className?: string;\n}) {\n if (format === \"markdown\") {\n return (\n <div\n className={className}\n dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }}\n />\n );\n }\n\n if (format === \"html\") {\n return (\n <div\n className={className}\n dangerouslySetInnerHTML={{ __html: content }}\n />\n );\n }\n\n // Plain text fallback\n return (\n <div className={className}>\n <pre style={{ whiteSpace: \"pre-wrap\", fontFamily: \"inherit\" }}>\n {content}\n </pre>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Partners Page Component\n *\n * CMS-powered public partner programme page. Composes three sources of truth\n * we already manage in the admin:\n *\n * 1. **Marketing copy** — a single `ProductContentPage` matched by `tag`\n * (default `\"partner\"`) or by `slug`. Rendered through `ContentRenderer`\n * so admins can use the full CMS editor — no hardcoded copy in this file.\n * 2. **Downloadable documents** — `ProductPressKitAsset`s with category\n * `\"DOCUMENT\"` and a matching `tag` (default `\"partner\"`). Typically the\n * Partner / Reseller Agreement PDF, deck, FAQ, etc. Self-hides when empty.\n * 3. **\"Become a partner\" contact form** — embedded `<ContactPage>` with the\n * inquiry category **locked** to `\"partnership\"` so submissions land in the\n * admin support inbox tagged for the partner-program lane (shared inbox\n * routing for v1; per-category email routing is a separate backend change).\n *\n * The page is intentionally section-based and gracefully degrades: if the\n * admin hasn't created a content page yet, only the hero + form render; if\n * no documents are uploaded, the document section disappears; if neither\n * exists, the page is just a form. This keeps the partner page useful from\n * day one without blocking on CMS data.\n *\n * Mirrors the `PressKitPage` + `BlogListPage` architecture; data fetching\n * goes through the same `WebSDKClient` GraphQL helpers everything else uses.\n *\n * @example\n * ```tsx\n * import { PartnersPage } from '@burdenoff/website-sdk'\n *\n * <Route\n * path=\"/partners\"\n * element={\n * <PartnersPage\n * productName=\"VibeControls\"\n * contactEmail=\"partnerships@vibecontrols.com\"\n * contactPhone=\"+91-XXX-XXX-XXXX\"\n * officeAddress={{ line1: \"…\", line2: \"\", line3: \"\", country: \"India\" }}\n * />\n * }\n * />\n * ```\n */\n\nimport { useEffect, useState } from \"react\";\n\nimport { Download, FileText } from \"lucide-react\";\n\nimport { ContactPage } from \"./contact\";\nimport { useWebSDK, useWebSDKConfig } from \"../client/provider\";\nimport { ContentRenderer } from \"../content/content-provider\";\nimport { useProduct } from \"../product/product-provider\";\nimport { PageHead } from \"../seo/page-head\";\n\nimport type { ContactCategory, ContactPageProps } from \"./contact\";\nimport type { ContentPageListItem } from \"../content/content-provider\";\n\n/**\n * Office address shape consumed by `<ContactPage>`. Mirrored here as a\n * local type so we don't widen `contact.tsx`'s public surface just for\n * this consumer — keeps the contact module's exports unchanged.\n */\ninterface OfficeAddress {\n line1: string;\n line2: string;\n line3: string;\n country: string;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A downloadable document surfaced on the partners page. Same shape as\n * `PressKitAsset` but only the fields the card uses — keeps the type\n * surface tight and avoids a cross-file import of the press-kit type.\n */\ninterface PartnerDocument {\n id: string;\n category: string;\n title: string;\n description?: string | null;\n fileUrl: string;\n fileName?: string | null;\n fileSize?: number | null;\n mimeType?: string | null;\n version?: string | null;\n tags: string[];\n sortOrder: number;\n updatedAt: string;\n}\n\nexport interface PartnersPageProps {\n /** Product name (e.g. `\"VibeControls\"`). Falls back to SDK config. */\n productName?: string;\n\n // ── Hero ─────────────────────────────────────────────────────────────\n /** Hero headline. Default: `\"Partner with us\"`. */\n heroTitle?: string;\n /** Hero subtitle / pitch line. */\n heroSubtitle?: string;\n\n // ── CMS marketing copy section ───────────────────────────────────────\n /**\n * Tag filter for the marketing-copy body. Default: `\"partner\"`. The\n * component fetches the FIRST published `ProductContentPage` whose\n * tags array contains this tag and renders its body via\n * `ContentRenderer`. Self-hides if none exist.\n */\n contentTag?: string;\n /**\n * Pin a specific content page by slug. If set, overrides `contentTag`.\n * Useful when multiple partner pages exist and you want to render one\n * canonical version per route.\n */\n contentSlug?: string;\n\n // ── Documents section ────────────────────────────────────────────────\n /**\n * Tag filter for the downloadable documents. Default: `\"partner\"`.\n * Combined with the implicit `category === \"DOCUMENT\"` filter — only\n * Press Kit assets that match BOTH are rendered as cards. Self-hides\n * when empty.\n */\n documentsTag?: string;\n /** Documents-section heading. Default: `\"Partner Documents\"`. */\n documentsTitle?: string;\n /** Documents-section subtitle / lead. */\n documentsSubtitle?: string;\n\n // ── Contact form section ─────────────────────────────────────────────\n /**\n * Whether to render the \"Become a partner\" contact form. Default: `true`.\n * Set to `false` for a documents-only / read-only partner landing page.\n */\n showContactForm?: boolean;\n /**\n * Inquiry-category options for the embedded `<ContactPage>` dropdown.\n * Default: `{ value: \"partnership\", label: \"Partner program\" }` (a single,\n * required option so every submission is tagged for partner triage). Pass an\n * **array** to offer multiple selectable partner tracks (Referral, Reseller,\n * MSP, …). Pass `false` to disable the dropdown entirely.\n */\n contactCategory?: ContactCategory | ContactCategory[] | false;\n /** Heading shown above the form. Default: `\"Become a partner\"`. */\n formTitle?: string;\n /** Subtitle / lead above the form. */\n formSubtitle?: string;\n\n // ── Contact-form passthroughs (required for <ContactPage>) ───────────\n contactEmail: string;\n contactPhone: string;\n officeAddress: OfficeAddress;\n responseTime?: string;\n recaptchaSiteKey?: string;\n /** Forwarded to `<ContactPage additionalOptions>`. */\n additionalOptions?: ContactPageProps[\"additionalOptions\"];\n\n // ── SEO ──────────────────────────────────────────────────────────────\n seoTitle?: string;\n seoDescription?: string;\n seoKeywords?: string;\n\n className?: string;\n}\n\n// ============================================================================\n// Queries\n// ============================================================================\n\nconst PARTNER_CONTENT_QUERY = `\n query PartnerContent($productId: String!, $limit: Int) {\n publicContentPages(productId: $productId, limit: $limit, offset: 0) {\n items {\n id\n title\n slug\n excerpt\n content\n contentFormat\n thumbnail\n tags\n publishedAt\n lastUpdated\n }\n }\n }\n`;\n\nconst PARTNER_DOCUMENTS_QUERY = `\n query PartnerDocuments($productId: String!, $limit: Int) {\n publicPressKitAssets(productId: $productId, limit: $limit, offset: 0) {\n items {\n id\n category\n title\n description\n fileUrl\n fileName\n fileSize\n mimeType\n version\n tags\n sortOrder\n updatedAt\n }\n }\n }\n`;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction formatFileSize(bytes: number | null | undefined): string {\n if (!bytes || bytes <= 0) return \"\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\"];\n let i = 0;\n let n = bytes;\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024;\n i++;\n }\n return `${n.toFixed(n >= 10 || i === 0 ? 0 : 1)} ${units[i]}`;\n}\n\n/**\n * Download an asset as a file (vs opening in a tab). Same blob-fetch\n * pattern as press-kit `downloadAsset` — works wherever the bucket\n * allows cross-origin GET (verified for dev/alpha/prod presskit\n * buckets, 2026-05-20).\n */\nasync function downloadDocument(\n e: { preventDefault: () => void },\n doc: PartnerDocument,\n): Promise<void> {\n e.preventDefault();\n const name =\n doc.fileName ||\n doc.fileUrl.split(\"/\").pop()?.split(\"?\")[0] ||\n doc.title ||\n \"partner-document\";\n const openInTab = () =>\n window.open(doc.fileUrl, \"_blank\", \"noopener,noreferrer\");\n try {\n const res = await fetch(doc.fileUrl, { mode: \"cors\" });\n if (!res.ok) {\n openInTab();\n return;\n }\n const blob = await res.blob();\n const objUrl = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = objUrl;\n a.download = name;\n document.body.appendChild(a);\n a.click();\n a.remove();\n URL.revokeObjectURL(objUrl);\n } catch {\n openInTab();\n }\n}\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\nfunction PartnerHero({\n title,\n subtitle,\n}: {\n title: string;\n subtitle?: string;\n}) {\n return (\n <section className=\"bg-gradient-to-b from-background to-muted/20 py-16 md:py-24\">\n <div className=\"container mx-auto px-4 max-w-4xl text-center\">\n <h1 className=\"text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4\">\n {title}\n </h1>\n {subtitle && (\n <p className=\"text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto\">\n {subtitle}\n </p>\n )}\n </div>\n </section>\n );\n}\n\n/**\n * Strip a single leading top-level heading from CMS body content. The\n * `PartnerHero` already renders the page title, so a content body that also\n * opens with `# Title` (the natural way an author writes a page) would print\n * the title twice. Removing the body's leading heading keeps one visible\n * title and one `<h1>` per page. Only the *first* heading is touched — all\n * section headings below it are preserved.\n *\n * Exported for unit testing only; not re-exported from the package barrel.\n */\nexport function stripLeadingHeading(content: string, format?: string): string {\n if (format === \"html\") {\n return content.replace(/^\\s*<h1\\b[^>]*>[\\s\\S]*?<\\/h1>\\s*/i, \"\");\n }\n // markdown (default): drop a leading \"# Heading\" line + any trailing blanks.\n // Trailing newlines are optional (`*`, not `+`) so a body that is only\n // \"# Title\" with no trailing newline — common after editor/API trimming —\n // still gets stripped. `#\\s+` matches H1 only; `## Section` is left intact.\n return content.replace(/^\\s*#\\s+.*(?:\\r?\\n)*/, \"\");\n}\n\nfunction PartnerContentSection({\n page,\n}: {\n page: ContentPageListItem & { content?: string; contentFormat?: string };\n}) {\n // Restore typography for the markdown-rendered HTML — Tailwind preflight\n // strips browser defaults, and we don't want to assume consumer sites have\n // `@tailwindcss/typography` installed. Arbitrary-children selectors keep\n // this portable to every product website that consumes the SDK.\n return (\n <section className=\"py-12 md:py-16\">\n <div\n className={[\n \"mx-auto max-w-3xl px-4\",\n // Headings\n \"[&_h1]:text-3xl [&_h1]:font-bold [&_h1]:tracking-tight [&_h1]:mt-0 [&_h1]:mb-6\",\n \"[&_h2]:text-2xl [&_h2]:font-bold [&_h2]:tracking-tight [&_h2]:mt-10 [&_h2]:mb-4\",\n \"[&_h3]:text-xl [&_h3]:font-semibold [&_h3]:mt-7 [&_h3]:mb-3\",\n \"[&_h4]:text-lg [&_h4]:font-semibold [&_h4]:mt-6 [&_h4]:mb-2\",\n // Block elements\n \"[&_p]:my-4 [&_p]:leading-relaxed [&_p]:text-base\",\n \"[&_ul]:my-4 [&_ul]:pl-6 [&_ul]:list-disc [&_ul]:space-y-1\",\n \"[&_ol]:my-4 [&_ol]:pl-6 [&_ol]:list-decimal [&_ol]:space-y-1\",\n \"[&_li]:leading-relaxed\",\n \"[&_li>p]:my-1\",\n \"[&_blockquote]:border-l-4 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:italic [&_blockquote]:my-4 [&_blockquote]:text-muted-foreground\",\n \"[&_hr]:my-8 [&_hr]:border-border\",\n // Inline elements\n \"[&_strong]:font-semibold [&_strong]:text-foreground\",\n \"[&_em]:italic\",\n \"[&_a]:underline [&_a]:underline-offset-2 [&_a]:text-accent hover:[&_a]:text-accent/80 [&_a]:transition-colors\",\n \"[&_code]:rounded [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:text-sm [&_code]:font-mono\",\n \"[&_pre]:my-4 [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-muted [&_pre]:p-4 [&_pre]:text-sm\",\n \"[&_pre>code]:bg-transparent [&_pre>code]:p-0\",\n ].join(\" \")}\n >\n {page.content && (\n <ContentRenderer\n content={stripLeadingHeading(page.content, page.contentFormat)}\n format={\n // Validate before passing; unknown formats fall through to\n // ContentRenderer's default behavior (markdown rendering)\n // rather than getting silently force-cast to an\n // unsupported variant.\n page.contentFormat === \"markdown\" || page.contentFormat === \"html\"\n ? page.contentFormat\n : undefined\n }\n />\n )}\n </div>\n </section>\n );\n}\n\nfunction PartnerDocumentCard({ doc }: { doc: PartnerDocument }) {\n const sizeLabel = formatFileSize(doc.fileSize);\n const ext = doc.fileName?.split(\".\").pop()?.toUpperCase();\n return (\n <article className=\"flex flex-col gap-3 rounded-xl border border-border bg-card p-5 shadow-sm hover:shadow-md transition-shadow\">\n <div className=\"flex items-start gap-3\">\n <div className=\"rounded-lg bg-muted p-2.5 shrink-0\">\n <FileText size={20} className=\"text-muted-foreground\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold text-foreground truncate\">\n {doc.title}\n </h3>\n {doc.version && (\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n Version {doc.version}\n </p>\n )}\n </div>\n </div>\n {doc.description && (\n <p className=\"text-sm text-muted-foreground line-clamp-3\">\n {doc.description}\n </p>\n )}\n <div className=\"flex items-center justify-between gap-3 mt-auto pt-2 border-t border-border/60\">\n <div className=\"text-xs text-muted-foreground flex items-center gap-2\">\n {ext && <span>{ext}</span>}\n {sizeLabel && (\n <>\n <span aria-hidden>·</span>\n <span>{sizeLabel}</span>\n </>\n )}\n </div>\n <a\n href={doc.fileUrl}\n download={doc.fileName ?? undefined}\n onClick={(e) => void downloadDocument(e, doc)}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-1.5 text-sm font-medium text-foreground hover:bg-muted transition-colors\"\n >\n <Download size={14} />\n Download\n </a>\n </div>\n </article>\n );\n}\n\nfunction PartnerDocumentsSection({\n title,\n subtitle,\n docs,\n}: {\n title: string;\n subtitle?: string;\n docs: PartnerDocument[];\n}) {\n return (\n <section className=\"py-12 md:py-16 bg-muted/20\">\n <div className=\"container mx-auto px-4 max-w-5xl\">\n <header className=\"mb-8 md:mb-10 text-center\">\n <h2 className=\"text-2xl md:text-3xl font-bold text-foreground mb-2\">\n {title}\n </h2>\n {subtitle && (\n <p className=\"text-muted-foreground max-w-2xl mx-auto\">\n {subtitle}\n </p>\n )}\n </header>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\">\n {docs.map((doc) => (\n <PartnerDocumentCard key={doc.id} doc={doc} />\n ))}\n </div>\n </div>\n </section>\n );\n}\n\n// ============================================================================\n// Main component\n// ============================================================================\n\nconst DEFAULT_PARTNER_CATEGORY: ContactCategory = {\n value: \"partnership\",\n label: \"Partner program\",\n};\n\nexport function PartnersPage(props: PartnersPageProps) {\n const {\n productName: productNameProp,\n heroTitle = \"Partner with us\",\n heroSubtitle,\n\n contentTag = \"partner\",\n contentSlug,\n\n documentsTag = \"partner\",\n documentsTitle = \"Partner Documents\",\n documentsSubtitle,\n\n showContactForm = true,\n contactCategory,\n formTitle = \"Become a partner\",\n formSubtitle,\n\n contactEmail,\n contactPhone,\n officeAddress,\n responseTime,\n recaptchaSiteKey,\n additionalOptions,\n\n seoTitle,\n seoDescription,\n seoKeywords,\n className,\n } = props;\n\n const client = useWebSDK();\n const config = useWebSDKConfig();\n const { product } = useProduct();\n\n const resolvedProductId =\n product?.id ?? config?.productId ?? productNameProp ?? \"\";\n const resolvedProductName =\n productNameProp ?? product?.name ?? config?.productId ?? \"our team\";\n\n const [contentPage, setContentPage] = useState<\n (ContentPageListItem & { content?: string; contentFormat?: string }) | null\n >(null);\n const [docs, setDocs] = useState<PartnerDocument[]>([]);\n const [loading, setLoading] = useState<boolean>(true);\n\n // Single fetch on mount/productId-change — small payloads, no pagination needed\n // on a partners page (one content body + a handful of docs at most).\n useEffect(() => {\n if (!client || !resolvedProductId) {\n // Reset section state when the product scope unsets (e.g. provider re-\n // resolution between routes). Without this, the page would keep\n // rendering the previous product's content + docs because the render\n // guards only check `!loading` plus existing state.\n setContentPage(null);\n setDocs([]);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n\n void Promise.allSettled([\n client.query<{\n publicContentPages: {\n items: (ContentPageListItem & {\n content?: string;\n contentFormat?: string;\n })[];\n };\n }>(PARTNER_CONTENT_QUERY, { productId: resolvedProductId, limit: 50 }),\n client.query<{ publicPressKitAssets: { items: PartnerDocument[] } }>(\n PARTNER_DOCUMENTS_QUERY,\n { productId: resolvedProductId, limit: 50 },\n ),\n ]).then(([contentResult, docsResult]) => {\n if (cancelled) return;\n\n // Content page — match by slug if given, else first item carrying the tag.\n // Clear the previous match on a rejected request so stale data from an\n // earlier product / tag doesn't linger on screen across navigations.\n if (contentResult.status === \"rejected\") {\n setContentPage(null);\n } else if (contentResult.status === \"fulfilled\") {\n type ContentItem = ContentPageListItem & {\n content?: string;\n contentFormat?: string;\n };\n const items: ContentItem[] =\n contentResult.value.data?.publicContentPages?.items ?? [];\n const match: ContentItem | undefined = contentSlug\n ? items.find((p: ContentItem) => p.slug === contentSlug)\n : items.find((p: ContentItem) => p.tags?.includes(contentTag));\n setContentPage(match ?? null);\n }\n\n // Documents — only category === \"DOCUMENT\" AND tag matches AND has a fileUrl.\n // Same stale-clear behavior as the content section above.\n if (docsResult.status === \"rejected\") {\n setDocs([]);\n } else if (docsResult.status === \"fulfilled\") {\n const items: PartnerDocument[] =\n docsResult.value.data?.publicPressKitAssets?.items ?? [];\n const filtered = items\n .filter(\n (d: PartnerDocument) =>\n d.category === \"DOCUMENT\" &&\n d.tags?.includes(documentsTag) &&\n !!d.fileUrl,\n )\n .sort(\n (a: PartnerDocument, b: PartnerDocument) =>\n a.sortOrder - b.sortOrder,\n );\n setDocs(filtered);\n }\n\n setLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [client, resolvedProductId, contentSlug, contentTag, documentsTag]);\n\n // Normalise the contact-category options for the dropdown:\n // - `false` → no dropdown (explicitly disabled)\n // - a non-empty array → those partner tracks\n // - a single value → that one option\n // - unset OR `[]` → the default partner category\n // An empty array is treated as \"use the default\", not \"disable\" — so an\n // accidental `contactCategory={[]}` doesn't silently drop the dropdown; pass\n // `false` to disable it intentionally.\n let partnerCategories: ContactCategory[];\n if (contactCategory === false) {\n partnerCategories = [];\n } else if (Array.isArray(contactCategory)) {\n partnerCategories =\n contactCategory.length > 0 ? contactCategory : [DEFAULT_PARTNER_CATEGORY];\n } else {\n partnerCategories = [contactCategory ?? DEFAULT_PARTNER_CATEGORY];\n }\n\n return (\n <div className={className}>\n <PageHead\n title={seoTitle ?? `${heroTitle} — ${resolvedProductName}`}\n description={\n seoDescription ??\n heroSubtitle ??\n `Join the ${resolvedProductName} partner programme.`\n }\n keywords={seoKeywords}\n />\n\n <PartnerHero title={heroTitle} subtitle={heroSubtitle} />\n\n {!loading && contentPage && <PartnerContentSection page={contentPage} />}\n\n {!loading && docs.length > 0 && (\n <PartnerDocumentsSection\n title={documentsTitle}\n subtitle={documentsSubtitle}\n docs={docs}\n />\n )}\n\n {showContactForm && (\n <ContactPage\n productName={resolvedProductName}\n heroTitle={formTitle}\n // Embedded inside PartnersPage, which already owns the page <h1>.\n // Render the form's \"Become a partner\" as an <h2> section header so\n // there's a single <h1> per page and no competing full-size hero.\n headingLevel={2}\n heroDescription={\n formSubtitle ??\n `Tell us about your organisation and a partner manager from ${resolvedProductName} will be in touch.`\n }\n contactEmail={contactEmail}\n contactPhone={contactPhone}\n officeAddress={officeAddress}\n responseTime={responseTime}\n recaptchaSiteKey={recaptchaSiteKey}\n additionalOptions={additionalOptions}\n // Partnership-type dropdown: one or more partner tracks so every\n // submission is tagged for the partner-program lane. Skipped when the\n // consumer passes `false`.\n categories={partnerCategories}\n categoryLabel=\"Partnership type\"\n categoryRequired={partnerCategories.length > 0}\n />\n )}\n </div>\n );\n}\n"]}