@riverbankcms/sdk 0.139.0 → 0.141.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 (232) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-BDeenhi3.mjs → PreviewEditorSidebar-Q-fy9GYw.mjs} +4 -4
  3. package/dist/{PreviewEditorUI-DSRhgjF5.mjs → PreviewEditorUI-LYGzgk85.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-D2K8GLUG.mjs → PreviewQueryProvider-CN0ewic5.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CL7wSnYu.mjs → SdkPreviewModeRuntime-CoPYI5Jq.mjs} +90 -50
  6. package/dist/{SiteChromeCustomizeContext-BhDn-5ir.mjs → SiteChromeCustomizeContext-D8LePX8x.mjs} +2731 -1303
  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 +17 -31
  20. package/dist/_dts/api/src/domainConnection.d.ts +4 -0
  21. package/dist/_dts/api/src/endpoints.d.ts +93 -64
  22. package/dist/_dts/api/src/event-destination-policy.d.ts +2 -1
  23. package/dist/_dts/api/src/footerCompositionContracts.d.ts +25 -0
  24. package/dist/_dts/api/src/footerSettings.d.ts +9 -6
  25. package/dist/_dts/api/src/index.d.ts +6 -7
  26. package/dist/_dts/api/src/indexCoreTypes.d.ts +1 -1
  27. package/dist/_dts/api/src/indexExtendedTypes.d.ts +1 -1
  28. package/dist/_dts/api/src/launchReadiness.d.ts +1 -0
  29. package/dist/_dts/api/src/mailingListIntegration.d.ts +8 -2
  30. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  31. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +2 -1
  32. package/dist/_dts/api/src/navigation/types.d.ts +1 -1
  33. package/dist/_dts/api/src/onboarding/confirmationResend.d.ts +25 -0
  34. package/dist/_dts/api/src/onboarding/surfaceData.d.ts +32 -32
  35. package/dist/_dts/api/src/publicBookingAvailabilityEndpointDefinitions.d.ts +8 -0
  36. package/dist/_dts/api/src/publicExperience/commerceEndpoints.d.ts +1 -0
  37. package/dist/_dts/api/src/publicExperience/eventEndpoints.d.ts +11 -3
  38. package/dist/_dts/api/src/publicExperience/sharedTypes.d.ts +3 -29
  39. package/dist/_dts/api/src/publicOnboardingAttemptEndpointDefinitions.d.ts +65 -0
  40. package/dist/_dts/api/src/saveOutcome.d.ts +20 -0
  41. package/dist/_dts/api/src/sdkContracts.d.ts +3 -22
  42. package/dist/_dts/api/src/sdkPushContracts.d.ts +18 -0
  43. package/dist/_dts/api/src/sdkThemeWire.d.ts +44 -44
  44. package/dist/_dts/api/src/settings/permissions.d.ts +12 -0
  45. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +10 -29
  46. package/dist/_dts/api/src/siteOnboarding.d.ts +9 -9
  47. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +2 -4
  48. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +3 -1
  49. package/dist/_dts/api/src/siteSettings.d.ts +20 -7
  50. package/dist/_dts/api/src/types.d.ts +77 -77
  51. package/dist/_dts/api/src/wholeSeriesRuns.d.ts +2 -37
  52. package/dist/_dts/billing/src/membership/index.d.ts +3 -0
  53. package/dist/_dts/billing/src/plans/types.d.ts +3 -0
  54. package/dist/_dts/billing/src/site-arrangements.d.ts +23 -3
  55. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +20 -4
  56. package/dist/_dts/blocks/src/pageRenderAdmission.d.ts +2 -0
  57. package/dist/_dts/blocks/src/pageRendererContracts.d.ts +7 -0
  58. package/dist/_dts/blocks/src/portal/types.d.ts +2 -4
  59. package/dist/_dts/blocks/src/portal/waitlist-types.d.ts +35 -0
  60. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -0
  61. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +2 -0
  62. package/dist/_dts/blocks/src/system/blocks/events/eventSelectionFields.d.ts +122 -0
  63. package/dist/_dts/blocks/src/system/blocks/events/shared/calendarWindow.d.ts +2 -1
  64. package/dist/_dts/blocks/src/system/blocks/events/shared/eventSelection.d.ts +11 -0
  65. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +42 -0
  66. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -0
  67. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +2 -2
  68. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +47 -47
  69. package/dist/_dts/blocks/src/system/data/index.d.ts +2 -2
  70. package/dist/_dts/blocks/src/system/data/prefetchBlockData.d.ts +7 -1
  71. package/dist/_dts/blocks/src/system/data/types.d.ts +9 -0
  72. package/dist/_dts/blocks/src/system/data/utils.d.ts +1 -1
  73. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +27 -1
  74. package/dist/_dts/blocks/src/system/registry.d.ts +1 -0
  75. package/dist/_dts/blocks/src/system/runtime/api/client.d.ts +0 -28
  76. package/dist/_dts/blocks/src/system/runtime/api/index.d.ts +1 -1
  77. package/dist/_dts/blocks/src/system/runtime/api/types/events.d.ts +7 -3
  78. package/dist/_dts/blocks/src/system/runtime/api/types/portal.d.ts +1 -1
  79. package/dist/_dts/blocks/src/system/runtime/api/types/waitlist-claims.d.ts +7 -2
  80. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +42 -186
  81. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -93
  82. package/dist/_dts/blocks/src/system/runtime/hooks/useEventFilters.d.ts +2 -1
  83. package/dist/_dts/blocks/src/system/runtime/nodes/appointment-services.d.ts +48 -1
  84. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/EventRegistrationSurface.d.ts +1 -2
  85. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/TicketSelectionStep.d.ts +2 -0
  86. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/checkoutRecovery.d.ts +14 -0
  87. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.d.ts +56 -0
  88. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.d.ts +4 -0
  89. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/hooks.state.d.ts +5 -0
  90. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +6 -8
  91. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useCheckoutRecovery.d.ts +8 -0
  92. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.d.ts +3 -0
  93. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useDiscountCodeUi.state.d.ts +10 -3
  94. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventCheckoutHandoffRestore.d.ts +9 -0
  95. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationSubmit.d.ts +8 -7
  96. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationWizard.d.ts +14 -7
  97. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventSourceRecovery.d.ts +18 -0
  98. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useSettledCommerceView.d.ts +37 -0
  99. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.client.d.ts +1 -1
  100. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +24 -6
  101. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.server.d.ts +4 -2
  102. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.client.d.ts +4 -3
  103. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventCombined.interactive.d.ts +3 -0
  104. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +11 -101
  105. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +7 -2
  106. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/listOptions.d.ts +2 -0
  107. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +6 -0
  108. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +1 -0
  109. package/dist/_dts/blocks/src/system/runtime/resolver.d.ts +1 -0
  110. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +2 -6
  111. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +2 -2
  112. package/dist/_dts/blocks/src/system/runtime/shared/useWaitlistClaim.d.ts +2 -0
  113. package/dist/_dts/blocks/src/system/transforms/registry/eventCalendar.d.ts +12 -0
  114. package/dist/_dts/commerce/src/purchase/bookingInstalmentSchedule.d.ts +4 -0
  115. package/dist/_dts/commerce/src/purchase/event-registration-errors.d.ts +4 -0
  116. package/dist/_dts/commerce/src/purchase/orderItemMetadata.d.ts +27 -4
  117. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +2 -1
  118. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +3 -1
  119. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +3 -0
  120. package/dist/_dts/core/src/branded.d.ts +0 -8
  121. package/dist/_dts/core/src/index.d.ts +1 -0
  122. package/dist/_dts/core/src/mailing-list-setup-parser.d.ts +1 -1
  123. package/dist/_dts/core/src/mailing-list-setup.d.ts +14 -1
  124. package/dist/_dts/core/src/mailing-list-submission.d.ts +7 -27
  125. package/dist/_dts/core/src/participants.d.ts +2 -29
  126. package/dist/_dts/core/src/public-experience.d.ts +4 -0
  127. package/dist/_dts/core/src/public-profile.d.ts +27 -1
  128. package/dist/_dts/core/src/site-route-target.d.ts +9 -2
  129. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +296 -606
  130. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListGlobalSettingsSummary.d.ts +10 -0
  131. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/MailingListTargetingField.d.ts +3 -2
  132. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/context.d.ts +3 -2
  133. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/loaders.d.ts +3 -2
  134. package/dist/_dts/editor-blocks/src/widgets/mailing-list-targeting/targetingState.d.ts +19 -0
  135. package/dist/_dts/editor-blocks/src/widgets/site-option-picker/loaders.d.ts +27 -1
  136. package/dist/_dts/sdk/src/public-api/contracts.d.ts +14 -20
  137. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +2 -0
  138. package/dist/_dts/sdk/src/rendering/components/pageShared.d.ts +2 -0
  139. package/dist/_dts/sdk/src/rendering/helpers/pageRuntimeSupport.d.ts +7 -1
  140. package/dist/_dts/sdk/src/rendering/helpers/templateContent.d.ts +1 -0
  141. package/dist/_dts/sdk/src/version.d.ts +1 -1
  142. package/dist/_dts/theme-core/src/ThemeFontLoader.d.ts +17 -1
  143. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  144. package/dist/_dts/theme-core/src/buttons/affordanceSuppression.d.ts +17 -0
  145. package/dist/_dts/theme-core/src/buttons/buttonColourContract.d.ts +1 -1
  146. package/dist/_dts/theme-core/src/buttons/classNames.d.ts +16 -0
  147. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +0 -6
  148. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +4 -4
  149. package/dist/_dts/theme-core/src/cards/types.d.ts +21 -21
  150. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  151. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +8 -2
  152. package/dist/_dts/theme-core/src/header/legacyHeaderVariant.d.ts +2 -2
  153. package/dist/_dts/theme-core/src/hosted-booking-appearance.d.ts +54 -12
  154. package/dist/_dts/theme-core/src/index.d.ts +1 -1
  155. package/dist/_dts/theme-core/src/inputs/types.d.ts +2 -2
  156. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +54 -54
  157. package/dist/_dts/theme-core/src/runtime/buildThemeRuntimeFromBridge.d.ts +1 -4
  158. package/dist/_dts/theme-core/src/schema.d.ts +84 -84
  159. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +1 -1
  160. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  161. package/dist/_dts/theme-core/src/surfaces/foregroundInteraction.d.ts +77 -0
  162. package/dist/_dts/theme-core/src/surfaces/index.d.ts +1 -0
  163. package/dist/_dts/theme-core/src/typography/generateTypographyCss.d.ts +2 -2
  164. package/dist/_dts/ui/src/lib/use-delayed-flag.d.ts +9 -0
  165. package/dist/_dts/ui/src/pending-button.d.ts +10 -0
  166. package/dist/client/{BookingConsentAgreement-CZvTDtsK.mjs → BookingConsentAgreement-xJeYNdnb.mjs} +4 -4
  167. package/dist/client/{DiscountCodeDisclosure-D-DsLCMU.mjs → DiscountCodeDisclosure-DdT6uzl9.mjs} +1 -1
  168. package/dist/client/{EventCombined.client-dWqgd5ZO.mjs → EventCombined.client-Cp28uYuM.mjs} +12 -16
  169. package/dist/client/{EventListing.client-BMRa9IYp.mjs → EventListing.client-CD6AJsMr.mjs} +4 -17
  170. package/dist/client/{LeafletStaticMap-D21W9kBZ.mjs → LeafletStaticMap-DBsAi9-e.mjs} +1 -1
  171. package/dist/client/{accordion-FxF_ta47.mjs → accordion-6dwbOKYR.mjs} +1 -1
  172. package/dist/client/{bookingForm-YnwW4TGw.mjs → bookingForm-CZE9_qPQ.mjs} +7 -7
  173. package/dist/client/bookings.mjs +500 -233
  174. package/dist/client/{carousel-vng7fFT5.mjs → carousel-7VHGQARz.mjs} +2 -2
  175. package/dist/client/{carousel.client-59G_WMr4.mjs → carousel.client-DQTjCVQT.mjs} +1 -1
  176. package/dist/client/{cart-DEPDsjNk.mjs → cart-Qg_mvQhh.mjs} +3 -3
  177. package/dist/client/{checkout-CZRWu9rW.mjs → checkout-D84rpgdr.mjs} +3 -3
  178. package/dist/client/{checkoutUrls-BuseL0dw.mjs → checkoutUrls-FL6lRkrt.mjs} +1 -1
  179. package/dist/client/client.mjs +2315 -1017
  180. package/dist/client/{colorStyles-CrxJrPjJ.mjs → colorStyles-3013aRAY.mjs} +3 -1
  181. package/dist/client/{context-DvU_WUmd.mjs → context-Ctp3T0Wr.mjs} +6 -19
  182. package/dist/client/{dates-wnPMiRl5.mjs → dates-DJKFcI_N.mjs} +2 -2
  183. package/dist/client/{eventCalendar-BA3Q5L15.mjs → eventCalendar-CK31z3vs.mjs} +12 -8
  184. package/dist/client/{eventCombined-51wgR-1R.mjs → eventCombined-DiXd-ewn.mjs} +3 -3
  185. package/dist/client/{eventDetails-modaetpm.mjs → eventDetails-CTRgt2DK.mjs} +4 -4
  186. package/dist/client/{eventListing-D8t2J3Kv.mjs → eventListing-Dy9vi_j_.mjs} +3 -3
  187. package/dist/client/{eventRegistration-CYqtkCE_.mjs → eventRegistration-CnalYMr2.mjs} +618 -177
  188. package/dist/client/{form-CBKXN5In.mjs → form-eUiMveTT.mjs} +3 -3
  189. package/dist/client/{headerSection-DylDqNrs.mjs → headerSection-Dy9kQpB1.mjs} +2 -2
  190. package/dist/client/hooks.mjs +692 -212
  191. package/dist/client/{locationMap-CvWrG0vZ.mjs → locationMap-DalCmWU0.mjs} +3 -3
  192. package/dist/client/{media-BOHuueS5.mjs → media-DHpfFwd3.mjs} +1 -1
  193. package/dist/client/{newsletterForm-Btwk70zw.mjs → newsletterForm-SDDPvhS0.mjs} +150 -94
  194. package/dist/client/{pricing-Uzw-GQ6Y.mjs → pricing-OcMz4SnX.mjs} +1 -1
  195. package/dist/client/{productDetail-JLcUYKnd.mjs → productDetail-BQrgHElM.mjs} +3 -3
  196. package/dist/client/{productList-FM0cbUzj.mjs → productList-OnPn_UJj.mjs} +3 -3
  197. package/dist/client/{propsDecoder-DYzafZb2.mjs → propsDecoder-zBdsnS-N.mjs} +168 -32
  198. package/dist/client/rendering/client.mjs +1355 -519
  199. package/dist/client/rendering/islands.mjs +19 -19
  200. package/dist/client/rendering.mjs +2294 -953
  201. package/dist/client/{scrollToBlock-CvXszexS.mjs → scrollToBlock-BNM4Ob2Y.mjs} +28 -11
  202. package/dist/client/{shop-BIcjvy5a.mjs → shop-Bv1fPTwQ.mjs} +6 -6
  203. package/dist/client/{shop-commerce-BZQsy7xw.mjs → shop-commerce-D4KNGaW8.mjs} +7 -7
  204. package/dist/client/{shop-commerce-store-D5V7XAb5.mjs → shop-commerce-store-2N5EV0Rc.mjs} +1 -1
  205. package/dist/client/{shopShared-DowkXevB.mjs → shopShared-DvJGdHTV.mjs} +4 -4
  206. package/dist/client/{useEventFilters-oMoTw_JE.mjs → useEventFilters-BBBvGDHQ.mjs} +19 -13
  207. package/dist/preview-next/before-render.mjs +119 -64
  208. package/dist/preview-next/client/runtime.mjs +4 -4
  209. package/dist/preview-next/editor-chrome.css +4 -8
  210. package/dist/preview-next/keepAlive.mjs +119 -64
  211. package/dist/preview-next/middleware.mjs +119 -64
  212. package/dist/{previewAuthStore-COUyAKaX.mjs → previewAuthStore-Gjb6r6vz.mjs} +119 -64
  213. package/dist/{sdk-runtime-D4k2LSGF.mjs → sdk-runtime-Defnbfzw.mjs} +2 -2
  214. package/dist/{separator-UGtpag4Z.mjs → separator-CZXO3Sb0.mjs} +1 -1
  215. package/dist/server/components.mjs +1170 -384
  216. package/dist/server/config-validation.mjs +560 -105
  217. package/dist/server/config.mjs +564 -109
  218. package/dist/server/data.mjs +688 -212
  219. package/dist/server/index.mjs +126 -66
  220. package/dist/server/next.mjs +1429 -662
  221. package/dist/server/page-converter.mjs +372 -99
  222. package/dist/server/prebuild.mjs +1 -1
  223. package/dist/server/rendering/server.mjs +1624 -817
  224. package/dist/server/rendering.mjs +1200 -391
  225. package/dist/server/routing.mjs +767 -247
  226. package/dist/server/server.mjs +715 -276
  227. package/dist/server/theme-bridge.mjs +475 -110
  228. package/dist/server/theme.mjs +9 -3
  229. package/dist/styles/index.css +265 -45
  230. package/package.json +1 -1
  231. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +0 -29
  232. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +0 -13
