@riverbankcms/sdk 0.139.0 → 0.140.0

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 (196) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-BDeenhi3.mjs → PreviewEditorSidebar-CUyTzd5z.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DSRhgjF5.mjs → PreviewEditorUI-Agkw4v5i.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-D2K8GLUG.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CL7wSnYu.mjs → SdkPreviewModeRuntime-DdbeAdS8.mjs} +22 -8
  6. package/dist/{SiteChromeCustomizeContext-BhDn-5ir.mjs → SiteChromeCustomizeContext-CqGOz-Kv.mjs} +2053 -1110
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +165 -165
  8. package/dist/_dts/ai/src/contracts/siteStyleProposalSchemas.d.ts +212 -212
  9. package/dist/_dts/api/src/accessAdmin.d.ts +74 -104
  10. package/dist/_dts/api/src/aiEndpoints.d.ts +5 -1
  11. package/dist/_dts/api/src/authSubmission.d.ts +46 -0
  12. package/dist/_dts/api/src/billing.d.ts +8 -4
  13. package/dist/_dts/api/src/billingEndpointDefinitions.d.ts +23 -0
  14. package/dist/_dts/api/src/billingEndpointTypes.d.ts +26 -0
  15. package/dist/_dts/api/src/blocks.d.ts +2 -0
  16. package/dist/_dts/api/src/bookingRecords.d.ts +1 -2
  17. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +8 -1
  18. package/dist/_dts/api/src/communications.d.ts +0 -1
  19. package/dist/_dts/api/src/contentRuntime.d.ts +8 -3
  20. package/dist/_dts/api/src/endpoints.d.ts +93 -64
  21. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  22. package/dist/_dts/api/src/footerSettings.d.ts +9 -6
  23. package/dist/_dts/api/src/index.d.ts +5 -6
  24. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  25. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  26. package/dist/_dts/api/src/mailingListIntegration.d.ts +8 -2
  27. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  28. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  29. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  30. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +32 -32
  31. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +8 -0
  32. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  33. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  34. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +3 -29
  35. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  36. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  37. package/dist/_dts/api/src/sdkContracts.d.ts +3 -22
  38. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  39. package/dist/_dts/api/src/sdkThemeWire.d.ts +44 -44
  40. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  41. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +9 -5
  42. package/dist/_dts/api/src/siteOnboarding.d.ts +2 -9
  43. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +2 -4
  44. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  45. package/dist/_dts/api/src/siteSettings.d.ts +20 -7
  46. package/dist/_dts/api/src/types.d.ts +77 -77
  47. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  48. package/dist/_dts/billing/src/membership/index.d.ts +3 -0
  49. package/dist/_dts/billing/src/plans/types.d.ts +3 -0
  50. package/dist/_dts/billing/src/site-arrangements.d.ts +14 -3
  51. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +16 -4
  52. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  53. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +5 -0
  54. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  55. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  56. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  57. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  58. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  59. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -2
  60. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +2 -1
  61. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  62. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  63. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  64. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  65. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  66. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  67. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  68. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +30 -6
  69. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +15 -3
  70. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +43 -0
  71. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  72. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  73. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  74. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  75. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  76. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  77. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  78. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +10 -2
  79. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  80. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  81. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -6
  82. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  83. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +6 -0
  84. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +1 -0
  85. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  86. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  87. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  88. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  89. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  90. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +27 -4
  91. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  92. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  93. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +3 -0
  94. package/dist/_dts/core/src/branded.d.ts +0 -8
  95. package/dist/_dts/core/src/index.d.ts +1 -0
  96. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +1 -1
  97. package/dist/_dts/core/src/mailing-list-setup.d.ts +14 -1
  98. package/dist/_dts/core/src/mailing-list-submission.d.ts +7 -27
  99. package/dist/_dts/core/src/participants.d.ts +2 -29
  100. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  101. package/dist/_dts/core/src/public-profile.d.ts +27 -1
  102. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  103. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +293 -606
  104. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  105. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +3 -2
  106. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +3 -2
  107. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +3 -2
  108. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  109. package/dist/_dts/sdk/src/public-api/contracts.d.ts +14 -20
  110. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  111. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -0
  112. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +7 -1
  113. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  114. package/dist/_dts/sdk/src/version.d.ts +1 -1
  115. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  116. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  117. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  118. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  119. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  120. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  121. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  122. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  123. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  124. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  125. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  126. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  127. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  128. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  129. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  130. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  131. package/dist/client/{BookingConsentAgreement-CZvTDtsK.mjs → BookingConsentAgreement-CuKa82V4.mjs} +4 -4
  132. package/dist/client/{DiscountCodeDisclosure-D-DsLCMU.mjs → DiscountCodeDisclosure-BbYieKWB.mjs} +1 -1
  133. package/dist/client/{EventCombined.client-dWqgd5ZO.mjs → EventCombined.client-LTfR1Aby.mjs} +6 -6
  134. package/dist/client/{EventListing.client-BMRa9IYp.mjs → EventListing.client-DUHpYSuo.mjs} +2 -2
  135. package/dist/client/{LeafletStaticMap-D21W9kBZ.mjs → LeafletStaticMap-CHRupL6m.mjs} +1 -1
  136. package/dist/client/{accordion-FxF_ta47.mjs → accordion-6HiIFxNL.mjs} +1 -1
  137. package/dist/client/{bookingForm-YnwW4TGw.mjs → bookingForm-Dlmid43H.mjs} +7 -7
  138. package/dist/client/bookings.mjs +325 -140
  139. package/dist/client/{carousel-vng7fFT5.mjs → carousel-DmkZRRq_.mjs} +2 -2
  140. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  141. package/dist/client/{cart-DEPDsjNk.mjs → cart-CIC24330.mjs} +3 -3
  142. package/dist/client/{checkout-CZRWu9rW.mjs → checkout-D1Zw9imo.mjs} +3 -3
  143. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  144. package/dist/client/client.mjs +1717 -882
  145. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  146. package/dist/client/{context-DvU_WUmd.mjs → context-Cy1OayHx.mjs} +6 -19
  147. package/dist/client/{dates-wnPMiRl5.mjs → dates-aDcfoLHr.mjs} +2 -2
  148. package/dist/client/{eventCalendar-BA3Q5L15.mjs → eventCalendar-FQxMPAjf.mjs} +8 -8
  149. package/dist/client/{eventCombined-51wgR-1R.mjs → eventCombined-Dr3ac6Hb.mjs} +3 -3
  150. package/dist/client/{eventDetails-modaetpm.mjs → eventDetails-D-AzUHFQ.mjs} +4 -4
  151. package/dist/client/{eventListing-D8t2J3Kv.mjs → eventListing-B3XxBf3i.mjs} +3 -3
  152. package/dist/client/{eventRegistration-CYqtkCE_.mjs → eventRegistration-I6EaokFD.mjs} +500 -152
  153. package/dist/client/{form-CBKXN5In.mjs → form-BbWckVWY.mjs} +3 -3
  154. package/dist/client/{headerSection-DylDqNrs.mjs → headerSection-C9qU4Y7x.mjs} +2 -2
  155. package/dist/client/hooks.mjs +445 -180
  156. package/dist/client/{locationMap-CvWrG0vZ.mjs → locationMap-CLCShvlG.mjs} +3 -3
  157. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  158. package/dist/client/{newsletterForm-Btwk70zw.mjs → newsletterForm-Briukxzi.mjs} +130 -87
  159. package/dist/client/{pricing-Uzw-GQ6Y.mjs → pricing-Copadu-2.mjs} +1 -1
  160. package/dist/client/{productDetail-JLcUYKnd.mjs → productDetail-oujlRd-r.mjs} +3 -3
  161. package/dist/client/{productList-FM0cbUzj.mjs → productList-BRiIRUcd.mjs} +3 -3
  162. package/dist/client/{propsDecoder-DYzafZb2.mjs → propsDecoder-CB2KS_ko.mjs} +130 -24
  163. package/dist/client/rendering/client.mjs +911 -400
  164. package/dist/client/rendering/islands.mjs +19 -19
  165. package/dist/client/rendering.mjs +1696 -818
  166. package/dist/client/{scrollToBlock-CvXszexS.mjs → scrollToBlock-B1IS1_ua.mjs} +1 -1
  167. package/dist/client/{shop-BIcjvy5a.mjs → shop-Vn6yNFED.mjs} +6 -6
  168. package/dist/client/{shop-commerce-BZQsy7xw.mjs → shop-commerce-BVTqipYp.mjs} +7 -7
  169. package/dist/client/{shop-commerce-store-D5V7XAb5.mjs → shop-commerce-store-BVnJVy7v.mjs} +1 -1
  170. package/dist/client/{shopShared-DowkXevB.mjs → shopShared-COIeK77T.mjs} +4 -4
  171. package/dist/client/{useEventFilters-oMoTw_JE.mjs → useEventFilters-DzIUcS9n.mjs} +7 -7
  172. package/dist/preview-next/before-render.mjs +119 -64
  173. package/dist/preview-next/client/runtime.mjs +4 -4
  174. package/dist/preview-next/keepAlive.mjs +119 -64
  175. package/dist/preview-next/middleware.mjs +119 -64
  176. package/dist/{previewAuthStore-COUyAKaX.mjs → previewAuthStore-Gjb6r6vz.mjs} +119 -64
  177. package/dist/{sdk-runtime-D4k2LSGF.mjs → sdk-runtime-CnCLvZRv.mjs} +2 -2
  178. package/dist/{separator-UGtpag4Z.mjs → separator-DKDRJ1oH.mjs} +1 -1
  179. package/dist/server/components.mjs +787 -323
  180. package/dist/server/config-validation.mjs +328 -79
  181. package/dist/server/config.mjs +332 -83
  182. package/dist/server/data.mjs +441 -180
  183. package/dist/server/index.mjs +126 -66
  184. package/dist/server/next.mjs +1031 -595
  185. package/dist/server/page-converter.mjs +183 -74
  186. package/dist/server/prebuild.mjs +1 -1
  187. package/dist/server/rendering/server.mjs +1068 -592
  188. package/dist/server/rendering.mjs +802 -324
  189. package/dist/server/routing.mjs +506 -214
  190. package/dist/server/server.mjs +468 -244
  191. package/dist/server/theme-bridge.mjs +433 -100
  192. package/dist/server/theme.mjs +8 -2
  193. package/dist/styles/index.css +237 -43
  194. package/package.json +1 -1
  195. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  196. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
@@ -563,7 +563,7 @@ function parseUuidBrand(value, unsafeConstructor) {
563
563
  if (!UUID_PATTERN$2.test(normalized)) return err$2({ kind: "invalid_uuid" });
564
564
  return ok$2(unsafeConstructor(normalized));
565
565
  }