@@ -68,11 +68,11 @@ var UnsafePathSegmentError = class extends Error {
68
68
  function assertSafePathSegments(segments) {
69
69
  for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
70
70
  }
71
- function isRecord$40(value) {
71
+ function isRecord$41(value) {
72
72
  return typeof value === "object" && value !== null && !Array.isArray(value);
73
73
  }
74
74
  function isPathContainer(value) {
75
- return Array.isArray(value) || isRecord$40(value);
75
+ return Array.isArray(value) || isRecord$41(value);
76
76
  }
77
77
  function getContainerValue(container, segment) {
78
78
  if (typeof segment === "number") return Array.isArray(container) ? container[segment] : void 0;
@@ -1124,10 +1124,12 @@ const unsafeAsStorageBucketName = (value) => value;
1124
1124
  const unsafeAsStoragePath = (value) => value;
1125
1125
  const unsafeAsPositiveByteCount = (value) => value;
1126
1126
  const unsafeAsUserId = (id) => id;
1127
+ const unsafeAsContentVersionId = (id) => id;
1127
1128
  const parseSiteId = (value) => parseUuidBrand$1(value, unsafeAsSiteId);
1128
1129
  const parseApiKeyId = (value) => parseUuidBrand$1(value, unsafeAsApiKeyId);
1129
1130
  const parseEventOfferingId = (value) => parseUuidBrand$1(value, unsafeAsEventOfferingId);
1130
1131
  const parseUserId = (value) => parseUuidBrand$1(value, unsafeAsUserId);
1132
+ const parseContentVersionId = (value) => parseUuidBrand$1(value, unsafeAsContentVersionId);
1131
1133
  const parseEventSeriesId = (value) => parseUuidBrand$1(value, unsafeAsEventSeriesId);
1132
1134
  //#endregion
1133
1135
  //#region ../core/src/assert-never.ts
@@ -1400,7 +1402,7 @@ function parseEventPageSurfaceDestinationMode(value) {
1400
1402
  return value === "cms-managed" || value === "system-managed" ? value : void 0;
1401
1403
  }
1402
1404
  function parseEventPageSurfaceSubject(value) {
1403
- if (!isRecord$39(value)) return err$3({ kind: "notObject" });
1405
+ if (!isRecord$40(value)) return err$3({ kind: "notObject" });
1404
1406
  switch (value.kind) {
1405
1407
  case "eventSeries": {
1406
1408
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -1455,7 +1457,7 @@ function parseEventSeriesIdList(values) {
1455
1457
  }
1456
1458
  return ok$3(parsed);
1457
1459
  }
1458
- function isRecord$39(value) {
1460
+ function isRecord$40(value) {
1459
1461
  return typeof value === "object" && value !== null && !Array.isArray(value);
1460
1462
  }
1461
1463
  //#endregion
@@ -1699,7 +1701,7 @@ function toLocationCoordinates(value) {
1699
1701
  }
1700
1702
  //#endregion
1701
1703
  //#region ../core/src/rich-text.ts
1702
- function isRecord$37(value) {
1704
+ function isRecord$38(value) {
1703
1705
  return typeof value === "object" && value !== null && !Array.isArray(value);
1704
1706
  }
1705
1707
  function hasOnlyKeys(value, allowed) {
@@ -1718,10 +1720,10 @@ function isDenseArrayOf(value, predicate) {
1718
1720
  return true;
1719
1721
  }
1720
1722
  function isTipTapMark(value) {
1721
- return isRecord$37(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$37(value.attrs));
1723
+ return isRecord$38(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$38(value.attrs));
1722
1724
  }
1723
1725
  function isTipTapNode(value) {
1724
- 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;
1726
+ 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;
1725
1727
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
1726
1728
  return value.text === void 0;
1727
1729
  }
@@ -1740,22 +1742,28 @@ function parsePositiveInteger(value) {
1740
1742
  function parseNewsletterListId(value) {
1741
1743
  return parseTrimmedMatchingString(value, UUID_PATTERN$2);
1742
1744
  }
1745
+ function parseMailchimpAccountId(value) {
1746
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1747
+ }
1743
1748
  function parseMailchimpAudienceId$1(value) {
1744
1749
  return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1745
1750
  }
1746
1751
  function parseMailchimpInterestId(value) {
1747
1752
  return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1748
1753
  }
1754
+ function parseBrevoAccountId(value) {
1755
+ return parseTrimmedMatchingString(value, OPAQUE_ID_PATTERN);
1756
+ }
1749
1757
  function parseBrevoListId(value) {
1750
1758
  return parsePositiveInteger(value);
1751
1759
  }
1752
1760
  //#endregion
1753
1761
  //#region ../core/src/mailing-list-targeting-parser.ts
1754
1762
  function parseMailingListPlacementTargeting(value) {
1755
- if (!isRecord$36(value)) return targetingError("shape");
1763
+ if (!isRecord$37(value)) return targetingError("shape");
1756
1764
  if (value.mode === "default") return ok$3({ mode: "default" });
1757
1765
  if (value.mode !== "custom") return targetingError("mode");
1758
- if (!isRecord$36(value.selection)) return targetingError("selection");
1766
+ if (!isRecord$37(value.selection)) return targetingError("selection");
1759
1767
  switch (value.provider) {
1760
1768
  case "native": return parseNativeTargeting(value.selection);
1761
1769
  case "brevo": return parseBrevoTargeting(value.selection);
@@ -1859,7 +1867,7 @@ function parseUniqueIds(value, parseId) {
1859
1867
  }
1860
1868
  return ok$3(parsed);
1861
1869
  }
1862
- function isRecord$36(value) {
1870
+ function isRecord$37(value) {
1863
1871
  return typeof value === "object" && value !== null && !Array.isArray(value);
1864
1872
  }
1865
1873
  function targetingError(field) {
@@ -1881,6 +1889,31 @@ new Map([
1881
1889
  "legal"
1882
1890
  ].map((kind, index) => [kind, index]));
1883
1891
  //#endregion
1892
+ //#region ../core/src/mailing-list-setup.ts
1893
+ function isRecord$34(value) {
1894
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1895
+ }
1896
+ const DEFAULT_MAILING_LIST_SUCCESS_MESSAGE = "Thanks — you're on the list.";
1897
+ function parseMailingListProviderScope(value) {
1898
+ if (!isRecord$34(value)) return err$3("invalid_mailing_list_provider_scope");
1899
+ if (value.provider === "native") return ok$3({ provider: "native" });
1900
+ if (value.provider === "brevo") {
1901
+ const accountId = parseBrevoAccountId(value.accountId);
1902
+ return accountId !== null ? ok$3({
1903
+ provider: "brevo",
1904
+ accountId
1905
+ }) : err$3("invalid_mailing_list_provider_scope");
1906
+ }
1907
+ if (value.provider === "mailchimp") {
1908
+ const accountId = parseMailchimpAccountId(value.accountId);
1909
+ return accountId !== null ? ok$3({
1910
+ provider: "mailchimp",
1911
+ accountId
1912
+ }) : err$3("invalid_mailing_list_provider_scope");
1913
+ }
1914
+ return err$3("invalid_mailing_list_provider_scope");
1915
+ }
1916
+ //#endregion
1884
1917
  //#region ../core/src/mailing-list-setup-parser.ts
1885
1918
  function parseMailingListGlobalForm(value) {
1886
1919
  if (!isRecord$33(value)) return formError("shape");
@@ -1889,12 +1922,15 @@ function parseMailingListGlobalForm(value) {
1889
1922
  if (typeof value.includeOptionalPhone !== "boolean") return formError("includeOptionalPhone");
1890
1923
  const buttonLabel = parseRequiredString(value.buttonLabel);
1891
1924
  if (buttonLabel === null) return formError("buttonLabel");
1925
+ const successMessage = parseRequiredString(value.successMessage);
1926
+ if (successMessage === null) return formError("successMessage");
1892
1927
  const privacyNote = parseOptionalString(value.privacyNote);
1893
1928
  if (privacyNote === void 0) return formError("privacyNote");
1894
1929
  return ok$3({
1895
1930
  fields,
1896
1931
  includeOptionalPhone: value.includeOptionalPhone,
1897
1932
  buttonLabel,
1933
+ successMessage,
1898
1934
  privacyNote
1899
1935
  });
1900
1936
  }
@@ -2101,11 +2137,17 @@ function parseMailingListSignedSourceToken(value) {
2101
2137
  const parsed = typeof value === "string" ? value.trim() : "";
2102
2138
  return /^[A-Za-z0-9._~-]{16,1000}$/u.test(parsed) ? parsed : null;
2103
2139
  }
2104
- function buildMailingListSignupBlockSourceRef(blockId) {
2105
- const parsed = parseMailingListBlockId(blockId);
2106
- return parsed !== null ? {
2140
+ function parseMailingListContentVersionId(value) {
2141
+ const parsed = parseContentVersionId(value);
2142
+ return parsed.ok ? parsed.value : null;
2143
+ }
2144
+ function buildMailingListSignupBlockSourceRef(blockId, contentVersionId) {
2145
+ const parsedBlockId = parseMailingListBlockId(blockId);
2146
+ const parsedContentVersionId = parseMailingListContentVersionId(contentVersionId);
2147
+ return parsedBlockId !== null && parsedContentVersionId !== null ? {
2107
2148
  tag: "block_ref",
2108
- blockId: parsed
2149
+ blockId: parsedBlockId,
2150
+ contentVersionId: parsedContentVersionId
2109
2151
  } : null;
2110
2152
  }
2111
2153
  function sortStableJsonValue(value) {
@@ -4718,7 +4760,7 @@ const BUTTON_CONTRAST_POLICY = {
4718
4760
  nonTextMinimumRatio: 3,
4719
4761
  gradientSamplesPerSegment: 20,
4720
4762
  alphaBackgrounds: "reject-without-known-surface",
4721
- disabled: "retain-full-colour-contract"
4763
+ disabled: "validated-colour-pair-with-muted-control-opacity"
4722
4764
  };
4723
4765
  function formatButtonColourContractError(error) {
4724
4766
  switch (error.tag) {
@@ -5306,6 +5348,25 @@ function parseThemeForPersistence(value) {
5306
5348
  };
5307
5349
  }
5308
5350
  //#endregion
5351
+ //#region ../theme-core/src/buttons/affordanceSuppression.ts
5352
+ /**
5353
+ * Internal: the opt-out the generated affordance rule is written against.
5354
+ *
5355
+ * A button style may declare a trailing `affordance`, which the theme renders as
5356
+ * a CSS `::after` on every button of that variant. An authored button that
5357
+ * renders its own trailing icon must not also receive the theme's, or it shows
5358
+ * two.
5359
+ *
5360
+ * Deliberately not exported from `./index`. This used to be public, and two
5361
+ * block components reached past the theme to draw arrows of their own — one of
5362
+ * them doubling up on the styles that declare an affordance, both of them
5363
+ * overriding the twelve styles that deliberately declare none. Whether a button
5364
+ * carries a trailing affordance is the style's decision; the only caller that
5365
+ * legitimately opts out is the authored-button renderer, which reaches it
5366
+ * through `themeButtonClassNameWithTrailingIcon`.
5367
+ */
5368
+ const AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
5369
+ //#endregion
5309
5370
  //#region ../theme-core/src/buttons/classNames.ts
5310
5371
  /**
5311
5372
  * Parse content/runtime variant identifiers into the closed theme-button class
@@ -5338,6 +5399,461 @@ function themeButtonClassName(spec) {
5338
5399
  spec.extraClassName
5339
5400
  ].filter(Boolean).join(" ");
5340
5401
  }
5402
+ /**
5403
+ * Button classes for an authored button that renders its own trailing icon.
5404
+ *
5405
+ * A separate function rather than a flag on `themeButtonClassName`, because
5406
+ * there is exactly one caller and it should stay visible in a diff. The name
5407
+ * states what the caller knows to be true of its own markup — that it renders a
5408
+ * trailing icon — rather than what the theme does about it. The consequence is
5409
+ * the theme's to decide and to change; a caller naming the consequence would be
5410
+ * asserting a policy it does not own, and would quietly become a lie the moment
5411
+ * that policy moved.
5412
+ *
5413
+ * Do not reach for this to remove an arrow you simply do not want. A trailing
5414
+ * affordance is declared by the button style, and a block overriding that is the
5415
+ * defect this replaced.
5416
+ */
5417
+ function themeButtonClassNameWithTrailingIcon(spec) {
5418
+ return themeButtonClassName({
5419
+ ...spec,
5420
+ extraClassName: [spec.extraClassName, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ")
5421
+ });
5422
+ }
5423
+ const defaultThemeTokens = {
5424
+ color: {
5425
+ "background/base": "#ffffff",
5426
+ "background/elevated": "#f5f5f5",
5427
+ "surface/base": "#ffffff",
5428
+ "surface/subtle": "#f9f9fb",
5429
+ "surface/inverted": "#111111",
5430
+ "content/primary": "#111111",
5431
+ "content/secondary": "#3f3f46",
5432
+ "accent/primary": "#2563eb",
5433
+ "accent/secondary": "#1d4ed8",
5434
+ "border/base": "#e5e7eb"
5435
+ },
5436
+ typography: {
5437
+ "display/hero": {
5438
+ fontSize: "clamp(48px, 8vw, 96px)",
5439
+ lineHeight: "1.05",
5440
+ fontWeight: "700"
5441
+ },
5442
+ "display/section": {
5443
+ fontSize: "clamp(40px, 6vw, 72px)",
5444
+ lineHeight: "1.1",
5445
+ fontWeight: "700"
5446
+ },
5447
+ "heading/large": {
5448
+ fontSize: "clamp(32px, 4vw, 48px)",
5449
+ lineHeight: "1.2",
5450
+ fontWeight: "600"
5451
+ },
5452
+ "heading/medium": {
5453
+ fontSize: "clamp(24px, 3vw, 32px)",
5454
+ lineHeight: "1.25",
5455
+ fontWeight: "600"
5456
+ },
5457
+ "heading/small": {
5458
+ fontSize: "20px",
5459
+ lineHeight: "1.3",
5460
+ fontWeight: "600"
5461
+ },
5462
+ "body/normal": {
5463
+ fontSize: "16px",
5464
+ lineHeight: "1.6",
5465
+ fontWeight: "400"
5466
+ },
5467
+ "body/small": {
5468
+ fontSize: "14px",
5469
+ lineHeight: "1.5",
5470
+ fontWeight: "400"
5471
+ },
5472
+ caption: {
5473
+ fontSize: "12px",
5474
+ lineHeight: "1.4",
5475
+ fontWeight: "500"
5476
+ }
5477
+ },
5478
+ spacing: {
5479
+ none: "0px",
5480
+ "3xs": "4px",
5481
+ "2xs": "8px",
5482
+ xs: "12px",
5483
+ sm: "16px",
5484
+ md: "24px",
5485
+ lg: "32px",
5486
+ xl: "40px",
5487
+ "2xl": "56px",
5488
+ "3xl": "72px"
5489
+ },
5490
+ radius: {
5491
+ none: "0px",
5492
+ xs: "2px",
5493
+ sm: "4px",
5494
+ md: "8px",
5495
+ lg: "12px",
5496
+ pill: "999px",
5497
+ full: "9999px"
5498
+ },
5499
+ shadow: {
5500
+ none: "none",
5501
+ soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
5502
+ medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
5503
+ strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
5504
+ },
5505
+ palette: {
5506
+ surface: "#ffffff",
5507
+ "neutral-50": "#f9fafb",
5508
+ "neutral-900": "#111827",
5509
+ primary: "#2563eb",
5510
+ "primary-50": "#eff6ff",
5511
+ "primary-500": "#2563eb",
5512
+ "primary-900": "#1d4ed8",
5513
+ secondary: "#9333ea",
5514
+ "secondary-50": "#f3e8ff",
5515
+ "secondary-500": "#9333ea",
5516
+ "secondary-900": "#4c1d95",
5517
+ accent: "#f97316",
5518
+ "accent-50": "#fff7ed",
5519
+ "accent-500": "#f97316",
5520
+ "accent-900": "#7c2d12"
5521
+ }
5522
+ };
5523
+ /**
5524
+ * Project the expanded semantic palette into the token buckets consumed by
5525
+ * runtime transforms. Keep this mapping shared by full themes and the
5526
+ * tokens-only hosted-booking runtime so the two paths cannot drift.
5527
+ */
5528
+ function buildThemeTokens(palette) {
5529
+ const tokens = cloneThemeTokens(defaultThemeTokens);
5530
+ const paletteStrings = {};
5531
+ for (const [key, value] of Object.entries(palette)) if (typeof value === "string" && value.trim().length > 0) paletteStrings[key] = value;
5532
+ tokens.palette = paletteStrings;
5533
+ const resolveColor = (...keys) => {
5534
+ for (const key of keys) {
5535
+ const value = paletteStrings[key];
5536
+ if (value) return value;
5537
+ }
5538
+ };
5539
+ const assignColor = (token, ...keys) => {
5540
+ const value = resolveColor(...keys);
5541
+ if (value) tokens.color[token] = value;
5542
+ };
5543
+ assignColor("background/base", "background", "surface", "primary-50");
5544
+ assignColor("background/elevated", "surface", "background");
5545
+ assignColor("surface/base", "surface", "background");
5546
+ assignColor("surface/subtle", "neutral-100", "surface", "background");
5547
+ assignColor("surface/inverted", "neutral-900", "text", "primary-900");
5548
+ assignColor("content/primary", "text", "body", "neutral-900");
5549
+ assignColor("content/secondary", "mutedText", "secondary", "neutral-600");
5550
+ assignColor("accent/primary", "primary", "accent");
5551
+ assignColor("accent/secondary", "accent", "secondary", "primary-400");
5552
+ assignColor("border/base", "border", "neutral-300");
5553
+ return tokens;
5554
+ }
5555
+ function cloneThemeTokens(source) {
5556
+ return JSON.parse(JSON.stringify(source));
5557
+ }
5558
+ //#endregion
5559
+ //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
5560
+ /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
5561
+ function resolveOpaqueSurfaceHex(reference, palette, underlayReference) {
5562
+ const opaque = resolveConcreteColorHex(reference, palette);
5563
+ if (opaque) return opaque;
5564
+ if (!underlayReference) return null;
5565
+ const underlayHex = resolveConcreteColorHex(underlayReference, palette);
5566
+ if (!underlayHex) return null;
5567
+ const parts = parseColorTokenParts(reference);
5568
+ if (parts.kind === "token" && parts.opacityPercent !== null) {
5569
+ const foregroundHex = normalizePaletteHex(palette[parts.token] ?? "");
5570
+ return foregroundHex ? compositeHex(foregroundHex, underlayHex, parts.opacityPercent / 100) : null;
5571
+ }
5572
+ const rgba = parseRgba(parts.kind === "raw" ? parts.value : reference);
5573
+ return rgba ? compositeHex(rgbToHex$1(rgba.r, rgba.g, rgba.b), underlayHex, rgba.alpha) : null;
5574
+ }
5575
+ /** Resolve a colour reference only when it is already fully opaque. */
5576
+ function resolveConcreteColorHex(reference, palette) {
5577
+ const literalHex = normalizePaletteHex(reference);
5578
+ if (literalHex) return literalHex;
5579
+ const parts = parseColorTokenParts(reference);
5580
+ if (parts.kind === "token") {
5581
+ if (parts.opacityPercent !== null) return null;
5582
+ return normalizePaletteHex(palette[parts.token] ?? "");
5583
+ }
5584
+ const literal = parts.kind === "raw" ? parts.value : reference;
5585
+ if (literal.toLowerCase() === "black") return "#000000";
5586
+ if (literal.toLowerCase() === "white") return "#ffffff";
5587
+ return normalizePaletteHex(literal);
5588
+ }
5589
+ function compositeHex(foregroundHex, underlayHex, alpha) {
5590
+ const foreground = hexToRgb$1(foregroundHex);
5591
+ const underlay = hexToRgb$1(underlayHex);
5592
+ const channel = (foregroundValue, underlayValue) => Math.round(foregroundValue * alpha + underlayValue * (1 - alpha));
5593
+ return rgbToHex$1(channel(foreground.r, underlay.r), channel(foreground.g, underlay.g), channel(foreground.b, underlay.b));
5594
+ }
5595
+ function parseRgba(value) {
5596
+ const match = value.trim().match(/^rgba?\(\s*([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*(?:,|\/)\s*([\d.]+%?))?\s*\)$/i);
5597
+ if (!match) return null;
5598
+ const [, rSource, gSource, bSource] = match;
5599
+ if (!rSource || !gSource || !bSource) return null;
5600
+ const r = Number(rSource);
5601
+ const g = Number(gSource);
5602
+ const b = Number(bSource);
5603
+ const alpha = parseAlpha(match[4]);
5604
+ if (alpha === null || !isRgbChannel(r) || !isRgbChannel(g) || !isRgbChannel(b)) return null;
5605
+ return {
5606
+ r,
5607
+ g,
5608
+ b,
5609
+ alpha
5610
+ };
5611
+ }
5612
+ function parseAlpha(source) {
5613
+ if (!source) return 1;
5614
+ const value = source.endsWith("%") ? Number(source.slice(0, -1)) / 100 : Number(source);
5615
+ return Number.isFinite(value) && value >= 0 && value <= 1 ? value : null;
5616
+ }
5617
+ function isRgbChannel(value) {
5618
+ return Number.isFinite(value) && value >= 0 && value <= 255;
5619
+ }
5620
+ //#endregion
5621
+ //#region ../theme-core/src/surfaces/resolveSurfaceForeground.ts
5622
+ const FALLBACK_TEXT_TOKENS = [
5623
+ "text",
5624
+ "primaryForeground",
5625
+ "secondaryForeground",
5626
+ "accentForeground",
5627
+ "neutral-950",
5628
+ "neutral-50"
5629
+ ];
5630
+ const CANONICAL_EQUIVALENT_TOKEN_ORDER = [
5631
+ "text",
5632
+ "primaryForeground",
5633
+ "secondaryForeground",
5634
+ "accentForeground",
5635
+ "onPrimary",
5636
+ "onSecondary",
5637
+ "onAccent",
5638
+ "onSurface",
5639
+ "neutral-950",
5640
+ "neutral-50"
5641
+ ];
5642
+ /**
5643
+ * Resolve the complete foreground contract for an effective page/section or
5644
+ * site-chrome background.
5645
+ *
5646
+ * Deterministic colour backgrounds are validated at ordinary-text WCAG AA.
5647
+ * Existing image/video/gradient treatments are trusted only when they already
5648
+ * carry a usable foreground token; this function deliberately does not claim
5649
+ * pixel-level contrast proof for media.
5650
+ */
5651
+ function resolveSurfaceForeground(background, palette, candidates = {}, options = {}) {
5652
+ const authored = foregroundCandidates(background, candidates);
5653
+ if (background === null) return resolveDeterministicForeground("background", {
5654
+ ...authored,
5655
+ text: authored.text ?? "text"
5656
+ }, palette);
5657
+ if (background.type === "color") {
5658
+ const backgroundReference = normalizedReference(background.color);
5659
+ if (!backgroundReference || backgroundReference === "transparent") return { kind: "unknown" };
5660
+ return resolveDeterministicForeground(backgroundReference, authored, palette, options.compositeBase);
5661
+ }
5662
+ return resolveTrustedTreatmentForeground(authored, palette);
5663
+ }
5664
+ function foregroundCandidates(background, overrides) {
5665
+ return {
5666
+ text: overrides.text ?? background?.textColor ?? null,
5667
+ heading: overrides.heading ?? background?.headingColor ?? null,
5668
+ link: overrides.link ?? background?.linkColor ?? null,
5669
+ supporting: overrides.supporting ?? background?.supportingColor ?? null
5670
+ };
5671
+ }
5672
+ function resolveDeterministicForeground(backgroundReference, candidates, palette, compositeBase) {
5673
+ const backgroundHex = resolveOpaqueSurfaceHex(backgroundReference, palette, compositeBase);
5674
+ if (!backgroundHex) return resolveTrustedTreatmentForeground(candidates, palette);
5675
+ const backgroundToken = paletteToken(backgroundReference);
5676
+ const derivedOnToken = backgroundToken ? onColorTokenName(backgroundToken) : null;
5677
+ const text = firstSafeToken([
5678
+ candidates.text,
5679
+ derivedOnToken,
5680
+ ...FALLBACK_TEXT_TOKENS
5681
+ ], backgroundHex, palette, derivedOnToken ? [derivedOnToken] : []);
5682
+ if (!text) return { kind: "unknown" };
5683
+ return {
5684
+ kind: "known",
5685
+ roles: {
5686
+ text,
5687
+ heading: safeTokenOr(candidates.heading, text, backgroundHex, palette),
5688
+ link: safeTokenOr(candidates.link, text, backgroundHex, palette),
5689
+ supporting: safeTokenOr(candidates.supporting, text, backgroundHex, palette)
5690
+ }
5691
+ };
5692
+ }
5693
+ function resolveTrustedTreatmentForeground(candidates, palette) {
5694
+ const text = canonicalToken(candidates.text, palette);
5695
+ if (!text) return { kind: "unknown" };
5696
+ return {
5697
+ kind: "known",
5698
+ roles: {
5699
+ text,
5700
+ heading: canonicalToken(candidates.heading, palette) ?? text,
5701
+ link: canonicalToken(candidates.link, palette) ?? text,
5702
+ supporting: canonicalToken(candidates.supporting, palette) ?? text
5703
+ }
5704
+ };
5705
+ }
5706
+ function safeTokenOr(candidate, fallback, backgroundHex, palette) {
5707
+ return firstSafeToken([candidate], backgroundHex, palette) ?? fallback;
5708
+ }
5709
+ function firstSafeToken(candidates, backgroundHex, palette, preferredEquivalentTokens = []) {
5710
+ const seen = /* @__PURE__ */ new Set();
5711
+ for (const candidate of candidates) {
5712
+ const token = canonicalToken(candidate, palette, preferredEquivalentTokens);
5713
+ if (!token || seen.has(token)) continue;
5714
+ seen.add(token);
5715
+ const foregroundHex = resolveConcreteColorHex(token, palette);
5716
+ if (foregroundHex && contrastRatio(backgroundHex, foregroundHex) >= 4.5) return token;
5717
+ }
5718
+ return null;
5719
+ }
5720
+ function canonicalToken(reference, palette, preferredEquivalentTokens = []) {
5721
+ const normalized = normalizedReference(reference);
5722
+ if (!normalized || normalized === "transparent") return null;
5723
+ const direct = parseThemeColorToken(normalized);
5724
+ if (direct && resolveConcreteColorHex(direct, palette)) return direct;
5725
+ const referenceHex = resolveConcreteColorHex(normalized, palette);
5726
+ if (!referenceHex) return null;
5727
+ const equivalent = [
5728
+ ...preferredEquivalentTokens,
5729
+ ...CANONICAL_EQUIVALENT_TOKEN_ORDER,
5730
+ ...Object.keys(palette).sort()
5731
+ ].find((token) => {
5732
+ const parsed = parseThemeColorToken(token);
5733
+ return parsed !== null && resolveConcreteColorHex(parsed, palette)?.toLowerCase() === referenceHex.toLowerCase();
5734
+ });
5735
+ return equivalent ? parseThemeColorToken(equivalent) : null;
5736
+ }
5737
+ function paletteToken(reference) {
5738
+ const parts = parseColorTokenParts(reference);
5739
+ return parts.kind === "token" && parts.opacityPercent === null ? parts.token : null;
5740
+ }
5741
+ function normalizedReference(value) {
5742
+ if (typeof value !== "string") return null;
5743
+ const normalized = value.trim();
5744
+ return normalized.length > 0 ? normalized : null;
5745
+ }
5746
+ //#endregion
5747
+ //#region ../theme-core/src/utils/colorStyles.ts
5748
+ const COLOR_VAR_PREFIX = "--tb-";
5749
+ function parseToken(source) {
5750
+ const parts = parseColorTokenParts(source);
5751
+ if (parts.kind === "raw") return {
5752
+ token: source,
5753
+ raw: parts.value
5754
+ };
5755
+ if (parts.kind === "invalid") return { token: source };
5756
+ return {
5757
+ token: parts.token,
5758
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
5759
+ };
5760
+ }
5761
+ const SURFACE_TEXT_ROLE_BY_TOKEN = {
5762
+ text: "text",
5763
+ heading: "heading",
5764
+ mutedText: "supporting"
5765
+ };
5766
+ function surfaceRoleForTextToken(token) {
5767
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
5768
+ }
5769
+ /**
5770
+ * Converts a theme color token to a CSS rgb value.
5771
+ * This is the primary function for applying theme colors to CSS properties.
5772
+ *
5773
+ * @param token - Theme color token (semantic, with opacity, or raw)
5774
+ * @returns CSS color value (rgb with optional alpha, or raw CSS value)
5775
+ *
5776
+ * @example
5777
+ * rgbColorValue('primary') // => 'rgb(var(--tb-primary))'
5778
+ * rgbColorValue('surface/95') // => 'rgb(var(--tb-surface) / 0.95)'
5779
+ * rgbColorValue('raw:transparent') // => 'transparent'
5780
+ */
5781
+ function rgbColorValue(token) {
5782
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
5783
+ if (raw) return raw;
5784
+ const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
5785
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
5786
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
5787
+ }
5788
+ /**
5789
+ * Converts a theme color token to a CSS variable reference.
5790
+ * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
5791
+ *
5792
+ * @param token - Theme color token
5793
+ * @returns CSS variable reference
5794
+ *
5795
+ * @example
5796
+ * cssVarValue('primary') // => 'var(--tb-primary)'
5797
+ * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
5798
+ */
5799
+ function cssVarValue(token) {
5800
+ const { token: baseToken } = parseToken(token);
5801
+ return `var(${COLOR_VAR_PREFIX}${baseToken})`;
5802
+ }
5803
+ /**
5804
+ * Creates a backgroundColor style object from a theme token.
5805
+ *
5806
+ * @param token - Theme color token
5807
+ * @returns CSSProperties with backgroundColor
5808
+ */
5809
+ function backgroundColorStyle(token) {
5810
+ return { backgroundColor: rgbColorValue(token) };
5811
+ }
5812
+ /**
5813
+ * Creates a text color style object from a theme token.
5814
+ *
5815
+ * @param token - Theme color token
5816
+ * @returns CSSProperties with color
5817
+ */
5818
+ function textColorStyle(token) {
5819
+ const parsed = parseToken(token);
5820
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
5821
+ if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
5822
+ return { color: rgbColorValue(token) };
5823
+ }
5824
+ /**
5825
+ * Creates a border color style object from a theme token.
5826
+ *
5827
+ * @param token - Theme color token
5828
+ * @returns CSSProperties with borderColor
5829
+ */
5830
+ function borderColorStyle(token) {
5831
+ return { borderColor: rgbColorValue(token) };
5832
+ }
5833
+ /**
5834
+ * Merges multiple CSSProperties objects into a single object.
5835
+ * Later styles override earlier ones. Undefined values are filtered out.
5836
+ * Returns undefined if the merged result is empty.
5837
+ *
5838
+ * @param styles - Variable number of CSSProperties objects (can be undefined)
5839
+ * @returns Merged CSSProperties object, or undefined if empty
5840
+ *
5841
+ * @example
5842
+ * mergeStyles(
5843
+ * backgroundColorStyle('surface'),
5844
+ * textColorStyle('text'),
5845
+ * borderColorStyle('border')
5846
+ * )
5847
+ * // => { backgroundColor: '...', color: '...', borderColor: '...' }
5848
+ */
5849
+ function mergeStyles(...styles) {
5850
+ const merged = {};
5851
+ for (const style of styles) {
5852
+ if (!style) continue;
5853
+ Object.assign(merged, style);
5854
+ }
5855
+ return Object.keys(merged).length ? merged : void 0;
5856
+ }
5341
5857
  //#endregion
5342
5858
  //#region ../theme-core/src/tokens/resolver.ts
5343
5859
  /**
@@ -5365,7 +5881,7 @@ var TokenResolver = class {
5365
5881
  */
5366
5882
  getColor(token) {
5367
5883
  if (!this.tokenExists(token)) console.warn(`[TokenResolver] Color token "${token}" not found in theme palette. Button may render incorrectly.`);
5368
- return `rgb(var(--tb-${token}))`;
5884
+ return rgbColorValue(token);
5369
5885
  }
5370
5886
  /**
5371
5887
  * Adjust a color token's shade by a given amount
@@ -6837,305 +7353,6 @@ function affordanceIconMaskUrl(iconId) {
6837
7353
  return `data:image/svg+xml,${`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>${paths.map((d) => `<path d='${d}'/>`).join("")}</svg>`.replace(/"/g, "'").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ")}`;
6838
7354
  }
6839
7355
  //#endregion
6840
- //#region ../theme-core/src/palette/utils/opaqueSurfaceColor.ts
6841
- /** Resolve an opaque colour, compositing alpha against an explicit underlay. */
6842
- function resolveOpaqueSurfaceHex(reference, palette, underlayReference) {
6843
- const opaque = resolveConcreteColorHex(reference, palette);
6844
- if (opaque) return opaque;
6845
- if (!underlayReference) return null;
6846
- const underlayHex = resolveConcreteColorHex(underlayReference, palette);
6847
- if (!underlayHex) return null;
6848
- const parts = parseColorTokenParts(reference);
6849
- if (parts.kind === "token" && parts.opacityPercent !== null) {
6850
- const foregroundHex = normalizePaletteHex(palette[parts.token] ?? "");
6851
- return foregroundHex ? compositeHex(foregroundHex, underlayHex, parts.opacityPercent / 100) : null;
6852
- }
6853
- const rgba = parseRgba(parts.kind === "raw" ? parts.value : reference);
6854
- return rgba ? compositeHex(rgbToHex$1(rgba.r, rgba.g, rgba.b), underlayHex, rgba.alpha) : null;
6855
- }
6856
- /** Resolve a colour reference only when it is already fully opaque. */
6857
- function resolveConcreteColorHex(reference, palette) {
6858
- const literalHex = normalizePaletteHex(reference);
6859
- if (literalHex) return literalHex;
6860
- const parts = parseColorTokenParts(reference);
6861
- if (parts.kind === "token") {
6862
- if (parts.opacityPercent !== null) return null;
6863
- return normalizePaletteHex(palette[parts.token] ?? "");
6864
- }
6865
- const literal = parts.kind === "raw" ? parts.value : reference;
6866
- if (literal.toLowerCase() === "black") return "#000000";
6867
- if (literal.toLowerCase() === "white") return "#ffffff";
6868
- return normalizePaletteHex(literal);
6869
- }
6870
- function compositeHex(foregroundHex, underlayHex, alpha) {
6871
- const foreground = hexToRgb$1(foregroundHex);
6872
- const underlay = hexToRgb$1(underlayHex);
6873
- const channel = (foregroundValue, underlayValue) => Math.round(foregroundValue * alpha + underlayValue * (1 - alpha));
6874
- return rgbToHex$1(channel(foreground.r, underlay.r), channel(foreground.g, underlay.g), channel(foreground.b, underlay.b));
6875
- }
6876
- function parseRgba(value) {
6877
- const match = value.trim().match(/^rgba?\(\s*([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*,\s*|\s+)([\d.]+)(?:\s*(?:,|\/)\s*([\d.]+%?))?\s*\)$/i);
6878
- if (!match) return null;
6879
- const [, rSource, gSource, bSource] = match;
6880
- if (!rSource || !gSource || !bSource) return null;
6881
- const r = Number(rSource);
6882
- const g = Number(gSource);
6883
- const b = Number(bSource);
6884
- const alpha = parseAlpha(match[4]);
6885
- if (alpha === null || !isRgbChannel(r) || !isRgbChannel(g) || !isRgbChannel(b)) return null;
6886
- return {
6887
- r,
6888
- g,
6889
- b,
6890
- alpha
6891
- };
6892
- }
6893
- function parseAlpha(source) {
6894
- if (!source) return 1;
6895
- const value = source.endsWith("%") ? Number(source.slice(0, -1)) / 100 : Number(source);
6896
- return Number.isFinite(value) && value >= 0 && value <= 1 ? value : null;
6897
- }
6898
- function isRgbChannel(value) {
6899
- return Number.isFinite(value) && value >= 0 && value <= 255;
6900
- }
6901
- //#endregion
6902
- //#region ../theme-core/src/surfaces/resolveSurfaceForeground.ts
6903
- const FALLBACK_TEXT_TOKENS = [
6904
- "text",
6905
- "primaryForeground",
6906
- "secondaryForeground",
6907
- "accentForeground",
6908
- "neutral-950",
6909
- "neutral-50"
6910
- ];
6911
- const CANONICAL_EQUIVALENT_TOKEN_ORDER = [
6912
- "text",
6913
- "primaryForeground",
6914
- "secondaryForeground",
6915
- "accentForeground",
6916
- "onPrimary",
6917
- "onSecondary",
6918
- "onAccent",
6919
- "onSurface",
6920
- "neutral-950",
6921
- "neutral-50"
6922
- ];
6923
- /**
6924
- * Resolve the complete foreground contract for an effective page/section or
6925
- * site-chrome background.
6926
- *
6927
- * Deterministic colour backgrounds are validated at ordinary-text WCAG AA.
6928
- * Existing image/video/gradient treatments are trusted only when they already
6929
- * carry a usable foreground token; this function deliberately does not claim
6930
- * pixel-level contrast proof for media.
6931
- */
6932
- function resolveSurfaceForeground(background, palette, candidates = {}, options = {}) {
6933
- const authored = foregroundCandidates(background, candidates);
6934
- if (background === null) return resolveDeterministicForeground("background", {
6935
- ...authored,
6936
- text: authored.text ?? "text"
6937
- }, palette);
6938
- if (background.type === "color") {
6939
- const backgroundReference = normalizedReference(background.color);
6940
- if (!backgroundReference || backgroundReference === "transparent") return { kind: "unknown" };
6941
- return resolveDeterministicForeground(backgroundReference, authored, palette, options.compositeBase);
6942
- }
6943
- return resolveTrustedTreatmentForeground(authored, palette);
6944
- }
6945
- function foregroundCandidates(background, overrides) {
6946
- return {
6947
- text: overrides.text ?? background?.textColor ?? null,
6948
- heading: overrides.heading ?? background?.headingColor ?? null,
6949
- link: overrides.link ?? background?.linkColor ?? null,
6950
- supporting: overrides.supporting ?? background?.supportingColor ?? null
6951
- };
6952
- }
6953
- function resolveDeterministicForeground(backgroundReference, candidates, palette, compositeBase) {
6954
- const backgroundHex = resolveOpaqueSurfaceHex(backgroundReference, palette, compositeBase);
6955
- if (!backgroundHex) return resolveTrustedTreatmentForeground(candidates, palette);
6956
- const backgroundToken = paletteToken(backgroundReference);
6957
- const derivedOnToken = backgroundToken ? onColorTokenName(backgroundToken) : null;
6958
- const text = firstSafeToken([
6959
- candidates.text,
6960
- derivedOnToken,
6961
- ...FALLBACK_TEXT_TOKENS
6962
- ], backgroundHex, palette, derivedOnToken ? [derivedOnToken] : []);
6963
- if (!text) return { kind: "unknown" };
6964
- return {
6965
- kind: "known",
6966
- roles: {
6967
- text,
6968
- heading: safeTokenOr(candidates.heading, text, backgroundHex, palette),
6969
- link: safeTokenOr(candidates.link, text, backgroundHex, palette),
6970
- supporting: safeTokenOr(candidates.supporting, text, backgroundHex, palette)
6971
- }
6972
- };
6973
- }
6974
- function resolveTrustedTreatmentForeground(candidates, palette) {
6975
- const text = canonicalToken(candidates.text, palette);
6976
- if (!text) return { kind: "unknown" };
6977
- return {
6978
- kind: "known",
6979
- roles: {
6980
- text,
6981
- heading: canonicalToken(candidates.heading, palette) ?? text,
6982
- link: canonicalToken(candidates.link, palette) ?? text,
6983
- supporting: canonicalToken(candidates.supporting, palette) ?? text
6984
- }
6985
- };
6986
- }
6987
- function safeTokenOr(candidate, fallback, backgroundHex, palette) {
6988
- return firstSafeToken([candidate], backgroundHex, palette) ?? fallback;
6989
- }
6990
- function firstSafeToken(candidates, backgroundHex, palette, preferredEquivalentTokens = []) {
6991
- const seen = /* @__PURE__ */ new Set();
6992
- for (const candidate of candidates) {
6993
- const token = canonicalToken(candidate, palette, preferredEquivalentTokens);
6994
- if (!token || seen.has(token)) continue;
6995
- seen.add(token);
6996
- const foregroundHex = resolveConcreteColorHex(token, palette);
6997
- if (foregroundHex && contrastRatio(backgroundHex, foregroundHex) >= 4.5) return token;
6998
- }
6999
- return null;
7000
- }
7001
- function canonicalToken(reference, palette, preferredEquivalentTokens = []) {
7002
- const normalized = normalizedReference(reference);
7003
- if (!normalized || normalized === "transparent") return null;
7004
- const direct = parseThemeColorToken(normalized);
7005
- if (direct && resolveConcreteColorHex(direct, palette)) return direct;
7006
- const referenceHex = resolveConcreteColorHex(normalized, palette);
7007
- if (!referenceHex) return null;
7008
- const equivalent = [
7009
- ...preferredEquivalentTokens,
7010
- ...CANONICAL_EQUIVALENT_TOKEN_ORDER,
7011
- ...Object.keys(palette).sort()
7012
- ].find((token) => {
7013
- const parsed = parseThemeColorToken(token);
7014
- return parsed !== null && resolveConcreteColorHex(parsed, palette)?.toLowerCase() === referenceHex.toLowerCase();
7015
- });
7016
- return equivalent ? parseThemeColorToken(equivalent) : null;
7017
- }
7018
- function paletteToken(reference) {
7019
- const parts = parseColorTokenParts(reference);
7020
- return parts.kind === "token" && parts.opacityPercent === null ? parts.token : null;
7021
- }
7022
- function normalizedReference(value) {
7023
- if (typeof value !== "string") return null;
7024
- const normalized = value.trim();
7025
- return normalized.length > 0 ? normalized : null;
7026
- }
7027
- //#endregion
7028
- //#region ../theme-core/src/utils/colorStyles.ts
7029
- const COLOR_VAR_PREFIX = "--tb-";
7030
- function parseToken(source) {
7031
- const parts = parseColorTokenParts(source);
7032
- if (parts.kind === "raw") return {
7033
- token: source,
7034
- raw: parts.value
7035
- };
7036
- if (parts.kind === "invalid") return { token: source };
7037
- return {
7038
- token: parts.token,
7039
- opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
7040
- };
7041
- }
7042
- const SURFACE_TEXT_ROLE_BY_TOKEN = {
7043
- text: "text",
7044
- heading: "heading",
7045
- mutedText: "supporting"
7046
- };
7047
- function surfaceRoleForTextToken(token) {
7048
- return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
7049
- }
7050
- /**
7051
- * Converts a theme color token to a CSS rgb value.
7052
- * This is the primary function for applying theme colors to CSS properties.
7053
- *
7054
- * @param token - Theme color token (semantic, with opacity, or raw)
7055
- * @returns CSS color value (rgb with optional alpha, or raw CSS value)
7056
- *
7057
- * @example
7058
- * rgbColorValue('primary') // => 'rgb(var(--tb-primary))'
7059
- * rgbColorValue('surface/95') // => 'rgb(var(--tb-surface) / 0.95)'
7060
- * rgbColorValue('raw:transparent') // => 'transparent'
7061
- */
7062
- function rgbColorValue(token) {
7063
- const { token: baseToken, opacityPercent, raw } = parseToken(token);
7064
- if (raw) return raw;
7065
- const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
7066
- if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
7067
- return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
7068
- }
7069
- /**
7070
- * Converts a theme color token to a CSS variable reference.
7071
- * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
7072
- *
7073
- * @param token - Theme color token
7074
- * @returns CSS variable reference
7075
- *
7076
- * @example
7077
- * cssVarValue('primary') // => 'var(--tb-primary)'
7078
- * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
7079
- */
7080
- function cssVarValue(token) {
7081
- const { token: baseToken } = parseToken(token);
7082
- return `var(${COLOR_VAR_PREFIX}${baseToken})`;
7083
- }
7084
- /**
7085
- * Creates a backgroundColor style object from a theme token.
7086
- *
7087
- * @param token - Theme color token
7088
- * @returns CSSProperties with backgroundColor
7089
- */
7090
- function backgroundColorStyle(token) {
7091
- return { backgroundColor: rgbColorValue(token) };
7092
- }
7093
- /**
7094
- * Creates a text color style object from a theme token.
7095
- *
7096
- * @param token - Theme color token
7097
- * @returns CSSProperties with color
7098
- */
7099
- function textColorStyle(token) {
7100
- const parsed = parseToken(token);
7101
- const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
7102
- if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
7103
- return { color: rgbColorValue(token) };
7104
- }
7105
- /**
7106
- * Creates a border color style object from a theme token.
7107
- *
7108
- * @param token - Theme color token
7109
- * @returns CSSProperties with borderColor
7110
- */
7111
- function borderColorStyle(token) {
7112
- return { borderColor: rgbColorValue(token) };
7113
- }
7114
- /**
7115
- * Merges multiple CSSProperties objects into a single object.
7116
- * Later styles override earlier ones. Undefined values are filtered out.
7117
- * Returns undefined if the merged result is empty.
7118
- *
7119
- * @param styles - Variable number of CSSProperties objects (can be undefined)
7120
- * @returns Merged CSSProperties object, or undefined if empty
7121
- *
7122
- * @example
7123
- * mergeStyles(
7124
- * backgroundColorStyle('surface'),
7125
- * textColorStyle('text'),
7126
- * borderColorStyle('border')
7127
- * )
7128
- * // => { backgroundColor: '...', color: '...', borderColor: '...' }
7129
- */
7130
- function mergeStyles(...styles) {
7131
- const merged = {};
7132
- for (const style of styles) {
7133
- if (!style) continue;
7134
- Object.assign(merged, style);
7135
- }
7136
- return Object.keys(merged).length ? merged : void 0;
7137
- }
7138
- //#endregion
7139
7356
  //#region ../theme-core/src/utils/tokenOrColor.ts
7140
7357
  /**
7141
7358
  * Runtime color-reference fields intentionally accept any string, including
@@ -7621,26 +7838,19 @@ function resolvedButtonFocusDeclarations(indicator, role) {
7621
7838
  ] : [["outline", value("outline", `3px solid ${indicator.colorCss}`)], ["outline-offset", value("outline-offset", "3px")]];
7622
7839
  }
7623
7840
  /**
7624
- * Disabled buttons retain their validated colour pair and add a non-layout
7625
- * visual affordance. `currentColor` keeps the cue inside the same contrast
7626
- * relationship, while retaining pointer events lets the not-allowed cursor
7627
- * remain observable.
7841
+ * Disabled buttons are deliberately muted as unavailable controls. Native
7842
+ * disabled controls are exempt from active-control contrast requirements;
7843
+ * opacity distinguishes the state without introducing a focus-like outline.
7844
+ * Retaining pointer events lets the not-allowed cursor remain observable.
7628
7845
  */
7629
7846
  const RESOLVED_BUTTON_DISABLED_DECLARATIONS = [
7630
7847
  ["cursor", "not-allowed"],
7631
7848
  ["transform", "none"],
7632
7849
  ["box-shadow", "none"],
7633
- ["outline", "2px dashed currentColor"],
7634
- ["outline-offset", "-4px"]
7850
+ ["opacity", "0.55"]
7635
7851
  ];
7636
7852
  //#endregion
7637
7853
  //#region ../theme-core/src/buttons/generateButtonCss.ts
7638
- /**
7639
- * Class the `button` runtime node adds when it renders its own trailing icon,
7640
- * so a node-level icon suppresses the theme's CSS `::after` affordance.
7641
- * Shared so generator and renderer can't drift.
7642
- */
7643
- const AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
7644
7854
  const BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
7645
7855
  /**
7646
7856
  * Letter spacing token → CSS value.
@@ -10434,14 +10644,12 @@ function generateVariantCSS(variant, themeId, cardClasses, tokens, theme) {
10434
10644
  const shadowValue = generateShadowValue(shadow);
10435
10645
  rules.push(`box-shadow: ${shadowValue}`);
10436
10646
  }
10437
- rules.push(`display: flex`);
10438
- rules.push(`flex-direction: column`);
10439
- rules.push(`position: relative`);
10440
- rules.push(`overflow: visible`);
10647
+ const structureSelector = cardClasses.map((cardClass) => `:where([data-theme-scope="${themeId}"]) :where(.${cardClass})`).join(",\n");
10441
10648
  const mediaRadius = MEDIA_CORNER_MAP[corners];
10442
10649
  const mediaRules = [`border-top-left-radius: ${mediaRadius}`, `border-top-right-radius: ${mediaRadius}`];
10443
10650
  const contentRules = [`padding: ${resolveContentPadding(variant)}`];
10444
10651
  return [
10652
+ `${structureSelector} {\n display: flex;\n flex-direction: column;\n position: relative;\n overflow: visible;\n}`,
10445
10653
  `${containerSelector} {\n ${rules.join(";\n ")};\n}`,
10446
10654
  ...cardDecorationPseudoRules(containerSelectors, variant.decorations, resolveColor),
10447
10655
  `${fallbackBackgroundSelector} {\n background: transparent;\n}`,
@@ -11833,8 +12041,14 @@ const headerInteractionPillPaletteValues = [
11833
12041
  "accent"
11834
12042
  ];
11835
12043
  /**
11836
- * "No pill": the nav link keeps whatever hover treatment its recipe compiled,
11837
- * and the palette step writes nothing at all (#1318 Phase 4c decision 2).
12044
+ * "No pill": a colour change on hover rather than a filled background.
12045
+ *
12046
+ * The palette step writes nothing (#1318 Phase 4c decision 2), but on a
12047
+ * foreground-adaptive style that is not the end of the story: the hover colour
12048
+ * is derived from the resolved opening foreground at render time, paired with
12049
+ * the resting colour, so `quiet` resolves to a definite colour rather than to
12050
+ * whatever brand token the recipe happened to name. See
12051
+ * `applyOpeningForeground`.
11838
12052
  *
11839
12053
  * It exists because "a colour change on hover, no filled background" was not
11840
12054
  * expressible in the vocabulary, and it is what
@@ -12858,6 +13072,28 @@ const bookingRequirementConsentFieldSchema = z$1.object({
12858
13072
  const bookingConsentCarrierSchema = z$1.union([blockBookingConsentSchema, bookingRequirementConsentFieldSchema]);
12859
13073
  //#endregion
12860
13074
  //#region ../blocks/src/system/blocks/events/shared/schemas.ts
13075
+ const publicEventLoaderQuerySchemaShape = {
13076
+ limit: z$1.string().optional(),
13077
+ from: z$1.string().optional(),
13078
+ to: z$1.string().optional(),
13079
+ afterStartsAt: z$1.string().optional(),
13080
+ afterId: z$1.string().optional(),
13081
+ categoryIds: z$1.string().optional(),
13082
+ venueId: z$1.string().optional(),
13083
+ staffMemberId: z$1.string().optional(),
13084
+ eventSurface: z$1.string().optional(),
13085
+ eventPresets: z$1.string().optional(),
13086
+ scheduleScope: z$1.string().optional(),
13087
+ seriesId: z$1.string().optional(),
13088
+ seriesIds: z$1.string().optional(),
13089
+ runSeriesId: z$1.string().optional(),
13090
+ seriesSlug: z$1.string().optional(),
13091
+ includeOccurrenceId: z$1.string().optional(),
13092
+ readIntent: z$1.string().optional(),
13093
+ detailLevel: z$1.string().optional(),
13094
+ readProfile: z$1.string().optional()
13095
+ };
13096
+ z$1.object(publicEventLoaderQuerySchemaShape);
12861
13097
  const eventPresetSchema = z$1.enum([
12862
13098
  "event",
12863
13099
  "class",
@@ -13265,6 +13501,7 @@ const calendarWindowQuerySchema = z$1.object({
13265
13501
  eventSurface: z$1.enum(eventSurfaceScopeValues).optional(),
13266
13502
  eventPresets: z$1.string().optional(),
13267
13503
  scheduleScope: z$1.enum(eventScheduleScopeValues).optional(),
13504
+ seriesIds: z$1.string().optional(),
13268
13505
  categoryIds: z$1.string().optional(),
13269
13506
  venueId: z$1.string().transform(normalizeCalendarFilterId).optional(),
13270
13507
  staffMemberId: z$1.string().transform(normalizeCalendarFilterId).optional()
@@ -15245,141 +15482,6 @@ function assertUniqueLayoutProfileKeys(profiles) {
15245
15482
  });
15246
15483
  if (duplicates.length > 0) throw new Error(`Duplicate block layout design profiles: ${duplicates.join(", ")}`);
15247
15484
  }
15248
- const defaultThemeTokens = {
15249
- color: {
15250
- "background/base": "#ffffff",
15251
- "background/elevated": "#f5f5f5",
15252
- "surface/base": "#ffffff",
15253
- "surface/subtle": "#f9f9fb",
15254
- "surface/inverted": "#111111",
15255
- "content/primary": "#111111",
15256
- "content/secondary": "#3f3f46",
15257
- "accent/primary": "#2563eb",
15258
- "accent/secondary": "#1d4ed8",
15259
- "border/base": "#e5e7eb"
15260
- },
15261
- typography: {
15262
- "display/hero": {
15263
- fontSize: "clamp(48px, 8vw, 96px)",
15264
- lineHeight: "1.05",
15265
- fontWeight: "700"
15266
- },
15267
- "display/section": {
15268
- fontSize: "clamp(40px, 6vw, 72px)",
15269
- lineHeight: "1.1",
15270
- fontWeight: "700"
15271
- },
15272
- "heading/large": {
15273
- fontSize: "clamp(32px, 4vw, 48px)",
15274
- lineHeight: "1.2",
15275
- fontWeight: "600"
15276
- },
15277
- "heading/medium": {
15278
- fontSize: "clamp(24px, 3vw, 32px)",
15279
- lineHeight: "1.25",
15280
- fontWeight: "600"
15281
- },
15282
- "heading/small": {
15283
- fontSize: "20px",
15284
- lineHeight: "1.3",
15285
- fontWeight: "600"
15286
- },
15287
- "body/normal": {
15288
- fontSize: "16px",
15289
- lineHeight: "1.6",
15290
- fontWeight: "400"
15291
- },
15292
- "body/small": {
15293
- fontSize: "14px",
15294
- lineHeight: "1.5",
15295
- fontWeight: "400"
15296
- },
15297
- caption: {
15298
- fontSize: "12px",
15299
- lineHeight: "1.4",
15300
- fontWeight: "500"
15301
- }
15302
- },
15303
- spacing: {
15304
- none: "0px",
15305
- "3xs": "4px",
15306
- "2xs": "8px",
15307
- xs: "12px",
15308
- sm: "16px",
15309
- md: "24px",
15310
- lg: "32px",
15311
- xl: "40px",
15312
- "2xl": "56px",
15313
- "3xl": "72px"
15314
- },
15315
- radius: {
15316
- none: "0px",
15317
- xs: "2px",
15318
- sm: "4px",
15319
- md: "8px",
15320
- lg: "12px",
15321
- pill: "999px",
15322
- full: "9999px"
15323
- },
15324
- shadow: {
15325
- none: "none",
15326
- soft: "0px 2px 8px rgba(15, 23, 42, 0.08)",
15327
- medium: "0px 6px 18px rgba(15, 23, 42, 0.12)",
15328
- strong: "0px 12px 36px rgba(15, 23, 42, 0.16)"
15329
- },
15330
- palette: {
15331
- surface: "#ffffff",
15332
- "neutral-50": "#f9fafb",
15333
- "neutral-900": "#111827",
15334
- primary: "#2563eb",
15335
- "primary-50": "#eff6ff",
15336
- "primary-500": "#2563eb",
15337
- "primary-900": "#1d4ed8",
15338
- secondary: "#9333ea",
15339
- "secondary-50": "#f3e8ff",
15340
- "secondary-500": "#9333ea",
15341
- "secondary-900": "#4c1d95",
15342
- accent: "#f97316",
15343
- "accent-50": "#fff7ed",
15344
- "accent-500": "#f97316",
15345
- "accent-900": "#7c2d12"
15346
- }
15347
- };
15348
- /**
15349
- * Project the expanded semantic palette into the token buckets consumed by
15350
- * runtime transforms. Keep this mapping shared by full themes and the
15351
- * tokens-only hosted-booking runtime so the two paths cannot drift.
15352
- */
15353
- function buildThemeTokens(palette) {
15354
- const tokens = cloneThemeTokens(defaultThemeTokens);
15355
- const paletteStrings = {};
15356
- for (const [key, value] of Object.entries(palette)) if (typeof value === "string" && value.trim().length > 0) paletteStrings[key] = value;
15357
- tokens.palette = paletteStrings;
15358
- const resolveColor = (...keys) => {
15359
- for (const key of keys) {
15360
- const value = paletteStrings[key];
15361
- if (value) return value;
15362
- }
15363
- };
15364
- const assignColor = (token, ...keys) => {
15365
- const value = resolveColor(...keys);
15366
- if (value) tokens.color[token] = value;
15367
- };
15368
- assignColor("background/base", "background", "surface", "primary-50");
15369
- assignColor("background/elevated", "surface", "background");
15370
- assignColor("surface/base", "surface", "background");
15371
- assignColor("surface/subtle", "neutral-100", "surface", "background");
15372
- assignColor("surface/inverted", "neutral-900", "text", "primary-900");
15373
- assignColor("content/primary", "text", "body", "neutral-900");
15374
- assignColor("content/secondary", "mutedText", "secondary", "neutral-600");
15375
- assignColor("accent/primary", "primary", "accent");
15376
- assignColor("accent/secondary", "accent", "secondary", "primary-400");
15377
- assignColor("border/base", "border", "neutral-300");
15378
- return tokens;
15379
- }
15380
- function cloneThemeTokens(source) {
15381
- return JSON.parse(JSON.stringify(source));
15382
- }
15383
15485
  //#endregion
15384
15486
  //#region ../theme-core/src/site-styles/backgroundAppearance.ts
15385
15487
  const backgroundAppearanceQuickColorTokenNames = [
@@ -23228,6 +23330,7 @@ function isDisplayMediaKind$2(kind) {
23228
23330
  }
23229
23331
  const siteOptionSources = [
23230
23332
  "eventCategories",
23333
+ "eventSeries",
23231
23334
  "venues",
23232
23335
  "staffMembers"
23233
23336
  ];
@@ -27596,6 +27699,35 @@ function buildBookingFormInteractiveIslandProps(props) {
27596
27699
  });
27597
27700
  }
27598
27701
  //#endregion
27702
+ //#region ../blocks/src/system/blocks/events/shared/eventSelection.ts
27703
+ /** Invalid saved selections fail closed rather than widening discovery. */
27704
+ function resolveEventSelection(mode, value) {
27705
+ if (mode !== "selected") return { kind: "matching" };
27706
+ const candidates = Array.isArray(value) ? value : typeof value === "string" ? value.split(",").filter(Boolean) : [];
27707
+ const ids = [];
27708
+ for (const candidate of candidates) {
27709
+ if (typeof candidate !== "string") return {
27710
+ kind: "selected",
27711
+ seriesIds: []
27712
+ };
27713
+ const parsed = parseEventSeriesId(candidate.trim());
27714
+ if (!parsed.ok) return {
27715
+ kind: "selected",
27716
+ seriesIds: []
27717
+ };
27718
+ ids.push(parsed.value);
27719
+ }
27720
+ return {
27721
+ kind: "selected",
27722
+ seriesIds: [...new Set(ids)].sort()
27723
+ };
27724
+ }
27725
+ /** Undefined means discovery; an empty string is an explicitly empty selection. */
27726
+ function eventSeriesScopeCsv(value) {
27727
+ if (value == null) return void 0;
27728
+ return typeof value === "string" ? value : value.join(",");
27729
+ }
27730
+ //#endregion
27599
27731
  //#region ../blocks/src/system/runtime/nodes/events/domain/capacity.ts
27600
27732
  /**
27601
27733
  * Compute remaining spots for an event from `availableSpots` with a fallback
@@ -30215,12 +30347,12 @@ const EventCompactRow = ({ event, buttonVariant = "primary", buttonText }) => {
30215
30347
  }), cta.hidden ? /* @__PURE__ */ jsx("span", {
30216
30348
  className: "event-compact-row-status",
30217
30349
  children: cta.label
30218
- }) : /* @__PURE__ */ jsxs("a", {
30350
+ }) : /* @__PURE__ */ jsx("a", {
30219
30351
  href: cta.href,
30220
30352
  target: cta.external ? "_blank" : void 0,
30221
30353
  rel: cta.external ? "noopener noreferrer" : void 0,
30222
30354
  className: `${buttonClass} event-compact-row-cta`,
30223
- children: [/* @__PURE__ */ jsx("span", { children: cta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, { "aria-hidden": "true" })]
30355
+ children: /* @__PURE__ */ jsx("span", { children: cta.label })
30224
30356
  })]
30225
30357
  })]
30226
30358
  })]
@@ -30512,6 +30644,7 @@ const eventCollectionFilterSourceSchemaShape = {
30512
30644
  eventSurface: eventSurfaceScopeSchema$1.nullable().optional(),
30513
30645
  filterEventPresets: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
30514
30646
  scheduleScope: eventScheduleScopeSchema$1.nullable().optional(),
30647
+ seriesIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
30515
30648
  filterCategoryIds: z$1.union([z$1.string(), z$1.array(z$1.string())]).nullable().optional(),
30516
30649
  filterStaffMemberId: z$1.string().nullable().optional(),
30517
30650
  filterVenueId: z$1.string().nullable().optional()
@@ -30558,6 +30691,7 @@ const eventCollectionDisplaySchemaShape = {
30558
30691
  eventSurface: eventSurfaceScopeSchema$1,
30559
30692
  filterEventPresets: z$1.string().nullable(),
30560
30693
  scheduleScope: eventScheduleScopeSchema$1,
30694
+ seriesIds: z$1.string().nullable().optional(),
30561
30695
  filterCategoryIds: z$1.string().nullable(),
30562
30696
  filterStaffMemberId: z$1.string().nullable(),
30563
30697
  filterVenueId: z$1.string().nullable(),
@@ -30605,11 +30739,15 @@ function buildEventCollectionDisplay(source) {
30605
30739
  };
30606
30740
  }
30607
30741
  function buildEventCollectionFilterDisplay(source) {
30608
- return {
30609
- showFilters: source.showFilters ?? true,
30610
- showCategoryFilter: source.showCategoryFilter ?? "auto",
30611
- showVenueFilter: source.showVenueFilter ?? false,
30612
- showStaffFilter: source.showStaffFilter ?? true,
30742
+ const selected = source.seriesIds != null;
30743
+ const matchingFilters = selected ? {
30744
+ eventSurface: "all",
30745
+ filterEventPresets: null,
30746
+ scheduleScope: "any",
30747
+ filterCategoryIds: null,
30748
+ filterStaffMemberId: null,
30749
+ filterVenueId: null
30750
+ } : {
30613
30751
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
30614
30752
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
30615
30753
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
@@ -30617,6 +30755,14 @@ function buildEventCollectionFilterDisplay(source) {
30617
30755
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
30618
30756
  filterVenueId: normalizeEventVenueId(source.filterVenueId)
30619
30757
  };
30758
+ return {
30759
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
30760
+ showFilters: selected ? false : source.showFilters ?? true,
30761
+ showCategoryFilter: source.showCategoryFilter ?? "auto",
30762
+ showVenueFilter: source.showVenueFilter ?? false,
30763
+ showStaffFilter: source.showStaffFilter ?? true,
30764
+ ...matchingFilters
30765
+ };
30620
30766
  }
30621
30767
  function buildEventCollectionPresentationDisplay(source) {
30622
30768
  return {
@@ -30631,14 +30777,15 @@ function buildEventCollectionPresentationDisplay(source) {
30631
30777
  }
30632
30778
  function buildEventCollectionHydration(source, now = /* @__PURE__ */ new Date()) {
30633
30779
  const timeZone = source.calendarWindow?.scope.timeZone ?? toBookingTimeZone(source.bookingTimeZone);
30780
+ const selected = source.seriesIds != null;
30634
30781
  return {
30635
30782
  calendarWindow: source.calendarWindow ?? void 0,
30636
30783
  siteId: source.siteId,
30637
30784
  stage: source.stage,
30638
30785
  prefetchedEvents: source.events != null,
30639
- eventSurface: normalizeEventSurfaceScope(source.eventSurface),
30640
- filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
30641
- scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
30786
+ eventSurface: selected ? "all" : normalizeEventSurfaceScope(source.eventSurface),
30787
+ filterEventPresets: selected ? null : normalizeEventSurfacePresetsCsv(source.filterEventPresets),
30788
+ scheduleScope: selected ? "any" : normalizeEventScheduleScope(source.scheduleScope),
30642
30789
  calendarContext: {
30643
30790
  timeZone,
30644
30791
  initialToday: source.calendarWindow?.initialToday ?? getLocalScheduleDate(now, timeZone)
@@ -30724,6 +30871,7 @@ const eventListingHydrationSchema = z$1.object({
30724
30871
  eventSurface: eventSurfaceScopeSchema,
30725
30872
  filterEventPresets: z$1.string().nullable(),
30726
30873
  scheduleScope: eventScheduleScopeSchema,
30874
+ seriesIds: z$1.string().nullable().optional(),
30727
30875
  filterCategoryIds: z$1.string().nullable().optional(),
30728
30876
  filterStaffMemberId: z$1.string().nullable().optional(),
30729
30877
  filterVenueId: z$1.string().nullable().optional(),
@@ -30784,6 +30932,7 @@ const eventListingBlockRuntime = defineProgressiveBlockRuntime({
30784
30932
  eventSurface: normalizeEventSurfaceScope(source.eventSurface),
30785
30933
  filterEventPresets: normalizeEventSurfacePresetsCsv(source.filterEventPresets),
30786
30934
  scheduleScope: normalizeEventScheduleScope(source.scheduleScope),
30935
+ seriesIds: eventSeriesScopeCsv(source.seriesIds),
30787
30936
  filterCategoryIds: normalizeEventCategoryIdsCsv(source.filterCategoryIds),
30788
30937
  filterStaffMemberId: normalizeEventStaffMemberId(source.filterStaffMemberId),
30789
30938
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
@@ -31033,6 +31182,44 @@ function toWholeSeriesRegistrationEvents(events) {
31033
31182
  return groupPublicEventsByRun(events).map(toWholeSeriesRegistrationEvent).filter((event) => event !== null);
31034
31183
  }
31035
31184
  //#endregion
31185
+ //#region ../blocks/src/system/runtime/nodes/event-registration/eventSourceRecovery.ts
31186
+ const { limit: _rawLimit, eventSurface: _rawEventSurface, scheduleScope: _rawScheduleScope, detailLevel: _rawDetailLevel, ...stringEventQueryShape } = publicEventLoaderQuerySchemaShape;
31187
+ const eventRecoveryRequestSchema = z$1.object({
31188
+ ...stringEventQueryShape,
31189
+ limit: z$1.coerce.number().int().positive().optional(),
31190
+ eventSurface: z$1.enum(eventSurfaceScopeValues).optional(),
31191
+ scheduleScope: z$1.enum(eventScheduleScopeValues).optional(),
31192
+ detailLevel: z$1.enum(["full", "listing"]).optional(),
31193
+ stage: z$1.enum(["preview", "published"]).optional()
31194
+ });
31195
+ function resolveEventRegistrationEventSource(input) {
31196
+ if (input.wholeSeriesRunEvents != null) return {
31197
+ kind: "loaded",
31198
+ events: input.wholeSeriesRunEvents
31199
+ };
31200
+ if (input.events != null) return {
31201
+ kind: "loaded",
31202
+ events: input.events
31203
+ };
31204
+ return {
31205
+ kind: "unresolved",
31206
+ request: parseEventLoaderRecoveryRequest(input.failures?.wholeSeriesRunEvents ?? input.failures?.events)
31207
+ };
31208
+ }
31209
+ const eventLoaderFailureSchema = z$1.object({
31210
+ endpoint: z$1.literal("listPublicEvents"),
31211
+ params: eventRecoveryRequestSchema.extend({ siteId: z$1.string().optional() })
31212
+ });
31213
+ function parseEventLoaderRecoveryRequest(value) {
31214
+ const parsed = eventLoaderFailureSchema.safeParse(value);
31215
+ if (!parsed.success) return null;
31216
+ const { siteId: _siteId, stage, ...params } = parsed.data.params;
31217
+ return {
31218
+ ...params,
31219
+ stage: stage ?? "published"
31220
+ };
31221
+ }
31222
+ //#endregion
31036
31223
  //#region ../blocks/src/system/runtime/nodes/event-registration.interactive.ts
31037
31224
  const EVENT_REGISTRATION_GENERIC_SHELL_STEP_LABELS = [
31038
31225
  "Date",
@@ -31050,8 +31237,6 @@ const eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistra
31050
31237
  const eventRegistrationHydrationSchemaShape = {
31051
31238
  occurrenceContext: occurrenceContextSchema.optional(),
31052
31239
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
31053
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31054
- wholeSeriesRunEvents: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31055
31240
  maxTickets: z$1.string().optional(),
31056
31241
  showVenue: z$1.boolean().optional(),
31057
31242
  showCapacity: z$1.boolean().optional(),
@@ -31063,12 +31248,22 @@ const eventRegistrationHydrationSchemaShape = {
31063
31248
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
31064
31249
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
31065
31250
  };
31251
+ const eventRegistrationEventSourceSchema = z$1.discriminatedUnion("kind", [z$1.object({
31252
+ kind: z$1.literal("loaded"),
31253
+ events: z$1.array(eventRegistrationPublicEventSchema)
31254
+ }), z$1.object({
31255
+ kind: z$1.literal("unresolved"),
31256
+ request: eventRecoveryRequestSchema.nullable()
31257
+ })]);
31066
31258
  const eventRegistrationSourceSchema = z$1.object({
31067
31259
  siteId: z$1.string().optional(),
31068
31260
  apiBaseUrl: z$1.string().optional(),
31069
31261
  portalToken: z$1.string().nullable().optional(),
31070
31262
  previewToken: z$1.string().nullable().optional(),
31071
31263
  ...eventRegistrationHydrationSchemaShape,
31264
+ events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31265
+ wholeSeriesRunEvents: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31266
+ eventLoaderFailures: z$1.record(z$1.string(), z$1.unknown()).nullable().optional(),
31072
31267
  className: z$1.string().nullable().optional(),
31073
31268
  buttonText: z$1.string().nullable().optional(),
31074
31269
  maxTickets: z$1.string().nullable().optional(),
@@ -31089,7 +31284,10 @@ const eventRegistrationDisplaySchema = z$1.discriminatedUnion("state", [z$1.obje
31089
31284
  titleText: z$1.string(),
31090
31285
  bodyText: z$1.string()
31091
31286
  })]);
31092
- const eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
31287
+ const eventRegistrationHydrationSchema = z$1.object({
31288
+ ...eventRegistrationHydrationSchemaShape,
31289
+ eventSource: eventRegistrationEventSourceSchema
31290
+ });
31093
31291
  const eventRegistrationRenderSchema = z$1.object({
31094
31292
  display: eventRegistrationDisplaySchema,
31095
31293
  hydration: eventRegistrationHydrationSchema
@@ -31148,16 +31346,12 @@ function buildEventRegistrationShellStepLabels(source, scopedSourceEvents) {
31148
31346
  function toScopedEventRegistrationEvents(scopedSourceEvents) {
31149
31347
  return [...toRegistrationEvents(scopedSourceEvents), ...toWholeSeriesRegistrationEvents(scopedSourceEvents)];
31150
31348
  }
31151
- function scopeEventRegistrationSourceEvents(source) {
31152
- return resolveEventRegistrationScopedEvents(source.wholeSeriesRunEvents ?? source.events ?? [], {
31349
+ function scopeEventRegistrationSourceEvents(source, eventSource) {
31350
+ return resolveEventRegistrationScopedEvents(eventSource.kind === "loaded" ? eventSource.events : [], {
31153
31351
  occurrenceContext: source.occurrenceContext,
31154
31352
  subject: source.subject
31155
31353
  });
31156
31354
  }
31157
- function resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents) {
31158
- if (source.events == null && source.wholeSeriesRunEvents == null) return null;
31159
- return [...scopedSourceEvents];
31160
- }
31161
31355
  /**
31162
31356
  * The one run this surface is registering for, when the scoped events describe
31163
31357
  * exactly one. More than one run means the visitor still has to choose.
@@ -31197,14 +31391,21 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
31197
31391
  render: createZodCodec(eventRegistrationRenderSchema)
31198
31392
  },
31199
31393
  buildRender: (source) => {
31200
- const scopedSourceEvents = scopeEventRegistrationSourceEvents(source);
31201
- const events = resolveLoadedEventRegistrationSourceEvents(source, scopedSourceEvents);
31394
+ const eventSource = resolveEventRegistrationEventSource({
31395
+ events: source.events,
31396
+ wholeSeriesRunEvents: source.wholeSeriesRunEvents,
31397
+ failures: source.eventLoaderFailures
31398
+ });
31399
+ const scopedSourceEvents = scopeEventRegistrationSourceEvents(source, eventSource);
31202
31400
  return {
31203
31401
  display: buildEventRegistrationDisplayFromScopedEvents(source, scopedSourceEvents),
31204
31402
  hydration: {
31205
31403
  occurrenceContext: source.occurrenceContext ?? null,
31206
31404
  subject: source.subject ?? null,
31207
- events,
31405
+ eventSource: eventSource.kind === "loaded" ? {
31406
+ ...eventSource,
31407
+ events: [...scopedSourceEvents]
31408
+ } : eventSource,
31208
31409
  maxTickets: source.maxTickets ?? void 0,
31209
31410
  showVenue: source.showVenue,
31210
31411
  showCapacity: source.showCapacity,
@@ -31599,6 +31800,15 @@ const newsletterFieldSchema = z$1.object({
31599
31800
  placeholder: z$1.string().optional()
31600
31801
  });
31601
31802
  const mailingListSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignupBlockId);
31803
+ const mailingListContentVersionIdSchema = z$1.string().transform((value, ctx) => {
31804
+ const parsed = parseMailingListContentVersionId(value);
31805
+ if (parsed) return parsed;
31806
+ ctx.addIssue({
31807
+ code: z$1.ZodIssueCode.custom,
31808
+ message: "Invalid mailing-list content version ID"
31809
+ });
31810
+ return z$1.NEVER;
31811
+ });
31602
31812
  const signedMailingListSourceTokenSchema = z$1.string().trim().min(1).transform(parseRequiredMailingListSignedSourceToken);
31603
31813
  const newsletterSourceCommonSchema = z$1.object({
31604
31814
  siteId: z$1.string().optional(),
@@ -31612,7 +31822,8 @@ const newsletterSourceCommonSchema = z$1.object({
31612
31822
  const newsletterSourceSchema = z$1.discriminatedUnion("source", [
31613
31823
  newsletterSourceCommonSchema.extend({
31614
31824
  source: z$1.literal("block"),
31615
- blockId: z$1.string().nullable().optional()
31825
+ blockId: z$1.string().nullable().optional(),
31826
+ contentVersionId: z$1.string().nullable().optional()
31616
31827
  }),
31617
31828
  newsletterSourceCommonSchema.extend({
31618
31829
  source: z$1.literal("signed-footer"),
@@ -31628,6 +31839,7 @@ const newsletterDisplaySchema = z$1.object({
31628
31839
  availability: z$1.enum(["ready", "unavailable"]),
31629
31840
  className: z$1.string().nullable(),
31630
31841
  buttonLabel: z$1.string(),
31842
+ successMessage: z$1.string(),
31631
31843
  buttonVariant: newsletterButtonVariantSchema,
31632
31844
  privacyNote: z$1.string().nullable(),
31633
31845
  fields: z$1.array(newsletterFieldSchema),
@@ -31642,7 +31854,8 @@ const newsletterHydrationSchema = z$1.object({
31642
31854
  tag: z$1.literal("block-source"),
31643
31855
  sourceRef: z$1.object({
31644
31856
  tag: z$1.literal("block_ref"),
31645
- blockId: mailingListSignupBlockIdSchema
31857
+ blockId: mailingListSignupBlockIdSchema,
31858
+ contentVersionId: mailingListContentVersionIdSchema
31646
31859
  }).nullable()
31647
31860
  }),
31648
31861
  z$1.object({
@@ -31681,6 +31894,7 @@ function buildNewsletterDisplay(source) {
31681
31894
  fields: { preset: "emailOnly" },
31682
31895
  includeOptionalPhone: false,
31683
31896
  buttonLabel: "Subscribe",
31897
+ successMessage: DEFAULT_MAILING_LIST_SUCCESS_MESSAGE,
31684
31898
  privacyNote: null
31685
31899
  };
31686
31900
  const targeting = source.targeting ?? { mode: "default" };
@@ -31690,6 +31904,7 @@ function buildNewsletterDisplay(source) {
31690
31904
  availability: runtimeTargetingIsAvailable(context, targeting, choices) ? "ready" : "unavailable",
31691
31905
  className: source.className ?? null,
31692
31906
  buttonLabel: form.buttonLabel,
31907
+ successMessage: form.successMessage,
31693
31908
  buttonVariant: source.buttonVariant ?? "primary",
31694
31909
  privacyNote: form.privacyNote,
31695
31910
  fields: getGlobalFormFields(form),
@@ -31720,7 +31935,7 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
31720
31935
  function projectNewsletterFormHydrationTarget(source) {
31721
31936
  switch (source.source) {
31722
31937
  case "block": {
31723
- const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId);
31938
+ const sourceRef = buildMailingListSignupBlockSourceRef(source.blockId, source.contentVersionId);
31724
31939
  if (sourceRef?.tag === "block_ref") return {
31725
31940
  tag: "block-source",
31726
31941
  sourceRef
@@ -33977,6 +34192,14 @@ const PUBLIC_BOOKING_AVAILABILITY_ENDPOINT_DEFINITIONS = defineEndpointDefinitio
33977
34192
  auth: "public",
33978
34193
  responseKind: "json"
33979
34194
  },
34195
+ getPublicBookingServiceBySlug: {
34196
+ path: "/public/bookings/services/by-slug/{slug}",
34197
+ method: "GET",
34198
+ revalidate: publicReadFreshnessSeconds("getPublicBookingService"),
34199
+ tags: [TAG_TEMPLATES.publicBookingServices],
34200
+ auth: "public",
34201
+ responseKind: "json"
34202
+ },
33980
34203
  getPublicBookingResourcesReference: {
33981
34204
  path: "/public/bookings/resources/reference",
33982
34205
  method: "GET",
@@ -34529,11 +34752,105 @@ const PUBLIC_READ_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
34529
34752
  responseKind: "json"
34530
34753
  }
34531
34754
  });
34755
+ //#endregion
34756
+ //#region ../api/src/publicOnboardingAttemptEndpointDefinitions.ts
34757
+ /**
34758
+ * The anonymous onboarding attempt, addressed by its opaque resume token.
34759
+ *
34760
+ * Every route here is reached before there is an account, so none of them can
34761
+ * be scoped to a site or a user: the token is the whole credential. They are
34762
+ * kept together so that stays obvious.
34763
+ */
34764
+ const PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
34765
+ createPublicOnboardingAttempt: {
34766
+ path: "/public/onboarding/attempts",
34767
+ method: "POST",
34768
+ auth: "public",
34769
+ errors: [],
34770
+ responseKind: "json"
34771
+ },
34772
+ createPublicOnboardingLogoUploadUrl: {
34773
+ path: "/public/onboarding/attempts/{attemptToken}/logo-upload-url",
34774
+ method: "POST",
34775
+ auth: "public",
34776
+ errors: [],
34777
+ responseKind: "json"
34778
+ },
34779
+ uploadPublicOnboardingLogo: {
34780
+ path: "/public/onboarding/attempts/{attemptToken}/logo",
34781
+ method: "POST",
34782
+ auth: "public",
34783
+ errors: [],
34784
+ responseKind: "json"
34785
+ },
34786
+ getPublicOnboardingAttempt: {
34787
+ path: "/public/onboarding/attempts/{attemptToken}",
34788
+ method: "GET",
34789
+ auth: "public",
34790
+ errors: [],
34791
+ responseKind: "json"
34792
+ },
34793
+ getPublicOnboardingAttemptProgress: {
34794
+ path: "/public/onboarding/attempts/{attemptToken}/status",
34795
+ method: "GET",
34796
+ auth: "public",
34797
+ errors: [],
34798
+ responseKind: "json"
34799
+ },
34800
+ updatePublicOnboardingAttempt: {
34801
+ path: "/public/onboarding/attempts/{attemptToken}",
34802
+ method: "PATCH",
34803
+ auth: "public",
34804
+ errors: [],
34805
+ responseKind: "json"
34806
+ },
34807
+ runPublicOnboardingAttempt: {
34808
+ path: "/public/onboarding/attempts/{attemptToken}/run",
34809
+ method: "POST",
34810
+ auth: "public",
34811
+ errors: [],
34812
+ responseKind: "json"
34813
+ },
34814
+ resendPublicOnboardingAttemptConfirmation: {
34815
+ path: "/public/onboarding/attempts/{attemptToken}/resend-confirmation",
34816
+ method: "POST",
34817
+ auth: "public",
34818
+ errors: [],
34819
+ responseKind: "json"
34820
+ }
34821
+ });
34822
+ //#endregion
34823
+ //#region ../api/src/billingEndpointDefinitions.ts
34824
+ const BILLING_ENDPOINT_DEFINITIONS = defineEndpointDefinitions({
34825
+ adminChangePlan: {
34826
+ path: "/admin/billing/plan",
34827
+ method: "POST",
34828
+ tags: ["admin", "billing"],
34829
+ auth: "admin",
34830
+ responseKind: "json"
34831
+ },
34832
+ changePlan: {
34833
+ path: "/billing/plan/change",
34834
+ method: "POST",
34835
+ tags: ["billing"],
34836
+ auth: "user",
34837
+ responseKind: "json"
34838
+ },
34839
+ createBillingPortalSession: {
34840
+ path: "/billing/portal/session",
34841
+ method: "POST",
34842
+ tags: ["billing"],
34843
+ auth: "user",
34844
+ responseKind: "json"
34845
+ }
34846
+ });
34532
34847
  const API_ENDPOINTS$1 = {
34533
34848
  ...ACCOUNT_ENDPOINT_DEFINITIONS,
34849
+ ...PUBLIC_ONBOARDING_ATTEMPT_ENDPOINT_DEFINITIONS,
34534
34850
  ...PUBLIC_EVENT_ENDPOINT_DEFINITIONS,
34535
34851
  ...GIFTING_ENDPOINT_DEFINITIONS,
34536
34852
  ...PUBLIC_READ_ENDPOINT_DEFINITIONS,
34853
+ ...BILLING_ENDPOINT_DEFINITIONS,
34537
34854
  aiContentUpdateChat: {
34538
34855
  path: "/ai/content-update-chat",
34539
34856
  method: "POST",
@@ -34687,55 +35004,6 @@ const API_ENDPOINTS$1 = {
34687
35004
  errors: [],
34688
35005
  responseKind: "json"
34689
35006
  },
34690
- createPublicOnboardingAttempt: {
34691
- path: "/public/onboarding/attempts",
34692
- method: "POST",
34693
- auth: "public",
34694
- errors: [],
34695
- responseKind: "json"
34696
- },
34697
- createPublicOnboardingLogoUploadUrl: {
34698
- path: "/public/onboarding/attempts/{attemptToken}/logo-upload-url",
34699
- method: "POST",
34700
- auth: "public",
34701
- errors: [],
34702
- responseKind: "json"
34703
- },
34704
- uploadPublicOnboardingLogo: {
34705
- path: "/public/onboarding/attempts/{attemptToken}/logo",
34706
- method: "POST",
34707
- auth: "public",
34708
- errors: [],
34709
- responseKind: "json"
34710
- },
34711
- getPublicOnboardingAttempt: {
34712
- path: "/public/onboarding/attempts/{attemptToken}",
34713
- method: "GET",
34714
- auth: "public",
34715
- errors: [],
34716
- responseKind: "json"
34717
- },
34718
- getPublicOnboardingAttemptProgress: {
34719
- path: "/public/onboarding/attempts/{attemptToken}/status",
34720
- method: "GET",
34721
- auth: "public",
34722
- errors: [],
34723
- responseKind: "json"
34724
- },
34725
- updatePublicOnboardingAttempt: {
34726
- path: "/public/onboarding/attempts/{attemptToken}",
34727
- method: "PATCH",
34728
- auth: "public",
34729
- errors: [],
34730
- responseKind: "json"
34731
- },
34732
- runPublicOnboardingAttempt: {
34733
- path: "/public/onboarding/attempts/{attemptToken}/run",
34734
- method: "POST",
34735
- auth: "public",
34736
- errors: [],
34737
- responseKind: "json"
34738
- },
34739
35007
  aiSiteWizardSuggestGoals: {
34740
35008
  path: "/sites/{siteId}/ai/site-wizard/goals",
34741
35009
  method: "POST",
@@ -36251,20 +36519,6 @@ const API_ENDPOINTS$1 = {
36251
36519
  auth: "admin",
36252
36520
  responseKind: "json"
36253
36521
  },
36254
- adminChangePlan: {
36255
- path: "/admin/billing/plan",
36256
- method: "POST",
36257
- tags: ["admin", "billing"],
36258
- auth: "admin",
36259
- responseKind: "json"
36260
- },
36261
- changePlan: {
36262
- path: "/billing/plan/change",
36263
- method: "POST",
36264
- tags: ["billing"],
36265
- auth: "user",
36266
- responseKind: "json"
36267
- },
36268
36522
  mfaTotpEnroll: {
36269
36523
  path: "/auth/mfa/totp/enroll",
36270
36524
  method: "POST",
@@ -36613,7 +36867,12 @@ const API_ENDPOINTS$1 = {
36613
36867
  path: "/public/sites/{siteId}/sitemap",
36614
36868
  method: "GET",
36615
36869
  revalidate: 60,
36616
- tags: [TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings],
36870
+ tags: [
36871
+ TAG_TEMPLATES.siteRoutableContent,
36872
+ TAG_TEMPLATES.siteSettings,
36873
+ TAG_TEMPLATES.publicEvents,
36874
+ TAG_TEMPLATES.publicBookingServices
36875
+ ],
36617
36876
  auth: "public",
36618
36877
  responseKind: "json"
36619
36878
  },
@@ -39932,6 +40191,17 @@ const API_ENDPOINTS$1 = {
39932
40191
  auth: "public",
39933
40192
  responseKind: "json"
39934
40193
  },
40194
+ portalCancelWaitlistEntry: {
40195
+ path: "/portal/waitlists/{entryId}/cancel",
40196
+ method: "POST",
40197
+ auth: "public",
40198
+ responseKind: "json",
40199
+ errors: [
40200
+ "resource:not_found",
40201
+ "resource:conflict",
40202
+ "server:internal_error"
40203
+ ]
40204
+ },
39935
40205
  portalGetEventGuests: {
39936
40206
  path: "/portal/events/{registrationId}/guests",
39937
40207
  method: "GET",
@@ -42524,6 +42794,26 @@ const headerRuntimeTransforms = [{
42524
42794
  run: resolveHeaderChromeRuntimeContract
42525
42795
  }];
42526
42796
  const defaultTransforms = createTransformRegistry([
42797
+ {
42798
+ id: "events.calendarSelectionParam",
42799
+ kind: "formatter",
42800
+ summary: "Resolve selected events instead of discovery filters",
42801
+ schema: z$1.object({ key: z$1.enum([
42802
+ "seriesIds",
42803
+ "eventSurface",
42804
+ "filterEventPresets",
42805
+ "scheduleScope",
42806
+ "filterCategoryIds",
42807
+ "filterStaffMemberId",
42808
+ "filterVenueId"
42809
+ ]) }),
42810
+ run(value, { key }) {
42811
+ const content = asPartialObject(value) ?? {};
42812
+ const selection = resolveEventSelection(content.eventSelection, content.selectedEventSeriesIds);
42813
+ if (selection.kind === "selected") return key === "seriesIds" ? selection.seriesIds : void 0;
42814
+ return key === "seriesIds" ? void 0 : content[key];
42815
+ }
42816
+ },
42527
42817
  {
42528
42818
  id: "events.calendarReadEnabled",
42529
42819
  kind: "formatter",
@@ -43701,17 +43991,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
43701
43991
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
43702
43992
  return null;
43703
43993
  }
43704
- const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
43705
43994
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
43706
43995
  if (variantId && !resolvedVariantId) {
43707
43996
  console.error("[ButtonNode] Invalid button variant", { variantId });
43708
43997
  return null;
43709
43998
  }
43710
- const combinedClassName = resolvedVariantId ? themeButtonClassName({
43999
+ const combinedClassName = resolvedVariantId ? (affordanceIcon ? themeButtonClassNameWithTrailingIcon : themeButtonClassName)({
43711
44000
  variant: resolvedVariantId,
43712
44001
  size,
43713
- extraClassName
43714
- }) : extraClassName;
44002
+ extraClassName: className
44003
+ }) : className;
43715
44004
  if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
43716
44005
  href: resolvedHref,
43717
44006
  target,
@@ -44894,10 +45183,11 @@ const publicPricingSchema = z$1.object({
44894
45183
  singlePriceAmount: z$1.number().nullable(),
44895
45184
  slidingMinAmount: z$1.number().nullable(),
44896
45185
  slidingMaxAmount: z$1.number().nullable(),
44897
- options: z$1.array(publicPricingOptionSchema)
45186
+ options: z$1.array(publicPricingOptionSchema).readonly()
44898
45187
  });
44899
45188
  const publicAppointmentServiceSchema = z$1.object({
44900
45189
  id: z$1.string().min(1),
45190
+ slug: z$1.string().min(1).optional(),
44901
45191
  title: z$1.string(),
44902
45192
  description: z$1.string().nullable().optional(),
44903
45193
  durationMinutes: z$1.number().int().positive(),
@@ -44974,7 +45264,7 @@ function formatAmountOrFree(amount, currency) {
44974
45264
  currency
44975
45265
  }, { decimals: "auto" });
44976
45266
  }
44977
- function buildRows(services, pathname) {
45267
+ function buildRows(services, pathname, servicePathPrefix) {
44978
45268
  return services.map((service) => ({
44979
45269
  id: service.id,
44980
45270
  title: service.title,
@@ -44985,7 +45275,8 @@ function buildRows(services, pathname) {
44985
45275
  href: resolveDedicatedBookingHref(pathname, {
44986
45276
  kind: "appointment_service",
44987
45277
  serviceId: service.id
44988
- })
45278
+ }),
45279
+ detailsHref: servicePathPrefix && service.slug ? `${servicePathPrefix.replace(/\/$/, "")}/${encodeURIComponent(service.slug)}` : null
44989
45280
  }));
44990
45281
  }
44991
45282
  function buildAppointmentServicesView(input) {
@@ -45004,13 +45295,14 @@ function buildAppointmentServicesView(input) {
45004
45295
  };
45005
45296
  return {
45006
45297
  kind: "items",
45007
- rows: buildRows(parsed.services, input.pathname)
45298
+ rows: buildRows(parsed.services, input.pathname, input.servicePathPrefix ?? null)
45008
45299
  };
45009
45300
  }
45010
- function AppointmentServicesNode({ sectionHeading, services, pathname, className }) {
45301
+ function AppointmentServicesNode({ sectionHeading, services, pathname, servicePathPrefix, className }) {
45011
45302
  const view = buildAppointmentServicesView({
45012
45303
  services,
45013
- pathname: typeof pathname === "string" ? pathname : void 0
45304
+ pathname: typeof pathname === "string" ? pathname : void 0,
45305
+ servicePathPrefix: typeof servicePathPrefix === "string" ? servicePathPrefix : null
45014
45306
  });
45015
45307
  const rootClassName = `appointment-services ${className ?? ""}`.trim();
45016
45308
  const RowTitle = sectionHeading ? "h3" : "h2";
@@ -45041,7 +45333,10 @@ function AppointmentServicesNode({ sectionHeading, services, pathname, className
45041
45333
  children: [
45042
45334
  /* @__PURE__ */ jsx(RowTitle, {
45043
45335
  className: "appointment-services-row-title rb-text-lg rb-font-medium rb-leading-tight",
45044
- children: row.title
45336
+ children: row.detailsHref ? /* @__PURE__ */ jsx("a", {
45337
+ href: row.detailsHref,
45338
+ children: row.title
45339
+ }) : row.title
45045
45340
  }),
45046
45341
  row.description ? /* @__PURE__ */ jsx("p", {
45047
45342
  className: "appointment-services-row-description rb-text-sm rb-leading-6 status-muted",
@@ -46571,13 +46866,10 @@ function OfferingsPreviewContent(props) {
46571
46866
  }),
46572
46867
  groupCta ? /* @__PURE__ */ jsx("footer", {
46573
46868
  className: "offerings-preview-card-footer rb-mt-auto rb-flex",
46574
- children: /* @__PURE__ */ jsxs("a", {
46869
+ children: /* @__PURE__ */ jsx("a", {
46575
46870
  className: groupLinkClass,
46576
46871
  href: groupCta.href,
46577
- children: [/* @__PURE__ */ jsx("span", { children: groupCta.label }), /* @__PURE__ */ jsx(ArrowRightIcon, {
46578
- "aria-hidden": "true",
46579
- className: "offerings-preview-link-icon rb-h-4 rb-w-4"
46580
- })]
46872
+ children: /* @__PURE__ */ jsx("span", { children: groupCta.label })
46581
46873
  })
46582
46874
  }) : null
46583
46875
  ]
@@ -47744,6 +48036,7 @@ const eventRegistrationBlockDefinition = {
47744
48036
  } },
47745
48037
  events: { $bind: { from: "data.events" } },
47746
48038
  wholeSeriesRunEvents: { $bind: { from: "data.wholeSeriesRunEvents" } },
48039
+ loaderFailures: { $bind: { from: "$root.loaderFailures" } },
47747
48040
  sitePasses: { $bind: { from: "data.sitePasses" } },
47748
48041
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
47749
48042
  stage: { $bind: {
@@ -47938,22 +48231,121 @@ const formBlockDefinition = {
47938
48231
  runtime: formBlockRuntime
47939
48232
  };
47940
48233
  //#endregion
48234
+ //#region ../blocks/src/system/blocks/events/eventSelectionFields.ts
48235
+ const eventSelectionFields = [{
48236
+ id: "eventSelection",
48237
+ type: "select",
48238
+ label: "Events to show",
48239
+ required: false,
48240
+ multiple: false,
48241
+ defaultValue: "matching",
48242
+ options: [{
48243
+ value: "matching",
48244
+ label: "All matching events"
48245
+ }, {
48246
+ value: "selected",
48247
+ label: "Selected events"
48248
+ }],
48249
+ ui: { intent: "behavior" }
48250
+ }, createSiteOptionSelectField({
48251
+ id: "selectedEventSeriesIds",
48252
+ label: "Selected events",
48253
+ description: "Show upcoming dates for these events. Other event filters do not apply.",
48254
+ required: false,
48255
+ multiple: true,
48256
+ defaultValue: [],
48257
+ optionSource: "eventSeries",
48258
+ ui: {
48259
+ intent: "behavior",
48260
+ searchThreshold: 1,
48261
+ visibleWhen: {
48262
+ field: "eventSelection",
48263
+ equals: "selected"
48264
+ }
48265
+ }
48266
+ })];
48267
+ function withEventSelectionVisibility(field) {
48268
+ if (![
48269
+ "eventSurface",
48270
+ "filterEventPresets",
48271
+ "scheduleScope",
48272
+ "filterCategoryIds",
48273
+ "filterStaffMemberId",
48274
+ "filterVenueId",
48275
+ "showFilters",
48276
+ "showCategoryFilter",
48277
+ "showVenueFilter",
48278
+ "showStaffFilter"
48279
+ ].includes(field.id)) return field;
48280
+ const visibleWhen = field.ui?.visibleWhen;
48281
+ return {
48282
+ ...field,
48283
+ ui: {
48284
+ ...field.ui,
48285
+ visibleWhen: { allOf: [{
48286
+ field: "eventSelection",
48287
+ notEquals: "selected"
48288
+ }, ...visibleWhen ? [visibleWhen] : []] }
48289
+ }
48290
+ };
48291
+ }
48292
+ //#endregion
47941
48293
  //#region ../blocks/src/system/blocks/events/eventCalendarDataLoaders.ts
47942
48294
  const scopeParams = {
47943
48295
  siteId: { $bind: { from: "$root.siteId" } },
48296
+ seriesIds: { $bind: {
48297
+ from: "content",
48298
+ transforms: [{
48299
+ id: "events.calendarSelectionParam",
48300
+ options: { key: "seriesIds" }
48301
+ }]
48302
+ } },
47944
48303
  stage: { $bind: {
47945
48304
  from: "$root.previewStage",
47946
48305
  fallback: "published"
47947
48306
  } },
47948
- eventSurface: { $bind: { from: "content.eventSurface" } },
48307
+ eventSurface: { $bind: {
48308
+ from: "content",
48309
+ transforms: [{
48310
+ id: "events.calendarSelectionParam",
48311
+ options: { key: "eventSurface" }
48312
+ }, { id: "value.csv" }]
48313
+ } },
47949
48314
  eventPresets: { $bind: {
47950
- from: "content.filterEventPresets",
47951
- transforms: [{ id: "value.csv" }]
48315
+ from: "content",
48316
+ transforms: [{
48317
+ id: "events.calendarSelectionParam",
48318
+ options: { key: "filterEventPresets" }
48319
+ }, { id: "value.csv" }]
47952
48320
  } },
47953
- scheduleScope: { $bind: { from: "content.scheduleScope" } },
47954
- categoryIds: { $bind: { from: "content.filterCategoryIds" } },
47955
- staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
47956
- venueId: { $bind: { from: "content.filterVenueId" } }
48321
+ scheduleScope: { $bind: {
48322
+ from: "content",
48323
+ transforms: [{
48324
+ id: "events.calendarSelectionParam",
48325
+ options: { key: "scheduleScope" }
48326
+ }, { id: "value.csv" }]
48327
+ } },
48328
+ categoryIds: { $bind: {
48329
+ from: "content",
48330
+ transforms: [{
48331
+ id: "events.calendarSelectionParam",
48332
+ options: { key: "filterCategoryIds" }
48333
+ }, { id: "value.csv" }]
48334
+ } },
48335
+ staffMemberId: { $bind: {
48336
+ from: "content",
48337
+ transforms: [{
48338
+ id: "events.calendarSelectionParam",
48339
+ options: { key: "filterStaffMemberId" }
48340
+ }, { id: "value.csv" }]
48341
+ } },
48342
+ venueId: { $bind: {
48343
+ from: "content",
48344
+ transforms: [{
48345
+ id: "events.calendarSelectionParam",
48346
+ options: { key: "filterVenueId" }
48347
+ }, { id: "value.csv" }]
48348
+ } }
47957
48349
  };
47958
48350
  /** Combined renders two jobs; calendar-only variants never pay for the list seed. */
47959
48351
  const eventCalendarDataLoaders = {
@@ -48083,6 +48475,13 @@ const eventCalendarLayout = [styledSection({
48083
48475
  from: "content.defaultCalendarView",
48084
48476
  fallback: "month"
48085
48477
  } },
48478
+ seriesIds: { $bind: {
48479
+ from: "content",
48480
+ transforms: [{
48481
+ id: "events.calendarSelectionParam",
48482
+ options: { key: "seriesIds" }
48483
+ }]
48484
+ } },
48086
48485
  showFilters: { $bind: {
48087
48486
  from: "content.showFilters",
48088
48487
  fallback: true
@@ -48104,17 +48503,47 @@ const eventCalendarLayout = [styledSection({
48104
48503
  fallback: true
48105
48504
  } },
48106
48505
  eventSurface: { $bind: {
48107
- from: "content.eventSurface",
48108
- fallback: "all"
48506
+ from: "content",
48507
+ transforms: [{
48508
+ id: "events.calendarSelectionParam",
48509
+ options: { key: "eventSurface" }
48510
+ }]
48511
+ } },
48512
+ filterEventPresets: { $bind: {
48513
+ from: "content",
48514
+ transforms: [{
48515
+ id: "events.calendarSelectionParam",
48516
+ options: { key: "filterEventPresets" }
48517
+ }]
48109
48518
  } },
48110
- filterEventPresets: { $bind: { from: "content.filterEventPresets" } },
48111
48519
  scheduleScope: { $bind: {
48112
- from: "content.scheduleScope",
48113
- fallback: "any"
48520
+ from: "content",
48521
+ transforms: [{
48522
+ id: "events.calendarSelectionParam",
48523
+ options: { key: "scheduleScope" }
48524
+ }]
48525
+ } },
48526
+ filterCategoryIds: { $bind: {
48527
+ from: "content",
48528
+ transforms: [{
48529
+ id: "events.calendarSelectionParam",
48530
+ options: { key: "filterCategoryIds" }
48531
+ }]
48532
+ } },
48533
+ filterStaffMemberId: { $bind: {
48534
+ from: "content",
48535
+ transforms: [{
48536
+ id: "events.calendarSelectionParam",
48537
+ options: { key: "filterStaffMemberId" }
48538
+ }]
48539
+ } },
48540
+ filterVenueId: { $bind: {
48541
+ from: "content",
48542
+ transforms: [{
48543
+ id: "events.calendarSelectionParam",
48544
+ options: { key: "filterVenueId" }
48545
+ }]
48114
48546
  } },
48115
- filterCategoryIds: { $bind: { from: "content.filterCategoryIds" } },
48116
- filterStaffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
48117
- filterVenueId: { $bind: { from: "content.filterVenueId" } },
48118
48547
  cardRole: { $bind: {
48119
48548
  from: "content._cardStyles.role",
48120
48549
  fallback: "default"
@@ -48618,6 +49047,7 @@ const eventCalendarAdditionalFields = [
48618
49047
  }
48619
49048
  }
48620
49049
  },
49050
+ ...eventSelectionFields,
48621
49051
  {
48622
49052
  id: "eventSurface",
48623
49053
  type: "select",
@@ -48827,7 +49257,7 @@ const eventCalendarBlockDefinition = {
48827
49257
  titleSource: "heading",
48828
49258
  description: "Display events with calendar, list, or combined views with filtering",
48829
49259
  skipSectionStyles: true,
48830
- additionalFields: eventCalendarAdditionalFields,
49260
+ additionalFields: eventCalendarAdditionalFields.map(withEventSelectionVisibility),
48831
49261
  styleTokens: {
48832
49262
  background: "surface",
48833
49263
  typography: "body",
@@ -51555,9 +51985,10 @@ function cx(...classes) {
51555
51985
  * Server-safe placeholder for event registration.
51556
51986
  * Provides a static container for island hydration without importing client hooks.
51557
51987
  */
51558
- function EventRegistrationSSR({ blockId, subject, children, ...sourceProps }) {
51988
+ function EventRegistrationSSR({ blockId, subject, loaderFailures, children, ...sourceProps }) {
51559
51989
  const islandProps = buildEventRegistrationInteractiveIslandProps({
51560
51990
  ...sourceProps,
51991
+ eventLoaderFailures: blockId ? loaderFailures?.[blockId] : void 0,
51561
51992
  subject: normalizeEventRegistrationPageSurfaceSubject(subject)
51562
51993
  });
51563
51994
  const display = islandProps.render.display;
@@ -51890,7 +52321,7 @@ function NewsletterFormSSR(props) {
51890
52321
  className: clsx("newsletter-form-ssr", className),
51891
52322
  children: /* @__PURE__ */ jsx("p", {
51892
52323
  role: "status",
51893
- children: "Mailing-list signup is not available right now."
52324
+ children: "We can’t accept signups right now. Please try again later."
51894
52325
  })
51895
52326
  });
51896
52327
  const renderField = (field) => {
@@ -51936,14 +52367,18 @@ function NewsletterFormSSR(props) {
51936
52367
  children: [
51937
52368
  fields.map(renderField),
51938
52369
  islandProps.render.hydration.choicePresentation === "visitor_choice" ? /* @__PURE__ */ jsxs("fieldset", {
51939
- className: "newsletter-topics",
51940
- children: [/* @__PURE__ */ jsx("legend", { children: "What would you like to hear about?" }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
51941
- className: "newsletter-topic-choice",
52370
+ className: "fb-fieldset newsletter-topics",
52371
+ children: [/* @__PURE__ */ jsx("legend", {
52372
+ className: "form-label",
52373
+ children: "What would you like to hear about?"
52374
+ }), display.choices.map((choice) => /* @__PURE__ */ jsxs("label", {
52375
+ className: "fb-inline form-label newsletter-topic-choice",
51942
52376
  children: [/* @__PURE__ */ jsx("input", {
51943
52377
  type: "checkbox",
51944
52378
  name: "mailingListChoice",
51945
- value: choice.id
51946
- }), choice.label]
52379
+ value: choice.id,
52380
+ className: "form-checkbox"
52381
+ }), /* @__PURE__ */ jsx("span", { children: choice.label })]
51947
52382
  }, choice.id))]
51948
52383
  }) : null,
51949
52384
  /* @__PURE__ */ jsx("div", {
@@ -52932,6 +53367,18 @@ function resolveChildren(nodes, context) {
52932
53367
  function isReactNode(value) {
52933
53368
  return value !== null && value !== void 0;
52934
53369
  }
53370
+ function resolveNodeMetadata(nodeType, context) {
53371
+ return {
53372
+ pathBase: context.pathBase,
53373
+ blockId: context.blockId,
53374
+ blockKind: context.blockKind,
53375
+ blockContent: context.blockContent,
53376
+ fragmentRegistry: context.fragmentRegistry,
53377
+ previewAuthoring: context.previewAuthoring,
53378
+ ...nodeType.toLowerCase() === "newsletter-form" ? { contentVersionId: context.contentVersionId } : {},
53379
+ ...nodeType === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {}
53380
+ };
53381
+ }
52935
53382
  /**
52936
53383
  * Resolves a node definition into a React element.
52937
53384
  * Handles conditionals ($when), scopes ($scopes), repeaters ($repeat), bindings ($bind), and children.
@@ -52967,13 +53414,7 @@ function resolveNode(node, context, indexFallback) {
52967
53414
  const elementProps = {
52968
53415
  ...props,
52969
53416
  key: node.key ?? indexFallback,
52970
- pathBase: context.pathBase,
52971
- blockId: context.blockId,
52972
- blockKind: context.blockKind,
52973
- blockContent: context.blockContent,
52974
- ...node.type === "media" && context.imageResolveContext ? { imageResolveContext: context.imageResolveContext } : {},
52975
- fragmentRegistry: context.fragmentRegistry,
52976
- previewAuthoring: context.previewAuthoring
53417
+ ...resolveNodeMetadata(node.type, context)
52977
53418
  };
52978
53419
  const element = React.createElement(component, elementProps, ...children);
52979
53420
  if (headingDecorationPlan.kind === "skip") return element;
@@ -53848,9 +54289,56 @@ function generateNavLinkCSS(options) {
53848
54289
  if (baseRules.length > 0) cssChunks.unshift(`\n${selector} {\n ${baseRules.join("\n ")}\n}\n`);
53849
54290
  if (hoverRules.length > 0) cssChunks.push(`\n${hoverSelector} {\n ${hoverRules.join("\n ")}\n}\n`);
53850
54291
  if (activeRules.length > 0) cssChunks.push(`\n${activeSelector} {\n ${activeRules.join("\n ")}\n}\n`);
54292
+ cssChunks.push(navLinkFocusVisibleCss(selector, style, theme, tokens));
53851
54293
  cssChunks.push(generateInteractiveChildInheritanceCSS(selector));
53852
54294
  return cssChunks.join("");
53853
54295
  }
54296
+ /**
54297
+ * Keyboard focus indicator for nav links, in the header, the footer and header
54298
+ * dropdown menus — the three surfaces `generateNavLinkCSS` serves.
54299
+ *
54300
+ * Emitted unconditionally rather than as an effect, because focus visibility is
54301
+ * a floor rather than a style choice. Only the interaction-palette pill ever
54302
+ * wrote an `effects.focus` group, so every other nav — every `quiet` palette,
54303
+ * every footer, every dropdown — previously fell back to whatever outline the
54304
+ * browser drew.
54305
+ *
54306
+ * The outline takes the link's own resolved colour, so on a header that adapts
54307
+ * to the section it floats over it moves with the adaptation instead of
54308
+ * asserting a brand colour against an unknown backdrop.
54309
+ *
54310
+ * Where the style asks for `soft-glow`, the same halo goes on the outline. That
54311
+ * treatment exists because the theme has already conceded the resolved colour
54312
+ * alone is not reliable over an unpredictable backdrop — a hero photograph with
54313
+ * mixed luminance. Without it the text would stay legible by its halo while the
54314
+ * focus ring, which is the part with a contrast requirement of its own, would
54315
+ * not.
54316
+ *
54317
+ * A style that also paints a focus pill keeps it: this adds an outline around
54318
+ * that pill rather than replacing it.
54319
+ */
54320
+ function navLinkFocusVisibleCss(selector, style, theme, tokens) {
54321
+ const color = tokens.getColor(style.colorToken);
54322
+ const halo = buildTextContrastShadow({
54323
+ theme,
54324
+ colorToken: style.colorToken,
54325
+ treatment: style.contrastTreatment
54326
+ });
54327
+ return `
54328
+ ${selector}:focus-visible {
54329
+ outline: 2px solid ${color};
54330
+ outline-offset: ${focusOutlineOffset(selector)};${halo ? `\n box-shadow: ${halo};` : ""}
54331
+ }
54332
+ `;
54333
+ }
54334
+ /**
54335
+ * Dropdown items are full-width inside a panel with no horizontal padding, so
54336
+ * an outset outline would paint over and past the panel's own border. Keeping
54337
+ * it flush is the only way it reads as belonging to the item.
54338
+ */
54339
+ function focusOutlineOffset(selector) {
54340
+ return selector.includes("nav-dropdown-link") ? "-2px" : "3px";
54341
+ }
53854
54342
  function buildTextContrastShadow(input) {
53855
54343
  if (input.treatment !== "soft-glow") return null;
53856
54344
  return isLikelyLightColorToken(input.theme, input.colorToken) ? "0 1px 3px rgb(0 0 0 / 0.55), 0 0 18px rgb(0 0 0 / 0.38)" : "0 1px 3px rgb(255 255 255 / 0.72), 0 0 18px rgb(255 255 255 / 0.5)";
@@ -56983,7 +57471,7 @@ function pageBlockPosition(index, blockCount) {
56983
57471
  //#endregion
56984
57472
  //#region ../blocks/src/pageRendererContracts.ts
56985
57473
  function buildPageRendererRootRuntime(dataContext) {
56986
- const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false } = dataContext ?? {};
57474
+ const { siteId = null, pageId = null, pathname = null, bookingTimeZone, previewStage = "published", apiBaseUrl = null, portalToken = null, bookingOfferingPresets = [], appointmentServicePathPrefix = null, mailingList = { tag: "not_configured" }, eventRegistrationOverlayEnabled = false, loaderFailures = {} } = dataContext ?? {};
56987
57475
  return {
56988
57476
  siteId,
56989
57477
  pageId,
@@ -56993,8 +57481,10 @@ function buildPageRendererRootRuntime(dataContext) {
56993
57481
  apiBaseUrl,
56994
57482
  portalToken,
56995
57483
  bookingOfferingPresets,
57484
+ appointmentServicePathPrefix,
56996
57485
  mailingList,
56997
- eventRegistrationOverlayEnabled
57486
+ eventRegistrationOverlayEnabled,
57487
+ loaderFailures
56998
57488
  };
56999
57489
  }
57000
57490
  //#endregion
@@ -61670,7 +62160,8 @@ const appointmentServicesBlockDefinition = {
61670
62160
  el("appointment-services", {
61671
62161
  sectionHeading: { $bind: { from: "content.heading" } },
61672
62162
  services: { $bind: { from: "data.services" } },
61673
- pathname: { $bind: { from: "$root.pathname" } }
62163
+ pathname: { $bind: { from: "$root.pathname" } },
62164
+ servicePathPrefix: { $bind: { from: "$root.appointmentServicePathPrefix" } }
61674
62165
  })
61675
62166
  ], { gap: "lg" })
61676
62167
  })]
@@ -65953,7 +66444,7 @@ function collectNestedPreviewFieldConstraintEntries(field, path) {
65953
66444
  }
65954
66445
  function makeDefaultBlockComponent(args) {
65955
66446
  const { manifest } = args;
65956
- return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
66447
+ return function DefaultBlockComponent({ content, data, registry, theme, themeConfig, transforms, viewModelOverrides, pathBase, blockId, contentVersionId, blockKind, blockBindings, editableRouteMetadataFieldIds, fragmentRegistry, imageResolveContext, previewAuthoring }) {
65957
66448
  const perf = beginBlockRenderMeasurement();
65958
66449
  if (!theme) throw new Error("Block rendering requires theme tokens; none were provided to makeDefaultBlockComponent");
65959
66450
  if (!registry) throw new Error("Block rendering requires a component registry; none was provided");
@@ -65973,6 +66464,7 @@ function makeDefaultBlockComponent(args) {
65973
66464
  theme: withButtonSystem(theme, themeConfig),
65974
66465
  pathBase,
65975
66466
  blockId,
66467
+ contentVersionId,
65976
66468
  blockKind,
65977
66469
  blockContent: mergedContent,
65978
66470
  blockBindings,
@@ -66727,6 +67219,7 @@ function buildBlockOverrideProps(input) {
66727
67219
  ...blockSubjectProps(dataContext),
66728
67220
  imageResolveContext: input.imageResolveContext,
66729
67221
  blockId: block.id ?? null,
67222
+ contentVersionId: block.contentVersionId ?? null,
66730
67223
  blockKind: block.kind
66731
67224
  };
66732
67225
  }
@@ -66827,6 +67320,7 @@ function toPresentationPage(page) {
66827
67320
  id: block.id,
66828
67321
  kind: block.kind,
66829
67322
  purpose: block.purpose,
67323
+ ...block.contentVersionId ? { contentVersionId: block.contentVersionId } : {},
66830
67324
  ...block.bindings ? { bindings: block.bindings } : {}
66831
67325
  };
66832
67326
  return block.admission.kind === "renderable" ? {
@@ -69105,10 +69599,19 @@ const containerResponsiveThemeCss = `/*
69105
69599
  padding-top: 2.5rem;
69106
69600
  padding-bottom: 2.5rem;
69107
69601
  }
69602
+ /* Clearance for a surface that is not an authored block page.
69603
+ An authored page gets this through its opening block's container (see the
69604
+ overlay-clearance rule in styles.css). A reserved surface or a system
69605
+ destination page has no such block, so it consumes the same variable here.
69606
+ Marked with one class rather than per-surface selectors, because the last
69607
+ two additions to this family were both missed and shipped overlapping. */
69108
69608
  :where(.theme-scope)
69109
69609
  [data-site-document-layout-mode="header-overlay"]
69110
- [data-rb-reserved-surface].rb-reserved-surface-main {
69111
- padding-top: calc(var(--rb-reserved-surface-header-offset, 5.5rem) + 2.5rem);
69610
+ .rb-overlay-clearance-surface {
69611
+ padding-top: calc(
69612
+ var(--site-overlay-header-clearance, 5.5rem) +
69613
+ var(--site-overlay-opening-content-extra-pad, clamp(1rem, 2vw, 1.75rem))
69614
+ );
69112
69615
  }
69113
69616
  .rb-preview-editor-offset {
69114
69617
  padding-bottom: calc(
@@ -78110,7 +78613,9 @@ const containerResponsiveThemeCss = `/*
78110
78613
  text-align: left;
78111
78614
  }
78112
78615
 
78113
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__subtitle {
78616
+ :where(.theme-scope)
78617
+ :where([data-block="customer-portal"])
78618
+ .cp-login__subtitle {
78114
78619
  color: var(--cp-muted);
78115
78620
  font-size: 0.9375rem;
78116
78621
  text-align: left;
@@ -78137,7 +78642,9 @@ const containerResponsiveThemeCss = `/*
78137
78642
  text-align: left;
78138
78643
  }
78139
78644
 
78140
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link {
78645
+ :where(.theme-scope)
78646
+ :where([data-block="customer-portal"])
78647
+ .cp-login__reset-link {
78141
78648
  appearance: none;
78142
78649
  background: none;
78143
78650
  border: 0;
@@ -78151,11 +78658,15 @@ const containerResponsiveThemeCss = `/*
78151
78658
  text-underline-offset: 0.15em;
78152
78659
  }
78153
78660
 
78154
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link:hover {
78661
+ :where(.theme-scope)
78662
+ :where([data-block="customer-portal"])
78663
+ .cp-login__reset-link:hover {
78155
78664
  color: var(--cp-text);
78156
78665
  }
78157
78666
 
78158
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-login__reset-link:focus-visible {
78667
+ :where(.theme-scope)
78668
+ :where([data-block="customer-portal"])
78669
+ .cp-login__reset-link:focus-visible {
78159
78670
  outline: 2px solid currentColor;
78160
78671
  outline-offset: 3px;
78161
78672
  }
@@ -78200,7 +78711,9 @@ const containerResponsiveThemeCss = `/*
78200
78711
  border-bottom: none;
78201
78712
  }
78202
78713
 
78203
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-header__welcome {
78714
+ :where(.theme-scope)
78715
+ :where([data-block="customer-portal"])
78716
+ .cp-header__welcome {
78204
78717
  font-size: 1.125rem;
78205
78718
  font-weight: 500;
78206
78719
  }
@@ -78216,8 +78729,14 @@ const containerResponsiveThemeCss = `/*
78216
78729
  }
78217
78730
 
78218
78731
  @keyframes cp-fade-in {
78219
- from { opacity: 0; transform: translateY(4px); }
78220
- to { opacity: 1; transform: translateY(0); }
78732
+ from {
78733
+ opacity: 0;
78734
+ transform: translateY(4px);
78735
+ }
78736
+ to {
78737
+ opacity: 1;
78738
+ transform: translateY(0);
78739
+ }
78221
78740
  }
78222
78741
 
78223
78742
  /* Empty state */
@@ -78306,6 +78825,77 @@ const containerResponsiveThemeCss = `/*
78306
78825
  margin-top: 1rem;
78307
78826
  }
78308
78827
 
78828
+ /* Event waitlists */
78829
+ :where(.theme-scope) :where([data-block="customer-portal"]) .cp-waitlist-list {
78830
+ display: grid;
78831
+ gap: 1rem;
78832
+ }
78833
+
78834
+ :where(.theme-scope)
78835
+ :where([data-block="customer-portal"])
78836
+ .cp-waitlists
78837
+ > .cp-alert {
78838
+ margin-bottom: 1rem;
78839
+ }
78840
+
78841
+ :where(.theme-scope) :where([data-block="customer-portal"]) .cp-waitlist-card {
78842
+ transition:
78843
+ border-color 180ms ease,
78844
+ box-shadow 180ms ease;
78845
+ }
78846
+
78847
+ :where(.theme-scope)
78848
+ :where([data-block="customer-portal"])
78849
+ .cp-waitlist-card--focused {
78850
+ border-color: var(--cp-primary);
78851
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-primary) 22%, transparent);
78852
+ }
78853
+
78854
+ :where(.theme-scope)
78855
+ :where([data-block="customer-portal"])
78856
+ .cp-waitlist-card__summary,
78857
+ :where(.theme-scope)
78858
+ :where([data-block="customer-portal"])
78859
+ .cp-waitlist-card__position {
78860
+ font-weight: 600;
78861
+ }
78862
+
78863
+ :where(.theme-scope)
78864
+ :where([data-block="customer-portal"])
78865
+ .cp-waitlist-card
78866
+ .cp-card-body
78867
+ p {
78868
+ margin: 0.4rem 0;
78869
+ }
78870
+
78871
+ @container rb-site (max-width: 640px) {
78872
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
78873
+ :where(.theme-scope)
78874
+ :where([data-block="customer-portal"])
78875
+ .cp-waitlist-card
78876
+ .cp-card-header {
78877
+ flex-direction: column-reverse;
78878
+ }
78879
+
78880
+ :where(.theme-scope)
78881
+ :where([data-block="customer-portal"])
78882
+ .cp-waitlist-card
78883
+ .cp-card-actions {
78884
+ align-items: stretch;
78885
+ flex-direction: column;
78886
+ }
78887
+
78888
+ :where(.theme-scope)
78889
+ :where([data-block="customer-portal"])
78890
+ .cp-waitlist-card
78891
+ .cp-card-actions
78892
+ > * {
78893
+ justify-content: center;
78894
+ text-align: center;
78895
+ }
78896
+ }
78897
+ }
78898
+
78309
78899
  /* Badge */
78310
78900
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-badge {
78311
78901
  display: inline-flex;
@@ -78442,11 +79032,18 @@ const containerResponsiveThemeCss = `/*
78442
79032
  background: rgba(var(--tb-border), 0.2);
78443
79033
  }
78444
79034
 
78445
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table tbody tr:last-child td {
79035
+ :where(.theme-scope)
79036
+ :where([data-block="customer-portal"])
79037
+ .cp-table
79038
+ tbody
79039
+ tr:last-child
79040
+ td {
78446
79041
  border-bottom: none;
78447
79042
  }
78448
79043
 
78449
- :where(.theme-scope) :where([data-block="customer-portal"]) :is(.cp-row--past, .cp-row--muted) {
79044
+ :where(.theme-scope)
79045
+ :where([data-block="customer-portal"])
79046
+ :is(.cp-row--past, .cp-row--muted) {
78450
79047
  opacity: 0.65;
78451
79048
  }
78452
79049
 
@@ -78459,7 +79056,9 @@ const containerResponsiveThemeCss = `/*
78459
79056
  line-height: 1.2;
78460
79057
  }
78461
79058
 
78462
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__badges {
79059
+ :where(.theme-scope)
79060
+ :where([data-block="customer-portal"])
79061
+ .cp-row-title__badges {
78463
79062
  margin-left: auto;
78464
79063
  display: flex;
78465
79064
  flex-wrap: wrap;
@@ -78467,7 +79066,9 @@ const containerResponsiveThemeCss = `/*
78467
79066
  gap: 0.375rem;
78468
79067
  }
78469
79068
 
78470
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__text {
79069
+ :where(.theme-scope)
79070
+ :where([data-block="customer-portal"])
79071
+ .cp-row-title__text {
78471
79072
  min-width: 0;
78472
79073
  }
78473
79074
 
@@ -78487,12 +79088,16 @@ const containerResponsiveThemeCss = `/*
78487
79088
  line-height: 1.35;
78488
79089
  }
78489
79090
 
78490
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-note--success {
79091
+ :where(.theme-scope)
79092
+ :where([data-block="customer-portal"])
79093
+ .cp-row-note--success {
78491
79094
  border-left-color: rgb(var(--tb-success));
78492
79095
  color: rgb(var(--tb-success));
78493
79096
  }
78494
79097
 
78495
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-note--error {
79098
+ :where(.theme-scope)
79099
+ :where([data-block="customer-portal"])
79100
+ .cp-row-note--error {
78496
79101
  border-left-color: rgb(var(--tb-destructive));
78497
79102
  color: rgb(var(--tb-destructive));
78498
79103
  }
@@ -78511,16 +79116,23 @@ const containerResponsiveThemeCss = `/*
78511
79116
  white-space: nowrap;
78512
79117
  }
78513
79118
 
78514
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-col-actions .btn-sm {
79119
+ :where(.theme-scope)
79120
+ :where([data-block="customer-portal"])
79121
+ .cp-col-actions
79122
+ .btn-sm {
78515
79123
  white-space: nowrap;
78516
79124
  }
78517
79125
 
78518
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__link {
79126
+ :where(.theme-scope)
79127
+ :where([data-block="customer-portal"])
79128
+ .cp-row-title__link {
78519
79129
  color: inherit;
78520
79130
  text-decoration: none;
78521
79131
  }
78522
79132
 
78523
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-title__link:hover {
79133
+ :where(.theme-scope)
79134
+ :where([data-block="customer-portal"])
79135
+ .cp-row-title__link:hover {
78524
79136
  text-decoration: underline;
78525
79137
  text-decoration-thickness: 2px;
78526
79138
  text-underline-offset: 2px;
@@ -78542,7 +79154,9 @@ const containerResponsiveThemeCss = `/*
78542
79154
  }
78543
79155
 
78544
79156
  /* Profile actions */
78545
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-profile__actions {
79157
+ :where(.theme-scope)
79158
+ :where([data-block="customer-portal"])
79159
+ .cp-profile__actions {
78546
79160
  display: flex;
78547
79161
  gap: 0.75rem;
78548
79162
  margin-top: 1rem;
@@ -78609,28 +79223,39 @@ const containerResponsiveThemeCss = `/*
78609
79223
  gap: 0.375rem;
78610
79224
  }
78611
79225
 
78612
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__index {
79226
+ :where(.theme-scope)
79227
+ :where([data-block="customer-portal"])
79228
+ .cp-guest-edit-row__index {
78613
79229
  font-size: 0.75rem;
78614
79230
  font-weight: 500;
78615
79231
  color: var(--cp-muted);
78616
79232
  }
78617
79233
 
78618
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__fields {
79234
+ :where(.theme-scope)
79235
+ :where([data-block="customer-portal"])
79236
+ .cp-guest-edit-row__fields {
78619
79237
  display: flex;
78620
79238
  gap: 0.5rem;
78621
79239
  }
78622
79240
 
78623
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__fields input {
79241
+ :where(.theme-scope)
79242
+ :where([data-block="customer-portal"])
79243
+ .cp-guest-edit-row__fields
79244
+ input {
78624
79245
  flex: 1;
78625
79246
  min-width: 0;
78626
79247
  }
78627
79248
 
78628
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guest-edit-row__error {
79249
+ :where(.theme-scope)
79250
+ :where([data-block="customer-portal"])
79251
+ .cp-guest-edit-row__error {
78629
79252
  font-size: 0.75rem;
78630
79253
  color: var(--cp-error);
78631
79254
  }
78632
79255
 
78633
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-guests__actions {
79256
+ :where(.theme-scope)
79257
+ :where([data-block="customer-portal"])
79258
+ .cp-guests__actions {
78634
79259
  display: flex;
78635
79260
  gap: 0.5rem;
78636
79261
  margin-top: 0.5rem;
@@ -78644,13 +79269,18 @@ const containerResponsiveThemeCss = `/*
78644
79269
  }
78645
79270
 
78646
79271
  /* In the actions modal, tiles sit on a surface modal, so use "background" for contrast. */
78647
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-actions-list :where(.rb-tile) {
79272
+ :where(.theme-scope)
79273
+ :where([data-block="customer-portal"])
79274
+ .cp-actions-list
79275
+ :where(.rb-tile) {
78648
79276
  --rb-event-tile-bg: rgb(var(--tb-background));
78649
79277
  --rb-event-tile-border: rgb(var(--tb-border));
78650
79278
  }
78651
79279
 
78652
79280
  /* Actions trigger: icon-only kebab button */
78653
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-actions-trigger.btn-sm {
79281
+ :where(.theme-scope)
79282
+ :where([data-block="customer-portal"])
79283
+ .cp-actions-trigger.btn-sm {
78654
79284
  padding: 0.35rem !important;
78655
79285
  line-height: 1 !important;
78656
79286
  min-width: 32px;
@@ -78674,17 +79304,24 @@ const containerResponsiveThemeCss = `/*
78674
79304
  gap: 0.25rem;
78675
79305
  }
78676
79306
 
78677
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile__title {
79307
+ :where(.theme-scope)
79308
+ :where([data-block="customer-portal"])
79309
+ .cp-action-tile__title {
78678
79310
  font-weight: 600;
78679
79311
  font-size: 0.9375rem;
78680
79312
  }
78681
79313
 
78682
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile__desc {
79314
+ :where(.theme-scope)
79315
+ :where([data-block="customer-portal"])
79316
+ .cp-action-tile__desc {
78683
79317
  font-size: 0.875rem;
78684
79318
  line-height: 1.35;
78685
79319
  }
78686
79320
 
78687
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-action-tile--danger .cp-action-tile__title {
79321
+ :where(.theme-scope)
79322
+ :where([data-block="customer-portal"])
79323
+ .cp-action-tile--danger
79324
+ .cp-action-tile__title {
78688
79325
  color: rgb(var(--tb-destructive));
78689
79326
  }
78690
79327
 
@@ -78706,7 +79343,9 @@ const containerResponsiveThemeCss = `/*
78706
79343
  text-decoration: underline;
78707
79344
  }
78708
79345
 
78709
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-btn--link:hover {
79346
+ :where(.theme-scope)
79347
+ :where([data-block="customer-portal"])
79348
+ .cp-btn--link:hover {
78710
79349
  color: var(--cp-primary-hover);
78711
79350
  }
78712
79351
 
@@ -78745,34 +79384,48 @@ const containerResponsiveThemeCss = `/*
78745
79384
  margin-top: 0.75rem;
78746
79385
  }
78747
79386
 
78748
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__title {
79387
+ :where(.theme-scope)
79388
+ :where([data-block="customer-portal"])
79389
+ .cp-cancel-confirm__title {
78749
79390
  font-weight: 600;
78750
79391
  margin-bottom: 0.5rem;
78751
79392
  }
78752
79393
 
78753
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__message {
79394
+ :where(.theme-scope)
79395
+ :where([data-block="customer-portal"])
79396
+ .cp-cancel-confirm__message {
78754
79397
  margin-bottom: 0.25rem;
78755
79398
  }
78756
79399
 
78757
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__warning {
79400
+ :where(.theme-scope)
79401
+ :where([data-block="customer-portal"])
79402
+ .cp-cancel-confirm__warning {
78758
79403
  margin-bottom: 0.75rem;
78759
79404
  }
78760
79405
 
78761
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-cancel-confirm__actions {
79406
+ :where(.theme-scope)
79407
+ :where([data-block="customer-portal"])
79408
+ .cp-cancel-confirm__actions {
78762
79409
  display: flex;
78763
79410
  gap: 0.75rem;
78764
79411
  }
78765
79412
 
78766
79413
  /* Membership actions */
78767
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-membership-actions {
79414
+ :where(.theme-scope)
79415
+ :where([data-block="customer-portal"])
79416
+ .cp-membership-actions {
78768
79417
  margin-top: 0.75rem;
78769
79418
  }
78770
79419
 
78771
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-section-actions {
79420
+ :where(.theme-scope)
79421
+ :where([data-block="customer-portal"])
79422
+ .cp-section-actions {
78772
79423
  margin-top: 1rem;
78773
79424
  }
78774
79425
 
78775
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card-subtitle--spaced {
79426
+ :where(.theme-scope)
79427
+ :where([data-block="customer-portal"])
79428
+ .cp-card-subtitle--spaced {
78776
79429
  margin-top: 0.75rem;
78777
79430
  }
78778
79431
 
@@ -78796,9 +79449,18 @@ const containerResponsiveThemeCss = `/*
78796
79449
  display: none;
78797
79450
  }
78798
79451
 
78799
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-guests,
78800
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-tickets,
78801
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table :is(th, td).cp-col-actions {
79452
+ :where(.theme-scope)
79453
+ :where([data-block="customer-portal"])
79454
+ .cp-table
79455
+ :is(th, td).cp-col-guests,
79456
+ :where(.theme-scope)
79457
+ :where([data-block="customer-portal"])
79458
+ .cp-table
79459
+ :is(th, td).cp-col-tickets,
79460
+ :where(.theme-scope)
79461
+ :where([data-block="customer-portal"])
79462
+ .cp-table
79463
+ :is(th, td).cp-col-actions {
78802
79464
  display: none;
78803
79465
  }
78804
79466
 
@@ -78807,24 +79469,34 @@ const containerResponsiveThemeCss = `/*
78807
79469
  }
78808
79470
 
78809
79471
  /* Make the cell a positioning context for the kebab */
78810
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row > td:first-child {
79472
+ :where(.theme-scope)
79473
+ :where([data-block="customer-portal"])
79474
+ .cp-row
79475
+ > td:first-child {
78811
79476
  position: relative;
78812
79477
  padding-right: 2.5rem;
78813
79478
  }
78814
79479
 
78815
79480
  /* Position kebab in top-right of the cell */
78816
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-mobile-actions {
79481
+ :where(.theme-scope)
79482
+ :where([data-block="customer-portal"])
79483
+ .cp-row-mobile-actions {
78817
79484
  position: absolute;
78818
79485
  top: 0.5rem;
78819
79486
  right: 0.5rem;
78820
79487
  margin-top: 0;
78821
79488
  }
78822
79489
 
78823
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-row-mobile-actions .btn-sm {
79490
+ :where(.theme-scope)
79491
+ :where([data-block="customer-portal"])
79492
+ .cp-row-mobile-actions
79493
+ .btn-sm {
78824
79494
  width: auto;
78825
79495
  }
78826
79496
 
78827
- :where(.theme-scope) :where([data-block="customer-portal"]) .cp-profile__edit {
79497
+ :where(.theme-scope)
79498
+ :where([data-block="customer-portal"])
79499
+ .cp-profile__edit {
78828
79500
  align-self: stretch;
78829
79501
  }
78830
79502
  }
@@ -79272,6 +79944,47 @@ const containerResponsiveThemeCss = `/*
79272
79944
  gap: 0.25rem;
79273
79945
  }
79274
79946
 
79947
+ /* Topic choices (visitor picks what to hear about). Same treatment as the
79948
+ form block's .fb-fieldset / .fb-inline, defined here because the newsletter
79949
+ form also renders inside contact-newsletter and the site footer. */
79950
+ :where(.theme-scope) .newsletter-topics {
79951
+ display: flex;
79952
+ flex-direction: column;
79953
+ gap: 0.5rem;
79954
+ border: none;
79955
+ padding: 0;
79956
+ margin: 0;
79957
+ min-width: 0;
79958
+ }
79959
+
79960
+ :where(.theme-scope) .newsletter-topics > legend {
79961
+ padding: 0;
79962
+ margin-bottom: 0.25rem;
79963
+ }
79964
+
79965
+ :where(.theme-scope) .newsletter-topic-choice {
79966
+ display: flex;
79967
+ align-items: center;
79968
+ gap: 0.5rem;
79969
+ }
79970
+
79971
+ /* Error panel and field notes. The form block scopes these to its own
79972
+ data-block, so the newsletter form (which also renders in the footer)
79973
+ needs its own copy of the treatment. */
79974
+ :where(.theme-scope) .newsletter-form .fb-error:not([data-field-validation-message]) {
79975
+ background-color: var(--fb-error-bg);
79976
+ color: var(--fb-error-text);
79977
+ border: 1px solid var(--fb-error-border);
79978
+ border-radius: var(--rb-block-radius);
79979
+ padding: 1rem;
79980
+ font-size: 0.875rem;
79981
+ }
79982
+
79983
+ :where(.theme-scope) .newsletter-form [data-field-validation-message] {
79984
+ font-size: 0.875rem;
79985
+ color: var(--fb-error-text);
79986
+ }
79987
+
79275
79988
  /* Required indicator */
79276
79989
  :where(.theme-scope) .newsletter-required {
79277
79990
  color: rgb(var(--tb-primary));
@@ -79321,6 +80034,10 @@ const containerResponsiveThemeCss = `/*
79321
80034
  flex-shrink: 0;
79322
80035
  }
79323
80036
 
80037
+ :where(.theme-scope) .newsletter-inline .newsletter-topics {
80038
+ flex-basis: 100%;
80039
+ }
80040
+
79324
80041
  /* Mobile fallback for inline variant */
79325
80042
  @container rb-site (max-width: 640px) {
79326
80043
  @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
@@ -81739,12 +82456,12 @@ function normalizeContent(block) {
81739
82456
  }
81740
82457
  /**
81741
82458
  * Normalize params for API calls.
81742
- * Converts all values to strings.
82459
+ * Converts supplied values to strings, preserving absent versus explicitly empty params.
81743
82460
  */
81744
82461
  function normalizeParams(input) {
81745
82462
  if (!input || typeof input !== "object") return {};
81746
82463
  const output = {};
81747
- for (const [key, value] of Object.entries(input)) output[key] = coerceToString(value);
82464
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null) output[key] = coerceToString(value);
81748
82465
  return output;
81749
82466
  }
81750
82467
  function isNonArrayObject(value) {
@@ -81808,6 +82525,14 @@ function coercePayload(payload) {
81808
82525
  * - Frontend: provide internal API client
81809
82526
  * - SDK: provide SDK client with endpoint mapping
81810
82527
  */
82528
+ function projectDataLoaders(loaders, shouldLoad, blockId, blockKind) {
82529
+ if (!shouldLoad) return [...loaders];
82530
+ return loaders.filter(({ key }) => shouldLoad({
82531
+ blockId,
82532
+ blockKind,
82533
+ loaderKey: key
82534
+ }));
82535
+ }
81811
82536
  function shouldSkipResolvedLoader(input) {
81812
82537
  if (input.loader.requiredParams?.some((param) => !input.params[param]?.trim())) return true;
81813
82538
  return Boolean(input.isValidEndpoint && !input.isValidEndpoint(input.endpoint));
@@ -81833,8 +82558,12 @@ function shouldSkipResolvedLoader(input) {
81833
82558
  * ```
81834
82559
  */
81835
82560
  async function prefetchBlockData$1(page, context, options) {
81836
- const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings } = options;
82561
+ return (await prefetchBlockDataWithFailures(page, context, options)).resolvedData;
82562
+ }
82563
+ async function prefetchBlockDataWithFailures(page, context, options) {
82564
+ const { apiClient, isValidEndpoint, onError, getCustomBlockLoaders, getBlockDefinition: getBlockDefinition$1 = getBlockDefinition, resolveParamsBindings: resolveParamsBindings$1 = resolveParamsBindings, shouldLoad } = options;
81837
82565
  const results = {};
82566
+ const loaderFailures = {};
81838
82567
  const tasks = [];
81839
82568
  for (const block of page.blocks) {
81840
82569
  const blockId = block.id;
@@ -81849,6 +82578,7 @@ async function prefetchBlockData$1(page, context, options) {
81849
82578
  loader
81850
82579
  })) : [];
81851
82580
  } else loaders = [];
82581
+ loaders = projectDataLoaders(loaders, shouldLoad, blockId, block.kind);
81852
82582
  if (loaders.length === 0) continue;
81853
82583
  const root = {
81854
82584
  ...context.root ?? {},
@@ -81882,6 +82612,11 @@ async function prefetchBlockData$1(page, context, options) {
81882
82612
  const blockResults = results[blockId] ?? (results[blockId] = {});
81883
82613
  blockResults[key] = data;
81884
82614
  } catch (error) {
82615
+ const blockFailures = loaderFailures[blockId] ?? (loaderFailures[blockId] = {});
82616
+ blockFailures[key] = {
82617
+ endpoint,
82618
+ params
82619
+ };
81885
82620
  if (onError) onError(error, {
81886
82621
  block: block.kind,
81887
82622
  loader: key
@@ -81891,7 +82626,10 @@ async function prefetchBlockData$1(page, context, options) {
81891
82626
  }
81892
82627
  }
81893
82628
  if (tasks.length > 0) await Promise.all(tasks);
81894
- return results;
82629
+ return {
82630
+ resolvedData: results,
82631
+ loaderFailures
82632
+ };
81895
82633
  }
81896
82634
  //#endregion
81897
82635
  //#region ../blocks/src/system/data/loaderEndpoints.ts
@@ -81941,8 +82679,8 @@ function toStringParams(value) {
81941
82679
  for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
81942
82680
  return out;
81943
82681
  }
81944
- function stripEmptyStringValues(params) {
81945
- for (const [key, value] of Object.entries(params)) if (value === "") delete params[key];
82682
+ function stripEmptyStringValues(params, endpoint) {
82683
+ for (const [key, value] of Object.entries(params)) if (value === "" && !(key === "seriesIds" && (endpoint === "listPublicEvents" || endpoint === "listPublicEventCalendarWindow"))) delete params[key];
81946
82684
  }
81947
82685
  function ensureSiteId(params, context) {
81948
82686
  if (!params.siteId && typeof context.siteId === "string" && context.siteId) params.siteId = context.siteId;
@@ -81955,7 +82693,7 @@ function ensureSiteId(params, context) {
81955
82693
  */
81956
82694
  function normalizeLoaderParams(endpoint, params, context) {
81957
82695
  const out = toStringParams(params);
81958
- stripEmptyStringValues(out);
82696
+ stripEmptyStringValues(out, endpoint);
81959
82697
  if (endpoint === "getPublicFormById") {
81960
82698
  ensureSiteId(out, context);
81961
82699
  if (!out.formId && out.formSlug) {
@@ -82302,7 +83040,17 @@ const riverbankSiteConfigInputSchema = z$1.object({
82302
83040
  z$1.object({
82303
83041
  config: riverbankSiteConfigInputSchema,
82304
83042
  forceContentTypes: z$1.boolean().optional(),
82305
- mode: z$1.enum(["apply", "preview"]).optional()
83043
+ mode: z$1.enum(["apply", "preview"]).optional(),
83044
+ expectedMailingListProviderScope: z$1.unknown().transform((value, ctx) => {
83045
+ if (value === void 0) return void 0;
83046
+ const parsed = parseMailingListProviderScope(value);
83047
+ if (parsed.ok) return parsed.value;
83048
+ ctx.addIssue({
83049
+ code: "custom",
83050
+ message: "Invalid mailing-list provider scope"
83051
+ });
83052
+ return z$1.NEVER;
83053
+ }).optional()
82306
83054
  }).strict();
82307
83055
  //#endregion
82308
83056
  //#region ../api/src/sdkThemeWire.ts
@@ -84055,9 +84803,11 @@ function convertPageResponseBlock(block) {
84055
84803
  if (typeof block.id !== "string" && block.id !== null) throw new Error(`Invalid block id in page: expected string or null, got ${typeof block.id}`);
84056
84804
  if (typeof block.kind !== "string") throw new Error(`Invalid block kind in page: expected string, got ${typeof block.kind}`);
84057
84805
  if (typeof block.purpose !== "string") throw new Error(`Invalid block purpose in page: expected string, got ${typeof block.purpose}`);
84806
+ 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}`);
84058
84807
  const admission = readInvalidBlockAdmission(block.admission);
84059
84808
  return {
84060
84809
  id: block.id,
84810
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
84061
84811
  kind: block.kind,
84062
84812
  purpose: block.purpose,
84063
84813
  content: sanitizeSdkRuntimeBlockContent(block.kind, readContentRecord(block.content) ?? {}),
@@ -84090,6 +84840,7 @@ function projectRenderablePageOutline(page) {
84090
84840
  ...page,
84091
84841
  blocks: page.blocks.flatMap((block) => block.admission.kind === "renderable" ? [{
84092
84842
  id: block.id,
84843
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
84093
84844
  kind: block.kind,
84094
84845
  purpose: block.purpose,
84095
84846
  content: block.admission.content,
@@ -84100,6 +84851,7 @@ function projectRenderablePageOutline(page) {
84100
84851
  function admitSdkRuntimePageBlock(block, customBlocks) {
84101
84852
  const base = {
84102
84853
  id: block.id,
84854
+ ...block.contentVersionId !== void 0 ? { contentVersionId: block.contentVersionId } : {},
84103
84855
  kind: block.kind,
84104
84856
  purpose: block.purpose,
84105
84857
  ...block.bindings ? { bindings: block.bindings } : {}
@@ -86760,6 +87512,7 @@ function readEntrySlotKey(block) {
86760
87512
  function admitEntrySlotBlock(block, customBlocks) {
86761
87513
  const base = {
86762
87514
  id: block.id ?? block.blockId ?? null,
87515
+ contentVersionId: block.contentVersionId,
86763
87516
  kind: block.kind,
86764
87517
  purpose: block.purpose,
86765
87518
  ...isRecord$1(block.bindings) ? { bindings: block.bindings } : {}
@@ -87102,6 +87855,15 @@ function isEntryResponse(response) {
87102
87855
  function isPageSurfaceResponse(response) {
87103
87856
  return response.type === "pageSurface";
87104
87857
  }
87858
+ z$1.object({
87859
+ palette: paletteColorsSchema,
87860
+ paletteMode: paletteModeSchema,
87861
+ typography: z$1.object({
87862
+ headingFamily: z$1.string().trim().min(1),
87863
+ bodyFamily: z$1.string().trim().min(1)
87864
+ }).strict(),
87865
+ corners
87866
+ }).strict();
87105
87867
  //#endregion
87106
87868
  //#region src/rendering/blocks-theme-runtime.ts
87107
87869
  function parseBlocksTheme(theme) {
@@ -87273,7 +88035,7 @@ function PageContent(props) {
87273
88035
  previewToken,
87274
88036
  resolvedData,
87275
88037
  bookingOfferingPresets: bookingOfferingPresets ?? [],
87276
- mailingList,
88038
+ mailingList: mailingList ?? dataContext?.mailingList,
87277
88039
  bookingTimeZone: resolveSdkBookingTimeZone(bookingTimeZone),
87278
88040
  routes: routeMap,
87279
88041
  pagesByIdentifier,
@@ -88478,7 +89240,7 @@ var CircuitOpenError = class extends Error {
88478
89240
  * 1. This constant
88479
89241
  * 2. The "version" field in package.json
88480
89242
  */
88481
- const SDK_VERSION = "0.139.0";
89243
+ const SDK_VERSION = "0.141.0";
88482
89244
  //#endregion
88483
89245
  //#region src/next/content-load-failure.ts
88484
89246
  const SdkContentLoadError = RiverbankContentLoadError;
@@ -89440,7 +90202,12 @@ const API_ENDPOINTS = Object.freeze({
89440
90202
  path: "/public/sites/{siteId}/sitemap",
89441
90203
  method: "GET",
89442
90204
  revalidate: 60,
89443
- tags: ["riverbank:site:{siteId}:routable-content", "riverbank:site:{siteId}:settings"],
90205
+ tags: [
90206
+ "riverbank:site:{siteId}:routable-content",
90207
+ "riverbank:site:{siteId}:settings",
90208
+ "riverbank:site:{siteId}:public-events",
90209
+ "riverbank:site:{siteId}:public-booking-services"
90210
+ ],
89444
90211
  auth: "public",
89445
90212
  responseKind: "json"
89446
90213
  }