566
- var UUID_PATTERN$2, unsafeAsSiteId, unsafeAsApiKeyId, unsafeAsEventOfferingId, unsafeAsEventSeriesId, unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsUserId, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId, parseSiteId, parseApiKeyId, parseEventOfferingId, parseUserId, parseEventSeriesId;
566
+ var UUID_PATTERN$2, unsafeAsSiteId, unsafeAsApiKeyId, unsafeAsEventOfferingId, unsafeAsEventSeriesId, unsafeAsMediaAssetId, unsafeAsStorageBucketName, unsafeAsStoragePath, unsafeAsPositiveByteCount, unsafeAsPositiveSeconds, unsafeAsUserId, unsafeAsFormId, unsafeAsPassId, unsafeAsCustomerPassId, unsafeAsAppointmentServiceId, unsafeAsAppointmentResourceId, unsafeAsContentVersionId, parseSiteId, parseApiKeyId, parseEventOfferingId, parseUserId, parseContentVersionId, parseEventSeriesId;
567
567
  var init_branded = __esmMin((() => {
568
568
  init_result$1();
569
569
  UUID_PATTERN$2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -582,10 +582,12 @@ var init_branded = __esmMin((() => {
582
582
  unsafeAsCustomerPassId = (id) => id;
583
583
  unsafeAsAppointmentServiceId = (id) => id;
584
584
  unsafeAsAppointmentResourceId = (id) => id;
585
+ unsafeAsContentVersionId = (id) => id;
585
586
  parseSiteId = (value) => parseUuidBrand(value, unsafeAsSiteId);
586
587
  parseApiKeyId = (value) => parseUuidBrand(value, unsafeAsApiKeyId);
587
588
  parseEventOfferingId = (value) => parseUuidBrand(value, unsafeAsEventOfferingId);
588
589
  parseUserId = (value) => parseUuidBrand(value, unsafeAsUserId);
590
+ parseContentVersionId = (value) => parseUuidBrand(value, unsafeAsContentVersionId);
589
591
  parseEventSeriesId = (value) => parseUuidBrand(value, unsafeAsEventSeriesId);
590
592
  }));
591
593
  //#endregion
@@ -938,7 +940,7 @@ function parseEventPageSurfaceDestinationMode(value) {
938
940
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
939
941
  }
940
942
  function parseEventPageSurfaceSubject(value) {
941
- if (!isRecord$39(value)) return err$2({ kind: "notObject" });
943
+ if (!isRecord$40(value)) return err$2({ kind: "notObject" });
942
944
  switch (value.kind) {
943
945
  case "eventSeries": {
944
946
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -993,7 +995,7 @@ function parseEventSeriesIdList(values) {
993
995
  }
994
996
  return ok$2(parsed);
995
997
  }
996
- function isRecord$39(value) {
998
+ function isRecord$40(value) {
997
999
  return typeof value === "object" && value !== null && !Array.isArray(value);
998
1000
  }
999
1001
  var init_event_page_surface_subject = __esmMin((() => {
@@ -1485,7 +1487,6 @@ var init_assertNever$1 = __esmMin((() => {
1485
1487
  init_assert_never();
1486
1488
  }));
1487
1489
  var init_participants = __esmMin((() => {
1488
- init_branded();
1489
1490
  init_result$1();
1490
1491
  init_string();
1491
1492
  }));
@@ -1497,9 +1498,10 @@ var init_public_profile = __esmMin((() => {
1497
1498
  init_public_url_validation();
1498
1499
  init_result$1();
1499
1500
  }));
1501
+ var init_public_experience = __esmMin((() => {}));
1500
1502
  //#endregion
1501
1503
  //#region ../core/src/rich-text.ts
1502
- function isRecord$37(value) {
1504
+ function isRecord$38(value) {
1503
1505
  return typeof value === "object" && value !== null && !Array.isArray(value);
1504
1506
  }
1505
1507
  function hasOnlyKeys(value, allowed) {
@@ -1510,10 +1512,10 @@ function isDenseArrayOf(value, predicate) {
1510
1512
  return true;
1511
1513
  }
1512
1514
  function isTipTapMark(value) {
1513
- return isRecord$37(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$37(value.attrs));
1515
+ return isRecord$38(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$38(value.attrs));
1514
1516
  }
1515
1517
  function isTipTapNode(value) {
1516
- if (!isRecord$37(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$37(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1518
+ if (!isRecord$38(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$38(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
1517
1519
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1518
1520
  return value.text === void 0;
1519
1521
  }
@@ -1541,12 +1543,18 @@ function parsePositiveInteger(value) {
1541
1543
  function parseNewsletterListId(value) {
1542
1544
  return parseTrimmedMatchingString(value, UUID_PATTERN$1);
1543
1545
  }
1546
+ function parseMailchimpAccountId(value) {
1547
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1548
+ }
1544
1549
  function parseMailchimpAudienceId$1(value) {
1545
1550
  return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1546
1551
  }
1547
1552
  function parseMailchimpInterestId(value) {
1548
1553
  return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1549
1554
  }
1555
+ function parseBrevoAccountId(value) {
1556
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1557
+ }
1550
1558
  function parseBrevoListId(value) {
1551
1559
  return parsePositiveInteger(value);
1552
1560
  }
@@ -1558,10 +1566,10 @@ var init_mailing_list_identifiers = __esmMin((() => {
1558
1566
  //#endregion
1559
1567
  //#region ../core/src/mailing-list-targeting-parser.ts
1560
1568
  function parseMailingListPlacementTargeting(value) {
1561
- if (!isRecord$36(value)) return targetingError("shape");
1569
+ if (!isRecord$37(value)) return targetingError("shape");
1562
1570
  if (value.mode === "default") return ok$2({ mode: "default" });
1563
1571
  if (value.mode !== "custom") return targetingError("mode");
1564
- if (!isRecord$36(value.selection)) return targetingError("selection");
1572
+ if (!isRecord$37(value.selection)) return targetingError("selection");
1565
1573
  switch (value.provider) {
1566
1574
  case "native": return parseNativeTargeting(value.selection);
1567
1575
  case "brevo": return parseBrevoTargeting(value.selection);
@@ -1570,7 +1578,7 @@ function parseMailingListPlacementTargeting(value) {
1570
1578
  }
1571
1579
  }
1572
1580
  function parseMailingListVisitorSelection(value) {
1573
- if (!isRecord$36(value)) return visitorSelectionError("shape");
1581
+ if (!isRecord$37(value)) return visitorSelectionError("shape");
1574
1582
  switch (value.provider) {
1575
1583
  case "native": {
1576
1584
  const topicIds = parseVisitorIds(value.topicIds, parseNewsletterListId);
@@ -1703,7 +1711,7 @@ function parseVisitorIds(value, parseId) {
1703
1711
  }
1704
1712
  return parsed;
1705
1713
  }
1706
- function isRecord$36(value) {
1714
+ function isRecord$37(value) {
1707
1715
  return typeof value === "object" && value !== null && !Array.isArray(value);
1708
1716
  }
1709
1717
  function targetingError(field) {
@@ -1752,7 +1760,36 @@ var init_footer_navigation_layout = __esmMin((() => {}));
1752
1760
  //#endregion
1753
1761
  //#region ../core/src/footer-composition-types.ts
1754
1762
  var init_footer_composition_types = __esmMin((() => {}));
1755
- var init_mailing_list_setup = __esmMin((() => {}));
1763
+ //#endregion
1764
+ //#region ../core/src/mailing-list-setup.ts
1765
+ function isRecord$34(value) {
1766
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1767
+ }
1768
+ function parseMailingListProviderScope(value) {
1769
+ if (!isRecord$34(value)) return err$2("invalid_mailing_list_provider_scope");
1770
+ if (value.provider === "native") return ok$2({ provider: "native" });
1771
+ if (value.provider === "brevo") {
1772
+ const accountId = parseBrevoAccountId(value.accountId);
1773
+ return accountId !== null ? ok$2({
1774
+ provider: "brevo",
1775
+ accountId
1776
+ }) : err$2("invalid_mailing_list_provider_scope");
1777
+ }
1778
+ if (value.provider === "mailchimp") {
1779
+ const accountId = parseMailchimpAccountId(value.accountId);
1780
+ return accountId !== null ? ok$2({
1781
+ provider: "mailchimp",
1782
+ accountId
1783
+ }) : err$2("invalid_mailing_list_provider_scope");
1784
+ }
1785
+ return err$2("invalid_mailing_list_provider_scope");
1786
+ }
1787
+ var DEFAULT_MAILING_LIST_SUCCESS_MESSAGE;
1788
+ var init_mailing_list_setup = __esmMin((() => {
1789
+ init_mailing_list_identifiers();
1790
+ init_result$1();
1791
+ DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
1792
+ }));
1756
1793
  //#endregion
1757
1794
  //#region ../core/src/mailing-list-setup-parser.ts
1758
1795
  function parseMailingListGlobalForm(value) {
@@ -1762,12 +1799,15 @@ function parseMailingListGlobalForm(value) {
1762
1799
  if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
1763
1800
  const buttonLabel = parseRequiredString(value.buttonLabel);
1764
1801
  if (buttonLabel === null) return formError("buttonLabel");
1802
+ const successMessage = parseRequiredString(value.successMessage);
1803
+ if (successMessage === null) return formError("successMessage");
1765
1804
  const privacyNote = parseOptionalString(value.privacyNote);
1766
1805
  if (privacyNote === void 0) return formError("privacyNote");
1767
1806
  return ok$2({
1768
1807
  fields,
1769
1808
  includeOptionalPhone: value.includeOptionalPhone,
1770
1809
  buttonLabel,
1810
+ successMessage,
1771
1811
  privacyNote
1772
1812
  });
1773
1813
  }
@@ -1989,11 +2029,17 @@ function parseMailingListSignedSourceToken(value) {
1989
2029
  const parsed = typeof value === "string" ? value.trim() : "";
1990
2030
  return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
1991
2031
  }
1992
- function buildMailingListSignupBlockSourceRef(blockId) {
1993
- const parsed = parseMailingListBlockId(blockId);
1994
- return parsed !== null ? {
2032
+ function parseMailingListContentVersionId(value) {
2033
+ const parsed = parseContentVersionId(value);
2034
+ return parsed.ok ? parsed.value : null;
2035
+ }
2036
+ function buildMailingListSignupBlockSourceRef(blockId, contentVersionId) {
2037
+ const parsedBlockId = parseMailingListBlockId(blockId);
2038
+ const parsedContentVersionId = parseMailingListContentVersionId(contentVersionId);
2039
+ return parsedBlockId !== null && parsedContentVersionId !== null ? {
1995
2040
  tag: "block_ref",
1996
- blockId: parsed
2041
+ blockId: parsedBlockId,
2042
+ contentVersionId: parsedContentVersionId
1997
2043
  } : null;
1998
2044
  }
1999
2045
  var init_mailing_list_submission = __esmMin((() => {
@@ -2567,6 +2613,7 @@ var init_src$2 = __esmMin((() => {
2567
2613
  init_participant_identity();
2568
2614
  init_public_url_validation();
2569
2615
  init_public_profile();
2616
+ init_public_experience();
2570
2617
  init_rich_text();
2571
2618
  init_footer_composition();
2572
2619
  init_footer_navigation_layout();
@@ -5639,9 +5686,490 @@ var init_classNames = __esmMin((() => {
5639
5686
  init_types$14();
5640
5687
  }));
5641
5688
  //#endregion
5689
+ //#region ../theme-core/src/tokens/tokens.ts
5690
+ /**
5691
+ * Project the expanded semantic palette into the token buckets consumed by
5692
+ * runtime transforms. Keep this mapping shared by full themes and the
5693
+ * tokens-only hosted-booking runtime so the two paths cannot drift.
5694
+ */
5695
+ function buildThemeTokens(palette) {
5696
+ const tokens = cloneThemeTokens(defaultThemeTokens);
5697
+ const paletteStrings = {};
5698
+ for (const [key, value] of Object.entries(palette)) if (typeof value === "string" && value.trim().length > 0) paletteStrings[key] = value;
5699
+ tokens.palette = paletteStrings;
5700
+ const resolveColor = (...keys) => {
5701
+ for (const key of keys) {
5702
+ const value = paletteStrings[key];
5703
+ if (value) return value;
5704
+ }
5705
+ };
5706
+ const assignColor = (token, ...keys) => {
5707
+ const value = resolveColor(...keys);
5708
+ if (value) tokens.color[token] = value;
5709
+ };
5710
+ assignColor("background/base", "background", "surface", "primary-50");
5711
+ assignColor("background/elevated", "surface", "background");
5712
+ assignColor("surface/base", "surface", "background");
5713
+ assignColor("surface/subtle", "neutral-100", "surface", "background");
5714
+ assignColor("surface/inverted", "neutral-900", "text", "primary-900");
5715
+ assignColor("content/primary", "text", "body", "neutral-900");
5716
+ assignColor("content/secondary", "mutedText", "secondary", "neutral-600");
5717
+ assignColor("accent/primary", "primary", "accent");
5718
+ assignColor("accent/secondary", "accent", "secondary", "primary-400");
5719
+ assignColor("border/base", "border", "neutral-300");
5720
+ return tokens;
5721
+ }
5722
+ function cloneThemeTokens(source) {
5723
+ return JSON.parse(JSON.stringify(source));
5724
+ }
5725
+ var defaultThemeTokens;
5726
+ var init_tokens$1 = __esmMin((() => {
5727
+ defaultThemeTokens = {
5728
+ color: {
5729
+ "background/base": "#ffffff",
5730
+ "background/elevated": "#f5f5f5",
5731
+ "surface/base": "#ffffff",
5732
+ "surface/subtle": "#f9f9fb",
5733
+ "surface/inverted": "#111111",
5734
+ "content/primary": "#111111",
5735
+ "content/secondary": "#3f3f46",
5736
+ "accent/primary": "#2563eb",
5737
+ "accent/secondary": "#1d4ed8",
5738
+ "border/base": "#e5e7eb"
5739
+ },
5740
+ typography: {
5741
+ "display/hero": {
5742
+ fontSize: "clamp(48px, 8vw, 96px)",
5743
+ lineHeight: "1.05",
5744
+ fontWeight: "700"
5745
+ },
5746
+ "display/section": {
5747
+ fontSize: "clamp(40px, 6vw, 72px)",
5748
+ lineHeight: "1.1",
5749
+ fontWeight: "700"
5750
+ },
5751
+ "heading/large": {
5752
+ fontSize: "clamp(32px, 4vw, 48px)",
5753
+ lineHeight: "1.2",
5754
+ fontWeight: "600"
5755
+ },
5756
+ "heading/medium": {
5757
+ fontSize: "clamp(24px, 3vw, 32px)",
5758
+ lineHeight: "1.25",
5759
+ fontWeight: "600"
5760
+ },
5761
+ "heading/small": {
5762
+ fontSize: "20px",
5763
+ lineHeight: "1.3",
5764
+ fontWeight: "600"
5765
+ },
5766
+ "body/normal": {
5767
+ fontSize: "16px",
5768
+ lineHeight: "1.6",
5769
+ fontWeight: "400"
5770
+ },
5771
+ "body/small": {
5772
+ fontSize: "14px",
5773
+ lineHeight: "1.5",
5774
+ fontWeight: "400"
5775
+ },
5776
+ caption: {
5777
+ fontSize: "12px",
5778
+ lineHeight: "1.4",
5779
+ fontWeight: "500"
5780
+ }
5781
+ },
5782
+ spacing: {
5783
+ none: "0px",
5784
+ "3xs": "4px",
5785
+ "2xs": "8px",
5786
+ xs: "12px",
5787
+ sm: "16px",
5788
+ md: "24px",
5789
+ lg: "32px",
5790
+ xl: "40px",
5791
+ "2xl": "56px",
5792
+ "3xl": "72px"
5793
+ },
5794
+ radius: {
5795
+ none: "0px",
5796
+ xs: "2px",
5797
+ sm: "4px",
5798
+ md: "8px",
5799
+ lg: "12px",
5800
+ pill: "999px",
5801
+ full: "9999px"
5802
+ },
5803
+ shadow: {
5804
+ none: "none",
5805
+ soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
5806
+ medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
5807
+ strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
5808
+ },
5809
+ palette: {
5810
+ surface: "#ffffff",
5811
+ "neutral-50": "#f9fafb",
5812
+ "neutral-900": "#111827",
5813
+ primary: "#2563eb",
5814
+ "primary-50": "#eff6ff",
5815
+ "primary-500": "#2563eb",
5816
+ "primary-900": "#1d4ed8",
5817
+ secondary: "#9333ea",
5818
+ "secondary-50": "#f3e8ff",
5819
+ "secondary-500": "#9333ea",
5820
+ "secondary-900": "#4c1d95",
5821
+ accent: "#f97316",
5822
+ "accent-50": "#fff7ed",
5823
+ "accent-500": "#f97316",
5824
+ "accent-900": "#7c2d12"
5825
+ }
5826
+ };
5827
+ }));
5828
+ //#endregion
5829
+ //#region ../theme-core/src/tokens/index.ts
5830
+ var init_tokens = __esmMin((() => {
5831
+ init_tokens$1();
5832
+ init_blockColorTokens();
5833
+ init_themeColorTokens();
5834
+ init_colorTokenParts();
5835
+ init_resolver$1();
5836
+ }));
5837
+ var init_foregroundInteraction = __esmMin((() => {
5838
+ init_contrast$1();
5839
+ init_colorConversion();
5840
+ init_colorTokenParts();
5841
+ init_tokens();
5842
+ }));
5843
+ //#endregion
5844
+ //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
5845
+ /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
5846
+ function resolveOpaqueSurfaceHex(reference, palette, underlayReference) {
5847
+ const opaque = resolveConcreteColorHex(reference, palette);
5848
+ if (opaque) return opaque;
5849
+ if (!underlayReference) return null;
5850
+ const underlayHex = resolveConcreteColorHex(underlayReference, palette);
5851
+ if (!underlayHex) return null;
5852
+ const parts = parseColorTokenParts(reference);
5853
+ if (parts.kind === "token" && parts.opacityPercent !== null) {
5854
+ const foregroundHex = normalizePaletteHex(palette[parts.token] ?? "");
5855
+ return foregroundHex ? compositeHex(foregroundHex, underlayHex, parts.opacityPercent / 100) : null;
5856
+ }
5857
+ const rgba = parseRgba(parts.kind === "raw" ? parts.value : reference);
5858
+ return rgba ? compositeHex(rgbToHex$1(rgba.r, rgba.g, rgba.b), underlayHex, rgba.alpha) : null;
5859
+ }
5860
+ /** Resolve a colour reference only when it is already fully opaque. */
5861
+ function resolveConcreteColorHex(reference, palette) {
5862
+ const literalHex = normalizePaletteHex(reference);
5863
+ if (literalHex) return literalHex;
5864
+ const parts = parseColorTokenParts(reference);
5865
+ if (parts.kind === "token") {
5866
+ if (parts.opacityPercent !== null) return null;
5867
+ return normalizePaletteHex(palette[parts.token] ?? "");
5868
+ }
5869
+ const literal = parts.kind === "raw" ? parts.value : reference;
5870
+ if (literal.toLowerCase() === "black") return "#000000";
5871
+ if (literal.toLowerCase() === "white") return "#ffffff";
5872
+ return normalizePaletteHex(literal);
5873
+ }
5874
+ function compositeHex(foregroundHex, underlayHex, alpha) {
5875
+ const foreground = hexToRgb$1(foregroundHex);
5876
+ const underlay = hexToRgb$1(underlayHex);
5877
+ const channel = (foregroundValue, underlayValue) => Math.round(foregroundValue * alpha + underlayValue * (1 - alpha));
5878
+ return rgbToHex$1(channel(foreground.r, underlay.r), channel(foreground.g, underlay.g), channel(foreground.b, underlay.b));
5879
+ }
5880
+ function parseRgba(value) {
5881
+ const match = value.trim().match(/^rgba?\(\s*([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*(?:,|\/)\s*([\d.]+%?))?\s*\)$/i);
5882
+ if (!match) return null;
5883
+ const [, rSource, gSource, bSource] = match;
5884
+ if (!rSource || !gSource || !bSource) return null;
5885
+ const r = Number(rSource);
5886
+ const g = Number(gSource);
5887
+ const b = Number(bSource);
5888
+ const alpha = parseAlpha(match[4]);
5889
+ if (alpha === null || !isRgbChannel(r) || !isRgbChannel(g) || !isRgbChannel(b)) return null;
5890
+ return {
5891
+ r,
5892
+ g,
5893
+ b,
5894
+ alpha
5895
+ };
5896
+ }
5897
+ function parseAlpha(source) {
5898
+ if (!source) return 1;
5899
+ const value = source.endsWith("%") ? Number(source.slice(0, -1)) / 100 : Number(source);
5900
+ return Number.isFinite(value) && value >= 0 && value <= 1 ? value : null;
5901
+ }
5902
+ function isRgbChannel(value) {
5903
+ return Number.isFinite(value) && value >= 0 && value <= 255;
5904
+ }
5905
+ var init_opaqueSurfaceColor = __esmMin((() => {
5906
+ init_colors();
5907
+ init_colorTokenParts();
5908
+ init_colorConversion();
5909
+ }));
5910
+ //#endregion
5911
+ //#region ../theme-core/src/surfaces/resolveSurfaceForeground.ts
5912
+ /**
5913
+ * Resolve the complete foreground contract for an effective page/section or
5914
+ * site-chrome background.
5915
+ *
5916
+ * Deterministic colour backgrounds are validated at ordinary-text WCAG AA.
5917
+ * Existing image/video/gradient treatments are trusted only when they already
5918
+ * carry a usable foreground token; this function deliberately does not claim
5919
+ * pixel-level contrast proof for media.
5920
+ */
5921
+ function resolveSurfaceForeground(background, palette, candidates = {}, options = {}) {
5922
+ const authored = foregroundCandidates(background, candidates);
5923
+ if (background === null) return resolveDeterministicForeground("background", {
5924
+ ...authored,
5925
+ text: authored.text ?? "text"
5926
+ }, palette);
5927
+ if (background.type === "color") {
5928
+ const backgroundReference = normalizedReference(background.color);
5929
+ if (!backgroundReference || backgroundReference === "transparent") return { kind: "unknown" };
5930
+ return resolveDeterministicForeground(backgroundReference, authored, palette, options.compositeBase);
5931
+ }
5932
+ return resolveTrustedTreatmentForeground(authored, palette);
5933
+ }
5934
+ function foregroundCandidates(background, overrides) {
5935
+ return {
5936
+ text: overrides.text ?? background?.textColor ?? null,
5937
+ heading: overrides.heading ?? background?.headingColor ?? null,
5938
+ link: overrides.link ?? background?.linkColor ?? null,
5939
+ supporting: overrides.supporting ?? background?.supportingColor ?? null
5940
+ };
5941
+ }
5942
+ function resolveDeterministicForeground(backgroundReference, candidates, palette, compositeBase) {
5943
+ const backgroundHex = resolveOpaqueSurfaceHex(backgroundReference, palette, compositeBase);
5944
+ if (!backgroundHex) return resolveTrustedTreatmentForeground(candidates, palette);
5945
+ const backgroundToken = paletteToken(backgroundReference);
5946
+ const derivedOnToken = backgroundToken ? onColorTokenName(backgroundToken) : null;
5947
+ const text = firstSafeToken([
5948
+ candidates.text,
5949
+ derivedOnToken,
5950
+ ...FALLBACK_TEXT_TOKENS
5951
+ ], backgroundHex, palette, derivedOnToken ? [derivedOnToken] : []);
5952
+ if (!text) return { kind: "unknown" };
5953
+ return {
5954
+ kind: "known",
5955
+ roles: {
5956
+ text,
5957
+ heading: safeTokenOr(candidates.heading, text, backgroundHex, palette),
5958
+ link: safeTokenOr(candidates.link, text, backgroundHex, palette),
5959
+ supporting: safeTokenOr(candidates.supporting, text, backgroundHex, palette)
5960
+ }
5961
+ };
5962
+ }
5963
+ function resolveTrustedTreatmentForeground(candidates, palette) {
5964
+ const text = canonicalToken(candidates.text, palette);
5965
+ if (!text) return { kind: "unknown" };
5966
+ return {
5967
+ kind: "known",
5968
+ roles: {
5969
+ text,
5970
+ heading: canonicalToken(candidates.heading, palette) ?? text,
5971
+ link: canonicalToken(candidates.link, palette) ?? text,
5972
+ supporting: canonicalToken(candidates.supporting, palette) ?? text
5973
+ }
5974
+ };
5975
+ }
5976
+ function safeTokenOr(candidate, fallback, backgroundHex, palette) {
5977
+ return firstSafeToken([candidate], backgroundHex, palette) ?? fallback;
5978
+ }
5979
+ function firstSafeToken(candidates, backgroundHex, palette, preferredEquivalentTokens = []) {
5980
+ const seen = /* @__PURE__ */ new Set();
5981
+ for (const candidate of candidates) {
5982
+ const token = canonicalToken(candidate, palette, preferredEquivalentTokens);
5983
+ if (!token || seen.has(token)) continue;
5984
+ seen.add(token);
5985
+ const foregroundHex = resolveConcreteColorHex(token, palette);
5986
+ if (foregroundHex && contrastRatio(backgroundHex, foregroundHex) >= 4.5) return token;
5987
+ }
5988
+ return null;
5989
+ }
5990
+ function canonicalToken(reference, palette, preferredEquivalentTokens = []) {
5991
+ const normalized = normalizedReference(reference);
5992
+ if (!normalized || normalized === "transparent") return null;
5993
+ const direct = parseThemeColorToken(normalized);
5994
+ if (direct && resolveConcreteColorHex(direct, palette)) return direct;
5995
+ const referenceHex = resolveConcreteColorHex(normalized, palette);
5996
+ if (!referenceHex) return null;
5997
+ const equivalent = [
5998
+ ...preferredEquivalentTokens,
5999
+ ...CANONICAL_EQUIVALENT_TOKEN_ORDER,
6000
+ ...Object.keys(palette).sort()
6001
+ ].find((token) => {
6002
+ const parsed = parseThemeColorToken(token);
6003
+ return parsed !== null && resolveConcreteColorHex(parsed, palette)?.toLowerCase() === referenceHex.toLowerCase();
6004
+ });
6005
+ return equivalent ? parseThemeColorToken(equivalent) : null;
6006
+ }
6007
+ function paletteToken(reference) {
6008
+ const parts = parseColorTokenParts(reference);
6009
+ return parts.kind === "token" && parts.opacityPercent === null ? parts.token : null;
6010
+ }
6011
+ function normalizedReference(value) {
6012
+ if (typeof value !== "string") return null;
6013
+ const normalized = value.trim();
6014
+ return normalized.length > 0 ? normalized : null;
6015
+ }
6016
+ var FALLBACK_TEXT_TOKENS, CANONICAL_EQUIVALENT_TOKEN_ORDER;
6017
+ var init_resolveSurfaceForeground = __esmMin((() => {
6018
+ init_contrast$1();
6019
+ init_onColor();
6020
+ init_opaqueSurfaceColor();
6021
+ init_colorTokenParts();
6022
+ init_themeColorTokens();
6023
+ FALLBACK_TEXT_TOKENS = [
6024
+ "text",
6025
+ "primaryForeground",
6026
+ "secondaryForeground",
6027
+ "accentForeground",
6028
+ "neutral-950",
6029
+ "neutral-50"
6030
+ ];
6031
+ CANONICAL_EQUIVALENT_TOKEN_ORDER = [
6032
+ "text",
6033
+ "primaryForeground",
6034
+ "secondaryForeground",
6035
+ "accentForeground",
6036
+ "onPrimary",
6037
+ "onSecondary",
6038
+ "onAccent",
6039
+ "onSurface",
6040
+ "neutral-950",
6041
+ "neutral-50"
6042
+ ];
6043
+ }));
6044
+ //#endregion
6045
+ //#region ../theme-core/src/surfaces/index.ts
6046
+ var init_surfaces = __esmMin((() => {
6047
+ init_foregroundContract();
6048
+ init_foregroundInteraction();
6049
+ init_foregroundRoles();
6050
+ init_resolveSurfaceForeground();
6051
+ }));
6052
+ //#endregion
6053
+ //#region ../theme-core/src/utils/colorStyles.ts
6054
+ function parseToken(source) {
6055
+ const parts = parseColorTokenParts(source);
6056
+ if (parts.kind === "raw") return {
6057
+ token: source,
6058
+ raw: parts.value
6059
+ };
6060
+ if (parts.kind === "invalid") return { token: source };
6061
+ return {
6062
+ token: parts.token,
6063
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
6064
+ };
6065
+ }
6066
+ function surfaceRoleForTextToken(token) {
6067
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
6068
+ }
6069
+ /**
6070
+ * Converts a theme color token to a CSS rgb value.
6071
+ * This is the primary function for applying theme colors to CSS properties.
6072
+ *
6073
+ * @param token - Theme color token (semantic, with opacity, or raw)
6074
+ * @returns CSS color value (rgb with optional alpha, or raw CSS value)
6075
+ *
6076
+ * @example
6077
+ * rgbColorValue('primary') // => 'rgb(var(--tb-primary))'
6078
+ * rgbColorValue('surface/95') // => 'rgb(var(--tb-surface) / 0.95)'
6079
+ * rgbColorValue('raw:transparent') // => 'transparent'
6080
+ */
6081
+ function rgbColorValue(token) {
6082
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
6083
+ if (raw) return raw;
6084
+ const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
6085
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
6086
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
6087
+ }
6088
+ /**
6089
+ * Converts a theme color token to a CSS variable reference.
6090
+ * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
6091
+ *
6092
+ * @param token - Theme color token
6093
+ * @returns CSS variable reference
6094
+ *
6095
+ * @example
6096
+ * cssVarValue('primary') // => 'var(--tb-primary)'
6097
+ * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
6098
+ */
6099
+ function cssVarValue(token) {
6100
+ const { token: baseToken } = parseToken(token);
6101
+ return `var(${COLOR_VAR_PREFIX}${baseToken})`;
6102
+ }
6103
+ /**
6104
+ * Creates a backgroundColor style object from a theme token.
6105
+ *
6106
+ * @param token - Theme color token
6107
+ * @returns CSSProperties with backgroundColor
6108
+ */
6109
+ function backgroundColorStyle(token) {
6110
+ return { backgroundColor: rgbColorValue(token) };
6111
+ }
6112
+ /**
6113
+ * Creates a text color style object from a theme token.
6114
+ *
6115
+ * @param token - Theme color token
6116
+ * @returns CSSProperties with color
6117
+ */
6118
+ function textColorStyle(token) {
6119
+ const parsed = parseToken(token);
6120
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
6121
+ if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
6122
+ return { color: rgbColorValue(token) };
6123
+ }
6124
+ /**
6125
+ * Creates a border color style object from a theme token.
6126
+ *
6127
+ * @param token - Theme color token
6128
+ * @returns CSSProperties with borderColor
6129
+ */
6130
+ function borderColorStyle(token) {
6131
+ return { borderColor: rgbColorValue(token) };
6132
+ }
6133
+ /**
6134
+ * Merges multiple CSSProperties objects into a single object.
6135
+ * Later styles override earlier ones. Undefined values are filtered out.
6136
+ * Returns undefined if the merged result is empty.
6137
+ *
6138
+ * @param styles - Variable number of CSSProperties objects (can be undefined)
6139
+ * @returns Merged CSSProperties object, or undefined if empty
6140
+ *
6141
+ * @example
6142
+ * mergeStyles(
6143
+ * backgroundColorStyle('surface'),
6144
+ * textColorStyle('text'),
6145
+ * borderColorStyle('border')
6146
+ * )
6147
+ * // => { backgroundColor: '...', color: '...', borderColor: '...' }
6148
+ */
6149
+ function mergeStyles(...styles) {
6150
+ const merged = {};
6151
+ for (const style of styles) {
6152
+ if (!style) continue;
6153
+ Object.assign(merged, style);
6154
+ }
6155
+ return Object.keys(merged).length ? merged : void 0;
6156
+ }
6157
+ var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
6158
+ var init_colorStyles = __esmMin((() => {
6159
+ init_surfaces();
6160
+ init_colorTokenParts();
6161
+ COLOR_VAR_PREFIX = "--tb-";
6162
+ SURFACE_TEXT_ROLE_BY_TOKEN = {
6163
+ text: "text",
6164
+ heading: "heading",
6165
+ mutedText: "supporting"
6166
+ };
6167
+ }));
6168
+ //#endregion
5642
6169
  //#region ../theme-core/src/tokens/resolver.ts
5643
6170
  var TokenResolver;
5644
6171
  var init_resolver$1 = __esmMin((() => {
6172
+ init_colorStyles();
5645
6173
  TokenResolver = class {
5646
6174
  constructor(theme) {
5647
6175
  this.theme = theme;
@@ -5661,7 +6189,7 @@ var init_resolver$1 = __esmMin((() => {
5661
6189
  */
5662
6190
  getColor(token) {
5663
6191
  if (!this.tokenExists(token)) console.warn(`[TokenResolver] Color token "${token}" not found in theme palette. Button may render incorrectly.`);
5664
- return `rgb(var(--tb-${token}))`;
6192
+ return rgbColorValue(token);
5665
6193
  }
5666
6194
  /**
5667
6195
  * Adjust a color token's shade by a given amount
@@ -7193,330 +7721,6 @@ var init_affordanceIcons = __esmMin((() => {
7193
7721
  };
7194
7722
  }));
7195
7723
  //#endregion
7196
- //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
7197
- /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
7198
- function resolveOpaqueSurfaceHex(reference, palette, underlayReference) {
7199
- const opaque = resolveConcreteColorHex(reference, palette);
7200
- if (opaque) return opaque;
7201
- if (!underlayReference) return null;
7202
- const underlayHex = resolveConcreteColorHex(underlayReference, palette);
7203
- if (!underlayHex) return null;
7204
- const parts = parseColorTokenParts(reference);
7205
- if (parts.kind === "token" && parts.opacityPercent !== null) {
7206
- const foregroundHex = normalizePaletteHex(palette[parts.token] ?? "");
7207
- return foregroundHex ? compositeHex(foregroundHex, underlayHex, parts.opacityPercent / 100) : null;
7208
- }
7209
- const rgba = parseRgba(parts.kind === "raw" ? parts.value : reference);
7210
- return rgba ? compositeHex(rgbToHex$1(rgba.r, rgba.g, rgba.b), underlayHex, rgba.alpha) : null;
7211
- }
7212
- /** Resolve a colour reference only when it is already fully opaque. */
7213
- function resolveConcreteColorHex(reference, palette) {
7214
- const literalHex = normalizePaletteHex(reference);
7215
- if (literalHex) return literalHex;
7216
- const parts = parseColorTokenParts(reference);
7217
- if (parts.kind === "token") {
7218
- if (parts.opacityPercent !== null) return null;
7219
- return normalizePaletteHex(palette[parts.token] ?? "");
7220
- }
7221
- const literal = parts.kind === "raw" ? parts.value : reference;
7222
- if (literal.toLowerCase() === "black") return "#000000";
7223
- if (literal.toLowerCase() === "white") return "#ffffff";
7224
- return normalizePaletteHex(literal);
7225
- }
7226
- function compositeHex(foregroundHex, underlayHex, alpha) {
7227
- const foreground = hexToRgb$1(foregroundHex);
7228
- const underlay = hexToRgb$1(underlayHex);
7229
- const channel = (foregroundValue, underlayValue) => Math.round(foregroundValue * alpha + underlayValue * (1 - alpha));
7230
- return rgbToHex$1(channel(foreground.r, underlay.r), channel(foreground.g, underlay.g), channel(foreground.b, underlay.b));
7231
- }
7232
- function parseRgba(value) {
7233
- const match = value.trim().match(/^rgba?\(\s*([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*(?:,|\/)\s*([\d.]+%?))?\s*\)$/i);
7234
- if (!match) return null;
7235
- const [, rSource, gSource, bSource] = match;
7236
- if (!rSource || !gSource || !bSource) return null;
7237
- const r = Number(rSource);
7238
- const g = Number(gSource);
7239
- const b = Number(bSource);
7240
- const alpha = parseAlpha(match[4]);
7241
- if (alpha === null || !isRgbChannel(r) || !isRgbChannel(g) || !isRgbChannel(b)) return null;
7242
- return {
7243
- r,
7244
- g,
7245
- b,
7246
- alpha
7247
- };
7248
- }
7249
- function parseAlpha(source) {
7250
- if (!source) return 1;
7251
- const value = source.endsWith("%") ? Number(source.slice(0, -1)) / 100 : Number(source);
7252
- return Number.isFinite(value) && value >= 0 && value <= 1 ? value : null;
7253
- }
7254
- function isRgbChannel(value) {
7255
- return Number.isFinite(value) && value >= 0 && value <= 255;
7256
- }
7257
- var init_opaqueSurfaceColor = __esmMin((() => {
7258
- init_colors();
7259
- init_colorTokenParts();
7260
- init_colorConversion();
7261
- }));
7262
- //#endregion
7263
- //#region ../theme-core/src/surfaces/resolveSurfaceForeground.ts
7264
- /**
7265
- * Resolve the complete foreground contract for an effective page/section or
7266
- * site-chrome background.
7267
- *
7268
- * Deterministic colour backgrounds are validated at ordinary-text WCAG AA.
7269
- * Existing image/video/gradient treatments are trusted only when they already
7270
- * carry a usable foreground token; this function deliberately does not claim
7271
- * pixel-level contrast proof for media.
7272
- */
7273
- function resolveSurfaceForeground(background, palette, candidates = {}, options = {}) {
7274
- const authored = foregroundCandidates(background, candidates);
7275
- if (background === null) return resolveDeterministicForeground("background", {
7276
- ...authored,
7277
- text: authored.text ?? "text"
7278
- }, palette);
7279
- if (background.type === "color") {
7280
- const backgroundReference = normalizedReference(background.color);
7281
- if (!backgroundReference || backgroundReference === "transparent") return { kind: "unknown" };
7282
- return resolveDeterministicForeground(backgroundReference, authored, palette, options.compositeBase);
7283
- }
7284
- return resolveTrustedTreatmentForeground(authored, palette);
7285
- }
7286
- function foregroundCandidates(background, overrides) {
7287
- return {
7288
- text: overrides.text ?? background?.textColor ?? null,
7289
- heading: overrides.heading ?? background?.headingColor ?? null,
7290
- link: overrides.link ?? background?.linkColor ?? null,
7291
- supporting: overrides.supporting ?? background?.supportingColor ?? null
7292
- };
7293
- }
7294
- function resolveDeterministicForeground(backgroundReference, candidates, palette, compositeBase) {
7295
- const backgroundHex = resolveOpaqueSurfaceHex(backgroundReference, palette, compositeBase);
7296
- if (!backgroundHex) return resolveTrustedTreatmentForeground(candidates, palette);
7297
- const backgroundToken = paletteToken(backgroundReference);
7298
- const derivedOnToken = backgroundToken ? onColorTokenName(backgroundToken) : null;
7299
- const text = firstSafeToken([
7300
- candidates.text,
7301
- derivedOnToken,
7302
- ...FALLBACK_TEXT_TOKENS
7303
- ], backgroundHex, palette, derivedOnToken ? [derivedOnToken] : []);
7304
- if (!text) return { kind: "unknown" };
7305
- return {
7306
- kind: "known",
7307
- roles: {
7308
- text,
7309
- heading: safeTokenOr(candidates.heading, text, backgroundHex, palette),
7310
- link: safeTokenOr(candidates.link, text, backgroundHex, palette),
7311
- supporting: safeTokenOr(candidates.supporting, text, backgroundHex, palette)
7312
- }
7313
- };
7314
- }
7315
- function resolveTrustedTreatmentForeground(candidates, palette) {
7316
- const text = canonicalToken(candidates.text, palette);
7317
- if (!text) return { kind: "unknown" };
7318
- return {
7319
- kind: "known",
7320
- roles: {
7321
- text,
7322
- heading: canonicalToken(candidates.heading, palette) ?? text,
7323
- link: canonicalToken(candidates.link, palette) ?? text,
7324
- supporting: canonicalToken(candidates.supporting, palette) ?? text
7325
- }
7326
- };
7327
- }
7328
- function safeTokenOr(candidate, fallback, backgroundHex, palette) {
7329
- return firstSafeToken([candidate], backgroundHex, palette) ?? fallback;
7330
- }
7331
- function firstSafeToken(candidates, backgroundHex, palette, preferredEquivalentTokens = []) {
7332
- const seen = /* @__PURE__ */ new Set();
7333
- for (const candidate of candidates) {
7334
- const token = canonicalToken(candidate, palette, preferredEquivalentTokens);
7335
- if (!token || seen.has(token)) continue;
7336
- seen.add(token);
7337
- const foregroundHex = resolveConcreteColorHex(token, palette);
7338
- if (foregroundHex && contrastRatio(backgroundHex, foregroundHex) >= 4.5) return token;
7339
- }
7340
- return null;
7341
- }
7342
- function canonicalToken(reference, palette, preferredEquivalentTokens = []) {
7343
- const normalized = normalizedReference(reference);
7344
- if (!normalized || normalized === "transparent") return null;
7345
- const direct = parseThemeColorToken(normalized);
7346
- if (direct && resolveConcreteColorHex(direct, palette)) return direct;
7347
- const referenceHex = resolveConcreteColorHex(normalized, palette);
7348
- if (!referenceHex) return null;
7349
- const equivalent = [
7350
- ...preferredEquivalentTokens,
7351
- ...CANONICAL_EQUIVALENT_TOKEN_ORDER,
7352
- ...Object.keys(palette).sort()
7353
- ].find((token) => {
7354
- const parsed = parseThemeColorToken(token);
7355
- return parsed !== null && resolveConcreteColorHex(parsed, palette)?.toLowerCase() === referenceHex.toLowerCase();
7356
- });
7357
- return equivalent ? parseThemeColorToken(equivalent) : null;
7358
- }
7359
- function paletteToken(reference) {
7360
- const parts = parseColorTokenParts(reference);
7361
- return parts.kind === "token" && parts.opacityPercent === null ? parts.token : null;
7362
- }
7363
- function normalizedReference(value) {
7364
- if (typeof value !== "string") return null;
7365
- const normalized = value.trim();
7366
- return normalized.length > 0 ? normalized : null;
7367
- }
7368
- var FALLBACK_TEXT_TOKENS, CANONICAL_EQUIVALENT_TOKEN_ORDER;
7369
- var init_resolveSurfaceForeground = __esmMin((() => {
7370
- init_contrast$1();
7371
- init_onColor();
7372
- init_opaqueSurfaceColor();
7373
- init_colorTokenParts();
7374
- init_themeColorTokens();
7375
- FALLBACK_TEXT_TOKENS = [
7376
- "text",
7377
- "primaryForeground",
7378
- "secondaryForeground",
7379
- "accentForeground",
7380
- "neutral-950",
7381
- "neutral-50"
7382
- ];
7383
- CANONICAL_EQUIVALENT_TOKEN_ORDER = [
7384
- "text",
7385
- "primaryForeground",
7386
- "secondaryForeground",
7387
- "accentForeground",
7388
- "onPrimary",
7389
- "onSecondary",
7390
- "onAccent",
7391
- "onSurface",
7392
- "neutral-950",
7393
- "neutral-50"
7394
- ];
7395
- }));
7396
- //#endregion
7397
- //#region ../theme-core/src/surfaces/index.ts
7398
- var init_surfaces = __esmMin((() => {
7399
- init_foregroundContract();
7400
- init_foregroundRoles();
7401
- init_resolveSurfaceForeground();
7402
- }));
7403
- //#endregion
7404
- //#region ../theme-core/src/utils/colorStyles.ts
7405
- function parseToken(source) {
7406
- const parts = parseColorTokenParts(source);
7407
- if (parts.kind === "raw") return {
7408
- token: source,
7409
- raw: parts.value
7410
- };
7411
- if (parts.kind === "invalid") return { token: source };
7412
- return {
7413
- token: parts.token,
7414
- opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
7415
- };
7416
- }
7417
- function surfaceRoleForTextToken(token) {
7418
- return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
7419
- }
7420
- /**
7421
- * Converts a theme color token to a CSS rgb value.
7422
- * This is the primary function for applying theme colors to CSS properties.
7423
- *
7424
- * @param token - Theme color token (semantic, with opacity, or raw)
7425
- * @returns CSS color value (rgb with optional alpha, or raw CSS value)
7426
- *
7427
- * @example
7428
- * rgbColorValue('primary') // => 'rgb(var(--tb-primary))'
7429
- * rgbColorValue('surface/95') // => 'rgb(var(--tb-surface) / 0.95)'
7430
- * rgbColorValue('raw:transparent') // => 'transparent'
7431
- */
7432
- function rgbColorValue(token) {
7433
- const { token: baseToken, opacityPercent, raw } = parseToken(token);
7434
- if (raw) return raw;
7435
- const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
7436
- if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
7437
- return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
7438
- }
7439
- /**
7440
- * Converts a theme color token to a CSS variable reference.
7441
- * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
7442
- *
7443
- * @param token - Theme color token
7444
- * @returns CSS variable reference
7445
- *
7446
- * @example
7447
- * cssVarValue('primary') // => 'var(--tb-primary)'
7448
- * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
7449
- */
7450
- function cssVarValue(token) {
7451
- const { token: baseToken } = parseToken(token);
7452
- return `var(${COLOR_VAR_PREFIX}${baseToken})`;
7453
- }
7454
- /**
7455
- * Creates a backgroundColor style object from a theme token.
7456
- *
7457
- * @param token - Theme color token
7458
- * @returns CSSProperties with backgroundColor
7459
- */
7460
- function backgroundColorStyle(token) {
7461
- return { backgroundColor: rgbColorValue(token) };
7462
- }
7463
- /**
7464
- * Creates a text color style object from a theme token.
7465
- *
7466
- * @param token - Theme color token
7467
- * @returns CSSProperties with color
7468
- */
7469
- function textColorStyle(token) {
7470
- const parsed = parseToken(token);
7471
- const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
7472
- if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
7473
- return { color: rgbColorValue(token) };
7474
- }
7475
- /**
7476
- * Creates a border color style object from a theme token.
7477
- *
7478
- * @param token - Theme color token
7479
- * @returns CSSProperties with borderColor
7480
- */
7481
- function borderColorStyle(token) {
7482
- return { borderColor: rgbColorValue(token) };
7483
- }
7484
- /**
7485
- * Merges multiple CSSProperties objects into a single object.
7486
- * Later styles override earlier ones. Undefined values are filtered out.
7487
- * Returns undefined if the merged result is empty.
7488
- *
7489
- * @param styles - Variable number of CSSProperties objects (can be undefined)
7490
- * @returns Merged CSSProperties object, or undefined if empty
7491
- *
7492
- * @example
7493
- * mergeStyles(
7494
- * backgroundColorStyle('surface'),
7495
- * textColorStyle('text'),
7496
- * borderColorStyle('border')
7497
- * )
7498
- * // => { backgroundColor: '...', color: '...', borderColor: '...' }
7499
- */
7500
- function mergeStyles(...styles) {
7501
- const merged = {};
7502
- for (const style of styles) {
7503
- if (!style) continue;
7504
- Object.assign(merged, style);
7505
- }
7506
- return Object.keys(merged).length ? merged : void 0;
7507
- }
7508
- var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
7509
- var init_colorStyles = __esmMin((() => {
7510
- init_surfaces();
7511
- init_colorTokenParts();
7512
- COLOR_VAR_PREFIX = "--tb-";
7513
- SURFACE_TEXT_ROLE_BY_TOKEN = {
7514
- text: "text",
7515
- heading: "heading",
7516
- mutedText: "supporting"
7517
- };
7518
- }));
7519
- //#endregion
7520
7724
  //#region ../theme-core/src/utils/tokenOrColor.ts
7521
7725
  function isCssColorLiteral(value) {
7522
7726
  const trimmed = value.trim();
@@ -13124,15 +13328,34 @@ var init_bookingConsent = __esmMin((() => {
13124
13328
  checkboxLabel: z$1.string().min(1)
13125
13329
  });
13126
13330
  bookingConsentCarrierSchema = z$1.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
13127
- }));
13128
- //#endregion
13129
- //#region ../blocks/src/system/blocks/events/shared/schemas.ts
13130
- var eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
13331
+ })), publicEventLoaderQuerySchemaShape, eventPresetSchema, eventScheduleScopeSchema$2, publicEventRecurrenceSchema, eventDestinationModeSchema, publicEventDestinationSchema, eventVenueSchema, eventCategorySchema, accessRestrictionSchema, publicCurrencySchema, publicCentsSchema, publicPositiveCentsSchema, publicIsoDateTimeSchema, publicEventAttendanceModeSchema, publicEventAttendanceModeAvailabilitySchema, publicEventPricingOptionAvailabilitySchema, publicEventPricingOptionSchema, publicEventPricingSchema, publicTeamMemberSummarySchema, publicEventBookingAvailabilitySchema, publicRunSessionSchema, publicWholeSeriesRunSchema, publicEventBaseSchema, publicEventSchema, publicEventsArraySchema;
13131
13332
  var init_schemas = __esmMin((() => {
13132
13333
  init_media$1();
13133
13334
  init_richTextSchema();
13134
13335
  init_bookingPaymentTerms();
13135
13336
  init_bookingConsent();
13337
+ publicEventLoaderQuerySchemaShape = {
13338
+ limit: z$1.string().optional(),
13339
+ from: z$1.string().optional(),
13340
+ to: z$1.string().optional(),
13341
+ afterStartsAt: z$1.string().optional(),
13342
+ afterId: z$1.string().optional(),
13343
+ categoryIds: z$1.string().optional(),
13344
+ venueId: z$1.string().optional(),
13345
+ staffMemberId: z$1.string().optional(),
13346
+ eventSurface: z$1.string().optional(),
13347
+ eventPresets: z$1.string().optional(),
13348
+ scheduleScope: z$1.string().optional(),
13349
+ seriesId: z$1.string().optional(),
13350
+ seriesIds: z$1.string().optional(),
13351
+ runSeriesId: z$1.string().optional(),
13352
+ seriesSlug: z$1.string().optional(),
13353
+ includeOccurrenceId: z$1.string().optional(),
13354
+ readIntent: z$1.string().optional(),
13355
+ detailLevel: z$1.string().optional(),
13356
+ readProfile: z$1.string().optional()
13357
+ };
13358
+ z$1.object(publicEventLoaderQuerySchemaShape);
13136
13359
  eventPresetSchema = z$1.enum([
13137
13360
  "event",
13138
13361
  "class",
@@ -13559,7 +13782,7 @@ function planCalendarMonthRanges(months) {
13559
13782
  const sorted = [...new Set(months)].sort();
13560
13783
  const ranges = [];
13561
13784
  for (const month of sorted) {
13562
- const previous = ranges.at(-1);
13785
+ const previous = ranges[ranges.length - 1];
13563
13786
  const end = calendarMonthKey$1(addMonths(calendarMonthDate(month), 1));
13564
13787
  if (previous?.endMonthExclusive === month && monthNumber(end) - monthNumber(previous.startMonth) <= 3) previous.endMonthExclusive = end;
13565
13788
  else ranges.push({
@@ -15618,155 +15841,6 @@ var init_blockFlow = __esmMin((() => {
15618
15841
  init_types$8();
15619
15842
  }));
15620
15843
  //#endregion
15621
- //#region ../theme-core/src/tokens/tokens.ts
15622
- /**
15623
- * Project the expanded semantic palette into the token buckets consumed by
15624
- * runtime transforms. Keep this mapping shared by full themes and the
15625
- * tokens-only hosted-booking runtime so the two paths cannot drift.
15626
- */
15627
- function buildThemeTokens(palette) {
15628
- const tokens = cloneThemeTokens(defaultThemeTokens);
15629
- const paletteStrings = {};
15630
- for (const [key, value] of Object.entries(palette)) if (typeof value === "string" && value.trim().length > 0) paletteStrings[key] = value;
15631
- tokens.palette = paletteStrings;
15632
- const resolveColor = (...keys) => {
15633
- for (const key of keys) {
15634
- const value = paletteStrings[key];
15635
- if (value) return value;
15636
- }
15637
- };
15638
- const assignColor = (token, ...keys) => {
15639
- const value = resolveColor(...keys);
15640
- if (value) tokens.color[token] = value;
15641
- };
15642
- assignColor("background/base", "background", "surface", "primary-50");
15643
- assignColor("background/elevated", "surface", "background");
15644
- assignColor("surface/base", "surface", "background");
15645
- assignColor("surface/subtle", "neutral-100", "surface", "background");
15646
- assignColor("surface/inverted", "neutral-900", "text", "primary-900");
15647
- assignColor("content/primary", "text", "body", "neutral-900");
15648
- assignColor("content/secondary", "mutedText", "secondary", "neutral-600");
15649
- assignColor("accent/primary", "primary", "accent");
15650
- assignColor("accent/secondary", "accent", "secondary", "primary-400");
15651
- assignColor("border/base", "border", "neutral-300");
15652
- return tokens;
15653
- }
15654
- function cloneThemeTokens(source) {
15655
- return JSON.parse(JSON.stringify(source));
15656
- }
15657
- var defaultThemeTokens;
15658
- var init_tokens$1 = __esmMin((() => {
15659
- defaultThemeTokens = {
15660
- color: {
15661
- "background/base": "#ffffff",
15662
- "background/elevated": "#f5f5f5",
15663
- "surface/base": "#ffffff",
15664
- "surface/subtle": "#f9f9fb",
15665
- "surface/inverted": "#111111",
15666
- "content/primary": "#111111",
15667
- "content/secondary": "#3f3f46",
15668
- "accent/primary": "#2563eb",
15669
- "accent/secondary": "#1d4ed8",
15670
- "border/base": "#e5e7eb"
15671
- },
15672
- typography: {
15673
- "display/hero": {
15674
- fontSize: "clamp(48px, 8vw, 96px)",
15675
- lineHeight: "1.05",
15676
- fontWeight: "700"
15677
- },
15678
- "display/section": {
15679
- fontSize: "clamp(40px, 6vw, 72px)",
15680
- lineHeight: "1.1",
15681
- fontWeight: "700"
15682
- },
15683
- "heading/large": {
15684
- fontSize: "clamp(32px, 4vw, 48px)",
15685
- lineHeight: "1.2",
15686
- fontWeight: "600"
15687
- },
15688
- "heading/medium": {
15689
- fontSize: "clamp(24px, 3vw, 32px)",
15690
- lineHeight: "1.25",
15691
- fontWeight: "600"
15692
- },
15693
- "heading/small": {
15694
- fontSize: "20px",
15695
- lineHeight: "1.3",
15696
- fontWeight: "600"
15697
- },
15698
- "body/normal": {
15699
- fontSize: "16px",
15700
- lineHeight: "1.6",
15701
- fontWeight: "400"
15702
- },
15703
- "body/small": {
15704
- fontSize: "14px",
15705
- lineHeight: "1.5",
15706
- fontWeight: "400"
15707
- },
15708
- caption: {
15709
- fontSize: "12px",
15710
- lineHeight: "1.4",
15711
- fontWeight: "500"
15712
- }
15713
- },
15714
- spacing: {
15715
- none: "0px",
15716
- "3xs": "4px",
15717
- "2xs": "8px",
15718
- xs: "12px",
15719
- sm: "16px",
15720
- md: "24px",
15721
- lg: "32px",
15722
- xl: "40px",
15723
- "2xl": "56px",
15724
- "3xl": "72px"
15725
- },
15726
- radius: {
15727
- none: "0px",
15728
- xs: "2px",
15729
- sm: "4px",
15730
- md: "8px",
15731
- lg: "12px",
15732
- pill: "999px",
15733
- full: "9999px"
15734
- },
15735
- shadow: {
15736
- none: "none",
15737
- soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
15738
- medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
15739
- strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
15740
- },
15741
- palette: {
15742
- surface: "#ffffff",
15743
- "neutral-50": "#f9fafb",
15744
- "neutral-900": "#111827",
15745
- primary: "#2563eb",
15746
- "primary-50": "#eff6ff",
15747
- "primary-500": "#2563eb",
15748
- "primary-900": "#1d4ed8",
15749
- secondary: "#9333ea",
15750
- "secondary-50": "#f3e8ff",
15751
- "secondary-500": "#9333ea",
15752
- "secondary-900": "#4c1d95",
15753
- accent: "#f97316",
15754
- "accent-50": "#fff7ed",
15755
- "accent-500": "#f97316",
15756
- "accent-900": "#7c2d12"
15757
- }
15758
- };
15759
- }));
15760
- //#endregion
15761
- //#region ../theme-core/src/tokens/index.ts
15762
- var init_tokens = __esmMin((() => {
15763
- init_tokens$1();
15764
- init_blockColorTokens();
15765
- init_themeColorTokens();
15766
- init_colorTokenParts();
15767
- init_resolver$1();
15768
- }));
15769
- //#endregion
15770
15844
  //#region ../theme-core/src/site-styles/backgroundAppearance.ts
15771
15845
  function parseBackgroundAppearanceColorToken(value) {
15772
15846
  if (typeof value !== "string") return null;
@@ -21281,6 +21355,7 @@ function diffJsonPaths(left, right, path = "") {
21281
21355
  }
21282
21356
  var init_headerBytesComparison = __esmMin((() => {}));
21283
21357
  var init_headerOpeningForeground = __esmMin((() => {
21358
+ init_foregroundInteraction();
21284
21359
  init_expandPalette();
21285
21360
  init_colorConversion();
21286
21361
  init_tokens();
@@ -32526,6 +32601,49 @@ var init_registrationEventAdapter = __esmMin((() => {
32526
32601
  init_runGrouping();
32527
32602
  }));
32528
32603
  //#endregion
32604
+ //#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
32605
+ function resolveEventRegistrationEventSource(input) {
32606
+ if (input.wholeSeriesRunEvents != null) return {
32607
+ kind: "loaded",
32608
+ events: input.wholeSeriesRunEvents
32609
+ };
32610
+ if (input.events != null) return {
32611
+ kind: "loaded",
32612
+ events: input.events
32613
+ };
32614
+ return {
32615
+ kind: "unresolved",
32616
+ request: parseEventLoaderRecoveryRequest(input.failures?.wholeSeriesRunEvents ?? input.failures?.events)
32617
+ };
32618
+ }
32619
+ function parseEventLoaderRecoveryRequest(value) {
32620
+ const parsed = eventLoaderFailureSchema.safeParse(value);
32621
+ if (!parsed.success) return null;
32622
+ const { siteId: _siteId, stage, ...params } = parsed.data.params;
32623
+ return {
32624
+ ...params,
32625
+ stage: stage ?? "published"
32626
+ };
32627
+ }
32628
+ var _rawLimit, _rawEventSurface, _rawScheduleScope, _rawDetailLevel, stringEventQueryShape, eventRecoveryRequestSchema, eventLoaderFailureSchema;
32629
+ var init_eventSourceRecovery = __esmMin((() => {
32630
+ init_schemas();
32631
+ init_filtering();
32632
+ ({limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape} = publicEventLoaderQuerySchemaShape);
32633
+ eventRecoveryRequestSchema = z$1.object({
32634
+ ...stringEventQueryShape,
32635
+ limit: z$1.coerce.number().int().positive().optional(),
32636
+ eventSurface: z$1.enum(eventSurfaceScopeValues).optional(),
32637
+ scheduleScope: z$1.enum(eventScheduleScopeValues).optional(),
32638
+ detailLevel: z$1.enum(["full", "listing"]).optional(),
32639
+ stage: z$1.enum(["preview", "published"]).optional()
32640
+ });
32641
+ eventLoaderFailureSchema = z$1.object({
32642
+ endpoint: z$1.literal("listPublicEvents"),
32643
+ params: eventRecoveryRequestSchema.extend({ siteId: z$1.string().optional() })
32644
+ });
32645
+ }));
32646
+ //#endregion
32529
32647
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
32530
32648
  function buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents) {
32531
32649
  const selectedRun = resolveSelectedWholeSeriesRun(scopedSourceEvents);
@@ -32574,16 +32692,12 @@ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
32574
32692
  function toScopedEventRegistrationEvents(scopedSourceEvents) {
32575
32693
  return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
32576
32694
  }
32577
- function scopeEventRegistrationSourceEvents(source) {
32578
- return resolveEventRegistrationScopedEvents(source.wholeSeriesRunEvents ?? source.events ?? [], {
32695
+ function scopeEventRegistrationSourceEvents(source, eventSource) {
32696
+ return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
32579
32697
  occurrenceContext: source.occurrenceContext,
32580
32698
  subject: source.subject
32581
32699
  });
32582
32700
  }
32583
- function resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents) {
32584
- if (source.events == null && source.wholeSeriesRunEvents == null) return null;
32585
- return [...scopedSourceEvents];
32586
- }
32587
32701
  /**
32588
32702
  * The one run this surface is registering for, when the scoped events describe
32589
32703
  * exactly one. More than one run means the visitor still has to choose.
@@ -32640,7 +32754,7 @@ function buildEventRegistrationInteractiveIslandProps(props) {
32640
32754
  source: props
32641
32755
  });
32642
32756
  }
32643
- var EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS, EVENT_REGISTRATION_SHELL_STEP_LABELS, eventRegistrationPublicEventSchema, eventRegistrationHydrationSchemaShape, eventRegistrationSourceSchema, eventRegistrationDisplaySchema, eventRegistrationHydrationSchema, eventRegistrationRenderSchema, eventRegistrationIslandMetaCodec, eventRegistrationIslandMetaKeys, eventRegistrationBlockRuntime, eventRegistrationInteractiveIslandPropsCodec;
32757
+ var EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS, EVENT_REGISTRATION_SHELL_STEP_LABELS, eventRegistrationPublicEventSchema, eventRegistrationHydrationSchemaShape, eventRegistrationEventSourceSchema, eventRegistrationSourceSchema, eventRegistrationDisplaySchema, eventRegistrationHydrationSchema, eventRegistrationRenderSchema, eventRegistrationIslandMetaCodec, eventRegistrationIslandMetaKeys, eventRegistrationBlockRuntime, eventRegistrationInteractiveIslandPropsCodec;
32644
32758
  var init_event_registration_interactive = __esmMin((() => {
32645
32759
  init_schemas();
32646
32760
  init_runGrouping();
@@ -32654,6 +32768,7 @@ var init_event_registration_interactive = __esmMin((() => {
32654
32768
  init_wizardSteps$1();
32655
32769
  init_registrationDerivations();
32656
32770
  init_registrationEventAdapter();
32771
+ init_eventSourceRecovery();
32657
32772
  EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
32658
32773
  "Date",
32659
32774
  "Tickets",
@@ -32670,8 +32785,6 @@ var init_event_registration_interactive = __esmMin((() => {
32670
32785
  eventRegistrationHydrationSchemaShape = {
32671
32786
  occurrenceContext: occurrenceContextSchema.optional(),
32672
32787
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
32673
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32674
- wholeSeriesRunEvents: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32675
32788
  maxTickets: z$1.string().optional(),
32676
32789
  showVenue: z$1.boolean().optional(),
32677
32790
  showCapacity: z$1.boolean().optional(),
@@ -32683,12 +32796,22 @@ var init_event_registration_interactive = __esmMin((() => {
32683
32796
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
32684
32797
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
32685
32798
  };
32799
+ eventRegistrationEventSourceSchema = z$1.discriminatedUnion("kind", [z$1.object({
32800
+ kind: z$1.literal("loaded"),
32801
+ events: z$1.array(eventRegistrationPublicEventSchema)
32802
+ }), z$1.object({
32803
+ kind: z$1.literal("unresolved"),
32804
+ request: eventRecoveryRequestSchema.nullable()
32805
+ })]);
32686
32806
  eventRegistrationSourceSchema = z$1.object({
32687
32807
  siteId: z$1.string().optional(),
32688
32808
  apiBaseUrl: z$1.string().optional(),
32689
32809
  portalToken: z$1.string().nullable().optional(),
32690
32810
  previewToken: z$1.string().nullable().optional(),
32691
32811
  ...eventRegistrationHydrationSchemaShape,
32812
+ events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32813
+ wholeSeriesRunEvents: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32814
+ eventLoaderFailures: z$1.record(z$1.string(), z$1.unknown()).nullable().optional(),
32692
32815
  className: z$1.string().nullable().optional(),
32693
32816
  buttonText: z$1.string().nullable().optional(),
32694
32817
  maxTickets: z$1.string().nullable().optional(),
@@ -32709,7 +32832,10 @@ var init_event_registration_interactive = __esmMin((() => {
32709
32832
  titleText: z$1.string(),
32710
32833
  bodyText: z$1.string()
32711
32834
  })]);
32712
- eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
32835
+ eventRegistrationHydrationSchema = z$1.object({
32836
+ ...eventRegistrationHydrationSchemaShape,
32837
+ eventSource: eventRegistrationEventSourceSchema
32838
+ });
32713
32839
  eventRegistrationRenderSchema = z$1.object({
32714
32840
  display: eventRegistrationDisplaySchema,
32715
32841
  hydration: eventRegistrationHydrationSchema
@@ -32729,14 +32855,21 @@ var init_event_registration_interactive = __esmMin((() => {
32729
32855
  render: createZodCodec(eventRegistrationRenderSchema)
32730
32856
  },
32731
32857
  buildRender: (source) => {
32732
- const scopedSourceEvents = scopeEventRegistrationSourceEvents(source);
32733
- const events = resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents);
32858
+ const eventSource = resolveEventRegistrationEventSource({
32859
+ events: source.events,
32860
+ wholeSeriesRunEvents: source.wholeSeriesRunEvents,
32861
+ failures: source.eventLoaderFailures
32862
+ });
32863
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
32734
32864
  return {
32735
32865
  display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
32736
32866
  hydration: {
32737
32867
  occurrenceContext: source.occurrenceContext ?? null,
32738
32868
  subject: source.subject ?? null,
32739
- events,
32869
+ eventSource: eventSource.kind === "loaded" ? {
32870
+ ...eventSource,
32871
+ events: [...scopedSourceEvents]
32872
+ } : eventSource,
32740
32873
  maxTickets: source.maxTickets ?? void 0,
32741
32874
  showVenue: source.showVenue,
32742
32875
  showCapacity: source.showCapacity,
@@ -33131,6 +33264,7 @@ function buildNewsletterDisplay(source) {
33131
33264
  fields: { preset: "emailOnly" },
33132
33265
  includeOptionalPhone: false,
33133
33266
  buttonLabel: "Subscribe",
33267
+ successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
33134
33268
  privacyNote: null
33135
33269
  };
33136
33270
  const targeting = source.targeting ?? { mode: "default" };
@@ -33140,6 +33274,7 @@ function buildNewsletterDisplay(source) {
33140
33274
  availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
33141
33275
  className: source.className ?? null,
33142
33276
  buttonLabel: form.buttonLabel,
33277
+ successMessage: form.successMessage,
33143
33278
  buttonVariant: source.buttonVariant ?? "primary",
33144
33279
  privacyNote: form.privacyNote,
33145
33280
  fields: getGlobalFormFields(form),
@@ -33149,7 +33284,7 @@ function buildNewsletterDisplay(source) {
33149
33284
  function projectNewsletterFormHydrationTarget(source) {
33150
33285
  switch (source.source) {
33151
33286
  case "block": {
33152
- const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId);
33287
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
33153
33288
  if (sourceRef?.tag === "block_ref") return {
33154
33289
  tag: "block-source",
33155
33290
  sourceRef
@@ -33249,7 +33384,7 @@ function parseRequiredMailingListSignedSourceToken(value) {
33249
33384
  if (!parsed) throw new Error("Mailing-list signup signed source ref requires token");
33250
33385
  return parsed;
33251
33386
  }
33252
- var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
33387
+ var newsletterButtonVariantSchema, mailingListContextSchema, mailingListTargetingSchema, newsletterFieldSchema, mailingListSignupBlockIdSchema, mailingListContentVersionIdSchema, signedMailingListSourceTokenSchema, newsletterSourceCommonSchema, newsletterSourceSchema, newsletterDisplaySchema, newsletterHydrationSchema, newsletterRenderSchema, newsletterIslandMetaCodec, newsletterIslandMetaKeys, newsletterFormBlockRuntime, newsletterFormInteractiveIslandPropsCodec;
33253
33388
  var init_newsletter_form_interactive = __esmMin((() => {
33254
33389
  init_src$2();
33255
33390
  init_islands();
@@ -33287,6 +33422,15 @@ var init_newsletter_form_interactive = __esmMin((() => {
33287
33422
  placeholder: z$1.string().optional()
33288
33423
  });
33289
33424
  mailingListSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
33425
+ mailingListContentVersionIdSchema = z$1.string().transform((value, ctx) => {
33426
+ const parsed = parseMailingListContentVersionId(value);
33427
+ if (parsed) return parsed;
33428
+ ctx.addIssue({
33429
+ code: z$1.ZodIssueCode.custom,
33430
+ message: "Invalid mailing-list content version ID"
33431
+ });
33432
+ return z$1.NEVER;
33433
+ });
33290
33434
  signedMailingListSourceTokenSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
33291
33435
  newsletterSourceCommonSchema = z$1.object({
33292
33436
  siteId: z$1.string().optional(),
@@ -33300,7 +33444,8 @@ var init_newsletter_form_interactive = __esmMin((() => {
33300
33444
  newsletterSourceSchema = z$1.discriminatedUnion("source", [
33301
33445
  newsletterSourceCommonSchema.extend({
33302
33446
  source: z$1.literal("block"),
33303
- blockId: z$1.string().nullable().optional()
33447
+ blockId: z$1.string().nullable().optional(),
33448
+ contentVersionId: z$1.string().nullable().optional()
33304
33449
  }),
33305
33450
  newsletterSourceCommonSchema.extend({
33306
33451
  source: z$1.literal("signed-footer"),
@@ -33316,6 +33461,7 @@ var init_newsletter_form_interactive = __esmMin((() => {
33316
33461
  availability: z$1.enum(["ready", "unavailable"]),
33317
33462
  className: z$1.string().nullable(),
33318
33463
  buttonLabel: z$1.string(),
33464
+ successMessage: z$1.string(),
33319
33465
  buttonVariant: newsletterButtonVariantSchema,
33320
33466
  privacyNote: z$1.string().nullable(),
33321
33467
  fields: z$1.array(newsletterFieldSchema),
@@ -33330,7 +33476,8 @@ var init_newsletter_form_interactive = __esmMin((() => {
33330
33476
  tag: z$1.literal("block-source"),
33331
33477
  sourceRef: z$1.object({
33332
33478
  tag: z$1.literal("block_ref"),
33333
- blockId: mailingListSignupBlockIdSchema
33479
+ blockId: mailingListSignupBlockIdSchema,
33480
+ contentVersionId: mailingListContentVersionIdSchema
33334
33481
  }).nullable()
33335
33482
  }),
33336
33483
  z$1.object({
@@ -35795,6 +35942,14 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
35795
35942
  auth: "public",
35796
35943
  responseKind: "json"
35797
35944
  },
35945
+ getPublicBookingServiceBySlug: {
35946
+ path: "/public/bookings/services/by-slug/{slug}",
35947
+ method: "GET",
35948
+ revalidate: publicReadFreshnessSeconds("getPublicBookingService"),
35949
+ tags: [TAG_TEMPLATES.publicBookingServices],
35950
+ auth: "public",
35951
+ responseKind: "json"
35952
+ },
35798
35953
  getPublicBookingResourcesReference: {
35799
35954
  path: "/public/bookings/resources/reference",
35800
35955
  method: "GET",
@@ -36348,11 +36503,105 @@ const PUBLIC_READ_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
36348
36503
  responseKind: "json"
36349
36504
  }
36350
36505
  });
36506
+ //#endregion
36507
+ //#region ../api/src/publicOnboardingAttemptEndpointDefinitions.ts
36508
+ /**
36509
+ * The anonymous onboarding attempt, addressed by its opaque resume token.
36510
+ *
36511
+ * Every route here is reached before there is an account, so none of them can
36512
+ * be scoped to a site or a user: the token is the whole credential. They are
36513
+ * kept together so that stays obvious.
36514
+ */
36515
+ const PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
36516
+ createPublicOnboardingAttempt: {
36517
+ path: "/public/onboarding/attempts",
36518
+ method: "POST",
36519
+ auth: "public",
36520
+ errors: [],
36521
+ responseKind: "json"
36522
+ },
36523
+ createPublicOnboardingLogoUploadUrl: {
36524
+ path: "/public/onboarding/attempts/{attemptToken}/logo-upload-url",
36525
+ method: "POST",
36526
+ auth: "public",
36527
+ errors: [],
36528
+ responseKind: "json"
36529
+ },
36530
+ uploadPublicOnboardingLogo: {
36531
+ path: "/public/onboarding/attempts/{attemptToken}/logo",
36532
+ method: "POST",
36533
+ auth: "public",
36534
+ errors: [],
36535
+ responseKind: "json"
36536
+ },
36537
+ getPublicOnboardingAttempt: {
36538
+ path: "/public/onboarding/attempts/{attemptToken}",
36539
+ method: "GET",
36540
+ auth: "public",
36541
+ errors: [],
36542
+ responseKind: "json"
36543
+ },
36544
+ getPublicOnboardingAttemptProgress: {
36545
+ path: "/public/onboarding/attempts/{attemptToken}/status",
36546
+ method: "GET",
36547
+ auth: "public",
36548
+ errors: [],
36549
+ responseKind: "json"
36550
+ },
36551
+ updatePublicOnboardingAttempt: {
36552
+ path: "/public/onboarding/attempts/{attemptToken}",
36553
+ method: "PATCH",
36554
+ auth: "public",
36555
+ errors: [],
36556
+ responseKind: "json"
36557
+ },
36558
+ runPublicOnboardingAttempt: {
36559
+ path: "/public/onboarding/attempts/{attemptToken}/run",
36560
+ method: "POST",
36561
+ auth: "public",
36562
+ errors: [],
36563
+ responseKind: "json"
36564
+ },
36565
+ resendPublicOnboardingAttemptConfirmation: {
36566
+ path: "/public/onboarding/attempts/{attemptToken}/resend-confirmation",
36567
+ method: "POST",
36568
+ auth: "public",
36569
+ errors: [],
36570
+ responseKind: "json"
36571
+ }
36572
+ });
36573
+ //#endregion
36574
+ //#region ../api/src/billingEndpointDefinitions.ts
36575
+ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
36576
+ adminChangePlan: {
36577
+ path: "/admin/billing/plan",
36578
+ method: "POST",
36579
+ tags: ["admin", "billing"],
36580
+ auth: "admin",
36581
+ responseKind: "json"
36582
+ },
36583
+ changePlan: {
36584
+ path: "/billing/plan/change",
36585
+ method: "POST",
36586
+ tags: ["billing"],
36587
+ auth: "user",
36588
+ responseKind: "json"
36589
+ },
36590
+ createBillingPortalSession: {
36591
+ path: "/billing/portal/session",
36592
+ method: "POST",
36593
+ tags: ["billing"],
36594
+ auth: "user",
36595
+ responseKind: "json"
36596
+ }
36597
+ });
36351
36598
  const API_ENDPOINTS$1 = {
36352
36599
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
36600
+ ...PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS,
36353
36601
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
36354
36602
  ...GIFTING_ENDPOINT_DEFINITIONS,
36355
36603
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
36604
+ ...BILLING_ENDPOINT_DEFINITIONS,
36356
36605
  aiContentUpdateChat: {
36357
36606
  path: "/ai/content-update-chat",
36358
36607
  method: "POST",
@@ -36506,55 +36755,6 @@ const API_ENDPOINTS$1 = {
36506
36755
  errors: [],
36507
36756
  responseKind: "json"
36508
36757
  },
36509
- createPublicOnboardingAttempt: {
36510
- path: "/public/onboarding/attempts",
36511
- method: "POST",
36512
- auth: "public",
36513
- errors: [],
36514
- responseKind: "json"
36515
- },
36516
- createPublicOnboardingLogoUploadUrl: {
36517
- path: "/public/onboarding/attempts/{attemptToken}/logo-upload-url",
36518
- method: "POST",
36519
- auth: "public",
36520
- errors: [],
36521
- responseKind: "json"
36522
- },
36523
- uploadPublicOnboardingLogo: {
36524
- path: "/public/onboarding/attempts/{attemptToken}/logo",
36525
- method: "POST",
36526
- auth: "public",
36527
- errors: [],
36528
- responseKind: "json"
36529
- },
36530
- getPublicOnboardingAttempt: {
36531
- path: "/public/onboarding/attempts/{attemptToken}",
36532
- method: "GET",
36533
- auth: "public",
36534
- errors: [],
36535
- responseKind: "json"
36536
- },
36537
- getPublicOnboardingAttemptProgress: {
36538
- path: "/public/onboarding/attempts/{attemptToken}/status",
36539
- method: "GET",
36540
- auth: "public",
36541
- errors: [],
36542
- responseKind: "json"
36543
- },
36544
- updatePublicOnboardingAttempt: {
36545
- path: "/public/onboarding/attempts/{attemptToken}",
36546
- method: "PATCH",
36547
- auth: "public",
36548
- errors: [],
36549
- responseKind: "json"
36550
- },
36551
- runPublicOnboardingAttempt: {
36552
- path: "/public/onboarding/attempts/{attemptToken}/run",
36553
- method: "POST",
36554
- auth: "public",
36555
- errors: [],
36556
- responseKind: "json"
36557
- },
36558
36758
  aiSiteWizardSuggestGoals: {
36559
36759
  path: "/sites/{siteId}/ai/site-wizard/goals",
36560
36760
  method: "POST",
@@ -38070,20 +38270,6 @@ const API_ENDPOINTS$1 = {
38070
38270
  auth: "admin",
38071
38271
  responseKind: "json"
38072
38272
  },
38073
- adminChangePlan: {
38074
- path: "/admin/billing/plan",
38075
- method: "POST",
38076
- tags: ["admin", "billing"],
38077
- auth: "admin",
38078
- responseKind: "json"
38079
- },
38080
- changePlan: {
38081
- path: "/billing/plan/change",
38082
- method: "POST",
38083
- tags: ["billing"],
38084
- auth: "user",
38085
- responseKind: "json"
38086
- },
38087
38273
  mfaTotpEnroll: {
38088
38274
  path: "/auth/mfa/totp/enroll",
38089
38275
  method: "POST",
@@ -38432,7 +38618,12 @@ const API_ENDPOINTS$1 = {
38432
38618
  path: "/public/sites/{siteId}/sitemap",
38433
38619
  method: "GET",
38434
38620
  revalidate: 60,
38435
- tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings],
38621
+ tags: [
38622
+ TAG_TEMPLATES.siteRoutableContent,
38623
+ TAG_TEMPLATES.siteSettings,
38624
+ TAG_TEMPLATES.publicEvents,
38625
+ TAG_TEMPLATES.publicBookingServices
38626
+ ],
38436
38627
  auth: "public",
38437
38628
  responseKind: "json"
38438
38629
  },
@@ -41751,6 +41942,17 @@ const API_ENDPOINTS$1 = {
41751
41942
  auth: "public",
41752
41943
  responseKind: "json"
41753
41944
  },
41945
+ portalCancelWaitlistEntry: {
41946
+ path: "/portal/waitlists/{entryId}/cancel",
41947
+ method: "POST",
41948
+ auth: "public",
41949
+ responseKind: "json",
41950
+ errors: [
41951
+ "resource:not_found",
41952
+ "resource:conflict",
41953
+ "server:internal_error"
41954
+ ]
41955
+ },
41754
41956
  portalGetEventGuests: {
41755
41957
  path: "/portal/events/{registrationId}/guests",
41756
41958
  method: "GET",
@@ -46894,7 +47096,7 @@ const publicPricingSchema = z$1.object({
46894
47096
  singlePriceAmount: z$1.number().nullable(),
46895
47097
  slidingMinAmount: z$1.number().nullable(),
46896
47098
  slidingMaxAmount: z$1.number().nullable(),
46897
- options: z$1.array(publicPricingOptionSchema)
47099
+ options: z$1.array(publicPricingOptionSchema).readonly()
46898
47100
  });
46899
47101
  const publicAppointmentServiceSchema = z$1.object({
46900
47102
  id: z$1.string().min(1),
@@ -49843,6 +50045,7 @@ const eventRegistrationBlockDefinition = {
49843
50045
  } },
49844
50046
  events: { $bind: { from: "data.events" } },
49845
50047
  wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
50048
+ loaderFailures: { $bind: { from: "$root.loaderFailures" } },
49846
50049
  sitePasses: { $bind: { from: "data.sitePasses" } },
49847
50050
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
49848
50051
  stage: { $bind: {
@@ -53749,9 +53952,10 @@ function cx(...classes) {
53749
53952
  * Server-safe placeholder for event registration.
53750
53953
  * Provides a static container for island hydration without importing client hooks.
53751
53954
  */
53752
- function EventRegistrationSSR({ blockId, subject, children, ...sourceProps }) {
53955
+ function EventRegistrationSSR({ blockId, subject, loaderFailures, children, ...sourceProps }) {
53753
53956
  const islandProps = buildEventRegistrationInteractiveIslandProps({
53754
53957
  ...sourceProps,
53958
+ eventLoaderFailures: blockId ? loaderFailures?.[blockId] : void 0,
53755
53959
  subject: normalizeEventRegistrationPageSurfaceSubject(subject)
53756
53960
  });
53757
53961
  const display = islandProps.render.display;
@@ -54092,7 +54296,7 @@ function NewsletterFormSSR(props) {
54092
54296
  className: clsx("newsletter-form-ssr", className),
54093
54297
  children: /* @__PURE__ */ jsx("p", {
54094
54298
  role: "status",
54095
- children: "Mailing-list signup is not available right now."
54299
+ children: "We can’t accept signups right now. Please try again later."
54096
54300
  })
54097
54301
  });
54098
54302
  const renderField = (field) => {
@@ -54138,14 +54342,18 @@ function NewsletterFormSSR(props) {
54138
54342
  children: [
54139
54343
  fields.map(renderField),
54140
54344
  islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
54141
- className: "newsletter-topics",
54142
- children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
54143
- className: "newsletter-topic-choice",
54345
+ className: "fb-fieldset newsletter-topics",
54346
+ children: [/* @__PURE__ */ jsx("legend", {
54347
+ className: "form-label",
54348
+ children: "What would you like to hear about?"
54349
+ }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
54350
+ className: "fb-inline form-label newsletter-topic-choice",
54144
54351
  children: [/* @__PURE__ */ jsx("input", {
54145
54352
  type: "checkbox",
54146
54353
  name: "mailingListChoice",
54147
- value: choice.id
54148
- }), choice.label]
54354
+ value: choice.id,
54355
+ className: "form-checkbox"
54356
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
54149
54357
  }, choice.id))]
54150
54358
  }) : null,
54151
54359
  /* @__PURE__ */ jsx("div", {
@@ -55145,6 +55353,18 @@ function resolveChildren(nodes, context) {
55145
55353
  function isReactNode(value) {
55146
55354
  return value !== null && value !== void 0;
55147
55355
  }
55356
+ function resolveNodeMetadata(nodeType, context) {
55357
+ return {
55358
+ pathBase: context.pathBase,
55359
+ blockId: context.blockId,
55360
+ blockKind: context.blockKind,
55361
+ blockContent: context.blockContent,
55362
+ fragmentRegistry: context.fragmentRegistry,
55363
+ previewAuthoring: context.previewAuthoring,
55364
+ ...nodeType.toLowerCase() === "newsletter-form" ? { contentVersionId: context.contentVersionId } : {},
55365
+ ...nodeType === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {}
55366
+ };
55367
+ }
55148
55368
  /**
55149
55369
  * Resolves a node definition into a React element.
55150
55370
  * Handles conditionals ($when), scopes ($scopes), repeaters ($repeat), bindings ($bind), and children.
@@ -55180,13 +55400,7 @@ function resolveNode(node, context, indexFallback) {
55180
55400
  const elementProps = {
55181
55401
  ...props,
55182
55402
  key: node.key ?? indexFallback,
55183
- pathBase: context.pathBase,
55184
- blockId: context.blockId,
55185
- blockKind: context.blockKind,
55186
- blockContent: context.blockContent,
55187
- ...node.type === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {},
55188
- fragmentRegistry: context.fragmentRegistry,
55189
- previewAuthoring: context.previewAuthoring
55403
+ ...resolveNodeMetadata(node.type, context)
55190
55404
  };
55191
55405
  const element = React.createElement(component, elementProps, ...children);
55192
55406
  if (headingDecorationPlan.kind === "skip") return element;
@@ -59245,7 +59459,7 @@ function pageBlockPosition(index, blockCount) {
59245
59459
  //#endregion
59246
59460
  //#region ../blocks/src/pageRendererContracts.ts
59247
59461
  function buildPageRendererRootRuntime(dataContext) {
59248
- const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false } = dataContext ?? {};
59462
+ const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
59249
59463
  return {
59250
59464
  siteId,
59251
59465
  pageId,
@@ -59256,7 +59470,8 @@ function buildPageRendererRootRuntime(dataContext) {
59256
59470
  portalToken,
59257
59471
  bookingOfferingPresets,
59258
59472
  mailingList,
59259
- eventRegistrationOverlayEnabled
59473
+ eventRegistrationOverlayEnabled,
59474
+ loaderFailures
59260
59475
  };
59261
59476
  }
59262
59477
  //#endregion
@@ -68444,7 +68659,7 @@ function collectNestedPreviewFieldConstraintEntries(field, path) {
68444
68659
  }
68445
68660
  function makeDefaultBlockComponent(args) {
68446
68661
  const { manifest } = args;
68447
- return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
68662
+ return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, contentVersionId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
68448
68663
  const perf = beginBlockRenderMeasurement();
68449
68664
  if (!theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
68450
68665
  if (!registry) throw new Error("Block rendering requires a component registry; none was provided");
@@ -68464,6 +68679,7 @@ function makeDefaultBlockComponent(args) {
68464
68679
  theme: withButtonSystem(theme, themeConfig),
68465
68680
  pathBase,
68466
68681
  blockId,
68682
+ contentVersionId,
68467
68683
  blockKind,
68468
68684
  blockContent: mergedContent,
68469
68685
  blockBindings,
@@ -69235,6 +69451,7 @@ function buildBlockOverrideProps(input) {
69235
69451
  ...blockSubjectProps(dataContext),
69236
69452
  imageResolveContext: input.imageResolveContext,
69237
69453
  blockId: block.id ?? null,
69454
+ contentVersionId: block.contentVersionId ?? null,
69238
69455
  blockKind: block.kind
69239
69456
  };
69240
69457
  }
@@ -69335,6 +69552,7 @@ function toPresentationPage(page) {
69335
69552
  id: block.id,
69336
69553
  kind: block.kind,
69337
69554
  purpose: block.purpose,
69555
+ ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
69338
69556
  ...block.bindings ? { bindings: block.bindings } : {}
69339
69557
  };
69340
69558
  return block.admission.kind === "renderable" ? {
@@ -80691,7 +80909,9 @@ const containerResponsiveThemeCss = `/*
80691
80909
  text-align: left;
80692
80910
  }
80693
80911
 
80694
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__subtitle {
80912
+ :where(.theme-scope)
80913
+ :where([data-block="customer-portal"])
80914
+ .cp-login__subtitle {
80695
80915
  color: var(--cp-muted);
80696
80916
  font-size: 0.9375rem;
80697
80917
  text-align: left;
@@ -80718,7 +80938,9 @@ const containerResponsiveThemeCss = `/*
80718
80938
  text-align: left;
80719
80939
  }
80720
80940
 
80721
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link {
80941
+ :where(.theme-scope)
80942
+ :where([data-block="customer-portal"])
80943
+ .cp-login__reset-link {
80722
80944
  appearance: none;
80723
80945
  background: none;
80724
80946
  border: 0;
@@ -80732,11 +80954,15 @@ const containerResponsiveThemeCss = `/*
80732
80954
  text-underline-offset: 0.15em;
80733
80955
  }
80734
80956
 
80735
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link:hover {
80957
+ :where(.theme-scope)
80958
+ :where([data-block="customer-portal"])
80959
+ .cp-login__reset-link:hover {
80736
80960
  color: var(--cp-text);
80737
80961
  }
80738
80962
 
80739
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link:focus-visible {
80963
+ :where(.theme-scope)
80964
+ :where([data-block="customer-portal"])
80965
+ .cp-login__reset-link:focus-visible {
80740
80966
  outline: 2px solid currentColor;
80741
80967
  outline-offset: 3px;
80742
80968
  }
@@ -80781,7 +81007,9 @@ const containerResponsiveThemeCss = `/*
80781
81007
  border-bottom: none;
80782
81008
  }
80783
81009
 
80784
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-header__welcome {
81010
+ :where(.theme-scope)
81011
+ :where([data-block="customer-portal"])
81012
+ .cp-header__welcome {
80785
81013
  font-size: 1.125rem;
80786
81014
  font-weight: 500;
80787
81015
  }
@@ -80797,8 +81025,14 @@ const containerResponsiveThemeCss = `/*
80797
81025
  }
80798
81026
 
80799
81027
  @keyframes cp-fade-in {
80800
- from { opacity: 0; transform: translateY(4px); }
80801
- to { opacity: 1; transform: translateY(0); }
81028
+ from {
81029
+ opacity: 0;
81030
+ transform: translateY(4px);
81031
+ }
81032
+ to {
81033
+ opacity: 1;
81034
+ transform: translateY(0);
81035
+ }
80802
81036
  }
80803
81037
 
80804
81038
  /* Empty state */
@@ -80887,6 +81121,77 @@ const containerResponsiveThemeCss = `/*
80887
81121
  margin-top: 1rem;
80888
81122
  }
80889
81123
 
81124
+ /* Event waitlists */
81125
+ :where(.theme-scope) :where([data-block="customer-portal"]) .cp-waitlist-list {
81126
+ display: grid;
81127
+ gap: 1rem;
81128
+ }
81129
+
81130
+ :where(.theme-scope)
81131
+ :where([data-block="customer-portal"])
81132
+ .cp-waitlists
81133
+ > .cp-alert {
81134
+ margin-bottom: 1rem;
81135
+ }
81136
+
81137
+ :where(.theme-scope) :where([data-block="customer-portal"]) .cp-waitlist-card {
81138
+ transition:
81139
+ border-color 180ms ease,
81140
+ box-shadow 180ms ease;
81141
+ }
81142
+
81143
+ :where(.theme-scope)
81144
+ :where([data-block="customer-portal"])
81145
+ .cp-waitlist-card--focused {
81146
+ border-color: var(--cp-primary);
81147
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-primary) 22%, transparent);
81148
+ }
81149
+
81150
+ :where(.theme-scope)
81151
+ :where([data-block="customer-portal"])
81152
+ .cp-waitlist-card__summary,
81153
+ :where(.theme-scope)
81154
+ :where([data-block="customer-portal"])
81155
+ .cp-waitlist-card__position {
81156
+ font-weight: 600;
81157
+ }
81158
+
81159
+ :where(.theme-scope)
81160
+ :where([data-block="customer-portal"])
81161
+ .cp-waitlist-card
81162
+ .cp-card-body
81163
+ p {
81164
+ margin: 0.4rem 0;
81165
+ }
81166
+
81167
+ @container rb-site (max-width: 640px) {
81168
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
81169
+ :where(.theme-scope)
81170
+ :where([data-block="customer-portal"])
81171
+ .cp-waitlist-card
81172
+ .cp-card-header {
81173
+ flex-direction: column-reverse;
81174
+ }
81175
+
81176
+ :where(.theme-scope)
81177
+ :where([data-block="customer-portal"])
81178
+ .cp-waitlist-card
81179
+ .cp-card-actions {
81180
+ align-items: stretch;
81181
+ flex-direction: column;
81182
+ }
81183
+
81184
+ :where(.theme-scope)
81185
+ :where([data-block="customer-portal"])
81186
+ .cp-waitlist-card
81187
+ .cp-card-actions
81188
+ > * {
81189
+ justify-content: center;
81190
+ text-align: center;
81191
+ }
81192
+ }
81193
+ }
81194
+
80890
81195
  /* Badge */
80891
81196
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-badge {
80892
81197
  display: inline-flex;
@@ -81023,11 +81328,18 @@ const containerResponsiveThemeCss = `/*
81023
81328
  background: rgba(var(--tb-border), 0.2);
81024
81329
  }
81025
81330
 
81026
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table tbody tr:last-child td {
81331
+ :where(.theme-scope)
81332
+ :where([data-block="customer-portal"])
81333
+ .cp-table
81334
+ tbody
81335
+ tr:last-child
81336
+ td {
81027
81337
  border-bottom: none;
81028
81338
  }
81029
81339
 
81030
- :where(.theme-scope) :where([data-block="customer-portal"]) :is(.cp-row--past, .cp-row--muted) {
81340
+ :where(.theme-scope)
81341
+ :where([data-block="customer-portal"])
81342
+ :is(.cp-row--past, .cp-row--muted) {
81031
81343
  opacity: 0.65;
81032
81344
  }
81033
81345
 
@@ -81040,7 +81352,9 @@ const containerResponsiveThemeCss = `/*
81040
81352
  line-height: 1.2;
81041
81353
  }
81042
81354
 
81043
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__badges {
81355
+ :where(.theme-scope)
81356
+ :where([data-block="customer-portal"])
81357
+ .cp-row-title__badges {
81044
81358
  margin-left: auto;
81045
81359
  display: flex;
81046
81360
  flex-wrap: wrap;
@@ -81048,7 +81362,9 @@ const containerResponsiveThemeCss = `/*
81048
81362
  gap: 0.375rem;
81049
81363
  }
81050
81364
 
81051
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__text {
81365
+ :where(.theme-scope)
81366
+ :where([data-block="customer-portal"])
81367
+ .cp-row-title__text {
81052
81368
  min-width: 0;
81053
81369
  }
81054
81370
 
@@ -81068,12 +81384,16 @@ const containerResponsiveThemeCss = `/*
81068
81384
  line-height: 1.35;
81069
81385
  }
81070
81386
 
81071
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-note--success {
81387
+ :where(.theme-scope)
81388
+ :where([data-block="customer-portal"])
81389
+ .cp-row-note--success {
81072
81390
  border-left-color: rgb(var(--tb-success));
81073
81391
  color: rgb(var(--tb-success));
81074
81392
  }
81075
81393
 
81076
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-note--error {
81394
+ :where(.theme-scope)
81395
+ :where([data-block="customer-portal"])
81396
+ .cp-row-note--error {
81077
81397
  border-left-color: rgb(var(--tb-destructive));
81078
81398
  color: rgb(var(--tb-destructive));
81079
81399
  }
@@ -81092,16 +81412,23 @@ const containerResponsiveThemeCss = `/*
81092
81412
  white-space: nowrap;
81093
81413
  }
81094
81414
 
81095
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-col-actions .btn-sm {
81415
+ :where(.theme-scope)
81416
+ :where([data-block="customer-portal"])
81417
+ .cp-col-actions
81418
+ .btn-sm {
81096
81419
  white-space: nowrap;
81097
81420
  }
81098
81421
 
81099
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__link {
81422
+ :where(.theme-scope)
81423
+ :where([data-block="customer-portal"])
81424
+ .cp-row-title__link {
81100
81425
  color: inherit;
81101
81426
  text-decoration: none;
81102
81427
  }
81103
81428
 
81104
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__link:hover {
81429
+ :where(.theme-scope)
81430
+ :where([data-block="customer-portal"])
81431
+ .cp-row-title__link:hover {
81105
81432
  text-decoration: underline;
81106
81433
  text-decoration-thickness: 2px;
81107
81434
  text-underline-offset: 2px;
@@ -81123,7 +81450,9 @@ const containerResponsiveThemeCss = `/*
81123
81450
  }
81124
81451
 
81125
81452
  /* Profile actions */
81126
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-profile__actions {
81453
+ :where(.theme-scope)
81454
+ :where([data-block="customer-portal"])
81455
+ .cp-profile__actions {
81127
81456
  display: flex;
81128
81457
  gap: 0.75rem;
81129
81458
  margin-top: 1rem;
@@ -81190,28 +81519,39 @@ const containerResponsiveThemeCss = `/*
81190
81519
  gap: 0.375rem;
81191
81520
  }
81192
81521
 
81193
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__index {
81522
+ :where(.theme-scope)
81523
+ :where([data-block="customer-portal"])
81524
+ .cp-guest-edit-row__index {
81194
81525
  font-size: 0.75rem;
81195
81526
  font-weight: 500;
81196
81527
  color: var(--cp-muted);
81197
81528
  }
81198
81529
 
81199
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__fields {
81530
+ :where(.theme-scope)
81531
+ :where([data-block="customer-portal"])
81532
+ .cp-guest-edit-row__fields {
81200
81533
  display: flex;
81201
81534
  gap: 0.5rem;
81202
81535
  }
81203
81536
 
81204
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__fields input {
81537
+ :where(.theme-scope)
81538
+ :where([data-block="customer-portal"])
81539
+ .cp-guest-edit-row__fields
81540
+ input {
81205
81541
  flex: 1;
81206
81542
  min-width: 0;
81207
81543
  }
81208
81544
 
81209
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__error {
81545
+ :where(.theme-scope)
81546
+ :where([data-block="customer-portal"])
81547
+ .cp-guest-edit-row__error {
81210
81548
  font-size: 0.75rem;
81211
81549
  color: var(--cp-error);
81212
81550
  }
81213
81551
 
81214
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guests__actions {
81552
+ :where(.theme-scope)
81553
+ :where([data-block="customer-portal"])
81554
+ .cp-guests__actions {
81215
81555
  display: flex;
81216
81556
  gap: 0.5rem;
81217
81557
  margin-top: 0.5rem;
@@ -81225,13 +81565,18 @@ const containerResponsiveThemeCss = `/*
81225
81565
  }
81226
81566
 
81227
81567
  /* In the actions modal, tiles sit on a surface modal, so use "background" for contrast. */
81228
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-actions-list :where(.rb-tile) {
81568
+ :where(.theme-scope)
81569
+ :where([data-block="customer-portal"])
81570
+ .cp-actions-list
81571
+ :where(.rb-tile) {
81229
81572
  --rb-event-tile-bg: rgb(var(--tb-background));
81230
81573
  --rb-event-tile-border: rgb(var(--tb-border));
81231
81574
  }
81232
81575
 
81233
81576
  /* Actions trigger: icon-only kebab button */
81234
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-actions-trigger.btn-sm {
81577
+ :where(.theme-scope)
81578
+ :where([data-block="customer-portal"])
81579
+ .cp-actions-trigger.btn-sm {
81235
81580
  padding: 0.35rem !important;
81236
81581
  line-height: 1 !important;
81237
81582
  min-width: 32px;
@@ -81255,17 +81600,24 @@ const containerResponsiveThemeCss = `/*
81255
81600
  gap: 0.25rem;
81256
81601
  }
81257
81602
 
81258
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile__title {
81603
+ :where(.theme-scope)
81604
+ :where([data-block="customer-portal"])
81605
+ .cp-action-tile__title {
81259
81606
  font-weight: 600;
81260
81607
  font-size: 0.9375rem;
81261
81608
  }
81262
81609
 
81263
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile__desc {
81610
+ :where(.theme-scope)
81611
+ :where([data-block="customer-portal"])
81612
+ .cp-action-tile__desc {
81264
81613
  font-size: 0.875rem;
81265
81614
  line-height: 1.35;
81266
81615
  }
81267
81616
 
81268
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile--danger .cp-action-tile__title {
81617
+ :where(.theme-scope)
81618
+ :where([data-block="customer-portal"])
81619
+ .cp-action-tile--danger
81620
+ .cp-action-tile__title {
81269
81621
  color: rgb(var(--tb-destructive));
81270
81622
  }
81271
81623
 
@@ -81287,7 +81639,9 @@ const containerResponsiveThemeCss = `/*
81287
81639
  text-decoration: underline;
81288
81640
  }
81289
81641
 
81290
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-btn--link:hover {
81642
+ :where(.theme-scope)
81643
+ :where([data-block="customer-portal"])
81644
+ .cp-btn--link:hover {
81291
81645
  color: var(--cp-primary-hover);
81292
81646
  }
81293
81647
 
@@ -81326,34 +81680,48 @@ const containerResponsiveThemeCss = `/*
81326
81680
  margin-top: 0.75rem;
81327
81681
  }
81328
81682
 
81329
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__title {
81683
+ :where(.theme-scope)
81684
+ :where([data-block="customer-portal"])
81685
+ .cp-cancel-confirm__title {
81330
81686
  font-weight: 600;
81331
81687
  margin-bottom: 0.5rem;
81332
81688
  }
81333
81689
 
81334
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__message {
81690
+ :where(.theme-scope)
81691
+ :where([data-block="customer-portal"])
81692
+ .cp-cancel-confirm__message {
81335
81693
  margin-bottom: 0.25rem;
81336
81694
  }
81337
81695
 
81338
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__warning {
81696
+ :where(.theme-scope)
81697
+ :where([data-block="customer-portal"])
81698
+ .cp-cancel-confirm__warning {
81339
81699
  margin-bottom: 0.75rem;
81340
81700
  }
81341
81701
 
81342
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__actions {
81702
+ :where(.theme-scope)
81703
+ :where([data-block="customer-portal"])
81704
+ .cp-cancel-confirm__actions {
81343
81705
  display: flex;
81344
81706
  gap: 0.75rem;
81345
81707
  }
81346
81708
 
81347
81709
  /* Membership actions */
81348
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-membership-actions {
81710
+ :where(.theme-scope)
81711
+ :where([data-block="customer-portal"])
81712
+ .cp-membership-actions {
81349
81713
  margin-top: 0.75rem;
81350
81714
  }
81351
81715
 
81352
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-section-actions {
81716
+ :where(.theme-scope)
81717
+ :where([data-block="customer-portal"])
81718
+ .cp-section-actions {
81353
81719
  margin-top: 1rem;
81354
81720
  }
81355
81721
 
81356
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card-subtitle--spaced {
81722
+ :where(.theme-scope)
81723
+ :where([data-block="customer-portal"])
81724
+ .cp-card-subtitle--spaced {
81357
81725
  margin-top: 0.75rem;
81358
81726
  }
81359
81727
 
@@ -81377,9 +81745,18 @@ const containerResponsiveThemeCss = `/*
81377
81745
  display: none;
81378
81746
  }
81379
81747
 
81380
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-guests,
81381
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-tickets,
81382
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-actions {
81748
+ :where(.theme-scope)
81749
+ :where([data-block="customer-portal"])
81750
+ .cp-table
81751
+ :is(th, td).cp-col-guests,
81752
+ :where(.theme-scope)
81753
+ :where([data-block="customer-portal"])
81754
+ .cp-table
81755
+ :is(th, td).cp-col-tickets,
81756
+ :where(.theme-scope)
81757
+ :where([data-block="customer-portal"])
81758
+ .cp-table
81759
+ :is(th, td).cp-col-actions {
81383
81760
  display: none;
81384
81761
  }
81385
81762
 
@@ -81388,24 +81765,34 @@ const containerResponsiveThemeCss = `/*
81388
81765
  }
81389
81766
 
81390
81767
  /* Make the cell a positioning context for the kebab */
81391
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row > td:first-child {
81768
+ :where(.theme-scope)
81769
+ :where([data-block="customer-portal"])
81770
+ .cp-row
81771
+ > td:first-child {
81392
81772
  position: relative;
81393
81773
  padding-right: 2.5rem;
81394
81774
  }
81395
81775
 
81396
81776
  /* Position kebab in top-right of the cell */
81397
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-mobile-actions {
81777
+ :where(.theme-scope)
81778
+ :where([data-block="customer-portal"])
81779
+ .cp-row-mobile-actions {
81398
81780
  position: absolute;
81399
81781
  top: 0.5rem;
81400
81782
  right: 0.5rem;
81401
81783
  margin-top: 0;
81402
81784
  }
81403
81785
 
81404
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-mobile-actions .btn-sm {
81786
+ :where(.theme-scope)
81787
+ :where([data-block="customer-portal"])
81788
+ .cp-row-mobile-actions
81789
+ .btn-sm {
81405
81790
  width: auto;
81406
81791
  }
81407
81792
 
81408
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-profile__edit {
81793
+ :where(.theme-scope)
81794
+ :where([data-block="customer-portal"])
81795
+ .cp-profile__edit {
81409
81796
  align-self: stretch;
81410
81797
  }
81411
81798
  }
@@ -81853,6 +82240,30 @@ const containerResponsiveThemeCss = `/*
81853
82240
  gap: 0.25rem;
81854
82241
  }
81855
82242
 
82243
+ /* Topic choices (visitor picks what to hear about). Same treatment as the
82244
+ form block's .fb-fieldset / .fb-inline, defined here because the newsletter
82245
+ form also renders inside contact-newsletter and the site footer. */
82246
+ :where(.theme-scope) .newsletter-topics {
82247
+ display: flex;
82248
+ flex-direction: column;
82249
+ gap: 0.5rem;
82250
+ border: none;
82251
+ padding: 0;
82252
+ margin: 0;
82253
+ min-width: 0;
82254
+ }
82255
+
82256
+ :where(.theme-scope) .newsletter-topics > legend {
82257
+ padding: 0;
82258
+ margin-bottom: 0.25rem;
82259
+ }
82260
+
82261
+ :where(.theme-scope) .newsletter-topic-choice {
82262
+ display: flex;
82263
+ align-items: center;
82264
+ gap: 0.5rem;
82265
+ }
82266
+
81856
82267
  /* Required indicator */
81857
82268
  :where(.theme-scope) .newsletter-required {
81858
82269
  color: rgb(var(--tb-primary));
@@ -81902,6 +82313,10 @@ const containerResponsiveThemeCss = `/*
81902
82313
  flex-shrink: 0;
81903
82314
  }
81904
82315
 
82316
+ :where(.theme-scope) .newsletter-inline .newsletter-topics {
82317
+ flex-basis: 100%;
82318
+ }
82319
+
81905
82320
  /* Mobile fallback for inline variant */
81906
82321
  @container rb-site (max-width: 640px) {
81907
82322
  @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
@@ -84440,8 +84855,12 @@ function shouldSkipResolvedLoader(input) {
84440
84855
  * ```
84441
84856
  */
84442
84857
  async function prefetchBlockData$1(page, context, options) {
84858
+ return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
84859
+ }
84860
+ async function prefetchBlockDataWithFailures(page, context, options) {
84443
84861
  const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
84444
84862
  const results = {};
84863
+ const loaderFailures = {};
84445
84864
  const tasks = [];
84446
84865
  for (const block of page.blocks) {
84447
84866
  const blockId = block.id;
@@ -84489,6 +84908,11 @@ async function prefetchBlockData$1(page, context, options) {
84489
84908
  const blockResults = results[blockId] ?? (results[blockId] = {});
84490
84909
  blockResults[key] = data;
84491
84910
  } catch (error) {
84911
+ const blockFailures = loaderFailures[blockId] ?? (loaderFailures[blockId] = {});
84912
+ blockFailures[key] = {
84913
+ endpoint,
84914
+ params
84915
+ };
84492
84916
  if (onError) onError(error, {
84493
84917
  block: block.kind,
84494
84918
  loader: key
@@ -84498,7 +84922,10 @@ async function prefetchBlockData$1(page, context, options) {
84498
84922
  }
84499
84923
  }
84500
84924
  if (tasks.length > 0) await Promise.all(tasks);
84501
- return results;
84925
+ return {
84926
+ resolvedData: results,
84927
+ loaderFailures
84928
+ };
84502
84929
  }
84503
84930
  //#endregion
84504
84931
  //#region ../blocks/src/system/data/loaderEndpoints.ts
@@ -84706,6 +85133,7 @@ init_events$2();
84706
85133
  init_colorStyles();
84707
85134
  //#endregion
84708
85135
  //#region ../api/src/sdkConfig/contracts.ts
85136
+ init_src$2();
84709
85137
  /**
84710
85138
  * Canonical SDK config Zod contracts.
84711
85139
  *
@@ -84968,7 +85396,17 @@ const riverbankSiteConfigInputSchema = z$1.object({
84968
85396
  z$1.object({
84969
85397
  config: riverbankSiteConfigInputSchema,
84970
85398
  forceContentTypes: z$1.boolean().optional(),
84971
- mode: z$1.enum(["apply", "preview"]).optional()
85399
+ mode: z$1.enum(["apply", "preview"]).optional(),
85400
+ expectedMailingListProviderScope: z$1.unknown().transform((value, ctx) => {
85401
+ if (value === void 0) return void 0;
85402
+ const parsed = parseMailingListProviderScope(value);
85403
+ if (parsed.ok) return parsed.value;
85404
+ ctx.addIssue({
85405
+ code: "custom",
85406
+ message: "Invalid mailing-list provider scope"
85407
+ });
85408
+ return z$1.NEVER;
85409
+ }).optional()
84972
85410
  }).strict();
84973
85411
  //#endregion
84974
85412
  //#region ../api/src/sdkThemeWire.ts
@@ -86681,9 +87119,11 @@ function convertPageResponseBlock(block) {
86681
87119
  if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
86682
87120
  if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
86683
87121
  if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
87122
+ if (block.contentVersionId !== void 0 && block.contentVersionId !== null && typeof block.contentVersionId !== "string") throw new Error(`Invalid content version id in page: expected string or null, got ${typeof block.contentVersionId}`);
86684
87123
  const admission = readInvalidBlockAdmission(block.admission);
86685
87124
  return {
86686
87125
  id: block.id,
87126
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
86687
87127
  kind: block.kind,
86688
87128
  purpose: block.purpose,
86689
87129
  content: sanitizeSdkRuntimeBlockContent(block.kind, readContentRecord(block.content) ?? {}),
@@ -86716,6 +87156,7 @@ function projectRenderablePageOutline(page) {
86716
87156
  ...page,
86717
87157
  blocks: page.blocks.flatMap((block) => block.admission.kind === "renderable" ? [{
86718
87158
  id: block.id,
87159
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
86719
87160
  kind: block.kind,
86720
87161
  purpose: block.purpose,
86721
87162
  content: block.admission.content,
@@ -86726,6 +87167,7 @@ function projectRenderablePageOutline(page) {
86726
87167
  function admitSdkRuntimePageBlock(block, customBlocks) {
86727
87168
  const base = {
86728
87169
  id: block.id,
87170
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
86729
87171
  kind: block.kind,
86730
87172
  purpose: block.purpose,
86731
87173
  ...block.bindings ? { bindings: block.bindings } : {}
@@ -145193,6 +145635,9 @@ function isApiSuccessResponse(json) {
145193
145635
  * });
145194
145636
  * ```
145195
145637
  */
145638
+ function publicEventsQuery(params) {
145639
+ return { ...params ?? {} };
145640
+ }
145196
145641
  function createBlockApi(config) {
145197
145642
  const { baseUrl, auth, authOverrides, siteId, isPreview } = config;
145198
145643
  const dedup = createDeduplicationCache({ ttl: 100 });
@@ -145345,23 +145790,7 @@ function createBlockApi(config) {
145345
145790
  const path = buildPath(EVENTS.list.path, { siteId: sid });
145346
145791
  return request(EVENTS.list, {
145347
145792
  path,
145348
- query: {
145349
- from: params?.from,
145350
- to: params?.to,
145351
- afterStartsAt: params?.afterStartsAt,
145352
- afterId: params?.afterId,
145353
- limit: params?.limit,
145354
- stage: params?.stage,
145355
- eventSurface: params?.eventSurface,
145356
- eventPresets: params?.eventPresets,
145357
- scheduleScope: params?.scheduleScope,
145358
- categoryIds: params?.categoryIds,
145359
- venueId: params?.venueId,
145360
- staffMemberId: params?.staffMemberId,
145361
- seriesId: params?.seriesId,
145362
- includeOccurrenceId: params?.includeOccurrenceId,
145363
- detailLevel: params?.detailLevel
145364
- }
145793
+ query: publicEventsQuery(params)
145365
145794
  });
145366
145795
  },
145367
145796
  async getEventFilters(params) {
@@ -145425,7 +145854,7 @@ function createBlockApi(config) {
145425
145854
  const path = buildPath(WHOLE_SERIES.waitlistClaimResolve.path, { siteId: sid });
145426
145855
  return request(WHOLE_SERIES.waitlistClaimResolve, {
145427
145856
  path,
145428
- body: { claimToken: data.claimToken }
145857
+ body: data
145429
145858
  });
145430
145859
  },
145431
145860
  async getDiscountsAvailable(data) {
@@ -152799,12 +153228,6 @@ var init_ActionRow = __esmMin((() => {
152799
153228
  between: "rb-justify-between"
152800
153229
  };
152801
153230
  }));
152802
- var init_BookingOptionCompactRow = __esmMin((() => {
152803
- init_buttons();
152804
- }));
152805
- var init_BookingOptionList = __esmMin((() => {
152806
- init_BookingOptionCompactRow();
152807
- }));
152808
153231
  //#endregion
152809
153232
  //#region ../blocks/src/system/runtime/shared/components/LoggedInAsUser.tsx
152810
153233
  /**
@@ -152929,8 +153352,6 @@ var init_components = __esmMin((() => {
152929
153352
  init_CrossIcon();
152930
153353
  init_DiscountCodeDisclosure();
152931
153354
  init_ActionRow();
152932
- init_BookingOptionCompactRow();
152933
- init_BookingOptionList();
152934
153355
  init_FieldValidationMessage();
152935
153356
  init_FeedbackMessage();
152936
153357
  init_LoggedInAsUser();
@@ -153548,6 +153969,93 @@ var init_event_registration_headless_state = __esmMin((() => {
153548
153969
  init_event_registration_headless_planning();
153549
153970
  }));
153550
153971
  //#endregion
153972
+ //#region ../blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.ts
153973
+ /** Recovery may select held places; checkout still owns admission and payment validation. */
153974
+ function checkoutRecoveryOptionAvailability(availability) {
153975
+ if (availability.kind === "available" || availability.reason === "sold_out" || availability.reason === "overallCapacityUnavailable") return {
153976
+ kind: "available",
153977
+ remainingPlaces: null
153978
+ };
153979
+ return availability;
153980
+ }
153981
+ /**
153982
+ * A form-only projection for the explicit existing-checkout path. It permits
153983
+ * collecting the original selection without claiming a new place is available.
153984
+ * The public checkout service identifies the customer and remains the admission
153985
+ * authority; no reservation/customer data is exposed through this projection.
153986
+ */
153987
+ function getCheckoutRecoveryFormEligibility(eligibility) {
153988
+ if (!eligibility || eligibility.registration.kind !== "none" && eligibility.registration.kind !== "pending_payment" || eligibility.availability.kind === "unavailable" && eligibility.availability.reason !== "full" && eligibility.availability.reason !== "selectionRequired") return eligibility;
153989
+ const amountCents = eligibility.price ?? 0;
153990
+ if (amountCents <= 0 || !eligibility.currency || eligibility.availability.kind === "unavailable" && eligibility.availability.reason === "selectionRequired") return eligibility.registration.kind === "pending_payment" ? {
153991
+ ...eligibility,
153992
+ registration: { kind: "none" },
153993
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
153994
+ ...option,
153995
+ availability: checkoutRecoveryOptionAvailability(option.availability)
153996
+ }))
153997
+ } : eligibility;
153998
+ const currency = eligibility.currency;
153999
+ const paymentOptions = eligibility.paymentTerms.allowedOptions.map((option) => {
154000
+ switch (option.kind) {
154001
+ case "upfront": return {
154002
+ kind: "payInFull",
154003
+ amountCents,
154004
+ currency
154005
+ };
154006
+ case "deferred_manual": return {
154007
+ kind: "deferredManual",
154008
+ amountCents,
154009
+ currency
154010
+ };
154011
+ case "instalment_plan": return {
154012
+ kind: "instalmentPlan",
154013
+ amountCents,
154014
+ currency
154015
+ };
154016
+ case "flexible_balance": return {
154017
+ kind: "flexibleBalance",
154018
+ amountCents,
154019
+ currency
154020
+ };
154021
+ }
154022
+ });
154023
+ return {
154024
+ ...eligibility,
154025
+ registration: { kind: "none" },
154026
+ availability: {
154027
+ kind: "available",
154028
+ remainingPlaces: null,
154029
+ waitlistEnabled: eligibility.waitlistEnabled
154030
+ },
154031
+ eligible: paymentOptions.length > 0,
154032
+ isFull: false,
154033
+ canJoinWaitlist: false,
154034
+ isFree: false,
154035
+ requiresPayment: true,
154036
+ canPayDirectly: paymentOptions.length > 0,
154037
+ paymentOptions,
154038
+ eligiblePasses: [],
154039
+ eligibleMemberships: [],
154040
+ ticketTypes: eligibility.ticketTypes.map((option) => ({
154041
+ ...option,
154042
+ availability: checkoutRecoveryOptionAvailability(option.availability)
154043
+ }))
154044
+ };
154045
+ }
154046
+ function isSoldOutEventSelectable(event, waitlistAvailable) {
154047
+ return waitlistAvailable || canRecoverEventCheckout(event);
154048
+ }
154049
+ function canJoinWaitlistOutsideRecovery(event, attendanceMode, checkoutRecovery) {
154050
+ return !checkoutRecovery && event !== null && canJoinEventWaitlist(event, { attendanceMode });
154051
+ }
154052
+ function canRecoverEventCheckout(event) {
154053
+ return event !== null && (event.registrationSubject.kind === "wholeSeries" || event.pricing.kind !== "free" && event.pricing.kind !== "external");
154054
+ }
154055
+ var init_checkoutRecovery = __esmMin((() => {
154056
+ init_domain();
154057
+ }));
154058
+ //#endregion
153551
154059
  //#region ../blocks/src/system/runtime/nodes/event-registration/utils.ts
153552
154060
  function getPortalSubjectEmail(profile) {
153553
154061
  return profile?.email ?? null;
@@ -153719,6 +154227,7 @@ function getEventSelectionMode(events) {
153719
154227
  }
153720
154228
  var EventSelectionStep;
153721
154229
  var init_EventSelectionStep = __esmMin((() => {
154230
+ init_checkoutRecovery();
153722
154231
  init_utils();
153723
154232
  init_domain();
153724
154233
  EventSelectionStep = ({ events, selectedEvent, onSelect, showVenue, showCapacity }) => {
@@ -153735,7 +154244,7 @@ var init_EventSelectionStep = __esmMin((() => {
153735
154244
  const remaining = getRemainingPlaces(selectMostOpenCapacitySource(event));
153736
154245
  const isSoldOut = isEventFull(event);
153737
154246
  const canJoinWaitlist = canJoinEventWaitlistOnAnyMode(event);
153738
- const isUnavailable = isSoldOut && !canJoinWaitlist;
154247
+ const isUnavailable = isSoldOut && !isSoldOutEventSelectable(event, canJoinWaitlist);
153739
154248
  const isLowCapacity = remaining.kind === "low";
153740
154249
  const capacityLabel = formatEventRemainingPlaces(event, { full: "Sold out" });
153741
154250
  const timeZone = event.timeZone ?? null;
@@ -153781,6 +154290,36 @@ var init_EventSelectionStep = __esmMin((() => {
153781
154290
  };
153782
154291
  }));
153783
154292
  //#endregion
154293
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.ts
154294
+ /** Recovery belongs to the selected booking subject; changing events resets its scope. */
154295
+ function useCheckoutRecovery(event, setStep) {
154296
+ const [recoveryEventId, setRecoveryEventId] = useState(null);
154297
+ return {
154298
+ checkoutRecovery: event !== null && recoveryEventId === event.selectionId,
154299
+ startCheckoutRecovery: useCallback(() => {
154300
+ if (!event) return;
154301
+ setRecoveryEventId(event.selectionId);
154302
+ setStep("select-tickets");
154303
+ }, [event, setStep])
154304
+ };
154305
+ }
154306
+ /** Authenticated pending bookings enter the same form-only recovery path as guests. */
154307
+ function useCheckoutRecoveryEligibility(eligibility, step, checkoutRecovery, startCheckoutRecovery) {
154308
+ const registrationKind = eligibility?.registration.kind;
154309
+ useEffect(() => {
154310
+ if ((step === "select-event" || step === "select-tickets" || step === "enter-details" || step === "select-payment") && registrationKind === "pending_payment" && !checkoutRecovery) startCheckoutRecovery();
154311
+ }, [
154312
+ registrationKind,
154313
+ step,
154314
+ checkoutRecovery,
154315
+ startCheckoutRecovery
154316
+ ]);
154317
+ return useMemo(() => checkoutRecovery ? getCheckoutRecoveryFormEligibility(eligibility) : eligibility, [checkoutRecovery, eligibility]);
154318
+ }
154319
+ var init_useCheckoutRecovery = __esmMin((() => {
154320
+ init_checkoutRecovery();
154321
+ }));
154322
+ //#endregion
153784
154323
  //#region ../blocks/src/system/runtime/nodes/event-registration/registrationErrorRecovery.ts
153785
154324
  function resolveRegistrationRecoveryAction(step, action) {
153786
154325
  if (step === "payment-failed") return "payment-options";
@@ -154653,6 +155192,10 @@ var init_event_registration_errors = __esmMin((() => {
154653
155192
  message: "We’re checking your booking and payment. Please don’t try to book again yet. If you’ve already paid, you don’t need to pay again.",
154654
155193
  action: "payment-status"
154655
155194
  },
155195
+ paymentProviderUnavailable: {
155196
+ message: "We couldn’t reach the payment provider. Please try again in a minute.",
155197
+ action: "retry"
155198
+ },
154656
155199
  paymentPageUnavailable: {
154657
155200
  message: "We couldn’t open the payment page. Please refresh this page and try again. If this keeps happening, contact the organiser for help.",
154658
155201
  action: "retry"
@@ -154838,11 +155381,6 @@ function ensureWaitlistClaimLocationTracking() {
154838
155381
  } catch {}
154839
155382
  window.addEventListener("popstate", emitWaitlistClaimLocationChange);
154840
155383
  }
154841
- function getWaitlistClaimTokenFromUrl() {
154842
- if (typeof window === "undefined") return null;
154843
- const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
154844
- return token.length > 0 ? token : null;
154845
- }
154846
155384
  function subscribeToWaitlistClaimToken(callback) {
154847
155385
  if (typeof window === "undefined") return () => {};
154848
155386
  ensureWaitlistClaimLocationTracking();
@@ -154851,28 +155389,42 @@ function subscribeToWaitlistClaimToken(callback) {
154851
155389
  window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
154852
155390
  };
154853
155391
  }
154854
- function getWaitlistClaimTokenSnapshot() {
154855
- return getWaitlistClaimTokenFromUrl();
155392
+ function getWaitlistClaimLocationSnapshot() {
155393
+ return typeof window === "undefined" ? "" : window.location.search;
155394
+ }
155395
+ function parseWaitlistClaimCredential(search) {
155396
+ const params = new URLSearchParams(search);
155397
+ const token = params.get("waitlist_claim")?.trim();
155398
+ if (token) return {
155399
+ kind: "emailedToken",
155400
+ token
155401
+ };
155402
+ const entryId = params.get("waitlistEntry")?.trim();
155403
+ return entryId ? {
155404
+ kind: "portalOwnedEntry",
155405
+ entryId
155406
+ } : null;
154856
155407
  }
154857
155408
  function useWaitlistClaim() {
154858
155409
  return useWaitlistClaimWithDeps(useWaitlistClaimDeps);
154859
155410
  }
154860
155411
  function useWaitlistClaimWithDeps(deps) {
154861
- return useResolvedWaitlistClaim(deps, useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimTokenSnapshot, () => null));
155412
+ const locationSearch = useSyncExternalStore(subscribeToWaitlistClaimToken, getWaitlistClaimLocationSnapshot, () => "");
155413
+ return useResolvedWaitlistClaim(deps, useMemo(() => parseWaitlistClaimCredential(locationSearch), [locationSearch]));
154862
155414
  }
154863
- function useResolvedWaitlistClaim(deps, token) {
155415
+ function useResolvedWaitlistClaim(deps, credential) {
154864
155416
  const api = deps.useBlockApi();
154865
- const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(token), createInitialWaitlistClaimState);
155417
+ const [state, dispatch] = useReducer(waitlistClaimReducer, Boolean(credential), createInitialWaitlistClaimState);
154866
155418
  useEffect(() => {
154867
155419
  let cancelled = false;
154868
155420
  async function resolveClaim() {
154869
- if (!token) {
155421
+ if (!credential) {
154870
155422
  dispatch({ type: "cleared" });
154871
155423
  return;
154872
155424
  }
154873
155425
  dispatch({ type: "started" });
154874
155426
  try {
154875
- const result = await api.resolveWaitlistClaim({ claimToken: token });
155427
+ const result = credential.kind === "portalOwnedEntry" ? await api.resolveWaitlistClaim({ waitlistEntryId: credential.entryId }) : await api.resolveWaitlistClaim({ claimToken: credential.token });
154876
155428
  if (cancelled) return;
154877
155429
  dispatch({
154878
155430
  type: "resolved",
@@ -154890,9 +155442,10 @@ function useResolvedWaitlistClaim(deps, token) {
154890
155442
  return () => {
154891
155443
  cancelled = true;
154892
155444
  };
154893
- }, [api, token]);
155445
+ }, [api, credential]);
154894
155446
  return {
154895
- token,
155447
+ token: credential?.kind === "emailedToken" ? credential.token : null,
155448
+ entryId: credential?.kind === "portalOwnedEntry" ? credential.entryId : null,
154896
155449
  claim: getWaitlistClaim(state),
154897
155450
  error: getWaitlistClaimError(state),
154898
155451
  loginMessage: getWaitlistClaimLoginMessage(state),
@@ -155395,15 +155948,12 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
155395
155948
  * landed — a success, or a hand-off to checkout — because until then nobody
155396
155949
  * knows whether the first one committed.
155397
155950
  *
155398
- * Reusing it after a failure is safe even if the customer edits their
155399
- * details. The server consults the command record before it re-checks
155400
- * anything, so a submission that already booked is answered with the booking
155401
- * that exists — not refused for spending a credit or a claim that this very
155402
- * command already spent, and not treated as a second booking because a name
155403
- * or a note changed in between.
155951
+ * Identical retries retain the command after a lost response. Changed form
155952
+ * details get a new command so the server applies the new booking intent.
155404
155953
  */
155405
- const commandIdRef = useRef(null);
155406
- return async (method, passId, membershipId, selection, submitOptions) => {
155954
+ const commandRef = useRef(null);
155955
+ const inFlightRef = useRef(null);
155956
+ const submit = async (method, passId, membershipId, selection, submitOptions) => {
155407
155957
  const target = options.registrationTarget;
155408
155958
  if (!target) return {
155409
155959
  ok: false,
@@ -155411,44 +155961,34 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
155411
155961
  message: "Select an event to continue."
155412
155962
  };
155413
155963
  options.setStep("submitting");
155414
- const registrationCommandId = commandIdRef.current ?? deps.createClientCommandId();
155415
- commandIdRef.current = registrationCommandId;
155964
+ const registrationCommandId = commandRef.current?.id ?? deps.createClientCommandId();
155416
155965
  try {
155417
- const prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
155966
+ let prepared = prepareSubmitContext(options, registrationCommandId, target, method, passId, membershipId, selection);
155418
155967
  if (prepared.subject.kind === "wholeSeries" && method === "stripe") {
155419
- commandIdRef.current = null;
155968
+ commandRef.current = null;
155420
155969
  return await submitWholeSeriesCheckout(options, deps, {
155421
155970
  ...prepared,
155422
155971
  subject: prepared.subject
155423
155972
  }, submitOptions);
155424
155973
  }
155974
+ const request = buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId);
155975
+ const intentKey = registrationRequestIntentKey(request);
155976
+ if (commandRef.current !== null && commandRef.current.intentKey !== intentKey) prepared = {
155977
+ ...prepared,
155978
+ registrationCommandId: deps.createClientCommandId()
155979
+ };
155980
+ commandRef.current = {
155981
+ id: prepared.registrationCommandId,
155982
+ intentKey
155983
+ };
155425
155984
  const result = await options.api.registerForEvent({
155426
- registrationCommandId: prepared.registrationCommandId,
155427
- subject: prepared.subject,
155428
- ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
155429
- selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
155430
- email: options.formData.email.trim().toLowerCase(),
155431
- name: options.formData.name.trim(),
155432
- phone: options.formData.phone.trim() || void 0,
155433
- notes: options.formData.notes.trim() || void 0,
155434
- consentAccepted: options.formData.consentAccepted,
155435
- altchaSolution: options.altchaSolution,
155436
- paymentMethod: method,
155437
- customerPassId: method === "pass" ? passId : void 0,
155438
- customerMembershipId: method === "membership" ? membershipId : void 0,
155439
- bundleProductId: prepared.bundleProductId,
155440
- claimToken: options.claimToken ?? void 0,
155441
- guests: prepared.guestsPayload
155985
+ ...request,
155986
+ registrationCommandId: prepared.registrationCommandId
155442
155987
  });
155443
- commandIdRef.current = null;
155444
- if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
155445
- options.setRegistrationResult(toRegistrationResult(result));
155446
- options.setStep("success");
155447
- return {
155448
- ok: true,
155449
- outcome: { kind: "completed" }
155450
- };
155988
+ commandRef.current = null;
155989
+ return await completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions);
155451
155990
  } catch (error) {
155991
+ if (error instanceof BlockApiError && error.tag === "registrationPreparationChanged") commandRef.current = null;
155452
155992
  const { message, action } = registrationErrorPresentation(error);
155453
155993
  options.setErrorAction?.(action);
155454
155994
  options.setErrorMessage(message);
@@ -155460,6 +156000,24 @@ function useEventRegistrationSubmitWithDeps(options, deps) {
155460
156000
  };
155461
156001
  }
155462
156002
  };
156003
+ return (...args) => {
156004
+ if (inFlightRef.current) return inFlightRef.current;
156005
+ const pending = Promise.resolve().then(() => submit(...args));
156006
+ inFlightRef.current = pending;
156007
+ pending.finally(() => {
156008
+ if (inFlightRef.current === pending) inFlightRef.current = null;
156009
+ });
156010
+ return pending;
156011
+ };
156012
+ }
156013
+ async function completeRegistrationSubmission(options, deps, prepared, result, method, submitOptions) {
156014
+ if (needsOccurrenceCheckout(result, method)) return await submitOccurrenceCheckout(options, deps, prepared, result, method, submitOptions);
156015
+ options.setRegistrationResult(toRegistrationResult(result));
156016
+ options.setStep("success");
156017
+ return {
156018
+ ok: true,
156019
+ outcome: { kind: "completed" }
156020
+ };
155463
156021
  }
155464
156022
  function toTicketSelectionRequests(lines) {
155465
156023
  return lines.map((line) => ({
@@ -155534,6 +156092,7 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
155534
156092
  altchaSolution: options.altchaSolution,
155535
156093
  guests: prepared.guestsPayload,
155536
156094
  claimToken: options.claimToken ?? void 0,
156095
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
155537
156096
  discountCode: options.discountCode.trim() || void 0,
155538
156097
  collectionOptionKind: prepared.selectionSnapshot.collectionOptionKind,
155539
156098
  checkoutAttemptId,
@@ -155555,14 +156114,14 @@ async function submitWholeSeriesCheckout(options, deps, prepared, submitOptions)
155555
156114
  }
155556
156115
  if (result.bypassed) return completeBypassedCheckout(options);
155557
156116
  if (!result.checkoutUrl) throw new Error("Checkout URL missing");
155558
- savePendingCheckout(options, deps, prepared, checkoutAttemptId, {
156117
+ savePendingCheckout(options, deps, prepared, result.checkoutAttemptId, {
155559
156118
  scope: "wholeSeries",
155560
156119
  registrationId: result.registrationId
155561
156120
  });
155562
156121
  return redirectToCheckout(result.checkoutUrl, submitOptions);
155563
156122
  }
155564
156123
  function needsOccurrenceCheckout(result, method) {
155565
- return result.scope === "occurrence" && !result.alreadyRegistered && result.status === "confirmed" && result.pendingPayment && [
156124
+ return result.scope === "occurrence" && result.status === "confirmed" && result.pendingPayment && [
155566
156125
  "stripe",
155567
156126
  "pass_bundle",
155568
156127
  "membership_bundle"
@@ -155582,6 +156141,7 @@ async function submitOccurrenceCheckout(options, deps, prepared, registration, m
155582
156141
  kind: "occurrence",
155583
156142
  attendeeId: registration.attendeeId
155584
156143
  },
156144
+ registrationCommandId: prepared.registrationCommandId,
155585
156145
  checkoutType: method === "pass_bundle" ? "pass_bundle" : method === "membership_bundle" ? "membership_bundle" : "event",
155586
156146
  productId: prepared.bundleProductId,
155587
156147
  discountCode: options.discountCode.trim() || void 0,
@@ -155624,10 +156184,36 @@ function redirectToCheckout(checkoutUrl, submitOptions) {
155624
156184
  }
155625
156185
  };
155626
156186
  }
156187
+ function registrationRequestIntentKey(request) {
156188
+ const { registrationCommandId: _command, altchaSolution: _proof, ...intent } = request;
156189
+ return JSON.stringify(intent);
156190
+ }
156191
+ function buildOccurrenceRegistrationRequest(options, prepared, method, passId, membershipId) {
156192
+ return {
156193
+ registrationCommandId: prepared.registrationCommandId,
156194
+ subject: prepared.subject,
156195
+ ticketSelections: toTicketSelectionRequests(prepared.ticketSelections),
156196
+ selectedSlidingAmount: options.selectedSlidingAmount ?? void 0,
156197
+ email: options.formData.email.trim().toLowerCase(),
156198
+ name: options.formData.name.trim(),
156199
+ phone: options.formData.phone.trim() || void 0,
156200
+ notes: options.formData.notes.trim() || void 0,
156201
+ consentAccepted: options.formData.consentAccepted,
156202
+ altchaSolution: options.altchaSolution,
156203
+ paymentMethod: method,
156204
+ customerPassId: method === "pass" ? passId : void 0,
156205
+ customerMembershipId: method === "membership" ? membershipId : void 0,
156206
+ bundleProductId: prepared.bundleProductId,
156207
+ claimToken: options.claimToken ?? void 0,
156208
+ waitlistEntryId: options.waitlistEntryId ?? void 0,
156209
+ guests: prepared.guestsPayload
156210
+ };
156211
+ }
155627
156212
  var eventRegistrationSubmitDeps;
155628
156213
  var init_useEventRegistrationSubmit = __esmMin((() => {
155629
- init_registrationErrorPresentation();
156214
+ init_client$1();
155630
156215
  init_shared();
156216
+ init_registrationErrorPresentation();
155631
156217
  init_constants();
155632
156218
  init_sessionStorage();
155633
156219
  init_ticketSelectionLines();
@@ -155874,14 +156460,28 @@ function useEventRegistrationWizardWithDeps(options, deps) {
155874
156460
  }), [options.occurrenceContext, selectedEvent]);
155875
156461
  const registrationOccurrenceId = getRegistrationOccurrenceId(registrationTarget);
155876
156462
  const currentEvent = selectedEvent ?? preSelectedEvent;
156463
+ const setStep = useCallback((nextStep) => {
156464
+ dispatchFlow({
156465
+ type: "set-step",
156466
+ step: nextStep
156467
+ });
156468
+ }, []);
156469
+ const { checkoutRecovery, startCheckoutRecovery } = useCheckoutRecovery(currentEvent, setStep);
155877
156470
  const currentEventUsesTicketTypes = usesTieredPricing(currentEvent);
155878
- const currentCanJoinWaitlist = currentEvent ? canJoinEventWaitlist(currentEvent, { attendanceMode: selectedAttendanceMode }) : false;
156471
+ const currentCanJoinWaitlist = canJoinWaitlistOutsideRecovery(currentEvent, selectedAttendanceMode, checkoutRecovery);
155879
156472
  const usesTicketTypeSelections = currentEventUsesTicketTypes && !currentCanJoinWaitlist;
155880
156473
  const eventTicketTypesForSelection = useMemo(() => getVisibleTicketTypes({
155881
156474
  event: currentEvent,
155882
156475
  eligibility: null,
155883
156476
  selectedAttendanceMode
155884
- }), [currentEvent, selectedAttendanceMode]);
156477
+ }).map((option) => checkoutRecovery ? {
156478
+ ...option,
156479
+ availability: checkoutRecoveryOptionAvailability(option.availability)
156480
+ } : option), [
156481
+ currentEvent,
156482
+ selectedAttendanceMode,
156483
+ checkoutRecovery
156484
+ ]);
155885
156485
  const normalizedSelectedTicketLines = useMemo(() => normalizeTicketSelectionLines(selectedTicketLines), [selectedTicketLines]);
155886
156486
  const ticketTypeSelectionTotal = useMemo(() => getTicketSelectionTotal(normalizedSelectedTicketLines), [normalizedSelectedTicketLines]);
155887
156487
  const ticketsCount = usesTicketTypeSelections ? ticketTypeSelectionTotal : flowState.ticketsCount;
@@ -155919,17 +156519,11 @@ function useEventRegistrationWizardWithDeps(options, deps) {
155919
156519
  isAuthenticated: portalAuthState === "authenticated",
155920
156520
  occurrenceId: registrationOccurrenceId
155921
156521
  });
155922
- const eligibility = eligibilityResult.eligibility;
156522
+ const eligibility = useCheckoutRecoveryEligibility(eligibilityResult.eligibility, step, checkoutRecovery, startCheckoutRecovery);
155923
156523
  const eligibilityLoading = eligibilityResult.isLoading;
155924
156524
  const eligibilityError = eligibilityResult.error;
155925
156525
  const portalCreditState = eligibilityResult.creditState;
155926
156526
  const registrationState = eligibility?.registration ?? { kind: "none" };
155927
- const setStep = useCallback((nextStep) => {
155928
- dispatchFlow({
155929
- type: "set-step",
155930
- step: nextStep
155931
- });
155932
- }, []);
155933
156527
  const setTicketsCount = useCallback((nextTicketsCount) => {
155934
156528
  dispatchFlow({
155935
156529
  type: "set-tickets-count",
@@ -156037,10 +156631,14 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156037
156631
  event: currentEvent,
156038
156632
  eligibility,
156039
156633
  selectedAttendanceMode
156040
- }), [
156634
+ }).map((option) => checkoutRecovery ? {
156635
+ ...option,
156636
+ availability: checkoutRecoveryOptionAvailability(option.availability)
156637
+ } : option), [
156041
156638
  currentEvent,
156042
156639
  selectedAttendanceMode,
156043
- eligibility
156640
+ eligibility,
156641
+ checkoutRecovery
156044
156642
  ]);
156045
156643
  const singleSelectedPricingOptionId = getSingleSelectedPricingOptionId(normalizedSelectedTicketLines);
156046
156644
  const selectedTicketType = useMemo(() => findSelectedTicketType({
@@ -156064,8 +156662,12 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156064
156662
  const event = currentEvent;
156065
156663
  if (!usesTieredPricing(event)) return false;
156066
156664
  if ((event.deliveryMode ?? "in_person") === "hybrid" && !selectedAttendanceMode) return false;
156067
- return !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
156068
- }, [currentEvent, selectedAttendanceMode]);
156665
+ return checkoutRecovery || !canJoinEventWaitlist(event, { attendanceMode: selectedAttendanceMode });
156666
+ }, [
156667
+ currentEvent,
156668
+ selectedAttendanceMode,
156669
+ checkoutRecovery
156670
+ ]);
156069
156671
  const hasValidTicketSelection = hasValidPricingOptionSelection({
156070
156672
  selectionRequired: ticketTypeSelectionRequired,
156071
156673
  lines: normalizedSelectedTicketLines,
@@ -156269,6 +156871,7 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156269
156871
  guests,
156270
156872
  discountCode: discountUi.discountCode,
156271
156873
  claimToken: waitlistClaim.token,
156874
+ waitlistEntryId: waitlistClaim.entryId,
156272
156875
  setPendingRegistrationReference,
156273
156876
  setStep,
156274
156877
  setRegistrationResult: (result) => setRegistrationResult(result),
@@ -156331,6 +156934,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156331
156934
  scopedEvents,
156332
156935
  preSelectedEvent,
156333
156936
  hasPreSelectedContext,
156937
+ checkoutRecovery,
156938
+ startCheckoutRecovery,
156334
156939
  step,
156335
156940
  setStep,
156336
156941
  selectedEvent,
@@ -156415,6 +157020,8 @@ function useEventRegistrationWizardWithDeps(options, deps) {
156415
157020
  }
156416
157021
  var eventRegistrationWizardDeps;
156417
157022
  var init_useEventRegistrationWizard = __esmMin((() => {
157023
+ init_checkoutRecovery();
157024
+ init_useCheckoutRecovery();
156418
157025
  init_src$2();
156419
157026
  init_registrationErrorRecovery();
156420
157027
  init_api();
@@ -156577,6 +157184,50 @@ var init_MagicLinkForm = __esmMin((() => {
156577
157184
  init_MagicLinkForm_state();
156578
157185
  }));
156579
157186
  //#endregion
157187
+ //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
157188
+ var labels, ErrorStep;
157189
+ var init_ErrorStep = __esmMin((() => {
157190
+ init_shared();
157191
+ labels = {
157192
+ none: "",
157193
+ retry: "Try again",
157194
+ places: "Choose places",
157195
+ start: "Start again",
157196
+ details: "Check my details",
157197
+ "payment-options": "View payment options",
157198
+ "payment-status": "Check payment status",
157199
+ portal: "View my bookings",
157200
+ event: "View event"
157201
+ };
157202
+ ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
157203
+ const offerWaitlist = action === "places" && canJoinWaitlist;
157204
+ return /* @__PURE__ */ jsx(TerminalPanel, {
157205
+ tone: "error",
157206
+ className: "er-center",
157207
+ titleClassName: "er-title--lg er-message",
157208
+ icon: /* @__PURE__ */ jsx(StateIcon, {
157209
+ variant: "error",
157210
+ children: /* @__PURE__ */ jsx(CrossIcon, {})
157211
+ }),
157212
+ title: "We couldn’t complete your booking",
157213
+ body: /* @__PURE__ */ jsx("p", {
157214
+ className: "er-text--muted er-message",
157215
+ children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
157216
+ }),
157217
+ actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
157218
+ href: "/portal",
157219
+ className: "er-retry-btn",
157220
+ children: labels[action]
157221
+ }) : /* @__PURE__ */ jsx("button", {
157222
+ type: "button",
157223
+ onClick: onRetry,
157224
+ className: "er-retry-btn",
157225
+ children: offerWaitlist ? "Join the waiting list" : labels[action]
157226
+ })
157227
+ });
157228
+ };
157229
+ }));
157230
+ //#endregion
156580
157231
  //#region ../blocks/src/system/runtime/nodes/event-registration/EventRegistrationSummaryBar.tsx
156581
157232
  function getScheduleSummary(wizard, summaryEvent) {
156582
157233
  if (summaryEvent.registrationSubject.kind !== "wholeSeries") {
@@ -156866,7 +157517,7 @@ function SelectTicketsActions(props) {
156866
157517
  const currentEvent = wizard.selectedEvent ?? wizard.preSelectedEvent;
156867
157518
  const registrationOptionsPending = wizard.registrationOptionsState.tag === "idle" || wizard.registrationOptionsState.tag === "loading";
156868
157519
  const registrationOptionsFailed = wizard.registrationOptionsState.tag === "failed";
156869
- const isSoldOutWithoutWaitlist = !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
157520
+ const isSoldOutWithoutWaitlist = !wizard.checkoutRecovery && !hasWaitlistClaim && isFullWithNoWaitlist(currentEvent, wizard.selectedAttendanceMode);
156870
157521
  const isCheckingExistingRegistration = wizard.portalAuthState === "authenticated" && wizard.existingRegistrationLoading;
156871
157522
  const hasExistingRegistration = isExistingRegistrationBlocking$1(wizard);
156872
157523
  const ticketTypeSelectionBlocked = wizard.ticketTypeSelectionRequired && !wizard.hasValidTicketSelection;
@@ -157471,21 +158122,42 @@ function resolveTicketSelectionPricing(event) {
157471
158122
  currency: event ? publicEventPricingCurrency(event.pricing) : null
157472
158123
  };
157473
158124
  }
158125
+ function CheckoutRecoveryEntry(props) {
158126
+ return props.onContinue ? /* @__PURE__ */ jsx("button", {
158127
+ type: "button",
158128
+ className: "er-back-btn",
158129
+ onClick: props.onContinue,
158130
+ children: "Continue an existing booking"
158131
+ }) : null;
158132
+ }
158133
+ function getTicketSelectionCapacity(event, attendanceMode, checkoutRecovery) {
158134
+ if (checkoutRecovery) return {
158135
+ availableSpots: null,
158136
+ isSoldOut: false,
158137
+ canJoinWaitlist: false,
158138
+ eventAvailabilityLabel: null
158139
+ };
158140
+ const source = event ? selectEventCapacitySource(event, attendanceMode) : null;
158141
+ const availability = source ? getEventAvailability(source) : null;
158142
+ const canJoinWaitlist = source ? canJoinEventWaitlist(source) : false;
158143
+ return {
158144
+ availableSpots: availability?.available,
158145
+ isSoldOut: availability?.isFull ?? false,
158146
+ canJoinWaitlist,
158147
+ eventAvailabilityLabel: !canJoinWaitlist && source ? formatRemainingPlaces(source) : null
158148
+ };
158149
+ }
157474
158150
  var TicketSelectionStep;
157475
158151
  var init_TicketSelectionStep = __esmMin((() => {
157476
158152
  init_src$2();
157477
158153
  init_domain();
157478
158154
  init_utils();
157479
158155
  init_ticketSelectionLines();
157480
- TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" } }) => {
158156
+ TicketSelectionStep = ({ event, occurrenceContext: _occurrenceContext, selectedAttendanceMode = null, onAttendanceModeChange, ticketsCount, maxTickets, visibleTicketTypes: visibleTicketTypesOverride, ticketSelections = [], onTicketSelectionsChange, slidingScale = null, selectedSlidingAmountInput = "", slidingScaleSelectionMessage = null, onSlidingAmountChange, onTicketsChange, bookingUnit = { kind: "ticket" }, checkoutRecovery = false, onCheckoutRecovery }) => {
157481
158157
  const unit = bookingUnit.kind;
157482
158158
  const deliveryMode = event?.deliveryMode ?? "in_person";
157483
158159
  const attendanceModes = event?.attendanceModes ?? [];
157484
- const capacitySource = event ? selectEventCapacitySource(event, selectedAttendanceMode) : null;
157485
- const availability = capacitySource ? getEventAvailability(capacitySource) : null;
157486
- const availableSpots = availability?.available;
157487
- const isSoldOut = availability?.isFull ?? false;
157488
- const canJoinWaitlist = capacitySource ? canJoinEventWaitlist(capacitySource) : false;
158160
+ const { availableSpots, isSoldOut, canJoinWaitlist, eventAvailabilityLabel } = getTicketSelectionCapacity(event, selectedAttendanceMode, checkoutRecovery);
157489
158161
  const { mode: eventPricingMode, currency: eventPricingCurrency } = resolveTicketSelectionPricing(event);
157490
158162
  const usesTicketTypes = eventPricingMode === "tiered" && !canJoinWaitlist;
157491
158163
  const visibleTicketTypes = usesTicketTypes ? visibleTicketTypesOverride ?? getVisibleTicketTypes({
@@ -157504,7 +158176,6 @@ var init_TicketSelectionStep = __esmMin((() => {
157504
158176
  selectedTicketTypeRemainingCapacity: implicitTicketType?.availability.remainingPlaces ?? null,
157505
158177
  hasSelectedTicketType: implicitTicketType !== null
157506
158178
  });
157507
- const eventAvailabilityLabel = !canJoinWaitlist && capacitySource ? formatRemainingPlaces(capacitySource) : null;
157508
158179
  if (deliveryMode === "hybrid" && !selectedAttendanceMode) return /* @__PURE__ */ jsxs("div", {
157509
158180
  className: "rb-reg-stack er-stack",
157510
158181
  children: [
@@ -157525,13 +158196,17 @@ var init_TicketSelectionStep = __esmMin((() => {
157525
158196
  });
157526
158197
  if (isSoldOut && !canJoinWaitlist) return /* @__PURE__ */ jsxs("div", {
157527
158198
  className: "rb-reg-stack er-stack",
157528
- children: [/* @__PURE__ */ jsx("h3", {
157529
- className: "er-title",
157530
- children: "Sold out"
157531
- }), /* @__PURE__ */ jsx("p", {
157532
- className: "er-text er-text--muted",
157533
- children: "Sorry you missed out! This event is fully booked."
157534
- })]
158199
+ children: [
158200
+ /* @__PURE__ */ jsx("h3", {
158201
+ className: "er-title",
158202
+ children: "Sold out"
158203
+ }),
158204
+ /* @__PURE__ */ jsx("p", {
158205
+ className: "er-text er-text--muted",
158206
+ children: "Sorry you missed out! This event is fully booked."
158207
+ }),
158208
+ /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })
158209
+ ]
157535
158210
  });
157536
158211
  if (!eventPricingCurrency) return /* @__PURE__ */ jsx("div", {
157537
158212
  className: "rb-reg-stack er-stack",
@@ -157599,9 +158274,13 @@ var init_TicketSelectionStep = __esmMin((() => {
157599
158274
  })]
157600
158275
  })
157601
158276
  ] }),
157602
- canJoinWaitlist && /* @__PURE__ */ jsx("p", {
158277
+ canJoinWaitlist && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
157603
158278
  className: "er-text er-text--muted",
157604
158279
  children: "This event is currently full. Continue to join the waitlist if a place opens up."
158280
+ }), /* @__PURE__ */ jsx(CheckoutRecoveryEntry, { onContinue: onCheckoutRecovery })] }),
158281
+ checkoutRecovery && /* @__PURE__ */ jsx("p", {
158282
+ className: "er-text er-text--muted",
158283
+ children: "Enter the details from your earlier booking. We’ll check your checkout before continuing to payment."
157605
158284
  })
157606
158285
  ]
157607
158286
  });
@@ -158403,50 +159082,6 @@ var init_SuccessStep = __esmMin((() => {
158403
159082
  };
158404
159083
  }));
158405
159084
  //#endregion
158406
- //#region ../blocks/src/system/runtime/nodes/event-registration/ErrorStep.tsx
158407
- var labels, ErrorStep;
158408
- var init_ErrorStep = __esmMin((() => {
158409
- init_shared();
158410
- labels = {
158411
- none: "",
158412
- retry: "Try again",
158413
- places: "Choose places",
158414
- start: "Start again",
158415
- details: "Check my details",
158416
- "payment-options": "View payment options",
158417
- "payment-status": "Check payment status",
158418
- portal: "View my bookings",
158419
- event: "View event"
158420
- };
158421
- ErrorStep = ({ message, onRetry, action = "retry", canJoinWaitlist = false }) => {
158422
- const offerWaitlist = action === "places" && canJoinWaitlist;
158423
- return /* @__PURE__ */ jsx(TerminalPanel, {
158424
- tone: "error",
158425
- className: "er-center",
158426
- titleClassName: "er-title--lg er-message",
158427
- icon: /* @__PURE__ */ jsx(StateIcon, {
158428
- variant: "error",
158429
- children: /* @__PURE__ */ jsx(CrossIcon, {})
158430
- }),
158431
- title: "We couldn’t complete your booking",
158432
- body: /* @__PURE__ */ jsx("p", {
158433
- className: "er-text--muted er-message",
158434
- children: offerWaitlist ? "Sorry, this event is now full. You can join the waiting list, and we’ll email you if a place becomes available." : message
158435
- }),
158436
- actions: action === "none" ? void 0 : action === "portal" || action === "payment-status" ? /* @__PURE__ */ jsx("a", {
158437
- href: "/portal",
158438
- className: "er-retry-btn",
158439
- children: labels[action]
158440
- }) : /* @__PURE__ */ jsx("button", {
158441
- type: "button",
158442
- onClick: onRetry,
158443
- className: "er-retry-btn",
158444
- children: offerWaitlist ? "Join the waiting list" : labels[action]
158445
- })
158446
- });
158447
- };
158448
- }));
158449
- //#endregion
158450
159085
  //#region ../blocks/src/system/runtime/nodes/event-registration/VerifyingPaymentStep.tsx
158451
159086
  var VerifyingPaymentStep;
158452
159087
  var init_VerifyingPaymentStep = __esmMin((() => {
@@ -158733,12 +159368,14 @@ function EventRegistrationWizardContent(props) {
158733
159368
  onBookForSomeoneElse: wizard.handleBookForSomeoneElse
158734
159369
  }), /* @__PURE__ */ jsx(TicketSelectionStep, {
158735
159370
  event: wizard.selectedEvent,
159371
+ checkoutRecovery: wizard.checkoutRecovery,
159372
+ onCheckoutRecovery: canRecoverEventCheckout(wizard.selectedEvent) ? wizard.startCheckoutRecovery : void 0,
158736
159373
  occurrenceContext: wizard.occurrenceContext,
158737
159374
  selectedAttendanceMode: wizard.selectedAttendanceMode,
158738
159375
  onAttendanceModeChange: wizard.setSelectedAttendanceMode,
158739
159376
  ticketsCount: wizard.ticketsCount,
158740
159377
  maxTickets: wizard.maxTicketsNum,
158741
- visibleTicketTypes: wizard.eligibility ? wizard.visibleTicketTypes : void 0,
159378
+ visibleTicketTypes: wizard.visibleTicketTypes,
158742
159379
  ticketSelections: wizard.selectedTicketLines,
158743
159380
  onTicketSelectionsChange: wizard.setSelectedTicketLines,
158744
159381
  slidingScale: wizard.selectedEventSlidingScale,
@@ -158760,6 +159397,7 @@ var init_EventRegistrationWizardContent = __esmMin((() => {
158760
159397
  init_client();
158761
159398
  init_src();
158762
159399
  init_shared();
159400
+ init_checkoutRecovery();
158763
159401
  init_registrationStateMachine();
158764
159402
  init_siteCreditPreview();
158765
159403
  init_PaymentBlockingPanel();
@@ -158907,19 +159545,20 @@ function EventRegistrationSurface(props) {
158907
159545
  }), /* @__PURE__ */ jsx(EventRegistrationTerminalState, {
158908
159546
  wizard,
158909
159547
  supportEmail: props.supportEmail,
158910
- successMessage: props.successMessage
159548
+ successMessage: props.successMessage,
159549
+ buttonClass: props.buttonClass
158911
159550
  })]
158912
159551
  });
158913
159552
  }
158914
159553
  var init_EventRegistrationSurface = __esmMin((() => {
158915
- init_spinner();
158916
159554
  init_MagicLinkForm();
159555
+ init_spinner();
159556
+ init_ErrorStep();
158917
159557
  init_EventRegistrationSummaryBar();
158918
159558
  init_EventRegistrationWizardActions();
158919
159559
  init_EventRegistrationWizardContent();
158920
- init_StepIndicator();
158921
- init_ErrorStep();
158922
159560
  init_PaymentFailedStep();
159561
+ init_StepIndicator();
158923
159562
  init_SuccessStep();
158924
159563
  init_VerifyingPaymentStep();
158925
159564
  init_VerifyingTimeoutStep();
@@ -159318,6 +159957,88 @@ var init_PastOccurrenceNotice = __esmMin((() => {
159318
159957
  init_utils();
159319
159958
  }));
159320
159959
  //#endregion
159960
+ //#region ../blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.ts
159961
+ function useEventSourceRecovery(source, deps = defaultRecoveryDeps) {
159962
+ const api = deps.useApi();
159963
+ const wait = deps.wait;
159964
+ const [cycle, setCycle] = useState(0);
159965
+ const [state, setState] = useState(() => source.kind === "loaded" ? {
159966
+ kind: "ready",
159967
+ events: source.events
159968
+ } : { kind: "loading" });
159969
+ const retry = useCallback(() => {
159970
+ setState({ kind: "loading" });
159971
+ setCycle((value) => value + 1);
159972
+ }, []);
159973
+ useEffect(() => {
159974
+ if (source.kind === "loaded") {
159975
+ setState({
159976
+ kind: "ready",
159977
+ events: source.events
159978
+ });
159979
+ return;
159980
+ }
159981
+ if (!source.request) {
159982
+ setState({
159983
+ kind: "exhausted",
159984
+ retry
159985
+ });
159986
+ return;
159987
+ }
159988
+ const controller = new AbortController();
159989
+ const isCurrent = () => !controller.signal.aborted;
159990
+ (async () => {
159991
+ for (const delayMs of RECOVERY_DELAYS_MS) try {
159992
+ await wait(delayMs, controller.signal);
159993
+ const events = await api.getPublicEvents(source.request ?? void 0);
159994
+ if (isCurrent()) setState({
159995
+ kind: "ready",
159996
+ events
159997
+ });
159998
+ return;
159999
+ } catch {
160000
+ if (!isCurrent()) return;
160001
+ }
160002
+ if (isCurrent()) setState({
160003
+ kind: "exhausted",
160004
+ retry
160005
+ });
160006
+ })();
160007
+ return () => controller.abort();
160008
+ }, [
160009
+ api,
160010
+ cycle,
160011
+ retry,
160012
+ source,
160013
+ wait
160014
+ ]);
160015
+ return state;
160016
+ }
160017
+ function waitForRetry(milliseconds, signal) {
160018
+ if (signal.aborted) return Promise.reject(/* @__PURE__ */ new Error("Recovery aborted"));
160019
+ if (milliseconds === 0) return Promise.resolve();
160020
+ return new Promise((resolve, reject) => {
160021
+ const timeout = setTimeout(resolve, milliseconds);
160022
+ signal.addEventListener("abort", () => {
160023
+ clearTimeout(timeout);
160024
+ reject(/* @__PURE__ */ new Error("Recovery aborted"));
160025
+ }, { once: true });
160026
+ });
160027
+ }
160028
+ var RECOVERY_DELAYS_MS, defaultRecoveryDeps;
160029
+ var init_useEventSourceRecovery = __esmMin((() => {
160030
+ init_api();
160031
+ RECOVERY_DELAYS_MS = [
160032
+ 0,
160033
+ 250,
160034
+ 750
160035
+ ];
160036
+ defaultRecoveryDeps = {
160037
+ useApi: useBlockApi,
160038
+ wait: waitForRetry
160039
+ };
160040
+ }));
160041
+ //#endregion
159321
160042
  //#region ../blocks/src/system/runtime/nodes/event-registration.client.tsx
159322
160043
  function toEventRegistrationClientProps(props, display) {
159323
160044
  return {
@@ -159326,13 +160047,77 @@ function toEventRegistrationClientProps(props, display) {
159326
160047
  className: display.className ?? void 0
159327
160048
  };
159328
160049
  }
160050
+ function RecoverableEventRegistrationClient({ props, display }) {
160051
+ const recovery = useEventSourceRecovery(props.render.hydration.eventSource);
160052
+ if (recovery.kind === "loading") return /* @__PURE__ */ jsxs("div", {
160053
+ id: EVENT_REGISTRATION_ANCHOR_ID,
160054
+ className: "rb-reg-surface er-container er-registration-shell",
160055
+ "aria-busy": "true",
160056
+ role: "status",
160057
+ children: [
160058
+ /* @__PURE__ */ jsx("p", {
160059
+ className: "er-registration-shell__eyebrow",
160060
+ children: "Registration"
160061
+ }),
160062
+ /* @__PURE__ */ jsx("h3", {
160063
+ className: "er-title er-registration-shell__title",
160064
+ children: display.titleText
160065
+ }),
160066
+ /* @__PURE__ */ jsx("p", {
160067
+ className: "er-text er-text--muted",
160068
+ children: "Loading event dates…"
160069
+ }),
160070
+ /* @__PURE__ */ jsxs("div", {
160071
+ className: "er-event-grid er-registration-shell__cards",
160072
+ "aria-hidden": "true",
160073
+ children: [/* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" }), /* @__PURE__ */ jsx("div", { className: "er-event-card er-registration-shell__card" })]
160074
+ })
160075
+ ]
160076
+ });
160077
+ if (recovery.kind === "exhausted") return /* @__PURE__ */ jsxs("div", {
160078
+ id: EVENT_REGISTRATION_ANCHOR_ID,
160079
+ className: "rb-reg-surface er-container er-registration-shell",
160080
+ role: "alert",
160081
+ children: [/* @__PURE__ */ jsx("p", { children: "We couldn’t load the event dates. Please try again." }), /* @__PURE__ */ jsx("button", {
160082
+ type: "button",
160083
+ className: themeButtonClassName({
160084
+ variant: props.render.hydration.buttonVariant ?? "primary",
160085
+ size: "md"
160086
+ }),
160087
+ onClick: recovery.retry,
160088
+ children: "Try again"
160089
+ })]
160090
+ });
160091
+ const events = resolveEventRegistrationScopedEvents(recovery.events, {
160092
+ occurrenceContext: props.render.hydration.occurrenceContext,
160093
+ subject: props.render.hydration.subject
160094
+ });
160095
+ const recoveredDisplay = buildEventRegistrationDisplayFromScopedEvents({
160096
+ ...props.render.hydration,
160097
+ events,
160098
+ className: display.className,
160099
+ buttonText: display.summaryButtonText
160100
+ }, events);
160101
+ if (recoveredDisplay.state === "registration-closed") return /* @__PURE__ */ jsx(RegistrationClosedState, {
160102
+ title: recoveredDisplay.titleText,
160103
+ body: recoveredDisplay.bodyText
160104
+ });
160105
+ return /* @__PURE__ */ jsx(EventRegistrationClient, {
160106
+ ...toEventRegistrationClientProps(props, display),
160107
+ events
160108
+ });
160109
+ }
159329
160110
  var EventRegistrationClient, EventRegistrationIslandClient;
159330
160111
  var init_event_registration_client = __esmMin((() => {
159331
160112
  init_EventRegistrationWizard();
159332
160113
  init_registrationSurface();
159333
160114
  init_constants();
159334
160115
  init_PastOccurrenceNotice();
160116
+ init_event_registration_interactive();
159335
160117
  init_RegistrationClosedState();
160118
+ init_useEventSourceRecovery();
160119
+ init_eventScope();
160120
+ init_buttons();
159336
160121
  EventRegistrationClient = (clientProps) => {
159337
160122
  const surface = planEventRegistrationSurface({
159338
160123
  events: clientProps.events ?? [],
@@ -159358,7 +160143,10 @@ var init_event_registration_client = __esmMin((() => {
159358
160143
  title: props.render.display.titleText,
159359
160144
  body: props.render.display.bodyText
159360
160145
  });
159361
- return /* @__PURE__ */ jsx(EventRegistrationClient, { ...toEventRegistrationClientProps(props, props.render.display) });
160146
+ return /* @__PURE__ */ jsx(RecoverableEventRegistrationClient, {
160147
+ props,
160148
+ display: props.render.display
160149
+ });
159362
160150
  };
159363
160151
  }));
159364
160152
  //#endregion
@@ -163712,6 +164500,11 @@ function NewsletterFormClient({ render }) {
163712
164500
  const api = useBlockApi();
163713
164501
  const [submissionState, dispatchSubmission] = useReducer(newsletterFormSubmissionReducer, initialNewsletterFormSubmissionState);
163714
164502
  const [altchaSolution, setAltchaSolution] = useState(null);
164503
+ const successRef = useRef(null);
164504
+ const succeeded = isNewsletterFormSuccess(submissionState);
164505
+ useEffect(() => {
164506
+ if (succeeded) successRef.current?.focus();
164507
+ }, [succeeded]);
163715
164508
  const showSpamProtection = render.hydration.spamProtectionEnabled ?? isSpamProtectionEnabled();
163716
164509
  const fields = render.display.fields;
163717
164510
  const handleSubmit = async (e) => {
@@ -163751,7 +164544,7 @@ function NewsletterFormClient({ render }) {
163751
164544
  if (render.hydration.setupRevision === null || render.display.availability === "unavailable") {
163752
164545
  dispatchSubmission({
163753
164546
  type: "failed",
163754
- error: newsletterFormError("Mailing-list signup is not available right now.")
164547
+ error: newsletterFormError(SIGNUPS_PAUSED_MESSAGE)
163755
164548
  });
163756
164549
  return;
163757
164550
  }
@@ -163759,7 +164552,7 @@ function NewsletterFormClient({ render }) {
163759
164552
  if (visitorSelection === null) {
163760
164553
  dispatchSubmission({
163761
164554
  type: "failed",
163762
- error: newsletterFormError("Choose at least one email topic.")
164555
+ error: newsletterFieldError(TOPIC_CHOICE_FIELD_ID, "Choose at least one email topic.")
163763
164556
  });
163764
164557
  return;
163765
164558
  }
@@ -163791,71 +164584,27 @@ function NewsletterFormClient({ render }) {
163791
164584
  } catch (err) {
163792
164585
  dispatchSubmission({
163793
164586
  type: "failed",
163794
- error: newsletterFormError(err instanceof Error ? err.message : "Subscription failed. Please try again.")
164587
+ error: newsletterFormError(transportFailureMessage(err))
163795
164588
  });
163796
164589
  }
163797
164590
  };
163798
- const renderField = (field) => {
163799
- const inputId = `newsletter_${field.id}`;
163800
- const fieldError = getNewsletterSubmissionFieldError(submissionState, field.id);
163801
- const fieldErrorId = `${inputId}-error`;
163802
- const validationProps = getFieldValidationControlProps({
163803
- message: fieldError,
163804
- messageId: fieldErrorId
163805
- });
163806
- return /* @__PURE__ */ jsxs("div", {
163807
- className: "fb-field newsletter-field",
163808
- children: [
163809
- /* @__PURE__ */ jsxs("label", {
163810
- htmlFor: inputId,
163811
- className: "form-label",
163812
- children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
163813
- className: "newsletter-required",
163814
- "aria-hidden": "true",
163815
- children: "*"
163816
- })]
163817
- }),
163818
- /* @__PURE__ */ jsx("input", {
163819
- id: inputId,
163820
- name: field.id,
163821
- type: field.type,
163822
- required: field.required,
163823
- placeholder: field.placeholder,
163824
- className: "form-input",
163825
- autoComplete: field.type === "email" ? "email" : void 0,
163826
- disabled: isNewsletterFormSubmitting(submissionState),
163827
- ...validationProps
163828
- }),
163829
- fieldError && /* @__PURE__ */ jsx(FieldValidationMessage, {
163830
- id: fieldErrorId,
163831
- className: "fb-error",
163832
- children: fieldError
163833
- })
163834
- ]
163835
- }, field.id);
163836
- };
164591
+ const submitting = isNewsletterFormSubmitting(submissionState);
163837
164592
  const formError = getNewsletterSubmissionFormError(submissionState);
163838
- if (isNewsletterFormSuccess(submissionState)) {
163839
- const outcome = getNewsletterSuccessOutcome(submissionState);
163840
- return /* @__PURE__ */ jsx("div", {
163841
- className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
163842
- children: /* @__PURE__ */ jsx(FeedbackMessage, {
163843
- tone: "success",
163844
- className: "fb-success",
163845
- role: "status",
163846
- children: outcome === "confirmation_required" ? "Please check your inbox to confirm your signup." : "Thanks — you’re on the list."
163847
- })
163848
- });
163849
- }
164593
+ if (succeeded) return /* @__PURE__ */ jsx("div", {
164594
+ ref: successRef,
164595
+ tabIndex: -1,
164596
+ className: clsx("newsletter-form", "newsletter-success", render.display.className ?? void 0),
164597
+ children: /* @__PURE__ */ jsx(FeedbackMessage, {
164598
+ tone: "success",
164599
+ className: "fb-success",
164600
+ role: "status",
164601
+ children: getNewsletterSuccessOutcome(submissionState) === "confirmation_required" ? "Please check your inbox to confirm your signup." : render.display.successMessage
164602
+ })
164603
+ });
163850
164604
  if (render.display.availability === "unavailable") return /* @__PURE__ */ jsx(UnavailableNewsletterForm, { className: render.display.className });
163851
- return /* @__PURE__ */ jsxs("div", {
164605
+ return /* @__PURE__ */ jsx("div", {
163852
164606
  className: clsx("newsletter-form", render.display.className ?? void 0),
163853
- children: [formError && /* @__PURE__ */ jsx(FeedbackMessage, {
163854
- tone: "error",
163855
- className: "fb-error",
163856
- role: "alert",
163857
- children: formError
163858
- }), /* @__PURE__ */ jsxs("form", {
164607
+ children: /* @__PURE__ */ jsxs("form", {
163859
164608
  onSubmit: handleSubmit,
163860
164609
  className: "fb-form",
163861
164610
  children: [
@@ -163870,18 +164619,15 @@ function NewsletterFormClient({ render }) {
163870
164619
  /* @__PURE__ */ jsxs("div", {
163871
164620
  className: "newsletter-form-fields",
163872
164621
  children: [
163873
- fields.map(renderField),
163874
- render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
163875
- className: "newsletter-topics",
163876
- children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), render.display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
163877
- className: "newsletter-topic-choice",
163878
- children: [/* @__PURE__ */ jsx("input", {
163879
- type: "checkbox",
163880
- name: "mailingListChoice",
163881
- value: choice.id,
163882
- disabled: isNewsletterFormSubmitting(submissionState)
163883
- }), choice.label]
163884
- }, choice.id))]
164622
+ fields.map((field) => /* @__PURE__ */ jsx(NewsletterField, {
164623
+ field,
164624
+ submitting,
164625
+ error: getNewsletterSubmissionFieldError(submissionState, field.id)
164626
+ }, field.id)),
164627
+ render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsx(NewsletterTopicChoices, {
164628
+ choices: render.display.choices,
164629
+ submitting,
164630
+ error: getNewsletterSubmissionFieldError(submissionState, TOPIC_CHOICE_FIELD_ID)
163885
164631
  }) : null,
163886
164632
  showSpamProtection && /* @__PURE__ */ jsx("div", {
163887
164633
  className: "newsletter-altcha",
@@ -163890,6 +164636,12 @@ function NewsletterFormClient({ render }) {
163890
164636
  onSolutionChange: setAltchaSolution
163891
164637
  })
163892
164638
  }),
164639
+ formError && /* @__PURE__ */ jsx(FeedbackMessage, {
164640
+ tone: "error",
164641
+ className: "fb-error",
164642
+ role: "alert",
164643
+ children: formError
164644
+ }),
163893
164645
  /* @__PURE__ */ jsx("div", {
163894
164646
  className: "newsletter-submit",
163895
164647
  children: /* @__PURE__ */ jsx("button", {
@@ -163898,8 +164650,8 @@ function NewsletterFormClient({ render }) {
163898
164650
  variant: render.display.buttonVariant,
163899
164651
  size: "md"
163900
164652
  }),
163901
- disabled: isNewsletterFormSubmitting(submissionState),
163902
- children: isNewsletterFormSubmitting(submissionState) ? "Subscribing..." : render.display.buttonLabel
164653
+ disabled: submitting,
164654
+ children: submitting ? "Subscribing..." : render.display.buttonLabel
163903
164655
  })
163904
164656
  })
163905
164657
  ]
@@ -163909,9 +164661,70 @@ function NewsletterFormClient({ render }) {
163909
164661
  children: render.display.privacyNote
163910
164662
  })
163911
164663
  ]
163912
- })]
164664
+ })
163913
164665
  });
163914
164666
  }
164667
+ function NewsletterField({ field, submitting, error }) {
164668
+ const inputId = `newsletter_${field.id}`;
164669
+ const errorId = `${inputId}-error`;
164670
+ return /* @__PURE__ */ jsxs("div", {
164671
+ className: "fb-field newsletter-field",
164672
+ children: [
164673
+ /* @__PURE__ */ jsxs("label", {
164674
+ htmlFor: inputId,
164675
+ className: "form-label",
164676
+ children: [field.label, field.required && /* @__PURE__ */ jsx("span", {
164677
+ className: "newsletter-required",
164678
+ "aria-hidden": "true",
164679
+ children: "*"
164680
+ })]
164681
+ }),
164682
+ /* @__PURE__ */ jsx("input", {
164683
+ id: inputId,
164684
+ name: field.id,
164685
+ type: field.type,
164686
+ required: field.required,
164687
+ placeholder: field.placeholder,
164688
+ className: "form-input",
164689
+ autoComplete: field.type === "email" ? "email" : void 0,
164690
+ disabled: submitting,
164691
+ ...getFieldValidationControlProps({
164692
+ message: error,
164693
+ messageId: errorId
164694
+ })
164695
+ }),
164696
+ error && /* @__PURE__ */ jsx(FieldValidationMessage, {
164697
+ id: errorId,
164698
+ className: "fb-error",
164699
+ children: error
164700
+ })
164701
+ ]
164702
+ });
164703
+ }
164704
+ function NewsletterTopicChoices({ choices, submitting, error }) {
164705
+ const errorId = `newsletter_${TOPIC_CHOICE_FIELD_ID}-error`;
164706
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("fieldset", {
164707
+ className: "fb-fieldset newsletter-topics",
164708
+ "aria-describedby": error ? errorId : void 0,
164709
+ children: [/* @__PURE__ */ jsx("legend", {
164710
+ className: "form-label",
164711
+ children: "What would you like to hear about?"
164712
+ }), choices.map((choice) => /* @__PURE__ */ jsxs("label", {
164713
+ className: "fb-inline form-label newsletter-topic-choice",
164714
+ children: [/* @__PURE__ */ jsx("input", {
164715
+ type: "checkbox",
164716
+ name: TOPIC_CHOICE_FIELD_ID,
164717
+ value: choice.id,
164718
+ className: "form-checkbox",
164719
+ disabled: submitting
164720
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
164721
+ }, choice.id))]
164722
+ }), error && /* @__PURE__ */ jsx(FieldValidationMessage, {
164723
+ id: errorId,
164724
+ className: "fb-error",
164725
+ children: error
164726
+ })] });
164727
+ }
163915
164728
  function UnavailableNewsletterForm({ className }) {
163916
164729
  return /* @__PURE__ */ jsx("div", {
163917
164730
  className: clsx("newsletter-form", className ?? void 0),
@@ -163919,13 +164732,26 @@ function UnavailableNewsletterForm({ className }) {
163919
164732
  tone: "error",
163920
164733
  className: "fb-error",
163921
164734
  role: "status",
163922
- children: "Mailing-list signup is not available right now."
164735
+ children: SIGNUPS_PAUSED_MESSAGE
163923
164736
  })
163924
164737
  });
163925
164738
  }
164739
+ /**
164740
+ * Vetted copy for a request that never produced a signup response. The raw
164741
+ * error text ("Failed to fetch", "received invalid JSON") is for logs, not
164742
+ * visitors.
164743
+ */
164744
+ function transportFailureMessage(err) {
164745
+ if (err instanceof BlockApiError) {
164746
+ if (err.status === 429) return TOO_MANY_ATTEMPTS_MESSAGE;
164747
+ if (err.status === 403) return "We couldn’t verify this submission. Please try again.";
164748
+ if (err.status === 400 || err.status === 422) return "Please check your details and try again.";
164749
+ }
164750
+ return RETRY_SHORTLY_MESSAGE;
164751
+ }
163926
164752
  function readVisitorSelection(formData, hydration) {
163927
164753
  if (hydration.choicePresentation !== "visitor_choice") return void 0;
163928
- const ids = formData.getAll("mailingListChoice").flatMap((value) => typeof value === "string" ? [value] : []);
164754
+ const ids = formData.getAll(TOPIC_CHOICE_FIELD_ID).flatMap((value) => typeof value === "string" ? [value] : []);
163929
164755
  if (ids.length === 0) return null;
163930
164756
  const raw = hydration.choiceProvider === "native" ? {
163931
164757
  provider: "native",
@@ -163947,15 +164773,15 @@ function publicSignupError(outcome) {
163947
164773
  case "unavailable": switch (outcome.reason) {
163948
164774
  case "configuration_unavailable":
163949
164775
  case "authentication_failed":
163950
- case "target_unavailable": return "Mailing-list signup is not available right now.";
164776
+ case "target_unavailable": return SIGNUPS_PAUSED_MESSAGE;
163951
164777
  case "stale_configuration": return "This signup form has changed. Refresh the page, then try again.";
163952
- case "subscriber_suppressed": return "This address cannot be added. Please contact the site if you would like help.";
163953
- case "rate_limited": return "There have been too many signup attempts. Please wait a moment and try again.";
163954
- case "temporarily_unavailable": return "We could not sign you up just now. Please try again shortly.";
164778
+ case "rate_limited": return TOO_MANY_ATTEMPTS_MESSAGE;
164779
+ case "temporarily_unavailable": return RETRY_SHORTLY_MESSAGE;
163955
164780
  }
163956
164781
  case "uncertain": return "We could not confirm whether your signup completed. Please wait a moment, then try again.";
163957
164782
  }
163958
164783
  }
164784
+ var TOPIC_CHOICE_FIELD_ID, SIGNUPS_PAUSED_MESSAGE, RETRY_SHORTLY_MESSAGE, TOO_MANY_ATTEMPTS_MESSAGE;
163959
164785
  var init_newsletter_form_client = __esmMin((() => {
163960
164786
  init_clsx();
163961
164787
  init_client();
@@ -163967,6 +164793,10 @@ var init_newsletter_form_client = __esmMin((() => {
163967
164793
  init_FieldValidationMessage();
163968
164794
  init_newsletter_form_client_state();
163969
164795
  init_newsletter_form_submission();
164796
+ TOPIC_CHOICE_FIELD_ID = "mailingListChoice";
164797
+ SIGNUPS_PAUSED_MESSAGE = "We can’t accept signups right now. Please try again later.";
164798
+ RETRY_SHORTLY_MESSAGE = "We couldn’t confirm your signup. Please try again in a little while.";
164799
+ TOO_MANY_ATTEMPTS_MESSAGE = "There have been too many signup attempts. Please wait a moment and try again.";
163970
164800
  }));
163971
164801
  //#endregion
163972
164802
  //#region ../blocks/src/client/newsletter-form.ts
@@ -164428,7 +165258,7 @@ function PageContent(props) {
164428
165258
  previewToken,
164429
165259
  resolvedData,
164430
165260
  bookingOfferingPresets: bookingOfferingPresets ?? [],
164431
- mailingList,
165261
+ mailingList: mailingList ?? dataContext?.mailingList,
164432
165262
  bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
164433
165263
  routes: routeMap,
164434
165264
  pagesByIdentifier,
@@ -164629,7 +165459,7 @@ var SimpleCache = class {
164629
165459
  * 1. This constant
164630
165460
  * 2. The "version" field in package.json
164631
165461
  */
164632
- const SDK_VERSION = "0.139.0";
165462
+ const SDK_VERSION = "0.140.0";
164633
165463
  //#endregion
164634
165464
  //#region src/client/error.ts
164635
165465
  let _Symbol$for;
@@ -165019,7 +165849,12 @@ const API_ENDPOINTS = Object.freeze({
165019
165849
  path: "/public/sites/{siteId}/sitemap",
165020
165850
  method: "GET",
165021
165851
  revalidate: 60,
165022
- tags: ["riverbank:site:{siteId}:routable-content", "riverbank:site:{siteId}:settings"],
165852
+ tags: [
165853
+ "riverbank:site:{siteId}:routable-content",
165854
+ "riverbank:site:{siteId}:settings",
165855
+ "riverbank:site:{siteId}:public-events",
165856
+ "riverbank:site:{siteId}:public-booking-services"
165857
+ ],
165023
165858
  auth: "public",
165024
165859
  responseKind: "json"
165025
165860
  }