@riverbankcms/sdk 0.126.0 → 0.128.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 (212) hide show
  1. package/dist/{PreviewEditorSidebar-DcYJxTgc.mjs → PreviewEditorSidebar-Dbvb7GIr.mjs} +64 -68
  2. package/dist/{PreviewEditorUI-Ctt1yTJr.mjs → PreviewEditorUI-e9O9l20X.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-DgFDIwvK.mjs → PreviewQueryProvider-B1kbhaJD.mjs} +1 -1
  4. package/dist/SdkPreviewModeRuntime-BZHt6e9w.mjs +11006 -0
  5. package/dist/{SiteChromeCustomizeContext-C87qlKWw.mjs → SiteChromeCustomizeContext-CvuGbHJX.mjs} +51247 -20733
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +486 -36
  7. package/dist/_dts/api/src/bookingClosures.d.ts +19 -3
  8. package/dist/_dts/api/src/bookingManagementEndpoints.d.ts +4 -3
  9. package/dist/_dts/api/src/bookingRecords.d.ts +0 -13
  10. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +2 -2
  11. package/dist/_dts/api/src/communications.d.ts +2 -1
  12. package/dist/_dts/api/src/contactFormSummary.d.ts +15 -0
  13. package/dist/_dts/api/src/contentRuntime.d.ts +3 -10
  14. package/dist/_dts/api/src/endpoints.d.ts +1 -1
  15. package/dist/_dts/api/src/footerSettings.d.ts +11 -0
  16. package/dist/_dts/api/src/index.d.ts +2 -1
  17. package/dist/_dts/api/src/occurrenceScheduling.d.ts +48 -0
  18. package/dist/_dts/api/src/participantMessaging.d.ts +5 -3
  19. package/dist/_dts/api/src/publicExperience/siteEndpoints.d.ts +7 -0
  20. package/dist/_dts/api/src/sdkContracts.d.ts +7 -5
  21. package/dist/_dts/api/src/siteOperations.d.ts +12 -3
  22. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +3 -2
  23. package/dist/_dts/block-form/src/backend/store-backend.d.ts +2 -1
  24. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +1 -0
  25. package/dist/_dts/blocks/src/client/form.d.ts +1 -0
  26. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +1 -0
  27. package/dist/_dts/blocks/src/client/site-chrome.d.ts +1 -0
  28. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -8
  29. package/dist/_dts/blocks/src/index.d.ts +3 -2
  30. package/dist/_dts/blocks/src/lib/media.d.ts +267 -0
  31. package/dist/_dts/blocks/src/rendering/server.d.ts +1 -1
  32. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +41 -0
  33. package/dist/_dts/blocks/src/system/blocks/newsletter-signup-destination.d.ts +14 -23
  34. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +1 -1
  35. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +109 -23
  36. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +0 -13
  37. package/dist/_dts/blocks/src/system/data/loaderEndpoints.d.ts +1 -1
  38. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +42 -108
  39. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +21 -54
  40. package/dist/_dts/blocks/src/system/runtime/nodes/event-details/logic.d.ts +1 -1
  41. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/registrationSurface.d.ts +26 -0
  42. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +8 -0
  43. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +21 -0
  44. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +4 -4
  45. package/dist/_dts/blocks/src/system/runtime/nodes/mergeResolveImageUrlContexts.d.ts +7 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.interactive.d.ts +29 -78
  47. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.server.d.ts +1 -1
  48. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.submission.d.ts +3 -6
  49. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +27 -8
  50. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +2 -2
  51. package/dist/_dts/content-editor/src/FooterComposerOverview.d.ts +21 -0
  52. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +3 -1
  53. package/dist/_dts/content-editor/src/FooterEngagementEditorFields.d.ts +31 -0
  54. package/dist/_dts/content-editor/src/FooterEngagementEditorPanel.d.ts +17 -0
  55. package/dist/_dts/content-editor/src/footerComposer.d.ts +3 -0
  56. package/dist/_dts/content-editor/src/footerEngagementDraft.d.ts +57 -0
  57. package/dist/_dts/content-editor/src/footerEngagementEditor.d.ts +11 -0
  58. package/dist/_dts/content-editor/src/footerPreviewRuntime.d.ts +13 -0
  59. package/dist/_dts/content-editor/src/index.d.ts +1 -0
  60. package/dist/_dts/content-editor/src/ui/blockValidationManifestRegistry.d.ts +17 -0
  61. package/dist/_dts/content-editor/src/ui/blockValidationView.d.ts +1 -1
  62. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +4 -0
  63. package/dist/_dts/content-editor/src/useFooterComposerState.d.ts +35 -0
  64. package/dist/_dts/core/src/footer-arrangement.d.ts +2 -0
  65. package/dist/_dts/core/src/footer-composition-types.d.ts +118 -0
  66. package/dist/_dts/core/src/footer-composition.d.ts +7 -116
  67. package/dist/_dts/core/src/footer-engagement.d.ts +30 -0
  68. package/dist/_dts/core/src/index.d.ts +4 -0
  69. package/dist/_dts/core/src/newsletter-signup-destination.d.ts +38 -0
  70. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +200 -159
  71. package/dist/_dts/db/src/index.d.ts +1 -0
  72. package/dist/_dts/db/src/schemas/forms.d.ts +72 -2
  73. package/dist/_dts/db/src/schemas/standard-contact.d.ts +114 -0
  74. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +4 -0
  75. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockValidationManifests.d.ts +26 -0
  76. package/dist/_dts/editor-blocks/src/widgets/rich-text/imageInsert.d.ts +3 -3
  77. package/dist/_dts/media-editor/src/MediaEditor.d.ts +2 -2
  78. package/dist/_dts/media-editor/src/context.d.ts +1 -2
  79. package/dist/_dts/media-editor/src/index.d.ts +3 -1
  80. package/dist/_dts/media-editor/src/mediaSelection.d.ts +32 -0
  81. package/dist/_dts/media-editor/src/types.d.ts +3 -1
  82. package/dist/_dts/media-editor/src/useMediaSelection.d.ts +26 -0
  83. package/dist/_dts/preview-next/src/client/blocks/previewBatchLoaderParams.d.ts +6 -0
  84. package/dist/_dts/preview-next/src/client/index.d.ts +2 -0
  85. package/dist/_dts/preview-next/src/client/preview/EntryEditorPanel.d.ts +2 -5
  86. package/dist/_dts/preview-next/src/client/preview/EntrySlotBlockEditorPanel.d.ts +2 -5
  87. package/dist/_dts/preview-next/src/client/preview/HeaderMenuControls.d.ts +12 -0
  88. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -5
  89. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -4
  90. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +13 -2
  91. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +8 -4
  92. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +4 -49
  93. package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +8 -0
  94. package/dist/_dts/preview-next/src/client/preview/previewThemeRoles.d.ts +15 -0
  95. package/dist/_dts/preview-next/src/client/preview/siteChromeCustomizeTypes.d.ts +54 -0
  96. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +13 -3
  97. package/dist/_dts/preview-next/src/client/preview/siteChromeNavQuickControlHistory.d.ts +3 -0
  98. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +6 -3
  99. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +6 -5
  100. package/dist/_dts/sdk/src/cli/commands/push/execute/footer.d.ts +9 -0
  101. package/dist/_dts/sdk/src/cli/content/footerFile.d.ts +10 -0
  102. package/dist/_dts/sdk/src/cli/content/reader.d.ts +3 -5
  103. package/dist/_dts/sdk/src/cli/site-commands/footerCommands.d.ts +15 -3
  104. package/dist/_dts/sdk/src/client/combineAbortSignals.d.ts +2 -0
  105. package/dist/_dts/sdk/src/client/management/types.d.ts +6 -15
  106. package/dist/_dts/sdk/src/client/types.d.ts +10 -2
  107. package/dist/_dts/sdk/src/client/wholeSeriesReadOperations.d.ts +11 -0
  108. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  109. package/dist/_dts/sdk/src/config/validation.d.ts +3 -0
  110. package/dist/_dts/sdk/src/contracts/event-registration-content.d.ts +16 -0
  111. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +4 -15
  112. package/dist/_dts/sdk/src/public-api/contracts.d.ts +4 -18
  113. package/dist/_dts/sdk/src/public-api/teamMemberContracts.d.ts +17 -0
  114. package/dist/_dts/sdk/src/public-api/wholeSeriesContracts.d.ts +2 -0
  115. package/dist/_dts/sdk/src/rendering/blocks-page-renderer.d.ts +7 -0
  116. package/dist/_dts/sdk/src/rendering/index.d.ts +5 -3
  117. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -2
  118. package/dist/_dts/sdk/src/rendering/mediaAssets.d.ts +8 -2
  119. package/dist/_dts/sdk/src/version.d.ts +1 -1
  120. package/dist/_dts/site-commands/src/commandContract.d.ts +8 -1
  121. package/dist/_dts/site-commands/src/commands.d.ts +16 -2
  122. package/dist/_dts/theme-core/src/buttons/effects/presets/background.d.ts +1 -1
  123. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +0 -18
  124. package/dist/_dts/theme-core/src/buttons/types.d.ts +1 -3
  125. package/dist/_dts/theme-core/src/header/containerSchema.d.ts +20 -0
  126. package/dist/_dts/theme-core/src/header/generateHeaderCss.d.ts +1 -1
  127. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +14 -0
  128. package/dist/_dts/theme-core/src/header/legacyNavLinkStyle.d.ts +3 -0
  129. package/dist/_dts/theme-core/src/header/paintTargets.d.ts +31 -0
  130. package/dist/_dts/theme-core/src/header/scrollTreatment.d.ts +11 -0
  131. package/dist/_dts/theme-core/src/header/surfaceRules.d.ts +8 -0
  132. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +15 -0
  133. package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
  134. package/dist/_dts/theme-core/src/schema.d.ts +67 -19
  135. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +3 -51
  136. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +4 -11
  137. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +3 -51
  138. package/dist/_dts/theme-core/src/site-styles/headerInteractionPalette.d.ts +32 -0
  139. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +19 -106
  140. package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +22 -0
  141. package/dist/_dts/theme-core/src/site-styles/headerOpeningSection.d.ts +2 -0
  142. package/dist/_dts/theme-core/src/site-styles/headerStyleParts.d.ts +4 -0
  143. package/dist/_dts/theme-core/src/site-styles/index.d.ts +3 -0
  144. package/dist/_dts/theme-core/src/site-styles/lookOptionGroups.d.ts +24 -0
  145. package/dist/_dts/theme-core/src/site-styles/lookResolution.d.ts +1 -2
  146. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +4 -22
  147. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorOptions.d.ts +21 -0
  148. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +1 -1
  149. package/dist/_dts/theme-core/src/site-styles/siteChromeNavPreferences.d.ts +4 -1
  150. package/dist/cli/index.mjs +6272 -5706
  151. package/dist/client/{courseRegistration-BcemLAdN.mjs → CourseRegistrationWizard-xRmA7REV.mjs} +329 -49
  152. package/dist/client/{DiscountCodeDisclosure-DS0AuFWW.mjs → DiscountCodeDisclosure-B9vriL5C.mjs} +1 -1
  153. package/dist/client/{EventCombined.client-DtMxLr7q.mjs → EventCombined.client-BgVnVTlz.mjs} +2 -2
  154. package/dist/client/{EventListing.client-BdLSRNg1.mjs → EventListing.client-CqdsO7jO.mjs} +2 -2
  155. package/dist/client/{LeafletStaticMap-BrpC6vsT.mjs → LeafletStaticMap-CKPxot9M.mjs} +1 -1
  156. package/dist/client/{StepIndicator-CBYPFVoy.mjs → StepIndicator-DGCYuBJ1.mjs} +2 -2
  157. package/dist/client/{accordion-BqqwPJWM.mjs → accordion-BfN5Eqd-.mjs} +1 -1
  158. package/dist/client/{bookingForm-SneP3yxC.mjs → bookingForm-DOvCpBFP.mjs} +5 -5
  159. package/dist/client/bookings.mjs +126 -23
  160. package/dist/client/{carousel-BTIR9L3I.mjs → carousel-DPNmiH0f.mjs} +1 -1
  161. package/dist/client/{cart-bqiqd8SX.mjs → cart--egVXlrR.mjs} +3 -3
  162. package/dist/client/{checkout-WbTFV5v4.mjs → checkout-DywWtMcq.mjs} +3 -3
  163. package/dist/client/client.mjs +6111 -5794
  164. package/dist/client/courseRegistration-Dk9qFVwt.mjs +46 -0
  165. package/dist/client/{eventCalendar-CsxIw0V_.mjs → eventCalendar-Bkz2HjlS.mjs} +4 -4
  166. package/dist/client/{eventCombined-B6XMoHfa.mjs → eventCombined-D4kipYWg.mjs} +2 -2
  167. package/dist/client/{eventDetails-BJaoPPfo.mjs → eventDetails-Dz_5ix2Q.mjs} +56 -35
  168. package/dist/client/{eventListing-DgwdYHRT.mjs → eventListing-D0vm-zST.mjs} +2 -2
  169. package/dist/client/{eventRegistration-C0O3folu.mjs → eventRegistration-Cw1E4Q4p.mjs} +58 -6
  170. package/dist/client/{form-Bk9txGFt.mjs → form-C2Zf1n3K.mjs} +1 -1
  171. package/dist/client/{headerSection-yIBt0yTv.mjs → headerSection-CP05gzdc.mjs} +2 -2
  172. package/dist/client/hooks.mjs +1013 -935
  173. package/dist/client/{locationMap-C-3KIpv-.mjs → locationMap-Cl3x9PYJ.mjs} +2 -2
  174. package/dist/client/{newsletterForm-CzB8g8h2.mjs → newsletterForm-DyEJoClm.mjs} +26 -20
  175. package/dist/client/{pricing-C1QeDes_.mjs → pricing-DGuNR1W4.mjs} +1 -1
  176. package/dist/client/{productDetail-w7SBp5uc.mjs → productDetail-Cq-HrGew.mjs} +3 -3
  177. package/dist/client/{productList-D0tGKHGf.mjs → productList-DbB3jwqd.mjs} +3 -3
  178. package/dist/client/{propsDecoder-Bcin2DB3.mjs → propsDecoder-CiTuhUwY.mjs} +257 -142
  179. package/dist/client/rendering/client.mjs +1342 -1122
  180. package/dist/client/rendering/islands.mjs +18 -18
  181. package/dist/client/rendering.mjs +6622 -6321
  182. package/dist/client/{scrollToBlock-h-o_STf_.mjs → scrollToBlock-CShkRqab.mjs} +1 -1
  183. package/dist/client/{shop-BGzmL8O_.mjs → shop-Cu4Ib-ZA.mjs} +5 -5
  184. package/dist/client/{shop-commerce-lX8QxjX-.mjs → shop-commerce-BzpsOdh7.mjs} +4 -4
  185. package/dist/client/{shop-commerce-store-CEurARtu.mjs → shop-commerce-store-DaE7Fhj8.mjs} +1 -1
  186. package/dist/client/{shopShared-DXxH8xxw.mjs → shopShared-cF0c20vB.mjs} +2 -2
  187. package/dist/client/{useEventFilters-B591g9vd.mjs → useEventFilters-QZ3HMgaJ.mjs} +2 -2
  188. package/dist/client/{usePolling-BvnChV4m.mjs → usePolling-BKf0GcE-.mjs} +2 -2
  189. package/dist/preview-next/before-render.mjs +1 -1
  190. package/dist/preview-next/client/runtime.mjs +4 -4
  191. package/dist/preview-next/middleware.mjs +1 -1
  192. package/dist/{previewAuthStore-Dev9CdG9.mjs → previewAuthStore-BesgU5Xu.mjs} +1 -1
  193. package/dist/{sdk-runtime-M__i3Jce.mjs → sdk-runtime-Cn_QSCOg.mjs} +2 -2
  194. package/dist/{separator-VSlnI9bc.mjs → separator-CEoGABRc.mjs} +1 -1
  195. package/dist/server/components.mjs +1750 -1614
  196. package/dist/server/config-validation.mjs +1010 -935
  197. package/dist/server/config.mjs +1010 -935
  198. package/dist/server/data.mjs +1013 -935
  199. package/dist/server/index.mjs +40 -16
  200. package/dist/server/next.mjs +1790 -1632
  201. package/dist/server/page-converter.mjs +1012 -938
  202. package/dist/server/prebuild.mjs +1 -1
  203. package/dist/server/rendering/server.mjs +1746 -1601
  204. package/dist/server/rendering.mjs +1759 -1615
  205. package/dist/server/routing.mjs +1123 -975
  206. package/dist/server/server.mjs +1053 -951
  207. package/dist/server/theme-bridge.mjs +151 -118
  208. package/dist/server/theme.mjs +111 -23
  209. package/package.json +1 -1
  210. package/dist/SdkPreviewModeRuntime-CvW1vdQ4.mjs +0 -39468
  211. package/dist/_dts/editor-blocks/src/widgets/rich-text/ensureRichTextImageAssetIdentifier.d.ts +0 -8
  212. package/dist/client/MagicLinkForm-Bt3IuLMy.mjs +0 -327
@@ -220,7 +220,7 @@ function formatEventPricing(pricing, options = {}) {
220
220
  //#endregion
221
221
  //#region ../core/src/event-page-surface-subject.ts
222
222
  function parseEventPageSurfaceSubject(value) {
223
- if (!isRecord$36(value)) return err$3({ kind: "notObject" });
223
+ if (!isRecord$38(value)) return err$3({ kind: "notObject" });
224
224
  switch (value.kind) {
225
225
  case "eventSeries": {
226
226
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -263,7 +263,7 @@ function parseEventPageSurfaceSubject(value) {
263
263
  });
264
264
  }
265
265
  }
266
- function isRecord$36(value) {
266
+ function isRecord$38(value) {
267
267
  return typeof value === "object" && value !== null && !Array.isArray(value);
268
268
  }
269
269
  //#endregion
@@ -497,7 +497,7 @@ function toLocationCoordinates(value) {
497
497
  }
498
498
  //#endregion
499
499
  //#region ../core/src/rich-text.ts
500
- function isRecord$34(value) {
500
+ function isRecord$36(value) {
501
501
  return typeof value === "object" && value !== null && !Array.isArray(value);
502
502
  }
503
503
  function hasOnlyKeys(value, allowed) {
@@ -516,13 +516,16 @@ function isDenseArrayOf(value, predicate) {
516
516
  return true;
517
517
  }
518
518
  function isTipTapMark(value) {
519
- return isRecord$34(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$34(value.attrs));
519
+ return isRecord$36(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$36(value.attrs));
520
520
  }
521
521
  function isTipTapNode(value) {
522
- if (!isRecord$34(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$34(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;
522
+ if (!isRecord$36(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$36(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;
523
523
  if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
524
524
  return value.text === void 0;
525
525
  }
526
+ function parseNewsletterSignupDestinationProvider(value) {
527
+ return value === "riverbank" || value === "mailchimp" ? value : null;
528
+ }
526
529
  new Map([
527
530
  "brand",
528
531
  "supporting-text",
@@ -531,6 +534,7 @@ new Map([
531
534
  "business-address",
532
535
  "contact",
533
536
  "opening-hours",
537
+ "engagement",
534
538
  "legal-navigation",
535
539
  "legal"
536
540
  ].map((kind, index) => [kind, index]));
@@ -568,9 +572,9 @@ function resolvePlanningDateInput(input = {}) {
568
572
  }
569
573
  //#endregion
570
574
  //#region ../media-core/src/fileSafety.ts
571
- const CONTROL_CHARACTER_PATTERN$1 = /[\u0000-\u001f\u007f]/u;
575
+ const CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
572
576
  function containsUnsafePathSegmentCharacter(value) {
573
- return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN$1.test(value);
577
+ return value.includes("/") || value.includes("\\") || CONTROL_CHARACTER_PATTERN.test(value);
574
578
  }
575
579
  function isReservedPathSegment(value) {
576
580
  return value === "." || value === "..";
@@ -3594,6 +3598,99 @@ function createRichTextDoc(paragraphs) {
3594
3598
  } : { type: "paragraph" })
3595
3599
  };
3596
3600
  }
3601
+ const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
3602
+ "document",
3603
+ "spreadsheet",
3604
+ "archive",
3605
+ "audio"
3606
+ ];
3607
+ const hotspotSchema$1 = z.object({
3608
+ x: z.number().min(0).max(1),
3609
+ y: z.number().min(0).max(1),
3610
+ radius: z.number().optional()
3611
+ });
3612
+ const rotationSchema$1 = z.union([
3613
+ z.literal(0),
3614
+ z.literal(90),
3615
+ z.literal(180),
3616
+ z.literal(270)
3617
+ ]);
3618
+ const rectSchema$1 = z.tuple([
3619
+ z.number(),
3620
+ z.number(),
3621
+ z.number(),
3622
+ z.number()
3623
+ ]);
3624
+ const aspectCropSchema$1 = z.object({
3625
+ aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
3626
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
3627
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
3628
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
3629
+ });
3630
+ const transformSchema$1 = z.object({
3631
+ aspectCrops: z.preprocess((value) => {
3632
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
3633
+ return value;
3634
+ }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
3635
+ rect: rectSchema$1.optional(),
3636
+ hotspot: hotspotSchema$1.optional(),
3637
+ rotation: rotationSchema$1.optional()
3638
+ });
3639
+ const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
3640
+ tag: z.literal("storage"),
3641
+ assetId: z.string().optional(),
3642
+ storageBucket: z.string().min(1),
3643
+ storagePath: z.string().min(1)
3644
+ }), z.object({
3645
+ tag: z.literal("external-src"),
3646
+ assetId: z.string().optional(),
3647
+ src: z.string().url()
3648
+ })]);
3649
+ const mediaBaseSchema = z.object({
3650
+ purpose: z.string().optional(),
3651
+ placeholder: z.boolean().default(true).optional(),
3652
+ assetId: z.string().optional(),
3653
+ identifier: z.string().optional(),
3654
+ src: z.string().optional(),
3655
+ alt: z.string().optional(),
3656
+ filename: z.string().optional(),
3657
+ mimeType: z.string().optional(),
3658
+ width: z.number().optional(),
3659
+ height: z.number().optional(),
3660
+ storageBucket: z.string().optional(),
3661
+ storagePath: z.string().optional(),
3662
+ poster: mediaPosterSchema.optional(),
3663
+ transform: transformSchema$1.optional()
3664
+ });
3665
+ /**
3666
+ * Canonical identifier carried by media values that are safe to persist.
3667
+ * Parsing trims boundary input so downstream writers cannot retain whitespace-only
3668
+ * identifiers or independently disagree about normalization.
3669
+ */
3670
+ const mediaIdentifierSchema = z.string().trim().min(1).brand();
3671
+ const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
3672
+ const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
3673
+ const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
3674
+ const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
3675
+ const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
3676
+ const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
3677
+ const mediaSchema$1 = z.discriminatedUnion("type", [
3678
+ imageMediaSchema,
3679
+ videoMediaSchema,
3680
+ audioMediaSchema,
3681
+ documentMediaSchema,
3682
+ spreadsheetMediaSchema,
3683
+ archiveMediaSchema
3684
+ ]);
3685
+ const persistableMediaBaseSchema = mediaBaseSchema.extend({ identifier: mediaIdentifierSchema });
3686
+ z.discriminatedUnion("type", [
3687
+ persistableMediaBaseSchema.extend({ type: z.literal("image") }),
3688
+ persistableMediaBaseSchema.extend({ type: z.literal("video") }),
3689
+ persistableMediaBaseSchema.extend({ type: z.literal("audio") }),
3690
+ persistableMediaBaseSchema.extend({ type: z.literal("document") }),
3691
+ persistableMediaBaseSchema.extend({ type: z.literal("spreadsheet") }),
3692
+ persistableMediaBaseSchema.extend({ type: z.literal("archive") })
3693
+ ]);
3597
3694
  //#endregion
3598
3695
  //#region ../blocks/src/system/manifest/fieldValidation/index.ts
3599
3696
  const TEL_RE = /^[+()0-9\s-]{3,}$/;
@@ -3883,7 +3980,7 @@ function canonicalizeFieldValueForWrite(plan, value) {
3883
3980
  case "media": {
3884
3981
  if (!isPlainObject$5(value)) return value;
3885
3982
  const canonical = { ...value };
3886
- if (typeof canonical.identifier === "string" && canonical.identifier.trim().length > 0) deleteEnvSpecificKeys(canonical);
3983
+ if (mediaIdentifierSchema.safeParse(canonical.identifier).success) deleteEnvSpecificKeys(canonical);
3887
3984
  return canonical;
3888
3985
  }
3889
3986
  case "group": return canonicalizeObjectForWrite(selectedGroupChildPlans(plan, value), value);
@@ -3978,7 +4075,7 @@ function normalizeObjectChildren(children, value, ctx) {
3978
4075
  function normalizeInlineTextFallbacks(plans, values, ctx) {
3979
4076
  for (const plan of plans) {
3980
4077
  if (plan.kind !== "inlineText" || !plan.plainTextFallbackPath) continue;
3981
- if (!isMissingForPlan(plan, values[plan.fieldId])) continue;
4078
+ if (!isMissingForPlan(plan, values[plan.fieldId]) && !(ctx.allowIncomplete && !parseInlineTextFromUnknown(values[plan.fieldId]).ok)) continue;
3982
4079
  const fallback = getAtFieldPath(values, plan.plainTextFallbackPath);
3983
4080
  if (typeof fallback !== "string" || fallback.trim().length === 0) continue;
3984
4081
  values[plan.fieldId] = normalizeFieldValue(plan, plainTextToInlineText(fallback), ctx);
@@ -4019,7 +4116,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
4019
4116
  case "select": return validateSelectPlan(plan, value);
4020
4117
  case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
4021
4118
  case "inlineText": return validateInlineTextPlan(plan, value);
4022
- case "media": return isPlainObject$5(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0 && (value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type)) ? [] : [issue(plan, "invalidMedia")];
4119
+ case "media": return isPlainObject$5(value) && mediaIdentifierSchema.safeParse(value.identifier).success && (value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type)) ? [] : [issue(plan, "invalidMedia")];
4023
4120
  case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
4024
4121
  case "repeater": return validateRepeaterPlan(plan, value, ctx);
4025
4122
  case "group": return validateGroupPlan(plan, value, ctx);
@@ -4738,6 +4835,17 @@ function asAccessibleSurfaceToken(token) {
4738
4835
  return token;
4739
4836
  }
4740
4837
  //#endregion
4838
+ //#region ../theme-core/src/site-styles/lookOptionGroups.ts
4839
+ function defineLookOptionGroup(group) {
4840
+ defaultOption(group);
4841
+ return group;
4842
+ }
4843
+ function defaultOption(group) {
4844
+ const option = group.options.find((candidate) => candidate.id === group.defaultOptionId);
4845
+ if (option) return option;
4846
+ throw new Error(`Look option group "${group.id}" defaults to missing option "${group.defaultOptionId}".`);
4847
+ }
4848
+ //#endregion
4741
4849
  //#region ../theme-core/src/site-styles/types.ts
4742
4850
  /**
4743
4851
  * Defines a literal-preserving catalog while rejecting top-level extra keys on
@@ -4883,767 +4991,655 @@ function defineBlockDesignCapability(capability) {
4883
4991
  //#region ../theme-core/src/site-styles/appearancePresetResolution.ts
4884
4992
  function assertValidOptionGroups(preset) {
4885
4993
  preset.optionGroups?.forEach((group) => {
4886
- if (!group.options.find((option) => option.id === group.selectedOptionId)) throw new Error(`Appearance preset "${preset.id}" option group "${group.id}" selects missing option "${group.selectedOptionId}".`);
4994
+ defineLookOptionGroup(group);
4887
4995
  });
4888
4996
  }
4889
4997
  function defineBlockAppearancePreset(preset) {
4890
4998
  assertValidOptionGroups(preset);
4891
4999
  return preset;
4892
5000
  }
4893
- [...[
4894
- defineBlockAppearancePreset({
4895
- kind: "block-design",
4896
- id: "hero-immersive-image",
4897
- target: "hero",
4898
- label: "Immersive image hero",
4899
- blockKinds: ["block.hero"],
4900
- constraints: { layoutFamilies: ["centered", "compact"] },
4901
- layoutPatches: [{
4902
- constraints: { layoutVariantKeys: ["micro"] },
4903
- designPatch: {
4904
- sectionHeight: "banner",
4905
- heroTypographyScale: "display"
4906
- }
4907
- }],
4908
- design: {
4909
- sectionSurface: "hero-image",
4910
- contentFrame: plainFrame,
4911
- itemSurface: "none",
4912
- sectionHeight: "hero",
4913
- heroComposition: "center",
4914
- heroTypographyScale: "display",
4915
- imageSurfaceTreatment: { kind: "neutral-wash" }
5001
+ //#endregion
5002
+ //#region ../theme-core/src/site-styles/blockAppearancePresets.ts
5003
+ const brandScrimOptionGroups = [{
5004
+ id: "image-surface-treatment",
5005
+ label: "Treatment",
5006
+ defaultOptionId: "brand-scrim-primary",
5007
+ options: [{
5008
+ id: "brand-scrim-primary",
5009
+ label: "Brand scrim",
5010
+ designPatch: { imageSurfaceTreatment: {
5011
+ kind: "brand-scrim",
5012
+ token: "primary"
5013
+ } }
5014
+ }, {
5015
+ id: "neutral-scrim",
5016
+ label: "Neutral scrim",
5017
+ designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
5018
+ }]
5019
+ }];
5020
+ const microBannerLayoutPatches = [{
5021
+ constraints: { layoutVariantKeys: ["micro"] },
5022
+ designPatch: { sectionHeight: "banner" }
5023
+ }];
5024
+ defineBlockAppearancePreset({
5025
+ id: "hero-immersive-image",
5026
+ target: "hero",
5027
+ label: "Immersive image hero",
5028
+ blockKinds: ["block.hero"],
5029
+ constraints: { layoutFamilies: ["centered", "compact"] },
5030
+ layoutPatches: [{
5031
+ constraints: { layoutVariantKeys: ["micro"] },
5032
+ designPatch: {
5033
+ sectionHeight: "banner",
5034
+ heroTypographyScale: "display"
4916
5035
  }
4917
- }),
4918
- defineBlockAppearancePreset({
4919
- kind: "block-design",
4920
- id: "hero-bottom-left-panel",
4921
- target: "hero",
4922
- label: "Bottom-left panel hero",
4923
- blockKinds: ["block.hero"],
4924
- constraints: { layoutFamilies: ["centered", "compact"] },
4925
- optionGroups: [{
4926
- id: "image-surface-treatment",
4927
- label: "Treatment",
4928
- selectedOptionId: "neutral-scrim",
4929
- options: [{
4930
- id: "neutral-scrim",
4931
- label: "Neutral scrim",
4932
- designPatch: { imageSurfaceTreatment: {
4933
- kind: "neutral-scrim",
4934
- intensity: "balanced"
4935
- } }
4936
- }, {
4937
- id: "brand-scrim-primary",
4938
- label: "Brand scrim",
4939
- designPatch: { imageSurfaceTreatment: {
4940
- kind: "brand-scrim",
4941
- token: "primary",
4942
- intensity: "balanced"
4943
- } }
4944
- }]
4945
- }],
4946
- layoutPatches: [{
4947
- constraints: { layoutVariantKeys: ["micro"] },
4948
- designPatch: {
4949
- sectionHeight: "banner",
4950
- heroTypographyScale: "editorial"
4951
- }
4952
- }],
4953
- design: {
4954
- sectionSurface: "hero-image",
4955
- contentFrame: panelFrame("raised"),
4956
- itemSurface: "none",
4957
- sectionHeight: "immersive",
4958
- heroComposition: "bottom-left",
4959
- heroTypographyScale: "display",
4960
- imageSurfaceTreatment: {
5036
+ }],
5037
+ design: {
5038
+ sectionSurface: "hero-image",
5039
+ contentFrame: plainFrame,
5040
+ itemSurface: "none",
5041
+ sectionHeight: "hero",
5042
+ heroComposition: "center",
5043
+ heroTypographyScale: "display",
5044
+ imageSurfaceTreatment: { kind: "neutral-wash" }
5045
+ }
5046
+ }), defineBlockAppearancePreset({
5047
+ id: "hero-bottom-left-panel",
5048
+ target: "hero",
5049
+ label: "Bottom-left panel hero",
5050
+ blockKinds: ["block.hero"],
5051
+ constraints: { layoutFamilies: ["centered", "compact"] },
5052
+ optionGroups: [{
5053
+ id: "image-surface-treatment",
5054
+ label: "Treatment",
5055
+ defaultOptionId: "neutral-scrim",
5056
+ options: [{
5057
+ id: "neutral-scrim",
5058
+ label: "Neutral scrim",
5059
+ designPatch: { imageSurfaceTreatment: {
4961
5060
  kind: "neutral-scrim",
4962
5061
  intensity: "balanced"
4963
- }
4964
- }
4965
- }),
4966
- defineBlockAppearancePreset({
4967
- kind: "block-design",
4968
- id: "hero-poster-image",
4969
- target: "hero",
4970
- label: "Poster image hero",
4971
- blockKinds: ["block.hero"],
4972
- constraints: { layoutFamilies: ["centered", "compact"] },
4973
- layoutPatches: [{
4974
- constraints: { layoutVariantKeys: ["micro"] },
4975
- designPatch: {
4976
- sectionHeight: "banner",
4977
- heroTypographyScale: "display"
4978
- }
4979
- }],
4980
- design: {
4981
- sectionSurface: "hero-image",
4982
- contentFrame: plainFrame,
4983
- itemSurface: "none",
4984
- sectionHeight: "immersive",
4985
- heroComposition: "center",
4986
- heroTypographyScale: "poster",
4987
- imageSurfaceTreatment: {
5062
+ } }
5063
+ }, {
5064
+ id: "brand-scrim-primary",
5065
+ label: "Brand scrim",
5066
+ designPatch: { imageSurfaceTreatment: {
4988
5067
  kind: "brand-scrim",
4989
5068
  token: "primary",
4990
- intensity: "strong"
4991
- }
4992
- }
4993
- }),
4994
- defineBlockAppearancePreset({
4995
- kind: "block-design",
4996
- id: "hero-brand-scrim",
4997
- target: "hero",
4998
- label: "Brand scrim image hero",
4999
- blockKinds: ["block.hero"],
5000
- constraints: { layoutFamilies: ["centered", "compact"] },
5001
- optionGroups: [{
5002
- id: "image-surface-treatment",
5003
- label: "Treatment",
5004
- selectedOptionId: "brand-scrim-primary",
5005
- options: [{
5006
- id: "brand-scrim-primary",
5007
- label: "Brand scrim",
5008
- designPatch: { imageSurfaceTreatment: {
5009
- kind: "brand-scrim",
5010
- token: "primary"
5011
- } }
5012
- }, {
5013
- id: "neutral-scrim",
5014
- label: "Neutral scrim",
5015
- designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
5016
- }]
5017
- }],
5018
- layoutPatches: [{
5019
- constraints: { layoutVariantKeys: ["micro"] },
5020
- designPatch: { sectionHeight: "banner" }
5021
- }],
5022
- design: {
5023
- sectionSurface: "hero-image",
5024
- contentFrame: plainFrame,
5025
- itemSurface: "none",
5026
- sectionHeight: "immersive",
5027
- heroComposition: "center",
5028
- heroTypographyScale: "display",
5029
- imageSurfaceTreatment: {
5030
- kind: "brand-scrim",
5031
- token: "primary"
5032
- }
5033
- }
5034
- }),
5035
- defineBlockAppearancePreset({
5036
- kind: "block-design",
5037
- id: "hero-brand-scrim-fixed-frame",
5038
- target: "hero",
5039
- label: "Fixed-frame brand scrim hero",
5040
- blockKinds: ["block.hero"],
5041
- constraints: { layoutFamilies: ["centered", "compact"] },
5042
- optionGroups: [{
5043
- id: "image-surface-treatment",
5044
- label: "Treatment",
5045
- selectedOptionId: "brand-scrim-primary",
5046
- options: [{
5047
- id: "brand-scrim-primary",
5048
- label: "Brand scrim",
5049
- designPatch: { imageSurfaceTreatment: {
5050
- kind: "brand-scrim",
5051
- token: "primary"
5052
- } }
5053
- }, {
5054
- id: "neutral-scrim",
5055
- label: "Neutral scrim",
5056
- designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
5057
- }]
5058
- }],
5059
- layoutPatches: [{
5060
- constraints: { layoutVariantKeys: ["micro"] },
5061
- designPatch: { sectionHeight: "banner" }
5062
- }],
5063
- design: {
5064
- sectionSurface: "hero-image",
5065
- contentFrame: plainFrame,
5066
- itemSurface: "none",
5067
- sectionHeight: "immersive",
5068
- heroComposition: "center",
5069
- heroTypographyScale: "display",
5070
- imageSurfaceTreatment: {
5071
- kind: "brand-scrim",
5072
- token: "primary"
5073
- },
5074
- imageSurfaceMotion: "fixed-frame",
5075
- eyebrowTreatment: "accent-pill-bounce"
5076
- }
5077
- }),
5078
- defineBlockAppearancePreset({
5079
- kind: "block-design",
5080
- id: "hero-brand-depth-expressive",
5081
- target: "hero",
5082
- label: "Expressive brand-depth hero",
5083
- blockKinds: ["block.hero"],
5084
- constraints: { layoutFamilies: ["centered", "compact"] },
5085
- design: {
5086
- sectionSurface: "brand-depth-band",
5087
- contentFrame: plainFrame,
5088
- itemSurface: "none",
5089
- heroComposition: "center",
5090
- heroTypographyScale: "editorial",
5091
- eyebrowTreatment: "accent-pill-bounce"
5092
- }
5093
- }),
5094
- defineBlockAppearancePreset({
5095
- kind: "block-design",
5096
- id: "hero-contained-intro",
5097
- target: "hero",
5098
- label: "Contained intro hero",
5099
- blockKinds: ["block.hero"],
5100
- design: {
5101
- sectionSurface: "muted-band",
5102
- contentFrame: panelFrame("inset"),
5103
- itemSurface: "none",
5104
- heroComposition: "center",
5105
- heroTypographyScale: "editorial"
5106
- }
5107
- }),
5108
- defineBlockAppearancePreset({
5109
- kind: "block-design",
5110
- id: "hero-split-editorial",
5111
- target: "hero",
5112
- label: "Editorial split hero",
5113
- blockKinds: ["block.hero"],
5114
- constraints: { layoutFamilies: ["split"] },
5115
- design: {
5116
- sectionSurface: "base",
5117
- contentFrame: plainFrame,
5118
- itemSurface: "none",
5119
- heroTypographyScale: "editorial"
5120
- }
5121
- }),
5122
- defineBlockAppearancePreset({
5123
- kind: "block-design",
5124
- id: "hero-split-brand",
5125
- target: "hero",
5126
- label: "Brand split hero",
5127
- blockKinds: ["block.hero"],
5128
- constraints: { layoutFamilies: ["split"] },
5129
- design: {
5130
- sectionSurface: "brand-depth-band",
5131
- contentFrame: plainFrame,
5132
- itemSurface: "none",
5133
- heroTypographyScale: "display",
5134
- eyebrowTreatment: "accent-pill-bounce"
5135
- }
5136
- }),
5137
- defineBlockAppearancePreset({
5138
- kind: "block-design",
5139
- id: "hero-split-soft-panel",
5140
- target: "hero",
5141
- label: "Soft panel split hero",
5142
- blockKinds: ["block.hero"],
5143
- constraints: { layoutFamilies: ["split"] },
5144
- design: {
5145
- sectionSurface: "muted-band",
5146
- contentFrame: panelFrame("raised"),
5147
- itemSurface: "none",
5069
+ intensity: "balanced"
5070
+ } }
5071
+ }]
5072
+ }],
5073
+ layoutPatches: [{
5074
+ constraints: { layoutVariantKeys: ["micro"] },
5075
+ designPatch: {
5076
+ sectionHeight: "banner",
5148
5077
  heroTypographyScale: "editorial"
5149
5078
  }
5150
- }),
5151
- defineBlockAppearancePreset({
5152
- kind: "block-design",
5153
- id: "hero-split-accent",
5154
- target: "hero",
5155
- label: "Accent split hero",
5156
- blockKinds: ["block.hero"],
5157
- constraints: { layoutFamilies: ["split"] },
5158
- design: {
5159
- sectionSurface: "accent-band",
5160
- contentFrame: panelFrame("raised"),
5161
- itemSurface: "none",
5079
+ }],
5080
+ design: {
5081
+ sectionSurface: "hero-image",
5082
+ contentFrame: panelFrame("raised"),
5083
+ itemSurface: "none",
5084
+ sectionHeight: "immersive",
5085
+ heroComposition: "bottom-left",
5086
+ heroTypographyScale: "display",
5087
+ imageSurfaceTreatment: {
5088
+ kind: "neutral-scrim",
5089
+ intensity: "balanced"
5090
+ }
5091
+ }
5092
+ }), defineBlockAppearancePreset({
5093
+ id: "hero-poster-image",
5094
+ target: "hero",
5095
+ label: "Poster image hero",
5096
+ blockKinds: ["block.hero"],
5097
+ constraints: { layoutFamilies: ["centered", "compact"] },
5098
+ layoutPatches: [{
5099
+ constraints: { layoutVariantKeys: ["micro"] },
5100
+ designPatch: {
5101
+ sectionHeight: "banner",
5162
5102
  heroTypographyScale: "display"
5163
5103
  }
5164
- }),
5165
- defineBlockAppearancePreset({
5166
- kind: "block-design",
5167
- id: "intro-editorial-statement",
5168
- target: "intro",
5169
- label: "Editorial intro statement",
5170
- blockKinds: ["block.intro"],
5171
- constraints: { layoutVariantKeys: ["centered-copy", "statement-copy"] },
5172
- design: {
5173
- sectionSurface: "base",
5174
- contentFrame: plainFrame,
5175
- itemSurface: "none",
5176
- composition: {
5177
- kind: "intro",
5178
- treatment: "editorial-statement"
5179
- }
5180
- }
5181
- }),
5182
- defineBlockAppearancePreset({
5183
- kind: "block-design",
5184
- id: "intro-portrait-bio",
5185
- target: "intro",
5186
- label: "Portrait and bio",
5187
- blockKinds: ["block.intro"],
5188
- constraints: { layoutVariantKeys: ["media-copy"] },
5189
- design: {
5190
- sectionSurface: "base",
5191
- contentFrame: plainFrame,
5192
- itemSurface: "none",
5193
- composition: {
5194
- kind: "intro",
5195
- treatment: "portrait-bio"
5196
- }
5197
- }
5198
- }),
5199
- defineBlockAppearancePreset({
5200
- kind: "block-design",
5201
- id: "offerings-preview-default-cards",
5202
- target: "offerings",
5203
- label: "Default offering cards",
5204
- blockKinds: ["block.offerings-preview"],
5205
- design: {
5206
- sectionSurface: "base",
5207
- contentFrame: plainFrame,
5208
- itemSurface: "default"
5209
- }
5210
- }),
5211
- defineBlockAppearancePreset({
5212
- kind: "block-design",
5213
- id: "offerings-preview-secondary-cards",
5214
- target: "offerings",
5215
- label: "Secondary offering cards",
5216
- blockKinds: ["block.offerings-preview"],
5217
- design: {
5218
- sectionSurface: "muted-band",
5219
- contentFrame: plainFrame,
5220
- itemSurface: "inset"
5221
- }
5222
- }),
5223
- defineBlockAppearancePreset({
5224
- kind: "block-design",
5225
- id: "offerings-preview-non-carded",
5226
- target: "offerings",
5227
- label: "Non-carded offerings",
5228
- blockKinds: ["block.offerings-preview"],
5229
- design: {
5230
- sectionSurface: "muted-band",
5231
- contentFrame: plainFrame,
5232
- itemSurface: "editorial"
5233
- }
5234
- }),
5235
- defineBlockAppearancePreset({
5236
- kind: "block-design",
5237
- id: "offerings-preview-paired-feature-cards",
5238
- target: "offerings",
5239
- label: "Paired feature cards",
5240
- blockKinds: ["block.offerings-preview"],
5241
- constraints: { layoutVariantKeys: ["cards"] },
5242
- design: {
5243
- sectionSurface: "base",
5244
- contentFrame: plainFrame,
5245
- itemSurface: "none"
5246
- }
5247
- }),
5248
- defineBlockAppearancePreset({
5249
- kind: "block-design",
5250
- id: "offerings-preview-open-editorial-columns",
5251
- target: "offerings",
5252
- label: "Open editorial columns",
5253
- blockKinds: ["block.offerings-preview"],
5254
- constraints: { layoutVariantKeys: ["cards"] },
5255
- design: {
5256
- sectionSurface: "base",
5257
- contentFrame: plainFrame,
5258
- itemSurface: "none"
5259
- }
5260
- }),
5261
- defineBlockAppearancePreset({
5262
- kind: "block-design",
5263
- id: "offerings-preview-joined-programme-panel",
5264
- target: "offerings",
5265
- label: "Joined programme panel",
5266
- blockKinds: ["block.offerings-preview"],
5267
- constraints: { layoutVariantKeys: ["cards"] },
5268
- design: {
5269
- sectionSurface: "base",
5270
- contentFrame: plainFrame,
5271
- itemSurface: "none"
5272
- }
5273
- }),
5274
- defineBlockAppearancePreset({
5275
- kind: "block-design",
5276
- id: "feature-cards-raised-rule",
5277
- target: "feature-cards",
5278
- label: "Raised cards with rule",
5279
- blockKinds: ["block.feature-cards"],
5280
- design: {
5281
- sectionSurface: "base",
5282
- contentFrame: plainFrame,
5283
- itemSurface: "raised"
5284
- }
5285
- }),
5286
- defineBlockAppearancePreset({
5287
- kind: "block-design",
5288
- id: "feature-cards-bold-colors",
5289
- target: "feature-cards",
5290
- label: "Bold colour-blocked cards",
5291
- blockKinds: ["block.feature-cards"],
5292
- design: {
5293
- sectionSurface: "base",
5294
- contentFrame: plainFrame,
5295
- itemSurface: "color-blocked"
5296
- }
5297
- }),
5298
- defineBlockAppearancePreset({
5299
- kind: "block-design",
5300
- id: "feature-cards-editorial-columns",
5301
- target: "feature-cards",
5302
- label: "Editorial open columns",
5303
- blockKinds: ["block.feature-cards"],
5304
- design: {
5305
- sectionSurface: "base",
5306
- contentFrame: plainFrame,
5307
- itemSurface: "editorial"
5308
- }
5309
- }),
5310
- defineBlockAppearancePreset({
5311
- kind: "block-design",
5312
- id: "feature-cards-asymmetric-emphasis",
5313
- target: "feature-cards",
5314
- label: "Asymmetric emphasis pair",
5315
- blockKinds: ["block.feature-cards"],
5316
- constraints: { layoutFamilies: ["grid"] },
5317
- design: {
5318
- sectionSurface: "base",
5319
- contentFrame: plainFrame,
5320
- itemSurface: "none",
5321
- composition: {
5322
- kind: "feature-cards",
5323
- treatment: "asymmetric-emphasis"
5324
- }
5325
- }
5326
- }),
5327
- defineBlockAppearancePreset({
5328
- kind: "block-design",
5329
- id: "feature-cards-framed-programme",
5330
- target: "feature-cards",
5331
- label: "Framed programme cards",
5332
- blockKinds: ["block.feature-cards"],
5333
- constraints: { layoutFamilies: ["grid"] },
5334
- design: {
5335
- sectionSurface: "brand-depth-band",
5336
- contentFrame: plainFrame,
5337
- itemSurface: "inset",
5338
- composition: {
5339
- kind: "feature-cards",
5340
- treatment: "framed-programme"
5341
- }
5342
- }
5343
- }),
5344
- defineBlockAppearancePreset({
5345
- kind: "block-design",
5346
- id: "feature-cards-soft-panels",
5347
- target: "feature-cards",
5348
- label: "Soft tinted panels",
5349
- blockKinds: ["block.feature-cards"],
5350
- design: {
5351
- sectionSurface: "base",
5352
- contentFrame: plainFrame,
5353
- itemSurface: "inset"
5354
- }
5355
- }),
5356
- defineBlockAppearancePreset({
5357
- kind: "block-design",
5358
- id: "feature-cards-editorial-diptych",
5359
- target: "feature-cards",
5360
- label: "Editorial diptych",
5361
- blockKinds: ["block.feature-cards"],
5362
- constraints: { layoutVariantKeys: ["editorial-diptych"] },
5363
- design: {
5364
- sectionSurface: "base",
5365
- contentFrame: plainFrame,
5366
- itemSurface: "flat"
5367
- }
5368
- }),
5369
- defineBlockAppearancePreset({
5370
- kind: "block-design",
5371
- id: "feature-cards-editorial-pathways",
5372
- target: "feature-cards",
5373
- label: "Editorial pathways",
5374
- blockKinds: ["block.feature-cards"],
5375
- constraints: { layoutVariantKeys: ["editorial-pathways"] },
5376
- design: {
5377
- sectionSurface: "base",
5378
- contentFrame: plainFrame,
5379
- itemSurface: "flat"
5380
- }
5381
- }),
5382
- defineBlockAppearancePreset({
5383
- kind: "block-design",
5384
- id: "feature-cards-photo-tiles",
5385
- target: "feature-cards",
5386
- label: "Photo tiles",
5387
- blockKinds: ["block.feature-cards"],
5388
- design: {
5389
- sectionSurface: "base",
5390
- contentFrame: plainFrame,
5391
- itemSurface: "raised"
5392
- }
5393
- }),
5394
- defineBlockAppearancePreset({
5395
- kind: "block-design",
5396
- id: "events-lined-panel",
5397
- target: "events",
5398
- label: "Raised event panel",
5399
- blockKinds: ["block.event-calendar", "block.event-listing"],
5400
- design: {
5401
- sectionSurface: "base",
5402
- contentFrame: panelFrame("raised"),
5403
- itemSurface: "none"
5404
- }
5405
- }),
5406
- defineBlockAppearancePreset({
5407
- kind: "block-design",
5408
- id: "events-ruled-register",
5409
- target: "events",
5410
- label: "Ruled event register",
5411
- blockKinds: ["block.event-calendar", "block.event-listing"],
5412
- design: {
5413
- sectionSurface: "brand-depth-band",
5414
- contentFrame: plainFrame,
5415
- itemSurface: "none",
5416
- eventListTreatment: "ruled-register"
5417
- }
5418
- }),
5419
- defineBlockAppearancePreset({
5420
- kind: "block-design",
5421
- id: "events-editorial-register",
5422
- target: "events",
5423
- label: "Editorial event register",
5424
- blockKinds: ["block.event-calendar", "block.event-listing"],
5425
- design: {
5426
- sectionSurface: "base",
5427
- contentFrame: plainFrame,
5428
- itemSurface: "none",
5429
- eventListTreatment: "editorial-register"
5430
- }
5431
- }),
5432
- defineBlockAppearancePreset({
5433
- kind: "block-design",
5434
- id: "events-dense-index",
5435
- target: "events",
5436
- label: "Dense event index",
5437
- blockKinds: ["block.event-calendar", "block.event-listing"],
5438
- design: {
5439
- sectionSurface: "accent-band",
5440
- contentFrame: plainFrame,
5441
- itemSurface: "none",
5442
- eventListTreatment: "dense-index"
5443
- }
5444
- }),
5445
- defineBlockAppearancePreset({
5446
- kind: "block-design",
5447
- id: "schedule-details-brand-depth",
5448
- target: "events",
5449
- label: "Brand-depth schedule details",
5450
- blockKinds: ["block.event-details", "block.course-details"],
5451
- design: {
5452
- sectionSurface: "brand-depth-band",
5453
- contentFrame: plainFrame,
5454
- itemSurface: "none",
5455
- tileTreatment: "brand-depth"
5456
- }
5457
- }),
5458
- defineBlockAppearancePreset({
5459
- kind: "block-design",
5460
- id: "media-text-flush-feature",
5461
- target: "media-text",
5462
- label: "Flush media feature",
5463
- blockKinds: ["block.media-text"],
5464
- design: {
5465
- sectionSurface: "muted-band",
5466
- contentFrame: flushPanelFrame({ bleed: "start" }),
5467
- itemSurface: "none"
5468
- }
5469
- }),
5470
- defineBlockAppearancePreset({
5471
- kind: "block-design",
5472
- id: "testimonials-simple-cards",
5473
- target: "testimonials",
5474
- label: "Simple testimonial cards",
5475
- blockKinds: ["block.testimonials"],
5476
- design: {
5477
- sectionSurface: "base",
5478
- contentFrame: plainFrame,
5479
- itemSurface: "default"
5480
- }
5481
- }),
5482
- defineBlockAppearancePreset({
5483
- kind: "block-design",
5484
- id: "testimonials-raised-panel",
5485
- target: "testimonials",
5486
- label: "Raised testimonial panel",
5487
- blockKinds: ["block.testimonials"],
5488
- design: {
5489
- sectionSurface: "muted-band",
5490
- contentFrame: panelFrame("raised"),
5491
- itemSurface: "raised"
5492
- }
5493
- }),
5494
- defineBlockAppearancePreset({
5495
- kind: "block-design",
5496
- id: "testimonials-accent-panel",
5497
- target: "testimonials",
5498
- label: "Accent testimonial panel",
5499
- blockKinds: ["block.testimonials"],
5500
- design: {
5501
- sectionSurface: "accent-band",
5502
- contentFrame: panelFrame("raised"),
5503
- itemSurface: "raised"
5504
- }
5505
- }),
5506
- defineBlockAppearancePreset({
5507
- kind: "block-design",
5508
- id: "testimonials-default-cards",
5509
- target: "testimonials",
5510
- label: "Default cards",
5511
- blockKinds: ["block.testimonials"],
5512
- design: {
5513
- sectionSurface: "base",
5514
- contentFrame: plainFrame,
5515
- itemSurface: "none",
5516
- testimonialCardTreatment: "default"
5517
- }
5518
- }),
5519
- defineBlockAppearancePreset({
5520
- kind: "block-design",
5521
- id: "testimonials-statement-cards",
5522
- target: "testimonials",
5523
- label: "Statement cards",
5524
- blockKinds: ["block.testimonials"],
5525
- design: {
5526
- sectionSurface: "accent-band",
5527
- contentFrame: plainFrame,
5528
- itemSurface: "raised",
5529
- testimonialCardTreatment: "statement"
5530
- }
5531
- }),
5532
- defineBlockAppearancePreset({
5533
- kind: "block-design",
5534
- id: "testimonials-brand-statement-cards",
5535
- target: "testimonials",
5536
- label: "Brand statement cards",
5537
- blockKinds: ["block.testimonials"],
5538
- design: {
5539
- sectionSurface: "brand-depth-band",
5540
- contentFrame: plainFrame,
5541
- itemSurface: "raised",
5542
- testimonialCardTreatment: "statement"
5543
- }
5544
- }),
5545
- defineBlockAppearancePreset({
5546
- kind: "block-design",
5547
- id: "testimonials-non-carded",
5548
- target: "testimonials",
5549
- label: "Non-carded",
5550
- blockKinds: ["block.testimonials"],
5551
- design: {
5552
- sectionSurface: "muted-band",
5553
- contentFrame: plainFrame,
5554
- itemSurface: "none",
5555
- testimonialCardTreatment: "non-carded"
5556
- }
5557
- }),
5558
- defineBlockAppearancePreset({
5559
- kind: "block-design",
5560
- id: "testimonials-evergreen-lead",
5561
- target: "testimonials",
5562
- label: "Evergreen lead",
5563
- blockKinds: ["block.testimonials"],
5564
- constraints: { layoutVariantKeys: ["featured-editorial"] },
5565
- design: {
5566
- sectionSurface: "base",
5567
- contentFrame: plainFrame,
5568
- itemSurface: "none"
5569
- }
5570
- }),
5571
- defineBlockAppearancePreset({
5572
- kind: "block-design",
5573
- id: "testimonials-room-and-response",
5574
- target: "testimonials",
5575
- label: "Room and response",
5576
- blockKinds: ["block.testimonials"],
5577
- constraints: { layoutVariantKeys: ["featured-editorial"] },
5578
- design: {
5579
- sectionSurface: "base",
5580
- contentFrame: plainFrame,
5581
- itemSurface: "none"
5582
- }
5583
- }),
5584
- defineBlockAppearancePreset({
5585
- kind: "block-design",
5586
- id: "testimonials-open-floor",
5587
- target: "testimonials",
5588
- label: "Open floor",
5589
- blockKinds: ["block.testimonials"],
5590
- constraints: { layoutVariantKeys: ["featured-editorial"] },
5591
- design: {
5592
- sectionSurface: "base",
5593
- contentFrame: plainFrame,
5594
- itemSurface: "none"
5595
- }
5596
- }),
5597
- defineBlockAppearancePreset({
5598
- kind: "block-design",
5599
- id: "faq-base-accordion",
5600
- target: "faq",
5601
- label: "Base accordion FAQ",
5602
- blockKinds: ["block.faq"],
5603
- design: {
5604
- sectionSurface: "base",
5605
- contentFrame: plainFrame,
5606
- itemSurface: "default"
5607
- }
5608
- }),
5609
- defineBlockAppearancePreset({
5610
- kind: "block-design",
5611
- id: "faq-contained-help",
5612
- target: "faq",
5613
- label: "Contained help panel",
5614
- blockKinds: ["block.faq"],
5615
- design: {
5616
- sectionSurface: "muted-band",
5617
- contentFrame: panelFrame("inset"),
5618
- itemSurface: "default"
5619
- }
5620
- }),
5621
- defineBlockAppearancePreset({
5622
- kind: "block-design",
5623
- id: "contact-form-panel",
5624
- target: "contact-form",
5625
- label: "Raised form panel",
5626
- blockKinds: ["block.form"],
5627
- design: {
5628
- sectionSurface: "muted-band",
5629
- contentFrame: panelFrame("raised"),
5630
- itemSurface: "none"
5631
- }
5632
- }),
5633
- defineBlockAppearancePreset({
5634
- kind: "block-design",
5635
- id: "cta-accent-band",
5636
- target: "cta",
5637
- label: "Accent CTA band",
5638
- blockKinds: ["block.cta-full"],
5639
- design: {
5640
- sectionSurface: "accent-band",
5641
- contentFrame: plainFrame,
5642
- itemSurface: "none",
5643
- eyebrowTreatment: "accent"
5644
- }
5645
- })
5646
- ]];
5104
+ }],
5105
+ design: {
5106
+ sectionSurface: "hero-image",
5107
+ contentFrame: plainFrame,
5108
+ itemSurface: "none",
5109
+ sectionHeight: "immersive",
5110
+ heroComposition: "center",
5111
+ heroTypographyScale: "poster",
5112
+ imageSurfaceTreatment: {
5113
+ kind: "brand-scrim",
5114
+ token: "primary",
5115
+ intensity: "strong"
5116
+ }
5117
+ }
5118
+ }), defineBlockAppearancePreset({
5119
+ id: "hero-brand-scrim",
5120
+ target: "hero",
5121
+ label: "Brand scrim image hero",
5122
+ blockKinds: ["block.hero"],
5123
+ constraints: { layoutFamilies: ["centered", "compact"] },
5124
+ optionGroups: brandScrimOptionGroups,
5125
+ layoutPatches: microBannerLayoutPatches,
5126
+ design: {
5127
+ sectionSurface: "hero-image",
5128
+ contentFrame: plainFrame,
5129
+ itemSurface: "none",
5130
+ sectionHeight: "immersive",
5131
+ heroComposition: "center",
5132
+ heroTypographyScale: "display",
5133
+ imageSurfaceTreatment: {
5134
+ kind: "brand-scrim",
5135
+ token: "primary"
5136
+ }
5137
+ }
5138
+ }), defineBlockAppearancePreset({
5139
+ id: "hero-brand-scrim-fixed-frame",
5140
+ target: "hero",
5141
+ label: "Fixed-frame brand scrim hero",
5142
+ blockKinds: ["block.hero"],
5143
+ constraints: { layoutFamilies: ["centered", "compact"] },
5144
+ optionGroups: brandScrimOptionGroups,
5145
+ layoutPatches: microBannerLayoutPatches,
5146
+ design: {
5147
+ sectionSurface: "hero-image",
5148
+ contentFrame: plainFrame,
5149
+ itemSurface: "none",
5150
+ sectionHeight: "immersive",
5151
+ heroComposition: "center",
5152
+ heroTypographyScale: "display",
5153
+ imageSurfaceTreatment: {
5154
+ kind: "brand-scrim",
5155
+ token: "primary"
5156
+ },
5157
+ imageSurfaceMotion: "fixed-frame",
5158
+ eyebrowTreatment: "accent-pill-bounce"
5159
+ }
5160
+ }), defineBlockAppearancePreset({
5161
+ id: "hero-brand-depth-expressive",
5162
+ target: "hero",
5163
+ label: "Expressive brand-depth hero",
5164
+ blockKinds: ["block.hero"],
5165
+ constraints: { layoutFamilies: ["centered", "compact"] },
5166
+ design: {
5167
+ sectionSurface: "brand-depth-band",
5168
+ contentFrame: plainFrame,
5169
+ itemSurface: "none",
5170
+ heroComposition: "center",
5171
+ heroTypographyScale: "editorial",
5172
+ eyebrowTreatment: "accent-pill-bounce"
5173
+ }
5174
+ }), defineBlockAppearancePreset({
5175
+ id: "hero-contained-intro",
5176
+ target: "hero",
5177
+ label: "Contained intro hero",
5178
+ blockKinds: ["block.hero"],
5179
+ design: {
5180
+ sectionSurface: "muted-band",
5181
+ contentFrame: panelFrame("inset"),
5182
+ itemSurface: "none",
5183
+ heroComposition: "center",
5184
+ heroTypographyScale: "editorial"
5185
+ }
5186
+ }), defineBlockAppearancePreset({
5187
+ id: "hero-split-editorial",
5188
+ target: "hero",
5189
+ label: "Editorial split hero",
5190
+ blockKinds: ["block.hero"],
5191
+ constraints: { layoutFamilies: ["split"] },
5192
+ design: {
5193
+ sectionSurface: "base",
5194
+ contentFrame: plainFrame,
5195
+ itemSurface: "none",
5196
+ heroTypographyScale: "editorial"
5197
+ }
5198
+ }), defineBlockAppearancePreset({
5199
+ id: "hero-split-brand",
5200
+ target: "hero",
5201
+ label: "Brand split hero",
5202
+ blockKinds: ["block.hero"],
5203
+ constraints: { layoutFamilies: ["split"] },
5204
+ design: {
5205
+ sectionSurface: "brand-depth-band",
5206
+ contentFrame: plainFrame,
5207
+ itemSurface: "none",
5208
+ heroTypographyScale: "display",
5209
+ eyebrowTreatment: "accent-pill-bounce"
5210
+ }
5211
+ }), defineBlockAppearancePreset({
5212
+ id: "hero-split-soft-panel",
5213
+ target: "hero",
5214
+ label: "Soft panel split hero",
5215
+ blockKinds: ["block.hero"],
5216
+ constraints: { layoutFamilies: ["split"] },
5217
+ design: {
5218
+ sectionSurface: "muted-band",
5219
+ contentFrame: panelFrame("raised"),
5220
+ itemSurface: "none",
5221
+ heroTypographyScale: "editorial"
5222
+ }
5223
+ }), defineBlockAppearancePreset({
5224
+ id: "hero-split-accent",
5225
+ target: "hero",
5226
+ label: "Accent split hero",
5227
+ blockKinds: ["block.hero"],
5228
+ constraints: { layoutFamilies: ["split"] },
5229
+ design: {
5230
+ sectionSurface: "accent-band",
5231
+ contentFrame: panelFrame("raised"),
5232
+ itemSurface: "none",
5233
+ heroTypographyScale: "display"
5234
+ }
5235
+ }), defineBlockAppearancePreset({
5236
+ id: "intro-editorial-statement",
5237
+ target: "intro",
5238
+ label: "Editorial intro statement",
5239
+ blockKinds: ["block.intro"],
5240
+ constraints: { layoutVariantKeys: ["centered-copy", "statement-copy"] },
5241
+ design: {
5242
+ sectionSurface: "base",
5243
+ contentFrame: plainFrame,
5244
+ itemSurface: "none",
5245
+ composition: {
5246
+ kind: "intro",
5247
+ treatment: "editorial-statement"
5248
+ }
5249
+ }
5250
+ }), defineBlockAppearancePreset({
5251
+ id: "intro-portrait-bio",
5252
+ target: "intro",
5253
+ label: "Portrait and bio",
5254
+ blockKinds: ["block.intro"],
5255
+ constraints: { layoutVariantKeys: ["media-copy"] },
5256
+ design: {
5257
+ sectionSurface: "base",
5258
+ contentFrame: plainFrame,
5259
+ itemSurface: "none",
5260
+ composition: {
5261
+ kind: "intro",
5262
+ treatment: "portrait-bio"
5263
+ }
5264
+ }
5265
+ }), defineBlockAppearancePreset({
5266
+ id: "offerings-preview-default-cards",
5267
+ target: "offerings",
5268
+ label: "Default offering cards",
5269
+ blockKinds: ["block.offerings-preview"],
5270
+ design: {
5271
+ sectionSurface: "base",
5272
+ contentFrame: plainFrame,
5273
+ itemSurface: "default"
5274
+ }
5275
+ }), defineBlockAppearancePreset({
5276
+ id: "offerings-preview-secondary-cards",
5277
+ target: "offerings",
5278
+ label: "Secondary offering cards",
5279
+ blockKinds: ["block.offerings-preview"],
5280
+ design: {
5281
+ sectionSurface: "muted-band",
5282
+ contentFrame: plainFrame,
5283
+ itemSurface: "inset"
5284
+ }
5285
+ }), defineBlockAppearancePreset({
5286
+ id: "offerings-preview-non-carded",
5287
+ target: "offerings",
5288
+ label: "Non-carded offerings",
5289
+ blockKinds: ["block.offerings-preview"],
5290
+ design: {
5291
+ sectionSurface: "muted-band",
5292
+ contentFrame: plainFrame,
5293
+ itemSurface: "editorial"
5294
+ }
5295
+ }), defineBlockAppearancePreset({
5296
+ id: "offerings-preview-paired-feature-cards",
5297
+ target: "offerings",
5298
+ label: "Paired feature cards",
5299
+ blockKinds: ["block.offerings-preview"],
5300
+ constraints: { layoutVariantKeys: ["cards"] },
5301
+ design: {
5302
+ sectionSurface: "base",
5303
+ contentFrame: plainFrame,
5304
+ itemSurface: "none"
5305
+ }
5306
+ }), defineBlockAppearancePreset({
5307
+ id: "offerings-preview-open-editorial-columns",
5308
+ target: "offerings",
5309
+ label: "Open editorial columns",
5310
+ blockKinds: ["block.offerings-preview"],
5311
+ constraints: { layoutVariantKeys: ["cards"] },
5312
+ design: {
5313
+ sectionSurface: "base",
5314
+ contentFrame: plainFrame,
5315
+ itemSurface: "none"
5316
+ }
5317
+ }), defineBlockAppearancePreset({
5318
+ id: "offerings-preview-joined-programme-panel",
5319
+ target: "offerings",
5320
+ label: "Joined programme panel",
5321
+ blockKinds: ["block.offerings-preview"],
5322
+ constraints: { layoutVariantKeys: ["cards"] },
5323
+ design: {
5324
+ sectionSurface: "base",
5325
+ contentFrame: plainFrame,
5326
+ itemSurface: "none"
5327
+ }
5328
+ }), defineBlockAppearancePreset({
5329
+ id: "feature-cards-raised-rule",
5330
+ target: "feature-cards",
5331
+ label: "Raised cards with rule",
5332
+ blockKinds: ["block.feature-cards"],
5333
+ design: {
5334
+ sectionSurface: "base",
5335
+ contentFrame: plainFrame,
5336
+ itemSurface: "raised"
5337
+ }
5338
+ }), defineBlockAppearancePreset({
5339
+ id: "feature-cards-bold-colors",
5340
+ target: "feature-cards",
5341
+ label: "Bold colour-blocked cards",
5342
+ blockKinds: ["block.feature-cards"],
5343
+ design: {
5344
+ sectionSurface: "base",
5345
+ contentFrame: plainFrame,
5346
+ itemSurface: "color-blocked"
5347
+ }
5348
+ }), defineBlockAppearancePreset({
5349
+ id: "feature-cards-editorial-columns",
5350
+ target: "feature-cards",
5351
+ label: "Editorial open columns",
5352
+ blockKinds: ["block.feature-cards"],
5353
+ design: {
5354
+ sectionSurface: "base",
5355
+ contentFrame: plainFrame,
5356
+ itemSurface: "editorial"
5357
+ }
5358
+ }), defineBlockAppearancePreset({
5359
+ id: "feature-cards-asymmetric-emphasis",
5360
+ target: "feature-cards",
5361
+ label: "Asymmetric emphasis pair",
5362
+ blockKinds: ["block.feature-cards"],
5363
+ constraints: { layoutFamilies: ["grid"] },
5364
+ design: {
5365
+ sectionSurface: "base",
5366
+ contentFrame: plainFrame,
5367
+ itemSurface: "none",
5368
+ composition: {
5369
+ kind: "feature-cards",
5370
+ treatment: "asymmetric-emphasis"
5371
+ }
5372
+ }
5373
+ }), defineBlockAppearancePreset({
5374
+ id: "feature-cards-framed-programme",
5375
+ target: "feature-cards",
5376
+ label: "Framed programme cards",
5377
+ blockKinds: ["block.feature-cards"],
5378
+ constraints: { layoutFamilies: ["grid"] },
5379
+ design: {
5380
+ sectionSurface: "brand-depth-band",
5381
+ contentFrame: plainFrame,
5382
+ itemSurface: "inset",
5383
+ composition: {
5384
+ kind: "feature-cards",
5385
+ treatment: "framed-programme"
5386
+ }
5387
+ }
5388
+ }), defineBlockAppearancePreset({
5389
+ id: "feature-cards-soft-panels",
5390
+ target: "feature-cards",
5391
+ label: "Soft tinted panels",
5392
+ blockKinds: ["block.feature-cards"],
5393
+ design: {
5394
+ sectionSurface: "base",
5395
+ contentFrame: plainFrame,
5396
+ itemSurface: "inset"
5397
+ }
5398
+ }), defineBlockAppearancePreset({
5399
+ id: "feature-cards-editorial-diptych",
5400
+ target: "feature-cards",
5401
+ label: "Editorial diptych",
5402
+ blockKinds: ["block.feature-cards"],
5403
+ constraints: { layoutVariantKeys: ["editorial-diptych"] },
5404
+ design: {
5405
+ sectionSurface: "base",
5406
+ contentFrame: plainFrame,
5407
+ itemSurface: "flat"
5408
+ }
5409
+ }), defineBlockAppearancePreset({
5410
+ id: "feature-cards-editorial-pathways",
5411
+ target: "feature-cards",
5412
+ label: "Editorial pathways",
5413
+ blockKinds: ["block.feature-cards"],
5414
+ constraints: { layoutVariantKeys: ["editorial-pathways"] },
5415
+ design: {
5416
+ sectionSurface: "base",
5417
+ contentFrame: plainFrame,
5418
+ itemSurface: "flat"
5419
+ }
5420
+ }), defineBlockAppearancePreset({
5421
+ id: "feature-cards-photo-tiles",
5422
+ target: "feature-cards",
5423
+ label: "Photo tiles",
5424
+ blockKinds: ["block.feature-cards"],
5425
+ design: {
5426
+ sectionSurface: "base",
5427
+ contentFrame: plainFrame,
5428
+ itemSurface: "raised"
5429
+ }
5430
+ }), defineBlockAppearancePreset({
5431
+ id: "events-lined-panel",
5432
+ target: "events",
5433
+ label: "Raised event panel",
5434
+ blockKinds: ["block.event-calendar", "block.event-listing"],
5435
+ design: {
5436
+ sectionSurface: "base",
5437
+ contentFrame: panelFrame("raised"),
5438
+ itemSurface: "none"
5439
+ }
5440
+ }), defineBlockAppearancePreset({
5441
+ id: "events-ruled-register",
5442
+ target: "events",
5443
+ label: "Ruled event register",
5444
+ blockKinds: ["block.event-calendar", "block.event-listing"],
5445
+ design: {
5446
+ sectionSurface: "brand-depth-band",
5447
+ contentFrame: plainFrame,
5448
+ itemSurface: "none",
5449
+ eventListTreatment: "ruled-register"
5450
+ }
5451
+ }), defineBlockAppearancePreset({
5452
+ id: "events-editorial-register",
5453
+ target: "events",
5454
+ label: "Editorial event register",
5455
+ blockKinds: ["block.event-calendar", "block.event-listing"],
5456
+ design: {
5457
+ sectionSurface: "base",
5458
+ contentFrame: plainFrame,
5459
+ itemSurface: "none",
5460
+ eventListTreatment: "editorial-register"
5461
+ }
5462
+ }), defineBlockAppearancePreset({
5463
+ id: "events-dense-index",
5464
+ target: "events",
5465
+ label: "Dense event index",
5466
+ blockKinds: ["block.event-calendar", "block.event-listing"],
5467
+ design: {
5468
+ sectionSurface: "accent-band",
5469
+ contentFrame: plainFrame,
5470
+ itemSurface: "none",
5471
+ eventListTreatment: "dense-index"
5472
+ }
5473
+ }), defineBlockAppearancePreset({
5474
+ id: "schedule-details-brand-depth",
5475
+ target: "events",
5476
+ label: "Brand-depth schedule details",
5477
+ blockKinds: ["block.event-details", "block.course-details"],
5478
+ design: {
5479
+ sectionSurface: "brand-depth-band",
5480
+ contentFrame: plainFrame,
5481
+ itemSurface: "none",
5482
+ tileTreatment: "brand-depth"
5483
+ }
5484
+ }), defineBlockAppearancePreset({
5485
+ id: "media-text-flush-feature",
5486
+ target: "media-text",
5487
+ label: "Flush media feature",
5488
+ blockKinds: ["block.media-text"],
5489
+ design: {
5490
+ sectionSurface: "muted-band",
5491
+ contentFrame: flushPanelFrame({ bleed: "start" }),
5492
+ itemSurface: "none"
5493
+ }
5494
+ }), defineBlockAppearancePreset({
5495
+ id: "testimonials-simple-cards",
5496
+ target: "testimonials",
5497
+ label: "Simple testimonial cards",
5498
+ blockKinds: ["block.testimonials"],
5499
+ design: {
5500
+ sectionSurface: "base",
5501
+ contentFrame: plainFrame,
5502
+ itemSurface: "default"
5503
+ }
5504
+ }), defineBlockAppearancePreset({
5505
+ id: "testimonials-raised-panel",
5506
+ target: "testimonials",
5507
+ label: "Raised testimonial panel",
5508
+ blockKinds: ["block.testimonials"],
5509
+ design: {
5510
+ sectionSurface: "muted-band",
5511
+ contentFrame: panelFrame("raised"),
5512
+ itemSurface: "raised"
5513
+ }
5514
+ }), defineBlockAppearancePreset({
5515
+ id: "testimonials-accent-panel",
5516
+ target: "testimonials",
5517
+ label: "Accent testimonial panel",
5518
+ blockKinds: ["block.testimonials"],
5519
+ design: {
5520
+ sectionSurface: "accent-band",
5521
+ contentFrame: panelFrame("raised"),
5522
+ itemSurface: "raised"
5523
+ }
5524
+ }), defineBlockAppearancePreset({
5525
+ id: "testimonials-default-cards",
5526
+ target: "testimonials",
5527
+ label: "Default cards",
5528
+ blockKinds: ["block.testimonials"],
5529
+ design: {
5530
+ sectionSurface: "base",
5531
+ contentFrame: plainFrame,
5532
+ itemSurface: "none",
5533
+ testimonialCardTreatment: "default"
5534
+ }
5535
+ }), defineBlockAppearancePreset({
5536
+ id: "testimonials-statement-cards",
5537
+ target: "testimonials",
5538
+ label: "Statement cards",
5539
+ blockKinds: ["block.testimonials"],
5540
+ design: {
5541
+ sectionSurface: "accent-band",
5542
+ contentFrame: plainFrame,
5543
+ itemSurface: "raised",
5544
+ testimonialCardTreatment: "statement"
5545
+ }
5546
+ }), defineBlockAppearancePreset({
5547
+ id: "testimonials-brand-statement-cards",
5548
+ target: "testimonials",
5549
+ label: "Brand statement cards",
5550
+ blockKinds: ["block.testimonials"],
5551
+ design: {
5552
+ sectionSurface: "brand-depth-band",
5553
+ contentFrame: plainFrame,
5554
+ itemSurface: "raised",
5555
+ testimonialCardTreatment: "statement"
5556
+ }
5557
+ }), defineBlockAppearancePreset({
5558
+ id: "testimonials-non-carded",
5559
+ target: "testimonials",
5560
+ label: "Non-carded",
5561
+ blockKinds: ["block.testimonials"],
5562
+ design: {
5563
+ sectionSurface: "muted-band",
5564
+ contentFrame: plainFrame,
5565
+ itemSurface: "none",
5566
+ testimonialCardTreatment: "non-carded"
5567
+ }
5568
+ }), defineBlockAppearancePreset({
5569
+ id: "testimonials-evergreen-lead",
5570
+ target: "testimonials",
5571
+ label: "Evergreen lead",
5572
+ blockKinds: ["block.testimonials"],
5573
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
5574
+ design: {
5575
+ sectionSurface: "base",
5576
+ contentFrame: plainFrame,
5577
+ itemSurface: "none"
5578
+ }
5579
+ }), defineBlockAppearancePreset({
5580
+ id: "testimonials-room-and-response",
5581
+ target: "testimonials",
5582
+ label: "Room and response",
5583
+ blockKinds: ["block.testimonials"],
5584
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
5585
+ design: {
5586
+ sectionSurface: "base",
5587
+ contentFrame: plainFrame,
5588
+ itemSurface: "none"
5589
+ }
5590
+ }), defineBlockAppearancePreset({
5591
+ id: "testimonials-open-floor",
5592
+ target: "testimonials",
5593
+ label: "Open floor",
5594
+ blockKinds: ["block.testimonials"],
5595
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
5596
+ design: {
5597
+ sectionSurface: "base",
5598
+ contentFrame: plainFrame,
5599
+ itemSurface: "none"
5600
+ }
5601
+ }), defineBlockAppearancePreset({
5602
+ id: "faq-base-accordion",
5603
+ target: "faq",
5604
+ label: "Base accordion FAQ",
5605
+ blockKinds: ["block.faq"],
5606
+ design: {
5607
+ sectionSurface: "base",
5608
+ contentFrame: plainFrame,
5609
+ itemSurface: "default"
5610
+ }
5611
+ }), defineBlockAppearancePreset({
5612
+ id: "faq-contained-help",
5613
+ target: "faq",
5614
+ label: "Contained help panel",
5615
+ blockKinds: ["block.faq"],
5616
+ design: {
5617
+ sectionSurface: "muted-band",
5618
+ contentFrame: panelFrame("inset"),
5619
+ itemSurface: "default"
5620
+ }
5621
+ }), defineBlockAppearancePreset({
5622
+ id: "contact-form-panel",
5623
+ target: "contact-form",
5624
+ label: "Raised form panel",
5625
+ blockKinds: ["block.form"],
5626
+ design: {
5627
+ sectionSurface: "muted-band",
5628
+ contentFrame: panelFrame("raised"),
5629
+ itemSurface: "none"
5630
+ }
5631
+ }), defineBlockAppearancePreset({
5632
+ id: "cta-accent-band",
5633
+ target: "cta",
5634
+ label: "Accent CTA band",
5635
+ blockKinds: ["block.cta-full"],
5636
+ design: {
5637
+ sectionSurface: "accent-band",
5638
+ contentFrame: plainFrame,
5639
+ itemSurface: "none",
5640
+ eyebrowTreatment: "accent"
5641
+ }
5642
+ });
5647
5643
  //#endregion
5648
5644
  //#region ../theme-core/src/site-styles/headerCtaVariants.ts
5649
5645
  function hasButtonVariant(theme, variantId) {
@@ -7157,7 +7153,7 @@ function canonicalPaletteHashInput(colors, mode) {
7157
7153
  return `${mode}|${paletteColorFingerprint(colors)}`;
7158
7154
  }
7159
7155
  /**
7160
- * The shared TypeScript/SQL protocol. Do not reorder roles: the order comes
7156
+ * Stable curated-catalogue identity. Do not reorder roles: the order comes
7161
7157
  * from PALETTE_TOKEN_NAMES through canonicalPaletteHashInput.
7162
7158
  */
7163
7159
  function paletteValueKey(colors, mode) {
@@ -8727,6 +8723,32 @@ function parseBackgroundAppearanceColorToken(value) {
8727
8723
  function uniqueStrings(values) {
8728
8724
  return Array.from(new Set(values));
8729
8725
  }
8726
+ const headerInteractionPaletteSchema = z$1.enum([
8727
+ "primary",
8728
+ "secondary",
8729
+ "accent"
8730
+ ]);
8731
+ //#endregion
8732
+ //#region ../theme-core/src/site-styles/headerInteractionPalette.ts
8733
+ const clearSplitInteractionPalette = defineLookOptionGroup({
8734
+ id: "interaction-palette",
8735
+ label: "Hover colour",
8736
+ defaultOptionId: "accent",
8737
+ options: [
8738
+ {
8739
+ id: "accent",
8740
+ label: "Accent"
8741
+ },
8742
+ {
8743
+ id: "primary",
8744
+ label: "Primary"
8745
+ },
8746
+ {
8747
+ id: "secondary",
8748
+ label: "Secondary"
8749
+ }
8750
+ ]
8751
+ });
8730
8752
  //#endregion
8731
8753
  //#region ../theme-core/src/site-styles/logoBranding.ts
8732
8754
  const logoTextConfidenceValues = [
@@ -8949,7 +8971,7 @@ const overlayLogoAccommodations = [
8949
8971
  * optional nested styling fields that would otherwise leak from another Look.
8950
8972
  */
8951
8973
  function baseHeader(theme) {
8952
- const { navLinkStyle: _navLinkStyle, navFontRole: _navFontRole, navTypography: _navTypography, navTextSize: _navTextSize, dropdownStyle: _dropdownStyle, ctaVariant: _ctaVariant, navContainer: _navContainer, container: _container, shadow: _shadow, logo: _logo, logoText: _logoText, border: _border, ...header } = theme.header;
8974
+ const { navLinkStyle: _navLinkStyle, navFontRole: _navFontRole, navTypography: _navTypography, navTextSize: _navTextSize, interactionPalette: _interactionPalette, dropdownStyle: _dropdownStyle, ctaVariant: _ctaVariant, navContainer: _navContainer, container: _container, shadow: _shadow, logo: _logo, logoText: _logoText, border: _border, ...header } = theme.header;
8953
8975
  return {
8954
8976
  ...header,
8955
8977
  navContainer: {
@@ -8964,7 +8986,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8964
8986
  id: asHeaderLayoutId("classic"),
8965
8987
  label: "Classic",
8966
8988
  description: "Logo and navigation in one practical horizontal row.",
8967
- structure: "inline-classic",
8968
8989
  variant: "classic",
8969
8990
  defaultPositioning: "sticky",
8970
8991
  shrinkOnScroll: false
@@ -8973,7 +8994,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8973
8994
  id: asHeaderLayoutId("centered"),
8974
8995
  label: "Centered",
8975
8996
  description: "Logo centered above a balanced navigation row.",
8976
- structure: "centered-stack",
8977
8997
  variant: "centered",
8978
8998
  defaultPositioning: "static",
8979
8999
  shrinkOnScroll: false,
@@ -8989,7 +9009,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8989
9009
  id: asHeaderLayoutId("floating"),
8990
9010
  label: "Floating",
8991
9011
  description: "Detached header chrome that sits over the opening section.",
8992
- structure: "floating-shell",
8993
9012
  variant: "floating",
8994
9013
  defaultPositioning: "sticky",
8995
9014
  shrinkOnScroll: true,
@@ -9151,10 +9170,13 @@ const headerStyleCatalog = defineExactCatalog()([
9151
9170
  label: "Clear Split",
9152
9171
  description: "Floating logo with transparent navigation and no shared shell.",
9153
9172
  supportedLayoutIds: supportedLayouts(["floating"]),
9154
- navInteraction: "color-change",
9173
+ navInteraction: "pill-background",
9155
9174
  surface: "floating",
9156
- defaultDepth: "none",
9175
+ defaultDepth: "line",
9157
9176
  navTypography: "plain",
9177
+ openingForegroundTarget: "all",
9178
+ scrollTreatment: "contrast-glass",
9179
+ interactionPalette: clearSplitInteractionPalette,
9158
9180
  moods: ["editorial", "calm"]
9159
9181
  },
9160
9182
  {
@@ -9177,6 +9199,7 @@ const headerStyleCatalog = defineExactCatalog()([
9177
9199
  surface: "floating",
9178
9200
  defaultDepth: "shadow",
9179
9201
  navTypography: "quiet-caps",
9202
+ openingForegroundTarget: "brand-only",
9180
9203
  moods: ["expressive"]
9181
9204
  },
9182
9205
  {
@@ -9188,6 +9211,7 @@ const headerStyleCatalog = defineExactCatalog()([
9188
9211
  surface: "floating",
9189
9212
  defaultDepth: "shadow",
9190
9213
  navTypography: "heading",
9214
+ openingForegroundTarget: "brand-only",
9191
9215
  moods: ["calm", "editorial"]
9192
9216
  }
9193
9217
  ]);
@@ -9689,13 +9713,6 @@ const headerLookCatalog = defineExactCatalog()([
9689
9713
  {
9690
9714
  id: asHeaderLookId("clean-base"),
9691
9715
  label: "Clean base",
9692
- visualTreatment: "solid-neutral",
9693
- layoutBehavior: "sticky",
9694
- configuration: {
9695
- structure: "inline-classic",
9696
- treatment: "solid-neutral",
9697
- behavior: "sticky"
9698
- },
9699
9716
  openingRequirement: "none",
9700
9717
  logoAccommodations: inlineClassicLogoAccommodations,
9701
9718
  compile: cleanBaseHeader
@@ -9703,13 +9720,6 @@ const headerLookCatalog = defineExactCatalog()([
9703
9720
  {
9704
9721
  id: asHeaderLookId("classic-centered-nav"),
9705
9722
  label: "Centered nav",
9706
- visualTreatment: "solid-neutral",
9707
- layoutBehavior: "sticky",
9708
- configuration: {
9709
- structure: "inline-classic",
9710
- treatment: "solid-neutral",
9711
- behavior: "sticky"
9712
- },
9713
9723
  openingRequirement: "none",
9714
9724
  maxRecommendedNavItems: 6,
9715
9725
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9718,13 +9728,6 @@ const headerLookCatalog = defineExactCatalog()([
9718
9728
  {
9719
9729
  id: asHeaderLookId("brand-solid"),
9720
9730
  label: "Brand solid",
9721
- visualTreatment: "solid-brand",
9722
- layoutBehavior: "sticky-shrink",
9723
- configuration: {
9724
- structure: "inline-classic",
9725
- treatment: "solid-brand",
9726
- behavior: "sticky-shrink"
9727
- },
9728
9731
  openingRequirement: "none",
9729
9732
  logoAccommodations: inlineClassicLogoAccommodations,
9730
9733
  compile: solidBrandHeader
@@ -9732,13 +9735,6 @@ const headerLookCatalog = defineExactCatalog()([
9732
9735
  {
9733
9736
  id: asHeaderLookId("serif-line"),
9734
9737
  label: "Serif line",
9735
- visualTreatment: "light-serif",
9736
- layoutBehavior: "sticky",
9737
- configuration: {
9738
- structure: "centered-stack",
9739
- treatment: "light-serif",
9740
- behavior: "sticky"
9741
- },
9742
9738
  openingRequirement: "none",
9743
9739
  maxRecommendedNavItems: 6,
9744
9740
  logoAccommodations: centeredLogoAccommodations,
@@ -9747,13 +9743,6 @@ const headerLookCatalog = defineExactCatalog()([
9747
9743
  {
9748
9744
  id: asHeaderLookId("centered-calm"),
9749
9745
  label: "Centered calm",
9750
- visualTreatment: "light-serif",
9751
- layoutBehavior: "normal-flow",
9752
- configuration: {
9753
- structure: "centered-stack",
9754
- treatment: "light-serif",
9755
- behavior: "normal-flow"
9756
- },
9757
9746
  openingRequirement: "none",
9758
9747
  maxRecommendedNavItems: 5,
9759
9748
  logoAccommodations: centeredLogoAccommodations,
@@ -9762,13 +9751,6 @@ const headerLookCatalog = defineExactCatalog()([
9762
9751
  {
9763
9752
  id: asHeaderLookId("practical-utility"),
9764
9753
  label: "Practical utility",
9765
- visualTreatment: "solid-neutral",
9766
- layoutBehavior: "sticky-shrink",
9767
- configuration: {
9768
- structure: "inline-classic",
9769
- treatment: "solid-neutral",
9770
- behavior: "sticky-shrink"
9771
- },
9772
9754
  openingRequirement: "none",
9773
9755
  requiresProminentCta: true,
9774
9756
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9777,13 +9759,6 @@ const headerLookCatalog = defineExactCatalog()([
9777
9759
  {
9778
9760
  id: asHeaderLookId("minimal-transparent"),
9779
9761
  label: "Minimal transparent",
9780
- visualTreatment: "minimal-transparent",
9781
- layoutBehavior: "normal-flow",
9782
- configuration: {
9783
- structure: "inline-classic",
9784
- treatment: "minimal-transparent",
9785
- behavior: "normal-flow"
9786
- },
9787
9762
  openingRequirement: "reserved-space-ok",
9788
9763
  logoAccommodations: inlineClassicLogoAccommodations,
9789
9764
  compile: minimalTransparentHeader
@@ -9791,13 +9766,6 @@ const headerLookCatalog = defineExactCatalog()([
9791
9766
  {
9792
9767
  id: asHeaderLookId("transparent-overlay"),
9793
9768
  label: "Transparent overlay",
9794
- visualTreatment: "transparent-overlay",
9795
- layoutBehavior: "fixed-overlay",
9796
- configuration: {
9797
- structure: "inline-classic",
9798
- treatment: "transparent-overlay",
9799
- behavior: "fixed-overlay"
9800
- },
9801
9769
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9802
9770
  maxRecommendedNavItems: 5,
9803
9771
  logoAccommodations: overlayLogoAccommodations,
@@ -9806,24 +9774,13 @@ const headerLookCatalog = defineExactCatalog()([
9806
9774
  {
9807
9775
  id: asHeaderLookId("floating-glass"),
9808
9776
  label: "Floating glass",
9809
- visualTreatment: "floating-glass",
9810
- layoutBehavior: "fixed-floating",
9811
- configuration: {
9812
- structure: "floating-shell",
9813
- treatment: "floating-glass",
9814
- behavior: "fixed-floating"
9815
- },
9816
9777
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9817
9778
  maxRecommendedNavItems: 5,
9818
9779
  logoAccommodations: overlayLogoAccommodations,
9819
9780
  compile: floatingGlassHeader
9820
9781
  }
9821
9782
  ]);
9822
- new Set(headerLookCatalog.map((look) => headerConfigurationKey(look.configuration)));
9823
9783
  new Map(headerLookCatalog.map((look) => [look.id, look]));
9824
- function headerConfigurationKey(configuration) {
9825
- return `${configuration.structure}:${configuration.treatment}:${configuration.behavior}`;
9826
- }
9827
9784
  //#endregion
9828
9785
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
9829
9786
  function boundaryRuntimeMetrics(family, size, heightExpression) {
@@ -10027,8 +9984,6 @@ const VARIANT_ROLES = [
10027
9984
  "secondary",
10028
9985
  "outline",
10029
9986
  "ghost",
10030
- "link",
10031
- "tertiary",
10032
9987
  "accent"
10033
9988
  ];
10034
9989
  function isVariantRole(value) {
@@ -10040,7 +9995,7 @@ function isVariantRole(value) {
10040
9995
  * IDs become class selectors, so keep the contract deliberately narrower than
10041
9996
  * an arbitrary string and shared with every authoring/runtime boundary.
10042
9997
  */
10043
- const buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only");
9998
+ const buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only").refine((value) => value !== "link" && value !== "tertiary", { message: "Retired button role IDs are not valid variant IDs" });
10044
9999
  function asSpecialVariantId(value) {
10045
10000
  const parsed = buttonVariantIdSchema.safeParse(value);
10046
10001
  if (!parsed.success) throw new Error("SpecialVariantId must be a CSS-safe button variant ID");
@@ -13231,39 +13186,39 @@ function defaultTypographyForRecipe(recipe) {
13231
13186
  }
13232
13187
  //#endregion
13233
13188
  //#region ../theme-core/src/lib/media.ts
13234
- const hotspotSchema$1 = z.object({
13189
+ const hotspotSchema = z.object({
13235
13190
  x: z.number().min(0).max(1),
13236
13191
  y: z.number().min(0).max(1),
13237
13192
  radius: z.number().optional()
13238
13193
  });
13239
- const rotationSchema$1 = z.union([
13194
+ const rotationSchema = z.union([
13240
13195
  z.literal(0),
13241
13196
  z.literal(90),
13242
13197
  z.literal(180),
13243
13198
  z.literal(270)
13244
13199
  ]);
13245
- const rectSchema$1 = z.tuple([
13200
+ const rectSchema = z.tuple([
13246
13201
  z.number(),
13247
13202
  z.number(),
13248
13203
  z.number(),
13249
13204
  z.number()
13250
13205
  ]);
13251
- const aspectCropSchema$1 = z.object({
13206
+ const aspectCropSchema = z.object({
13252
13207
  aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
13253
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
13254
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
13255
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
13208
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
13209
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
13210
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
13256
13211
  });
13257
- const transformSchema$1 = z.object({
13212
+ const transformSchema = z.object({
13258
13213
  aspectCrops: z.preprocess((value) => {
13259
13214
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
13260
13215
  return value;
13261
- }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
13262
- rect: rectSchema$1.optional(),
13263
- hotspot: hotspotSchema$1.optional(),
13264
- rotation: rotationSchema$1.optional()
13216
+ }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
13217
+ rect: rectSchema.optional(),
13218
+ hotspot: hotspotSchema.optional(),
13219
+ rotation: rotationSchema.optional()
13265
13220
  });
13266
- const mediaSchema$1 = z.object({
13221
+ const mediaSchema = z.object({
13267
13222
  type: z.enum([
13268
13223
  "image",
13269
13224
  "video",
@@ -13284,7 +13239,7 @@ const mediaSchema$1 = z.object({
13284
13239
  height: z.number().optional(),
13285
13240
  storageBucket: z.string().optional(),
13286
13241
  storagePath: z.string().optional(),
13287
- transform: transformSchema$1.optional()
13242
+ transform: transformSchema.optional()
13288
13243
  });
13289
13244
  //#endregion
13290
13245
  //#region ../theme-core/src/palette/schema.ts
@@ -14117,264 +14072,6 @@ function generateInteractiveChildInheritanceCSS(selector) {
14117
14072
  return `\n${selector} * {\n font-family: inherit;\n font-weight: inherit;\n font-style: inherit;\n letter-spacing: inherit;\n text-transform: inherit;\n color: inherit;\n}\n`;
14118
14073
  }
14119
14074
  //#endregion
14120
- //#region ../theme-core/src/buttons/effects/presets/background.ts
14121
- /**
14122
- * Darken background on hover
14123
- *
14124
- * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
14125
- */
14126
- const darkenBackgroundEffect = {
14127
- id: "darken-background",
14128
- name: "Darken on Hover",
14129
- description: "Darkens the background color on hover",
14130
- category: "background",
14131
- pseudoElement: "none",
14132
- applicableTo: ["button"],
14133
- customizableOption: {
14134
- name: "amount",
14135
- type: "select",
14136
- label: "Darken Amount (shade step)",
14137
- default: 100,
14138
- options: [
14139
- 0,
14140
- 100,
14141
- 200,
14142
- 300,
14143
- 400,
14144
- 500,
14145
- 600,
14146
- 700,
14147
- 800,
14148
- 900
14149
- ]
14150
- },
14151
- isApplicable: (buttonConfig) => {
14152
- return buttonConfig.background.type === "solid";
14153
- },
14154
- generateCSS: (ctx) => {
14155
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
14156
- if (buttonConfig.background.type !== "solid") return "";
14157
- const amount = options.amount || 100;
14158
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
14159
- const darkerToken = tokens.adjustShade(baseToken, amount);
14160
- return `
14161
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14162
- background-color: ${tokens.getColor(darkerToken)};
14163
- }
14164
- `;
14165
- }
14166
- };
14167
- /**
14168
- * Lighten background on hover
14169
- *
14170
- * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
14171
- */
14172
- const lightenBackgroundEffect = {
14173
- id: "lighten-background",
14174
- name: "Lighten on Hover",
14175
- description: "Lightens the background color on hover",
14176
- category: "background",
14177
- pseudoElement: "none",
14178
- applicableTo: ["button"],
14179
- customizableOption: {
14180
- name: "amount",
14181
- type: "select",
14182
- label: "Lighten Amount (shade step)",
14183
- default: 100,
14184
- options: [
14185
- 0,
14186
- 100,
14187
- 200,
14188
- 300,
14189
- 400,
14190
- 500,
14191
- 600,
14192
- 700,
14193
- 800,
14194
- 900
14195
- ]
14196
- },
14197
- isApplicable: (buttonConfig) => {
14198
- return buttonConfig.background.type === "solid";
14199
- },
14200
- generateCSS: (ctx) => {
14201
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
14202
- if (buttonConfig.background.type !== "solid") return "";
14203
- const amount = options.amount || 100;
14204
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
14205
- const lighterToken = tokens.adjustShade(baseToken, -amount);
14206
- return `
14207
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14208
- background-color: ${tokens.getColor(lighterToken)};
14209
- }
14210
- `;
14211
- }
14212
- };
14213
- /**
14214
- * Fade background on hover (reduce opacity)
14215
- *
14216
- * Works with all background types.
14217
- */
14218
- const fadeBackgroundEffect = {
14219
- id: "fade-background",
14220
- name: "Fade on Hover",
14221
- description: "Reduces background opacity on hover",
14222
- category: "background",
14223
- pseudoElement: "none",
14224
- applicableTo: ["nav-link"],
14225
- customizableOption: {
14226
- name: "opacity",
14227
- type: "percentage",
14228
- label: "Hover Opacity",
14229
- default: 80
14230
- },
14231
- generateCSS: (ctx) => {
14232
- const { themeId, variantId, options } = ctx;
14233
- return `
14234
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14235
- opacity: ${(options.opacity || 80) / 100};
14236
- }
14237
- `;
14238
- }
14239
- };
14240
- /**
14241
- * Reduce opacity on hover (simple opacity reduction)
14242
- *
14243
- * Navigation-link effect that reduces opacity by a percentage (default 15%).
14244
- */
14245
- const opacityReduceEffect = {
14246
- id: "opacity-reduce",
14247
- name: "Reduce Opacity",
14248
- description: "Reduces navigation-link opacity on hover by a percentage",
14249
- category: "background",
14250
- pseudoElement: "none",
14251
- applicableTo: ["nav-link"],
14252
- customizableOption: {
14253
- name: "reduction",
14254
- type: "percentage",
14255
- label: "Opacity Reduction",
14256
- default: 15
14257
- },
14258
- generateCSS: (ctx) => {
14259
- const { themeId, variantId, options } = ctx;
14260
- return `
14261
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14262
- opacity: ${1 - (options.reduction || 15) / 100};
14263
- }
14264
- `;
14265
- }
14266
- };
14267
- /**
14268
- * Animated gradient background
14269
- *
14270
- * Animates a gradient background by shifting its position on hover.
14271
- * Works with gradient backgrounds only.
14272
- *
14273
- * Sets background-size to 200% and animates background-position from left to right.
14274
- */
14275
- const animatedGradientEffect = {
14276
- id: "animated-gradient",
14277
- name: "Animated Gradient",
14278
- description: "Animates gradient position on hover",
14279
- category: "background",
14280
- pseudoElement: "none",
14281
- applicableTo: ["button"],
14282
- customizableOption: {
14283
- name: "direction",
14284
- type: "select",
14285
- label: "Animation Direction",
14286
- default: "horizontal",
14287
- options: ["horizontal", "vertical"]
14288
- },
14289
- isApplicable: (buttonConfig) => {
14290
- return buttonConfig.background.type === "gradient";
14291
- },
14292
- generateCSS: (ctx) => {
14293
- const { themeId, variantId, options, buttonConfig } = ctx;
14294
- if (buttonConfig.background.type !== "gradient") return "";
14295
- const direction = options.direction || "horizontal";
14296
- return `
14297
- /* Setup animated gradient */
14298
- :where([data-theme-scope="${themeId}"]) .${variantId} {
14299
- background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
14300
- background-position: left center;
14301
- transition: background-position 0.3s ease;
14302
- }
14303
-
14304
- /* Animate gradient on hover */
14305
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14306
- background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
14307
- }
14308
- `;
14309
- }
14310
- };
14311
- /**
14312
- * Add background color on hover
14313
- *
14314
- * Works best with transparent backgrounds. Adds a solid background color on hover.
14315
- */
14316
- const backgroundOnHoverEffect = {
14317
- id: "background-on-hover",
14318
- name: "Background on Hover",
14319
- description: "Adds background color on hover",
14320
- category: "background",
14321
- pseudoElement: "none",
14322
- applicableTo: ["button", "nav-link"],
14323
- customizableOption: {
14324
- name: "colorToken",
14325
- type: "select",
14326
- label: "Background Color",
14327
- default: "neutral-800",
14328
- options: [
14329
- "neutral-700",
14330
- "neutral-800",
14331
- "neutral-900",
14332
- "primary"
14333
- ]
14334
- },
14335
- generateCSS: (ctx) => {
14336
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
14337
- const colorToken = options.colorToken || "neutral-800";
14338
- return `
14339
- /* Add background on hover */
14340
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14341
- background-color: ${tokens.getColor(colorToken)};${"textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : ""}
14342
- }
14343
- `;
14344
- }
14345
- };
14346
- /**
14347
- * Add semi-transparent background color on hover
14348
- *
14349
- * Adds a background with opacity/alpha channel. Perfect for retro/arcade styles.
14350
- */
14351
- const backgroundOnHoverAlphaEffect = {
14352
- id: "background-on-hover-alpha",
14353
- name: "Background on Hover (Transparent)",
14354
- description: "Adds semi-transparent background on hover",
14355
- category: "background",
14356
- pseudoElement: "none",
14357
- applicableTo: ["nav-link"],
14358
- customizableOption: {
14359
- name: "opacity",
14360
- type: "percentage",
14361
- label: "Opacity",
14362
- default: 50
14363
- },
14364
- generateCSS: (ctx) => {
14365
- const { themeId, variantId, stateGroup, options } = ctx;
14366
- const rawOpacity = options.opacity;
14367
- const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
14368
- const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
14369
- return `
14370
- /* Add semi-transparent background (${stateGroup}) */
14371
- :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
14372
- background-color: rgb(${cssVar} / ${clampedOpacity}%);
14373
- }
14374
- `;
14375
- }
14376
- };
14377
- //#endregion
14378
14075
  //#region ../theme-core/src/buttons/effects/cssUtils.ts
14379
14076
  /**
14380
14077
  * CSS Utilities for Effect Presets
@@ -14426,6 +14123,71 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
14426
14123
  `;
14427
14124
  }
14428
14125
  //#endregion
14126
+ //#region ../theme-core/src/buttons/effects/presets/background.ts
14127
+ /**
14128
+ * Darken background on hover
14129
+ *
14130
+ * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
14131
+ */
14132
+ const darkenBackgroundEffect = shadeBackgroundEffect({
14133
+ id: "darken-background",
14134
+ name: "Darken on Hover",
14135
+ description: "Darkens the background color on hover",
14136
+ label: "Darken Amount (shade step)",
14137
+ shadeDirection: 1
14138
+ });
14139
+ /**
14140
+ * Lighten background on hover
14141
+ *
14142
+ * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
14143
+ */
14144
+ const lightenBackgroundEffect = shadeBackgroundEffect({
14145
+ id: "lighten-background",
14146
+ name: "Lighten on Hover",
14147
+ description: "Lightens the background color on hover",
14148
+ label: "Lighten Amount (shade step)",
14149
+ shadeDirection: -1
14150
+ });
14151
+ function shadeBackgroundEffect(config) {
14152
+ return {
14153
+ id: config.id,
14154
+ name: config.name,
14155
+ description: config.description,
14156
+ category: "background",
14157
+ pseudoElement: "none",
14158
+ applicableTo: ["button"],
14159
+ customizableOption: {
14160
+ name: "amount",
14161
+ type: "select",
14162
+ label: config.label,
14163
+ default: 100,
14164
+ options: [
14165
+ 0,
14166
+ 100,
14167
+ 200,
14168
+ 300,
14169
+ 400,
14170
+ 500,
14171
+ 600,
14172
+ 700,
14173
+ 800,
14174
+ 900
14175
+ ]
14176
+ },
14177
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
14178
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
14179
+ if (buttonConfig.background.type !== "solid") return "";
14180
+ const amount = (options.amount || 100) * config.shadeDirection;
14181
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
14182
+ return `
14183
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14184
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
14185
+ }
14186
+ `;
14187
+ }
14188
+ };
14189
+ }
14190
+ //#endregion
14429
14191
  //#region ../theme-core/src/buttons/effects/registry.ts
14430
14192
  /**
14431
14193
  * Registry of all available effect presets
@@ -14433,11 +14195,144 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
14433
14195
  const EFFECT_PRESETS = [
14434
14196
  darkenBackgroundEffect,
14435
14197
  lightenBackgroundEffect,
14436
- fadeBackgroundEffect,
14437
- opacityReduceEffect,
14438
- animatedGradientEffect,
14439
- backgroundOnHoverEffect,
14440
- backgroundOnHoverAlphaEffect,
14198
+ {
14199
+ id: "fade-background",
14200
+ name: "Fade on Hover",
14201
+ description: "Reduces background opacity on hover",
14202
+ category: "background",
14203
+ pseudoElement: "none",
14204
+ applicableTo: ["nav-link"],
14205
+ customizableOption: {
14206
+ name: "opacity",
14207
+ type: "percentage",
14208
+ label: "Hover Opacity",
14209
+ default: 80
14210
+ },
14211
+ generateCSS: (ctx) => {
14212
+ const { themeId, variantId, options } = ctx;
14213
+ return `
14214
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14215
+ opacity: ${(options.opacity || 80) / 100};
14216
+ }
14217
+ `;
14218
+ }
14219
+ },
14220
+ {
14221
+ id: "opacity-reduce",
14222
+ name: "Reduce Opacity",
14223
+ description: "Reduces navigation-link opacity on hover by a percentage",
14224
+ category: "background",
14225
+ pseudoElement: "none",
14226
+ applicableTo: ["nav-link"],
14227
+ customizableOption: {
14228
+ name: "reduction",
14229
+ type: "percentage",
14230
+ label: "Opacity Reduction",
14231
+ default: 15
14232
+ },
14233
+ generateCSS: (ctx) => {
14234
+ const { themeId, variantId, options } = ctx;
14235
+ return `
14236
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14237
+ opacity: ${1 - (options.reduction || 15) / 100};
14238
+ }
14239
+ `;
14240
+ }
14241
+ },
14242
+ {
14243
+ id: "animated-gradient",
14244
+ name: "Animated Gradient",
14245
+ description: "Animates gradient position on hover",
14246
+ category: "background",
14247
+ pseudoElement: "none",
14248
+ applicableTo: ["button"],
14249
+ customizableOption: {
14250
+ name: "direction",
14251
+ type: "select",
14252
+ label: "Animation Direction",
14253
+ default: "horizontal",
14254
+ options: ["horizontal", "vertical"]
14255
+ },
14256
+ isApplicable: (buttonConfig) => {
14257
+ return buttonConfig.background.type === "gradient";
14258
+ },
14259
+ generateCSS: (ctx) => {
14260
+ const { themeId, variantId, options, buttonConfig } = ctx;
14261
+ if (buttonConfig.background.type !== "gradient") return "";
14262
+ const direction = options.direction || "horizontal";
14263
+ return `
14264
+ /* Setup animated gradient */
14265
+ :where([data-theme-scope="${themeId}"]) .${variantId} {
14266
+ background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
14267
+ background-position: left center;
14268
+ transition: background-position 0.3s ease;
14269
+ }
14270
+
14271
+ /* Animate gradient on hover */
14272
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
14273
+ background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
14274
+ }
14275
+ `;
14276
+ }
14277
+ },
14278
+ {
14279
+ id: "background-on-hover",
14280
+ name: "Background on Hover",
14281
+ description: "Adds background color on hover",
14282
+ category: "background",
14283
+ pseudoElement: "none",
14284
+ applicableTo: ["button", "nav-link"],
14285
+ customizableOption: {
14286
+ name: "colorToken",
14287
+ type: "select",
14288
+ label: "Background Color",
14289
+ default: "neutral-800",
14290
+ options: [
14291
+ "neutral-700",
14292
+ "neutral-800",
14293
+ "neutral-900",
14294
+ "primary"
14295
+ ]
14296
+ },
14297
+ generateCSS: (ctx) => {
14298
+ const { themeId, variantId, stateGroup, options, tokens, buttonConfig } = ctx;
14299
+ const colorToken = options.colorToken || "neutral-800";
14300
+ const color = tokens.getColor(colorToken);
14301
+ const navForeground = "textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : "";
14302
+ return `
14303
+ /* Add background on hover */
14304
+ ${getStateSelector(themeId, variantId, stateGroup)} {
14305
+ background-color: ${color};${navForeground}
14306
+ }
14307
+ `;
14308
+ }
14309
+ },
14310
+ {
14311
+ id: "background-on-hover-alpha",
14312
+ name: "Background on Hover (Transparent)",
14313
+ description: "Adds semi-transparent background on hover",
14314
+ category: "background",
14315
+ pseudoElement: "none",
14316
+ applicableTo: ["nav-link"],
14317
+ customizableOption: {
14318
+ name: "opacity",
14319
+ type: "percentage",
14320
+ label: "Opacity",
14321
+ default: 50
14322
+ },
14323
+ generateCSS: (ctx) => {
14324
+ const { themeId, variantId, stateGroup, options } = ctx;
14325
+ const rawOpacity = options.opacity;
14326
+ const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
14327
+ const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
14328
+ return `
14329
+ /* Add semi-transparent background (${stateGroup}) */
14330
+ :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
14331
+ background-color: rgb(${cssVar} / ${clampedOpacity}%);
14332
+ }
14333
+ `;
14334
+ }
14335
+ },
14441
14336
  {
14442
14337
  id: "border-glow",
14443
14338
  name: "Border Glow",
@@ -17376,6 +17271,166 @@ function resolveOnColorForThemeToken(token) {
17376
17271
  return shade <= 400 ? "#000000" : "#FFFFFF";
17377
17272
  }
17378
17273
  //#endregion
17274
+ //#region ../theme-core/src/header/paintTargets.ts
17275
+ /** Resolve the element that owns the visible header surface for each layout. */
17276
+ function getHeaderPaintTargets(variant, themeId, state = "base") {
17277
+ const scope = `:where([data-theme-scope="${themeId}"])`;
17278
+ const scrolledRoot = state === "scrolled" ? ".header-root.header-scrolled " : "";
17279
+ if (variant === "floating") {
17280
+ if (state === "scrolled") {
17281
+ const desktopOwner = `${scope} ${scrolledRoot}.header-floating-container`;
17282
+ const mobileOwner = `${scope} ${scrolledRoot}.header-mobile-bar`;
17283
+ return [{
17284
+ kind: "viewport-band",
17285
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
17286
+ ownerSelector: desktopOwner,
17287
+ selector: `${desktopOwner}::before`,
17288
+ mediaQuery: MQ_MD_UP,
17289
+ extent: {
17290
+ top: {
17291
+ customProperty: "--rb-header-floating-top-gap",
17292
+ value: "1rem",
17293
+ ownerProperty: "top"
17294
+ },
17295
+ bottom: {
17296
+ customProperty: "--rb-header-floating-bottom-extension",
17297
+ value: "0.75rem"
17298
+ }
17299
+ },
17300
+ ownerNeedsPositioning: false
17301
+ }, {
17302
+ kind: "viewport-band",
17303
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
17304
+ ownerSelector: mobileOwner,
17305
+ selector: `${mobileOwner}::before`,
17306
+ mediaQuery: MQ_MD_DOWN,
17307
+ extent: {
17308
+ top: {
17309
+ customProperty: "--rb-header-floating-top-gap",
17310
+ value: "0.75rem",
17311
+ ownerProperty: "margin-top"
17312
+ },
17313
+ bottom: {
17314
+ customProperty: "--rb-header-floating-bottom-extension",
17315
+ value: "0.75rem"
17316
+ }
17317
+ },
17318
+ ownerNeedsPositioning: true
17319
+ }];
17320
+ }
17321
+ return [{
17322
+ kind: "element-box",
17323
+ selector: `${scope} ${scrolledRoot}.header-floating-container`,
17324
+ mediaQuery: MQ_MD_UP
17325
+ }, {
17326
+ kind: "element-box",
17327
+ selector: `${scope} ${scrolledRoot}.header-mobile-bar`,
17328
+ mediaQuery: MQ_MD_DOWN
17329
+ }];
17330
+ }
17331
+ return [{
17332
+ kind: "element-box",
17333
+ selector: `${scope} .header-root${state === "scrolled" ? ".header-scrolled" : ""}::before`,
17334
+ pseudoElement: "inset"
17335
+ }];
17336
+ }
17337
+ function renderHeaderPaintTargetRules(targets, rules) {
17338
+ return targets.map((target) => {
17339
+ const block = renderHeaderPaintTargetRule(target, rules);
17340
+ return target.mediaQuery ? `@media ${target.mediaQuery} {\n${block}\n}` : block;
17341
+ }).join("\n");
17342
+ }
17343
+ function renderHeaderPaintTargetRule(target, rules) {
17344
+ switch (target.kind) {
17345
+ case "element-box": {
17346
+ const pseudoElementSetup = target.pseudoElement === "inset" ? [
17347
+ "content: \"\";",
17348
+ "position: absolute;",
17349
+ "inset: 0;",
17350
+ "pointer-events: none;",
17351
+ "border-radius: inherit;",
17352
+ "z-index: -1;"
17353
+ ] : [];
17354
+ return `${target.selector} {\n ${[...pseudoElementSetup, ...rules].join("\n ")}\n}`;
17355
+ }
17356
+ case "viewport-band": {
17357
+ const { top, bottom } = target.extent;
17358
+ const ownerRules = [
17359
+ `${top.customProperty}: ${top.value};`,
17360
+ `${bottom.customProperty}: ${bottom.value};`,
17361
+ `${top.ownerProperty}: var(${top.customProperty});`,
17362
+ ...target.ownerNeedsPositioning ? ["position: relative;"] : [],
17363
+ "isolation: isolate;",
17364
+ "background: none;",
17365
+ "backdrop-filter: none;",
17366
+ "-webkit-backdrop-filter: none;",
17367
+ "border: 0;",
17368
+ "box-shadow: none;"
17369
+ ];
17370
+ const bandRules = [
17371
+ "content: \"\";",
17372
+ "position: absolute;",
17373
+ `top: calc(-1 * var(${top.customProperty}));`,
17374
+ `bottom: calc(-1 * var(${bottom.customProperty}));`,
17375
+ "left: 50%;",
17376
+ "width: 100vw;",
17377
+ "transform: translateX(-50%);",
17378
+ "pointer-events: none;",
17379
+ "border-radius: 0;",
17380
+ "z-index: -1;",
17381
+ ...rules
17382
+ ];
17383
+ return `${target.clipSelector} {\n overflow-x: clip;\n}\n${target.ownerSelector} {\n ${ownerRules.join("\n ")}\n}\n${target.selector} {\n ${bandRules.join("\n ")}\n}`;
17384
+ }
17385
+ }
17386
+ }
17387
+ //#endregion
17388
+ //#region ../theme-core/src/header/scrollTreatment.ts
17389
+ const headerScrollTreatmentSchema = z$1.discriminatedUnion("kind", [z$1.object({
17390
+ kind: z$1.literal("contrast-glass"),
17391
+ backgroundTone: z$1.enum(["light", "dark"])
17392
+ })]).optional();
17393
+ const CONTRAST_GLASS_BLUR = "blur(12px)";
17394
+ function generateMobileOverlayBackdropFilterFix(themeId, variant) {
17395
+ const root = `:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])`;
17396
+ return `\n${(variant === "floating" ? [`${root} .header-mobile-bar`, `${root} .header-mobile-bar::before`] : [`${root}::before`]).join(",\n")} {\n backdrop-filter: none !important;\n -webkit-backdrop-filter: none !important;\n}\n`;
17397
+ }
17398
+ function generateHeaderScrollTreatmentStyles(treatment, themeId, variant, surfaceRules = []) {
17399
+ if (!treatment) return "";
17400
+ switch (treatment.kind) {
17401
+ case "contrast-glass": {
17402
+ const backgroundChannels = treatment.backgroundTone === "dark" ? "0 0 0" : "255 255 255";
17403
+ return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [
17404
+ `background-color: rgb(${backgroundChannels} / 0.60);`,
17405
+ `backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
17406
+ `-webkit-backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
17407
+ ...surfaceRules
17408
+ ]);
17409
+ }
17410
+ }
17411
+ }
17412
+ //#endregion
17413
+ //#region ../theme-core/src/header/containerSchema.ts
17414
+ const headerContainerSchema = z$1.object({
17415
+ rounded: z$1.enum([
17416
+ "none",
17417
+ "sm",
17418
+ "md",
17419
+ "lg",
17420
+ "xl",
17421
+ "2xl"
17422
+ ]).default("xl"),
17423
+ border: z$1.boolean().default(true),
17424
+ shadow: z$1.boolean().default(true),
17425
+ padding: z$1.enum([
17426
+ "sm",
17427
+ "md",
17428
+ "lg"
17429
+ ]).default("md"),
17430
+ tint: z$1.string().nullable().optional(),
17431
+ opacity: z$1.number().min(0).max(1).default(.12)
17432
+ }).optional();
17433
+ //#endregion
17379
17434
  //#region ../theme-core/src/schema.ts
17380
17435
  const axesSchema = z$1.object({
17381
17436
  tone: z$1.enum([
@@ -17536,7 +17591,7 @@ const boxBackgroundSchema = z$1.object({
17536
17591
  color: tokenOrCssColorValueSchema.nullable().optional(),
17537
17592
  gradient: z$1.string().nullable().optional(),
17538
17593
  gradientPresetId: z$1.string().min(1).nullable().optional(),
17539
- image: mediaSchema$1.nullable().optional(),
17594
+ image: mediaSchema.nullable().optional(),
17540
17595
  objectFit: z$1.enum([
17541
17596
  "fill",
17542
17597
  "fit",
@@ -17784,25 +17839,6 @@ const navFontWeight = z$1.enum([
17784
17839
  ]);
17785
17840
  const headerMaxWidth = z$1.enum(["container", "full"]);
17786
17841
  const headerBarFrame = z$1.enum(["full-bleed", "inset-shell"]);
17787
- const headerContainerSchema = z$1.object({
17788
- rounded: z$1.enum([
17789
- "none",
17790
- "sm",
17791
- "md",
17792
- "lg",
17793
- "xl",
17794
- "2xl"
17795
- ]).default("xl"),
17796
- border: z$1.boolean().default(true),
17797
- shadow: z$1.boolean().default(true),
17798
- padding: z$1.enum([
17799
- "sm",
17800
- "md",
17801
- "lg"
17802
- ]).default("md"),
17803
- tint: z$1.string().nullable().optional(),
17804
- opacity: z$1.number().min(0).max(1).default(.12)
17805
- }).optional();
17806
17842
  const headerBorderSchema = componentBorderSchema.extend({ position: z$1.enum([
17807
17843
  "bottom",
17808
17844
  "top",
@@ -17920,7 +17956,7 @@ const headerBackgroundSchema = z$1.object({
17920
17956
  contentOwner: z$1.literal(siteChromeBackgroundOverrideOwner).optional(),
17921
17957
  color: tokenOrCssColorValueSchema.nullable().optional(),
17922
17958
  gradient: gradientConfigSchema.nullable().optional(),
17923
- image: mediaSchema$1.nullable().optional(),
17959
+ image: mediaSchema.nullable().optional(),
17924
17960
  textColor: tokenOrCssColorValueSchema.nullable().optional()
17925
17961
  });
17926
17962
  const headerSchema = z$1.object({
@@ -17929,7 +17965,8 @@ const headerSchema = z$1.object({
17929
17965
  shrinkOnScroll: z$1.boolean(),
17930
17966
  maxWidth: headerMaxWidth,
17931
17967
  barFrame: headerBarFrame.optional(),
17932
- logoOverride: mediaSchema$1.nullable().optional(),
17968
+ scrollTreatment: headerScrollTreatmentSchema,
17969
+ logoOverride: mediaSchema.nullable().optional(),
17933
17970
  background: headerBackgroundSchema.default({
17934
17971
  type: "color",
17935
17972
  color: "surface"
@@ -17941,6 +17978,7 @@ const headerSchema = z$1.object({
17941
17978
  navFontRole: z$1.enum(["body", "heading"]).optional(),
17942
17979
  navTypography: z$1.enum(["body", "heading"]).optional(),
17943
17980
  navTextSize: navLinkStyleSchema.shape.textSize,
17981
+ interactionPalette: headerInteractionPaletteSchema.optional(),
17944
17982
  navPlacement: z$1.enum(["end", "center"]).optional(),
17945
17983
  container: headerContainerSchema,
17946
17984
  border: headerBorderSchema,
@@ -23417,15 +23455,6 @@ const heroCopyFragment = defineFragment({
23417
23455
  */
23418
23456
  const BLOCK_BUTTON_ROLES = PUBLIC_BUTTON_ROLES;
23419
23457
  const blockButtonRoleSchema = z$1.enum(BLOCK_BUTTON_ROLES);
23420
- /**
23421
- * Temporary rollout boundary for persisted content written before issue #1220.
23422
- * Authoring remains strict through `blockButtonRoleSchema`; this parser exists
23423
- * only until the post-deploy role rewrite has been audited in production.
23424
- */
23425
- function canonicalizePersistedBlockButtonRole(value) {
23426
- return value === "link" || value === "tertiary" ? "ghost" : value;
23427
- }
23428
- const persistedBlockButtonRoleSchema = z$1.preprocess((value) => typeof value === "string" ? canonicalizePersistedBlockButtonRole(value) : value, blockButtonRoleSchema);
23429
23458
  const BLOCK_BUTTON_ROLE_LABELS = {
23430
23459
  primary: "Primary",
23431
23460
  secondary: "Secondary",
@@ -25703,6 +25732,7 @@ const newsletterFormFragment = defineFragment({
25703
25732
  }
25704
25733
  ],
25705
25734
  layout: [el("newsletter-form", withApiBindings({
25735
+ source: "block",
25706
25736
  destinationProvider: { $bind: { from: "destinationProvider" } },
25707
25737
  listId: { $bind: { from: "listId" } },
25708
25738
  preset: { $bind: { from: "preset" } },
@@ -27225,6 +27255,7 @@ const contactNewsletterLayout = styledSection({
27225
27255
  as: "h2",
27226
27256
  className: "newsletter-copy-title"
27227
27257
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
27258
+ source: "block",
27228
27259
  listId: { $bind: { from: "listId" } },
27229
27260
  preset: { $bind: { from: "preset" } },
27230
27261
  includePhone: { $bind: { from: "includePhone" } },
@@ -29223,6 +29254,22 @@ const footerNavGroupsLayout = stack({
29223
29254
  }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], whenCollectionHasItems("footerMenu.groups"));
29224
29255
  //#endregion
29225
29256
  //#region ../blocks/src/system/blocks/site-footer.ts
29257
+ const footerStandardContactBindings = {
29258
+ value: { $bind: { from: "module.engagement.runtime.value" } },
29259
+ submitLabel: { $bind: { from: "module.engagement.runtime.submitLabel" } },
29260
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } }
29261
+ };
29262
+ const footerMailingListBindings = {
29263
+ source: { $bind: { from: "module.engagement.runtime.source" } },
29264
+ destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
29265
+ listId: { $bind: { from: "module.engagement.runtime.listId" } },
29266
+ preset: { $bind: { from: "module.engagement.runtime.preset" } },
29267
+ includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
29268
+ buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
29269
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
29270
+ privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
29271
+ };
29272
+ const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
29226
29273
  const brandLogo = link({
29227
29274
  href: "/",
29228
29275
  className: { $bind: {
@@ -29300,6 +29347,23 @@ const authoredCopy = richText({
29300
29347
  id: "content.interpolateRichTextTokens",
29301
29348
  options: { tokens: ["year", "site_name"] }
29302
29349
  }] }));
29350
+ const footerEngagement = stack({
29351
+ gap: "md",
29352
+ className: "rb-w-full"
29353
+ }, [
29354
+ text({
29355
+ as: "p",
29356
+ className: "rb-body rb-opacity-80"
29357
+ }, bind("module.engagement.intro"), when("module.engagement.intro")),
29358
+ form(withApiBindings({
29359
+ ...footerStandardContactBindings,
29360
+ ...footerSpamProtectionBinding
29361
+ }), [], when("module.engagement.kind", { equals: "standard-contact" })),
29362
+ el("newsletter-form", withApiBindings({
29363
+ ...footerMailingListBindings,
29364
+ ...footerSpamProtectionBinding
29365
+ }), [], when("module.engagement.kind", { equals: "mailing-list" }))
29366
+ ], when("module.kind", { equals: "engagement" }));
29303
29367
  const footerGroup = stack({
29304
29368
  gap: "md",
29305
29369
  align: "stretch",
@@ -29325,6 +29389,7 @@ const footerGroup = stack({
29325
29389
  contact,
29326
29390
  hours,
29327
29391
  socials,
29392
+ footerEngagement,
29328
29393
  stack({ className: "rb-w-full" }, [authoredCopy], when("module.kind", { equals: "supporting-text" })),
29329
29394
  stack({ className: "rb-w-full rb-lg-col-span-3" }, [authoredCopy], when("module.kind", { equals: "legal" }))
29330
29395
  ], repeat("group.modules", "module"))], repeat("region.groups", "group"));
@@ -29332,6 +29397,10 @@ const footerMainRegion = stack({
29332
29397
  className: { $bind: { from: "region.className" } },
29333
29398
  "data-footer-region": { $bind: { from: "region.kind" } }
29334
29399
  }, [footerGroup], when("region.kind", { equals: "main" }), repeat("content.footerRuntime.regions", "region"));
29400
+ const footerEngagementRegion = stack({
29401
+ className: { $bind: { from: "region.className" } },
29402
+ "data-footer-region": "engagement-row"
29403
+ }, [footerGroup], when("region.kind", { equals: "engagement-row" }), repeat("content.footerRuntime.regions", "region"));
29335
29404
  const footerBottomRegion = stack({ className: { $bind: {
29336
29405
  from: "$root.theme.footer",
29337
29406
  transforms: [{ id: "layout.footerBottomBarContainerClass" }],
@@ -29367,7 +29436,11 @@ const siteFooterManifest = createBlockManifest({
29367
29436
  fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
29368
29437
  } },
29369
29438
  "data-footer-membership": { $bind: { from: "content.footerRuntime.membershipKey" } }
29370
- }, [footerMainRegion, footerBottomRegion]),
29439
+ }, [
29440
+ footerEngagementRegion,
29441
+ footerMainRegion,
29442
+ footerBottomRegion
29443
+ ]),
29371
29444
  description: "Site-wide composed footer with canonical shared details.",
29372
29445
  styleTokens: { spacing: "md" },
29373
29446
  paletteHidden: true
@@ -31199,84 +31272,6 @@ const weeklySlotAvailabilityBlockDefinition = {
31199
31272
  mode: "server"
31200
31273
  } }
31201
31274
  };
31202
- const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
31203
- "document",
31204
- "spreadsheet",
31205
- "archive",
31206
- "audio"
31207
- ];
31208
- const hotspotSchema = z.object({
31209
- x: z.number().min(0).max(1),
31210
- y: z.number().min(0).max(1),
31211
- radius: z.number().optional()
31212
- });
31213
- const rotationSchema = z.union([
31214
- z.literal(0),
31215
- z.literal(90),
31216
- z.literal(180),
31217
- z.literal(270)
31218
- ]);
31219
- const rectSchema = z.tuple([
31220
- z.number(),
31221
- z.number(),
31222
- z.number(),
31223
- z.number()
31224
- ]);
31225
- const aspectCropSchema = z.object({
31226
- aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
31227
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
31228
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
31229
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
31230
- });
31231
- const transformSchema = z.object({
31232
- aspectCrops: z.preprocess((value) => {
31233
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
31234
- return value;
31235
- }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
31236
- rect: rectSchema.optional(),
31237
- hotspot: hotspotSchema.optional(),
31238
- rotation: rotationSchema.optional()
31239
- });
31240
- const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
31241
- tag: z.literal("storage"),
31242
- assetId: z.string().optional(),
31243
- storageBucket: z.string().min(1),
31244
- storagePath: z.string().min(1)
31245
- }), z.object({
31246
- tag: z.literal("external-src"),
31247
- assetId: z.string().optional(),
31248
- src: z.string().url()
31249
- })]);
31250
- const mediaBaseSchema = z.object({
31251
- purpose: z.string().optional(),
31252
- placeholder: z.boolean().default(true).optional(),
31253
- assetId: z.string().optional(),
31254
- identifier: z.string().optional(),
31255
- src: z.string().optional(),
31256
- alt: z.string().optional(),
31257
- filename: z.string().optional(),
31258
- mimeType: z.string().optional(),
31259
- width: z.number().optional(),
31260
- height: z.number().optional(),
31261
- storageBucket: z.string().optional(),
31262
- storagePath: z.string().optional(),
31263
- poster: mediaPosterSchema.optional(),
31264
- transform: transformSchema.optional()
31265
- });
31266
- const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
31267
- const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
31268
- const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
31269
- const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
31270
- const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
31271
- const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
31272
- const mediaSchema = z.discriminatedUnion("type", [
31273
- imageMediaSchema,
31274
- videoMediaSchema,
31275
- audioMediaSchema,
31276
- documentMediaSchema,
31277
- spreadsheetMediaSchema,
31278
- archiveMediaSchema
31279
- ]);
31280
31275
  //#endregion
31281
31276
  //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
31282
31277
  const bookingDepositRefundPolicySchema = z$1.enum(["refundable", "non_refundable"]);
@@ -31716,7 +31711,7 @@ const publicEventSchema = z$1.object({
31716
31711
  presentation: z$1.object({
31717
31712
  cardTitleOverride: z$1.string().nullable().optional(),
31718
31713
  summary: z$1.string().nullable().optional(),
31719
- image: mediaSchema.nullable().optional()
31714
+ image: mediaSchema$1.nullable().optional()
31720
31715
  }).optional(),
31721
31716
  slug: z$1.string(),
31722
31717
  path: z$1.string().nullable(),
@@ -32029,7 +32024,7 @@ const publicMembershipProductCollectionSchema = z$1.object({ memberships: z$1.ar
32029
32024
  * Kept in a shared module so the block definition and runtime contracts can
32030
32025
  * depend on the same schema without creating an initialization cycle.
32031
32026
  */
32032
- const occurrenceContextSchema$1 = z$1.object({
32027
+ const occurrenceContextSchema = z$1.object({
32033
32028
  id: z$1.string(),
32034
32029
  seriesId: z$1.string(),
32035
32030
  startsAt: z$1.string(),
@@ -32342,7 +32337,7 @@ function isEventCalendarListLayout(value) {
32342
32337
  //#region ../blocks/src/system/runtime/nodes/shared/contract-schemas.ts
32343
32338
  const previewStageSchema = z$1.enum(["preview", "published"]);
32344
32339
  const registrationButtonVariantSchema = blockButtonRoleSchema;
32345
- const eventButtonVariantSchema = persistedBlockButtonRoleSchema;
32340
+ const eventButtonVariantSchema = blockButtonRoleSchema;
32346
32341
  const eventLayoutSchema = z$1.enum(eventCalendarListLayoutValues);
32347
32342
  const eventCalendarDisplayModeSchema = z$1.enum(eventCalendarDisplayModeValues);
32348
32343
  const eventCalendarDefaultViewSchema = z$1.enum(eventCalendarDefaultViewValues);
@@ -32429,28 +32424,37 @@ const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
32429
32424
  "Payment"
32430
32425
  ];
32431
32426
  const eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
32432
- const eventRegistrationSourceSchema = z$1.object({
32433
- siteId: z$1.string().optional(),
32434
- apiBaseUrl: z$1.string().optional(),
32435
- portalToken: z$1.string().nullable().optional(),
32436
- previewToken: z$1.string().nullable().optional(),
32437
- occurrenceContext: occurrenceContextSchema$1.optional(),
32427
+ const eventRegistrationHydrationSchemaShape = {
32428
+ occurrenceContext: occurrenceContextSchema.optional(),
32438
32429
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
32439
32430
  events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32440
- className: z$1.string().nullable().optional(),
32441
- buttonText: z$1.string().nullable().optional(),
32442
- maxTickets: z$1.string().nullable().optional(),
32431
+ wholeSeriesOfferings: publicCoursesArraySchema.nullable().optional(),
32432
+ wholeSeriesOffering: publicCourseSchema.nullable().optional(),
32433
+ maxTickets: z$1.string().optional(),
32443
32434
  showVenue: z$1.boolean().optional(),
32444
32435
  showCapacity: z$1.boolean().optional(),
32436
+ showSessions: z$1.boolean().optional(),
32437
+ showPrice: z$1.boolean().optional(),
32445
32438
  successMessage: z$1.string().optional(),
32446
32439
  waitlistMessage: z$1.string().optional(),
32440
+ membershipMessage: z$1.string().optional(),
32447
32441
  buttonVariant: registrationButtonVariantSchema.optional(),
32448
32442
  overlayEnabled: z$1.boolean().optional(),
32449
32443
  spamProtectionEnabled: z$1.boolean().optional(),
32450
- stage: previewStageSchema.optional(),
32451
32444
  supportEmail: z$1.string().optional(),
32452
32445
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
32453
32446
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
32447
+ };
32448
+ const eventRegistrationSourceSchema = z$1.object({
32449
+ siteId: z$1.string().optional(),
32450
+ apiBaseUrl: z$1.string().optional(),
32451
+ portalToken: z$1.string().nullable().optional(),
32452
+ previewToken: z$1.string().nullable().optional(),
32453
+ ...eventRegistrationHydrationSchemaShape,
32454
+ className: z$1.string().nullable().optional(),
32455
+ buttonText: z$1.string().nullable().optional(),
32456
+ maxTickets: z$1.string().nullable().optional(),
32457
+ stage: previewStageSchema.optional()
32454
32458
  });
32455
32459
  const eventRegistrationDisplaySchema = z$1.object({
32456
32460
  kind: z$1.literal("event-registration"),
@@ -32461,22 +32465,7 @@ const eventRegistrationDisplaySchema = z$1.object({
32461
32465
  stepLabels: z$1.array(z$1.enum(EVENT_REGISTRATION_SHELL_STEP_LABELS)).min(1),
32462
32466
  summaryButtonText: z$1.string()
32463
32467
  });
32464
- const eventRegistrationHydrationSchema = z$1.object({
32465
- occurrenceContext: occurrenceContextSchema$1.optional(),
32466
- subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
32467
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
32468
- maxTickets: z$1.string().optional(),
32469
- showVenue: z$1.boolean().optional(),
32470
- showCapacity: z$1.boolean().optional(),
32471
- successMessage: z$1.string().optional(),
32472
- waitlistMessage: z$1.string().optional(),
32473
- buttonVariant: registrationButtonVariantSchema.optional(),
32474
- overlayEnabled: z$1.boolean().optional(),
32475
- spamProtectionEnabled: z$1.boolean().optional(),
32476
- supportEmail: z$1.string().optional(),
32477
- sitePasses: publicPassProductCollectionSchema.nullable().optional(),
32478
- siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
32479
- });
32468
+ const eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
32480
32469
  const eventRegistrationRenderSchema = z$1.object({
32481
32470
  display: eventRegistrationDisplaySchema,
32482
32471
  hydration: eventRegistrationHydrationSchema
@@ -32556,11 +32545,16 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
32556
32545
  occurrenceContext: source.occurrenceContext ?? null,
32557
32546
  subject: source.subject ?? null,
32558
32547
  events: source.events ?? null,
32548
+ wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
32549
+ wholeSeriesOffering: source.wholeSeriesOffering ?? null,
32559
32550
  maxTickets: source.maxTickets ?? void 0,
32560
32551
  showVenue: source.showVenue,
32561
32552
  showCapacity: source.showCapacity,
32553
+ showSessions: source.showSessions,
32554
+ showPrice: source.showPrice,
32562
32555
  successMessage: source.successMessage,
32563
32556
  waitlistMessage: source.waitlistMessage,
32557
+ membershipMessage: source.membershipMessage,
32564
32558
  buttonVariant: source.buttonVariant,
32565
32559
  overlayEnabled: source.overlayEnabled,
32566
32560
  spamProtectionEnabled: source.spamProtectionEnabled,
@@ -32595,6 +32589,159 @@ function buildEventRegistrationInteractiveIslandProps(props) {
32595
32589
  source: props
32596
32590
  });
32597
32591
  }
32592
+ //#endregion
32593
+ //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
32594
+ function isSaleWindowOpen(option, now) {
32595
+ if (!option.isActive) return false;
32596
+ if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
32597
+ if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
32598
+ return true;
32599
+ }
32600
+ function toExactOrFreeDisplay(amount, currency) {
32601
+ if (amount <= 0) return {
32602
+ kind: "free",
32603
+ currency
32604
+ };
32605
+ return {
32606
+ kind: "exact",
32607
+ amount,
32608
+ currency
32609
+ };
32610
+ }
32611
+ function getSelectableCoursePricingOptionsForNow(course, now) {
32612
+ if (course.pricing.pricingStrategy !== "tiered") return [];
32613
+ return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
32614
+ if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
32615
+ if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
32616
+ return left.name.localeCompare(right.name);
32617
+ });
32618
+ }
32619
+ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
32620
+ const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
32621
+ const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
32622
+ const currency = course.pricing.currency;
32623
+ switch (course.pricing.pricingStrategy) {
32624
+ case "free": return {
32625
+ currency,
32626
+ display: {
32627
+ kind: "free",
32628
+ currency
32629
+ },
32630
+ selectableOptions: [],
32631
+ requiresSelection: false,
32632
+ selectedOption: null,
32633
+ slidingScale: null,
32634
+ selectedSlidingAmount: null,
32635
+ selectedPriceAmount: 0,
32636
+ selectedRequiresPayment: false,
32637
+ hasPaidSelection: false,
32638
+ hasFreeSelection: true
32639
+ };
32640
+ case "single": {
32641
+ const amount = course.pricing.singlePriceAmount ?? 0;
32642
+ return {
32643
+ currency,
32644
+ display: toExactOrFreeDisplay(amount, currency),
32645
+ selectableOptions: [],
32646
+ requiresSelection: false,
32647
+ selectedOption: null,
32648
+ slidingScale: null,
32649
+ selectedSlidingAmount: null,
32650
+ selectedPriceAmount: amount,
32651
+ selectedRequiresPayment: amount > 0,
32652
+ hasPaidSelection: amount > 0,
32653
+ hasFreeSelection: amount <= 0
32654
+ };
32655
+ }
32656
+ case "tiered": {
32657
+ const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
32658
+ const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
32659
+ const lowestAmount = selectableOptions.reduce((lowest, option) => {
32660
+ if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
32661
+ return lowest;
32662
+ }, null);
32663
+ return {
32664
+ currency,
32665
+ display: lowestAmount === null ? {
32666
+ kind: "unavailable",
32667
+ currency
32668
+ } : selectableOptions.length > 1 && lowestAmount > 0 ? {
32669
+ kind: "from",
32670
+ amount: lowestAmount,
32671
+ currency
32672
+ } : toExactOrFreeDisplay(lowestAmount, currency),
32673
+ selectableOptions,
32674
+ requiresSelection: selectableOptions.length > 1,
32675
+ selectedOption,
32676
+ slidingScale: null,
32677
+ selectedSlidingAmount: null,
32678
+ selectedPriceAmount: selectedOption?.priceAmount ?? null,
32679
+ selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
32680
+ hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
32681
+ hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
32682
+ };
32683
+ }
32684
+ case "sliding_scale": {
32685
+ const minAmount = course.pricing.slidingMinAmount ?? null;
32686
+ const maxAmount = course.pricing.slidingMaxAmount ?? null;
32687
+ if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
32688
+ currency,
32689
+ display: {
32690
+ kind: "unavailable",
32691
+ currency
32692
+ },
32693
+ selectableOptions: [],
32694
+ requiresSelection: true,
32695
+ selectedOption: null,
32696
+ slidingScale: null,
32697
+ selectedSlidingAmount: null,
32698
+ selectedPriceAmount: null,
32699
+ selectedRequiresPayment: false,
32700
+ hasPaidSelection: false,
32701
+ hasFreeSelection: false
32702
+ };
32703
+ const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
32704
+ return {
32705
+ currency,
32706
+ display: {
32707
+ kind: "range",
32708
+ minAmount,
32709
+ maxAmount,
32710
+ currency
32711
+ },
32712
+ selectableOptions: [],
32713
+ requiresSelection: normalizedSelectedAmount === null,
32714
+ selectedOption: null,
32715
+ slidingScale: {
32716
+ minAmount,
32717
+ maxAmount,
32718
+ suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
32719
+ },
32720
+ selectedSlidingAmount: normalizedSelectedAmount,
32721
+ selectedPriceAmount: normalizedSelectedAmount,
32722
+ selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
32723
+ hasPaidSelection: maxAmount > 0,
32724
+ hasFreeSelection: minAmount === 0
32725
+ };
32726
+ }
32727
+ }
32728
+ }
32729
+ function formatCoursePriceDisplay(display, locale) {
32730
+ return formatBookingPriceDisplay(display, {
32731
+ decimals: "exact",
32732
+ locale
32733
+ });
32734
+ }
32735
+ function formatCoursePriceAmount(amount, currency, locale) {
32736
+ return formatCoursePriceDisplay(amount > 0 ? {
32737
+ kind: "exact",
32738
+ amount,
32739
+ currency
32740
+ } : {
32741
+ kind: "free",
32742
+ currency
32743
+ }, locale);
32744
+ }
32598
32745
  const eventRegistrationBlockDefinition = {
32599
32746
  manifest: createBlockManifest({
32600
32747
  id: "block.event-registration",
@@ -32690,6 +32837,24 @@ const eventRegistrationBlockDefinition = {
32690
32837
  defaultValue: true,
32691
32838
  ui: { intent: "display" }
32692
32839
  },
32840
+ {
32841
+ id: "showSessions",
32842
+ type: "boolean",
32843
+ label: "Show complete schedule",
32844
+ description: "Display every session for whole-series registrations",
32845
+ required: false,
32846
+ defaultValue: true,
32847
+ ui: { intent: "display" }
32848
+ },
32849
+ {
32850
+ id: "showPrice",
32851
+ type: "boolean",
32852
+ label: "Show price",
32853
+ description: "Display the whole-series price",
32854
+ required: false,
32855
+ defaultValue: true,
32856
+ ui: { intent: "display" }
32857
+ },
32693
32858
  {
32694
32859
  id: "successMessage",
32695
32860
  type: "text",
@@ -32700,6 +32865,26 @@ const eventRegistrationBlockDefinition = {
32700
32865
  defaultValue: "Thank you for registering! Check your email for confirmation details.",
32701
32866
  maxLength: 500
32702
32867
  },
32868
+ {
32869
+ id: "waitlistMessage",
32870
+ type: "text",
32871
+ label: "Waitlist message",
32872
+ description: "Message shown after joining a whole-series waitlist",
32873
+ required: false,
32874
+ multiline: true,
32875
+ defaultValue: "You've been added to the waitlist. We'll email you if a place becomes available.",
32876
+ maxLength: 500
32877
+ },
32878
+ {
32879
+ id: "membershipMessage",
32880
+ type: "text",
32881
+ label: "Membership registration message",
32882
+ description: "Message shown when a whole-series place is covered by membership",
32883
+ required: false,
32884
+ multiline: true,
32885
+ defaultValue: "Registered using your membership. Check your email for session details.",
32886
+ maxLength: 500
32887
+ },
32703
32888
  {
32704
32889
  id: "buttonText",
32705
32890
  type: "text",
@@ -32731,8 +32916,11 @@ const eventRegistrationBlockDefinition = {
32731
32916
  } },
32732
32917
  showVenue: { $bind: { from: "content.showVenue" } },
32733
32918
  showCapacity: { $bind: { from: "content.showCapacity" } },
32919
+ showSessions: { $bind: { from: "content.showSessions" } },
32920
+ showPrice: { $bind: { from: "content.showPrice" } },
32734
32921
  successMessage: { $bind: { from: "content.successMessage" } },
32735
32922
  waitlistMessage: { $bind: { from: "content.waitlistMessage" } },
32923
+ membershipMessage: { $bind: { from: "content.membershipMessage" } },
32736
32924
  buttonText: { $bind: {
32737
32925
  from: "content.buttonText",
32738
32926
  fallback: "Complete Registration"
@@ -32746,6 +32934,7 @@ const eventRegistrationBlockDefinition = {
32746
32934
  fallback: false
32747
32935
  } },
32748
32936
  events: { $bind: { from: "data.events" } },
32937
+ wholeSeriesOffering: { $bind: { from: "data.wholeSeriesOffering.offering" } },
32749
32938
  sitePasses: { $bind: { from: "data.sitePasses" } },
32750
32939
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
32751
32940
  stage: { $bind: {
@@ -32759,9 +32948,10 @@ const eventRegistrationBlockDefinition = {
32759
32948
  runtime: eventRegistrationBlockRuntime,
32760
32949
  dataSchemas: {
32761
32950
  events: publicEventsArraySchema.optional(),
32951
+ wholeSeriesOffering: z$1.object({ offering: publicCourseSchema }).optional(),
32762
32952
  sitePasses: publicPassProductCollectionSchema.optional(),
32763
32953
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
32764
- occurrenceContext: occurrenceContextSchema$1.optional()
32954
+ occurrenceContext: occurrenceContextSchema.optional()
32765
32955
  },
32766
32956
  dataLoaders: {
32767
32957
  events: {
@@ -32774,11 +32964,23 @@ const eventRegistrationBlockDefinition = {
32774
32964
  fallback: "published"
32775
32965
  } },
32776
32966
  readProfile: "registration",
32777
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
32967
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32778
32968
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
32779
32969
  },
32780
32970
  mode: "server"
32781
32971
  },
32972
+ wholeSeriesOffering: {
32973
+ endpoint: "getPublicWholeSeriesOffering",
32974
+ params: {
32975
+ siteId: { $bind: { from: "$root.siteId" } },
32976
+ eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32977
+ stage: { $bind: {
32978
+ from: "$root.previewStage",
32979
+ fallback: "published"
32980
+ } }
32981
+ },
32982
+ mode: "server"
32983
+ },
32782
32984
  sitePasses: {
32783
32985
  endpoint: "listPublicPasses",
32784
32986
  params: { siteId: { $bind: { from: "$root.siteId" } } },
@@ -32792,159 +32994,6 @@ const eventRegistrationBlockDefinition = {
32792
32994
  }
32793
32995
  };
32794
32996
  //#endregion
32795
- //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
32796
- function isSaleWindowOpen(option, now) {
32797
- if (!option.isActive) return false;
32798
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
32799
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
32800
- return true;
32801
- }
32802
- function toExactOrFreeDisplay(amount, currency) {
32803
- if (amount <= 0) return {
32804
- kind: "free",
32805
- currency
32806
- };
32807
- return {
32808
- kind: "exact",
32809
- amount,
32810
- currency
32811
- };
32812
- }
32813
- function getSelectableCoursePricingOptionsForNow(course, now) {
32814
- if (course.pricing.pricingStrategy !== "tiered") return [];
32815
- return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
32816
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
32817
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
32818
- return left.name.localeCompare(right.name);
32819
- });
32820
- }
32821
- function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
32822
- const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
32823
- const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
32824
- const currency = course.pricing.currency;
32825
- switch (course.pricing.pricingStrategy) {
32826
- case "free": return {
32827
- currency,
32828
- display: {
32829
- kind: "free",
32830
- currency
32831
- },
32832
- selectableOptions: [],
32833
- requiresSelection: false,
32834
- selectedOption: null,
32835
- slidingScale: null,
32836
- selectedSlidingAmount: null,
32837
- selectedPriceAmount: 0,
32838
- selectedRequiresPayment: false,
32839
- hasPaidSelection: false,
32840
- hasFreeSelection: true
32841
- };
32842
- case "single": {
32843
- const amount = course.pricing.singlePriceAmount ?? 0;
32844
- return {
32845
- currency,
32846
- display: toExactOrFreeDisplay(amount, currency),
32847
- selectableOptions: [],
32848
- requiresSelection: false,
32849
- selectedOption: null,
32850
- slidingScale: null,
32851
- selectedSlidingAmount: null,
32852
- selectedPriceAmount: amount,
32853
- selectedRequiresPayment: amount > 0,
32854
- hasPaidSelection: amount > 0,
32855
- hasFreeSelection: amount <= 0
32856
- };
32857
- }
32858
- case "tiered": {
32859
- const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
32860
- const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
32861
- const lowestAmount = selectableOptions.reduce((lowest, option) => {
32862
- if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
32863
- return lowest;
32864
- }, null);
32865
- return {
32866
- currency,
32867
- display: lowestAmount === null ? {
32868
- kind: "unavailable",
32869
- currency
32870
- } : selectableOptions.length > 1 && lowestAmount > 0 ? {
32871
- kind: "from",
32872
- amount: lowestAmount,
32873
- currency
32874
- } : toExactOrFreeDisplay(lowestAmount, currency),
32875
- selectableOptions,
32876
- requiresSelection: selectableOptions.length > 1,
32877
- selectedOption,
32878
- slidingScale: null,
32879
- selectedSlidingAmount: null,
32880
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
32881
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
32882
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
32883
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
32884
- };
32885
- }
32886
- case "sliding_scale": {
32887
- const minAmount = course.pricing.slidingMinAmount ?? null;
32888
- const maxAmount = course.pricing.slidingMaxAmount ?? null;
32889
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
32890
- currency,
32891
- display: {
32892
- kind: "unavailable",
32893
- currency
32894
- },
32895
- selectableOptions: [],
32896
- requiresSelection: true,
32897
- selectedOption: null,
32898
- slidingScale: null,
32899
- selectedSlidingAmount: null,
32900
- selectedPriceAmount: null,
32901
- selectedRequiresPayment: false,
32902
- hasPaidSelection: false,
32903
- hasFreeSelection: false
32904
- };
32905
- const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
32906
- return {
32907
- currency,
32908
- display: {
32909
- kind: "range",
32910
- minAmount,
32911
- maxAmount,
32912
- currency
32913
- },
32914
- selectableOptions: [],
32915
- requiresSelection: normalizedSelectedAmount === null,
32916
- selectedOption: null,
32917
- slidingScale: {
32918
- minAmount,
32919
- maxAmount,
32920
- suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
32921
- },
32922
- selectedSlidingAmount: normalizedSelectedAmount,
32923
- selectedPriceAmount: normalizedSelectedAmount,
32924
- selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
32925
- hasPaidSelection: maxAmount > 0,
32926
- hasFreeSelection: minAmount === 0
32927
- };
32928
- }
32929
- }
32930
- }
32931
- function formatCoursePriceDisplay(display, locale) {
32932
- return formatBookingPriceDisplay(display, {
32933
- decimals: "exact",
32934
- locale
32935
- });
32936
- }
32937
- function formatCoursePriceAmount(amount, currency, locale) {
32938
- return formatCoursePriceDisplay(amount > 0 ? {
32939
- kind: "exact",
32940
- amount,
32941
- currency
32942
- } : {
32943
- kind: "free",
32944
- currency
32945
- }, locale);
32946
- }
32947
- //#endregion
32948
32997
  //#region ../blocks/src/system/runtime/nodes/course-registration.interactive.ts
32949
32998
  const courseRegistrationSourceSchema = z$1.object({
32950
32999
  siteId: z$1.string().optional(),
@@ -33379,15 +33428,6 @@ const eventDetailsManifest = createBlockManifest({
33379
33428
  })], { gap: "lg" })
33380
33429
  })]
33381
33430
  });
33382
- const occurrenceContextSchema = z$1.object({
33383
- id: z$1.string(),
33384
- seriesId: z$1.string(),
33385
- startsAt: z$1.string(),
33386
- endsAt: z$1.string(),
33387
- timeZone: z$1.string(),
33388
- capacityOverride: z$1.number().nullable().optional(),
33389
- overrides: z$1.record(z$1.string(), z$1.unknown()).nullable().optional()
33390
- }).nullable();
33391
33431
  const eventAutoApplyDiscountPreviewBaseSchema = z$1.object({
33392
33432
  id: z$1.string(),
33393
33433
  publicLabel: z$1.string(),
@@ -33422,8 +33462,9 @@ const eventDetailsBlockDefinition = {
33422
33462
  from: "$root.previewStage",
33423
33463
  fallback: "published"
33424
33464
  } },
33425
- limit: "25",
33426
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
33465
+ limit: "100",
33466
+ readProfile: "details",
33467
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
33427
33468
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
33428
33469
  },
33429
33470
  mode: "server"
@@ -41990,9 +42031,6 @@ function parseSignedNewsletterDestinationRef(value) {
41990
42031
  const trimmed = parseTrimmedString$1(value);
41991
42032
  return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
41992
42033
  }
41993
- function parseNewsletterSignupDestinationProvider(value) {
41994
- return value === "riverbank" || value === "mailchimp" ? value : null;
41995
- }
41996
42034
  function buildNewsletterSignupBlockRef(blockId) {
41997
42035
  const parsed = parseNewsletterSignupBlockId(blockId);
41998
42036
  return parsed ? {
@@ -42139,19 +42177,9 @@ const newsletterFieldSchema = z$1.object({
42139
42177
  });
42140
42178
  const newsletterSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
42141
42179
  const signedNewsletterDestinationRefSchema = z$1.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
42142
- const newsletterPublicDestinationRefSchema = z$1.discriminatedUnion("tag", [z$1.object({
42143
- tag: z$1.literal("block_ref"),
42144
- blockId: newsletterSignupBlockIdSchema
42145
- }), z$1.object({
42146
- tag: z$1.literal("signed_destination_ref"),
42147
- token: signedNewsletterDestinationRefSchema
42148
- })]);
42149
- const newsletterSourceSchema = z$1.object({
42150
- blockId: z$1.string().nullable().optional(),
42180
+ const newsletterSourceCommonSchema = z$1.object({
42151
42181
  siteId: z$1.string().optional(),
42152
42182
  apiBaseUrl: z$1.string().optional(),
42153
- listId: z$1.string().nullable().optional(),
42154
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
42155
42183
  preset: newsletterPresetSchema.optional(),
42156
42184
  includePhone: z$1.boolean().optional(),
42157
42185
  buttonLabel: z$1.string().nullable().optional(),
@@ -42162,6 +42190,25 @@ const newsletterSourceSchema = z$1.object({
42162
42190
  spamProtectionEnabled: z$1.boolean().optional(),
42163
42191
  className: z$1.string().nullable().optional()
42164
42192
  });
42193
+ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
42194
+ newsletterSourceCommonSchema.extend({
42195
+ source: z$1.literal("block"),
42196
+ blockId: z$1.string().nullable().optional(),
42197
+ listId: z$1.string().nullable().optional(),
42198
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
42199
+ }),
42200
+ newsletterSourceCommonSchema.extend({
42201
+ source: z$1.literal("signed-footer"),
42202
+ destinationRef: z$1.object({
42203
+ tag: z$1.literal("signed_destination_ref"),
42204
+ token: signedNewsletterDestinationRefSchema
42205
+ })
42206
+ }),
42207
+ newsletterSourceCommonSchema.extend({
42208
+ source: z$1.literal("legacy-direct-list"),
42209
+ listId: z$1.string().nullable()
42210
+ })
42211
+ ]);
42165
42212
  const newsletterDisplaySchema = z$1.object({
42166
42213
  kind: z$1.literal("newsletter-form"),
42167
42214
  className: z$1.string().nullable(),
@@ -42172,8 +42219,26 @@ const newsletterDisplaySchema = z$1.object({
42172
42219
  fields: z$1.array(newsletterFieldSchema)
42173
42220
  });
42174
42221
  const newsletterHydrationSchema = z$1.object({
42175
- destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
42176
- listId: z$1.string().nullable().optional(),
42222
+ target: z$1.discriminatedUnion("tag", [
42223
+ z$1.object({
42224
+ tag: z$1.literal("block-source"),
42225
+ destinationRef: z$1.object({
42226
+ tag: z$1.literal("block_ref"),
42227
+ blockId: newsletterSignupBlockIdSchema
42228
+ }).nullable()
42229
+ }),
42230
+ z$1.object({
42231
+ tag: z$1.literal("signed-footer-source"),
42232
+ destinationRef: z$1.object({
42233
+ tag: z$1.literal("signed_destination_ref"),
42234
+ token: signedNewsletterDestinationRefSchema
42235
+ })
42236
+ }),
42237
+ z$1.object({
42238
+ tag: z$1.literal("legacy-direct-list"),
42239
+ listId: z$1.string().nullable()
42240
+ })
42241
+ ]),
42177
42242
  preset: newsletterPresetSchema,
42178
42243
  includePhone: z$1.boolean(),
42179
42244
  tags: z$1.string().nullable().optional(),
@@ -42207,20 +42272,43 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
42207
42272
  render: createZodCodec(newsletterRenderSchema)
42208
42273
  },
42209
42274
  buildRender: (source) => {
42210
- const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
42275
+ const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
42211
42276
  return {
42212
42277
  display: buildNewsletterDisplay(source),
42213
42278
  hydration: {
42214
- destinationRef: buildNewsletterSignupBlockRef(source.blockId),
42215
- listId: runtimeSource.listId,
42279
+ target: projectNewsletterFormHydrationTarget(source),
42216
42280
  preset: source.preset ?? "emailOnly",
42217
42281
  includePhone: source.includePhone ?? false,
42218
- tags: runtimeSource.tags,
42282
+ tags: runtimeSource ? runtimeSource.tags : source.tags,
42219
42283
  spamProtectionEnabled: source.spamProtectionEnabled
42220
42284
  }
42221
42285
  };
42222
42286
  }
42223
42287
  });
42288
+ function projectNewsletterFormHydrationTarget(source) {
42289
+ switch (source.source) {
42290
+ case "block": {
42291
+ const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
42292
+ if (destinationRef?.tag === "block_ref") return {
42293
+ tag: "block-source",
42294
+ destinationRef
42295
+ };
42296
+ return {
42297
+ tag: "legacy-direct-list",
42298
+ listId: source.listId ?? null
42299
+ };
42300
+ }
42301
+ case "signed-footer": return {
42302
+ tag: "signed-footer-source",
42303
+ destinationRef: source.destinationRef
42304
+ };
42305
+ case "legacy-direct-list": return {
42306
+ tag: "legacy-direct-list",
42307
+ listId: source.listId
42308
+ };
42309
+ default: return assertNever$24(source);
42310
+ }
42311
+ }
42224
42312
  function buildNewsletterFormInteractiveIslandProps(props) {
42225
42313
  return buildInteractiveIslandProps({
42226
42314
  runtime: newsletterFormBlockRuntime,
@@ -42336,7 +42424,7 @@ const newsletterSignupBlockDefinition = {
42336
42424
  //#endregion
42337
42425
  //#region ../blocks/src/system/blocks/team-members.ts
42338
42426
  const ITEM_NAME = "member";
42339
- const teamMemberPhotoSchema = mediaSchema.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
42427
+ const teamMemberPhotoSchema = mediaSchema$1.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
42340
42428
  const teamMemberDataSchema = z$1.object({
42341
42429
  _type: z$1.literal("teamMember"),
42342
42430
  id: z$1.string(),
@@ -43911,7 +43999,7 @@ function getBlockDefinition(name) {
43911
43999
  //#endregion
43912
44000
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
43913
44001
  function resolveBackgroundMedia(input) {
43914
- const parsedMedia = mediaSchema.safeParse(input.image);
44002
+ const parsedMedia = mediaSchema$1.safeParse(input.image);
43915
44003
  if (!parsedMedia.success) return null;
43916
44004
  switch (parsedMedia.data.type) {
43917
44005
  case "image":
@@ -45142,6 +45230,9 @@ function renderTrailingAffordanceIcon(affordance) {
45142
45230
  className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block"
45143
45231
  });
45144
45232
  }
45233
+ function isMissingRequiredLink(linkRequired, resolvedHref) {
45234
+ return linkRequired && resolvedHref.length === 0;
45235
+ }
45145
45236
  const ButtonNode = ({ value, children, href, variantId = "primary", size = "md", disabled, type = "button", target, rel, linkRequired = false, trailingIcon, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, className, ...rest }) => {
45146
45237
  const content = value ?? children;
45147
45238
  if (!content) {
@@ -45150,12 +45241,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
45150
45241
  }
45151
45242
  const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({ trailingIcon }));
45152
45243
  const resolvedHref = typeof href === "string" ? href.trim() : "";
45153
- if (linkRequired && resolvedHref.length === 0) {
45244
+ if (isMissingRequiredLink(linkRequired, resolvedHref)) {
45154
45245
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
45155
45246
  return null;
45156
45247
  }
45157
45248
  const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
45158
- const resolvedVariantId = parseThemeButtonVariantId(canonicalizePersistedBlockButtonRole(variantId));
45249
+ const resolvedVariantId = parseThemeButtonVariantId(variantId);
45250
+ if (variantId && !resolvedVariantId) {
45251
+ console.error("[ButtonNode] Invalid button variant", { variantId });
45252
+ return null;
45253
+ }
45159
45254
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
45160
45255
  variant: resolvedVariantId,
45161
45256
  size,
@@ -45284,8 +45379,9 @@ function iconForMediaType(type) {
45284
45379
  });
45285
45380
  }
45286
45381
  }
45287
- function normalizeButtonVariant(value) {
45288
- return isBlockButtonRole(value) ? value : "primary";
45382
+ function parseButtonVariant(value) {
45383
+ if (value === null || value === void 0) return "primary";
45384
+ return isBlockButtonRole(value) ? value : null;
45289
45385
  }
45290
45386
  function FileDownloadNode({ value, title, description, buttonLabel, buttonVariant, className }) {
45291
45387
  if (!value || !isDownloadableMediaType(value.type)) return null;
@@ -45295,7 +45391,11 @@ function FileDownloadNode({ value, title, description, buttonLabel, buttonVarian
45295
45391
  const heading = title?.trim() || filename;
45296
45392
  const body = description?.trim();
45297
45393
  const label = buttonLabel?.trim() || "Download";
45298
- const variant = normalizeButtonVariant(buttonVariant);
45394
+ const variant = parseButtonVariant(buttonVariant);
45395
+ if (!variant) {
45396
+ console.error("[FileDownloadNode] Invalid button variant", { buttonVariant });
45397
+ return null;
45398
+ }
45299
45399
  return /* @__PURE__ */ jsx("div", {
45300
45400
  className,
45301
45401
  children: /* @__PURE__ */ jsxs("div", {
@@ -46470,6 +46570,33 @@ function uniqByOccurrenceId(events) {
46470
46570
  }
46471
46571
  return out;
46472
46572
  }
46573
+ function selectFromOccurrenceContext(events, occurrenceContext) {
46574
+ if (!occurrenceContext) return null;
46575
+ const byId = events.find((event) => event.occurrenceId === occurrenceContext.id || event.id === occurrenceContext.id);
46576
+ if (byId) return byId;
46577
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46578
+ startsAt: occurrenceContext.startsAt,
46579
+ timeZone: occurrenceContext.timeZone
46580
+ }));
46581
+ return events.find((event) => getBookingLocalDateKey(toScheduledBookingDateTime({
46582
+ startsAt: event.startsAt,
46583
+ timeZone: event.timeZone
46584
+ })) === contextDate) ?? null;
46585
+ }
46586
+ function selectNextUpcoming(events, nowIso) {
46587
+ return [...events].filter((event) => isFutureOrNow(event.startsAt, nowIso)).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt))[0] ?? null;
46588
+ }
46589
+ function selectCompletedWholeSeries(events) {
46590
+ if (events.length === 0 || !events.every((event) => event.bookingScope === "whole_series")) return null;
46591
+ return [...events].sort((left, right) => Date.parse(right.startsAt) - Date.parse(left.startsAt))[0] ?? null;
46592
+ }
46593
+ function selectRelatedDates(input) {
46594
+ if (!input.seriesId) return [];
46595
+ const isWholeSeries = input.selected?.bookingScope === "whole_series";
46596
+ const selectedOccurrenceId = input.selected ? input.selected.occurrenceId || input.selected.id : null;
46597
+ const dates = input.events.filter((event) => event.seriesId === input.seriesId).filter((event) => isWholeSeries || isFutureOrNow(event.startsAt, input.nowIso)).filter((event) => !selectedOccurrenceId || (event.occurrenceId || event.id) !== selectedOccurrenceId).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt));
46598
+ return isWholeSeries ? dates : dates.slice(0, input.limit);
46599
+ }
46473
46600
  function selectEventDetails(args) {
46474
46601
  const all = uniqByOccurrenceId(resolveEventRegistrationScopedEvents((args.events ?? []).filter(Boolean), {
46475
46602
  occurrenceContext: args.occurrenceContext,
@@ -46477,37 +46604,22 @@ function selectEventDetails(args) {
46477
46604
  }));
46478
46605
  const occurrenceContext = args.occurrenceContext ?? null;
46479
46606
  const otherLimit = parseLimit$1(args.otherDatesLimit, 5);
46480
- const selectedFromContext = (() => {
46481
- if (!occurrenceContext) return null;
46482
- const byId = all.find((e) => e.occurrenceId === occurrenceContext.id || e.id === occurrenceContext.id) ?? null;
46483
- if (byId) return byId;
46484
- const ctxDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46485
- startsAt: occurrenceContext.startsAt,
46486
- timeZone: occurrenceContext.timeZone
46487
- }));
46488
- return all.find((e) => getBookingLocalDateKey(toScheduledBookingDateTime({
46489
- startsAt: e.startsAt,
46490
- timeZone: e.timeZone
46491
- })) === ctxDate) ?? null;
46492
- })();
46493
- const nextUpcoming = (() => {
46494
- const upcoming = all.filter((e) => isFutureOrNow(e.startsAt, args.nowIso));
46495
- upcoming.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
46496
- return upcoming[0] ?? null;
46497
- })();
46498
- const mode = selectedFromContext ? "selected" : "next";
46499
- const selected = selectedFromContext ?? nextUpcoming;
46607
+ const selectedFromContext = selectFromOccurrenceContext(all, occurrenceContext);
46608
+ const nextUpcoming = selectNextUpcoming(all, args.nowIso);
46609
+ const completedWholeSeries = selectCompletedWholeSeries(all);
46610
+ const selected = selectedFromContext ?? nextUpcoming ?? completedWholeSeries;
46611
+ const mode = selectedFromContext ? "selected" : nextUpcoming ? "next" : completedWholeSeries ? "completed" : "next";
46500
46612
  const timeZone = toBookingTimeZone(selected?.timeZone ?? all[0]?.timeZone ?? null);
46501
- const seriesId = occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null;
46502
- const selectedOccurrenceId = selected?.occurrenceId ?? null;
46503
46613
  return {
46504
46614
  mode,
46505
46615
  selected,
46506
- otherDates: seriesId ? all.filter((e) => e.seriesId === seriesId).filter((e) => isFutureOrNow(e.startsAt, args.nowIso)).filter((e) => {
46507
- const occId = e.occurrenceId || e.id;
46508
- if (selectedOccurrenceId && occId === selectedOccurrenceId) return false;
46509
- return true;
46510
- }).slice(0, otherLimit) : [],
46616
+ otherDates: selectRelatedDates({
46617
+ events: all,
46618
+ seriesId: occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null,
46619
+ selected,
46620
+ nowIso: args.nowIso,
46621
+ limit: otherLimit
46622
+ }),
46511
46623
  timeZone
46512
46624
  };
46513
46625
  }
@@ -46629,7 +46741,7 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46629
46741
  /* @__PURE__ */ jsxs("div", { children: [
46630
46742
  /* @__PURE__ */ jsx("div", {
46631
46743
  className: "rb-label rb-mb-2",
46632
- children: selection.mode === "next" ? "Next date" : "Date"
46744
+ children: selected.bookingScope === "whole_series" ? selection.mode === "next" ? "Next session" : "Selected session" : selection.mode === "next" ? "Next date" : "Date"
46633
46745
  }),
46634
46746
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: date }) }),
46635
46747
  /* @__PURE__ */ jsx("p", {
@@ -46667,18 +46779,27 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46667
46779
  }) : null] }, member.id))
46668
46780
  })]
46669
46781
  }) : null,
46670
- pricing
46782
+ pricing,
46783
+ selected.bookingScope === "whole_series" ? /* @__PURE__ */ jsxs("div", {
46784
+ className: "rb-mt-6",
46785
+ children: [/* @__PURE__ */ jsx("div", {
46786
+ className: "rb-label rb-mb-2",
46787
+ children: "Registration"
46788
+ }), /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: selected.wholeSeries?.enrollmentOpen ? "Open" : "Closed" }) })]
46789
+ }) : null
46671
46790
  ]
46672
46791
  });
46673
46792
  }
46674
46793
  function OtherEventDates({ selection }) {
46675
- if (selection.otherDates.length === 0) return null;
46794
+ const isWholeSeries = selection.selected?.bookingScope === "whole_series";
46795
+ const dates = isWholeSeries && selection.selected ? [selection.selected, ...selection.otherDates].sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt)) : selection.otherDates;
46796
+ if (dates.length === 0) return null;
46676
46797
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
46677
46798
  className: "rb-label",
46678
- children: "Other dates"
46799
+ children: isWholeSeries ? "Session schedule" : "Other dates"
46679
46800
  }), /* @__PURE__ */ jsx("div", {
46680
46801
  className: "rb-mt-2 rb-tiles-grid",
46681
- children: selection.otherDates.map((event) => /* @__PURE__ */ jsx("a", {
46802
+ children: dates.map((event) => /* @__PURE__ */ jsx("a", {
46682
46803
  className: "rb-tile rb-tile--interactive",
46683
46804
  ...resolveEventLinkProps(event),
46684
46805
  children: /* @__PURE__ */ jsx(DateTimeTile, {
@@ -49877,13 +49998,13 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
49877
49998
  * Renders the newsletter signup form for SSR with hydration support.
49878
49999
  * Uses the islands architecture pattern to hydrate on the client.
49879
50000
  */
49880
- function NewsletterFormSSR({ blockId, siteId, apiBaseUrl, listId, destinationProvider, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className }) {
50001
+ function NewsletterFormSSR(props) {
50002
+ const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
50003
+ const blockId = props.source === "block" ? props.blockId : null;
49881
50004
  const islandProps = buildNewsletterFormInteractiveIslandProps({
49882
- blockId,
50005
+ ...props,
49883
50006
  siteId,
49884
50007
  apiBaseUrl,
49885
- listId,
49886
- destinationProvider,
49887
50008
  preset,
49888
50009
  includePhone,
49889
50010
  buttonLabel,
@@ -52216,6 +52337,35 @@ function resolveColorTokenHex(theme, colorToken) {
52216
52337
  if (colorToken === "transparent") return null;
52217
52338
  return expandPalette(theme.palette)[colorToken] ?? null;
52218
52339
  }
52340
+ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
52341
+ `min-width: 12rem;`,
52342
+ `width: max-content;`,
52343
+ `max-width: min(22rem, calc(100vw - 2rem));`,
52344
+ `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
52345
+ ];
52346
+ //#endregion
52347
+ //#region ../theme-core/src/header/surfaceRules.ts
52348
+ /** Compile the at-rest surface independently of scroll treatment and paint geometry. */
52349
+ function buildHeaderSurfaceRules(header, tokens) {
52350
+ const base = [];
52351
+ const background = header.background;
52352
+ if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
52353
+ else if (background.type === "gradient" && background.gradient) {
52354
+ const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
52355
+ base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
52356
+ }
52357
+ const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
52358
+ if (!header.border || borderWidth === "0") return {
52359
+ base,
52360
+ border: []
52361
+ };
52362
+ const color = rgbColorValue(header.border.colorToken?.trim() || "border");
52363
+ const style = header.border.style === "dashed" ? "dashed" : "solid";
52364
+ return {
52365
+ base,
52366
+ border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
52367
+ };
52368
+ }
52219
52369
  //#endregion
52220
52370
  //#region ../theme-core/src/navigation/presets.ts
52221
52371
  /**
@@ -52377,12 +52527,71 @@ function getNavLinkPreset(presetId) {
52377
52527
  return NAV_LINK_PRESETS[presetId];
52378
52528
  }
52379
52529
  Object.keys(NAV_LINK_PRESETS);
52380
- const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
52381
- `min-width: 12rem;`,
52382
- `width: max-content;`,
52383
- `max-width: min(22rem, calc(100vw - 2rem));`,
52384
- `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
52385
- ];
52530
+ //#endregion
52531
+ //#region ../theme-core/src/header/legacyNavLinkStyle.ts
52532
+ function buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize) {
52533
+ const navStyle = header.navStyle ?? "minimal";
52534
+ const basePreset = getNavLinkPreset(navStyle);
52535
+ if (!basePreset) return null;
52536
+ const style = {
52537
+ ...basePreset,
52538
+ fontWeight: header.navWeight ?? basePreset.fontWeight,
52539
+ colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
52540
+ ...contrastTreatment ? { contrastTreatment } : {},
52541
+ ...navTextSize ? { textSize: navTextSize } : {}
52542
+ };
52543
+ if (header.navWeight === "bold" && navStyle === "solid") style.textTransform = "uppercase";
52544
+ applyLegacyNavEffects(style, header);
52545
+ applyLegacyGlassTreatment(style, header, navStyle);
52546
+ return style;
52547
+ }
52548
+ function applyLegacyNavEffects(style, header) {
52549
+ if (!header.navEffects) return;
52550
+ const effects = style.effects = {
52551
+ ...style.effects,
52552
+ hover: [...style.effects?.hover ?? []],
52553
+ active: [...style.effects?.active ?? []]
52554
+ };
52555
+ if (header.navEffects.glow) effects.hover.push({
52556
+ effectId: "outer-glow",
52557
+ options: { spread: 5 }
52558
+ });
52559
+ if (header.navEffects.neumorphic) {
52560
+ effects.hover.push({
52561
+ effectId: "neumorphic-shadow",
52562
+ options: { mode: "pressed" }
52563
+ });
52564
+ effects.hover.push({
52565
+ effectId: "text-color-change",
52566
+ options: { hoverColorToken: "primary" }
52567
+ });
52568
+ }
52569
+ if (header.navEffects.underlineGradient) effects.hover.push({
52570
+ effectId: "border-bottom-grow",
52571
+ options: { origin: "center" }
52572
+ });
52573
+ }
52574
+ function applyLegacyGlassTreatment(style, header, navStyle) {
52575
+ if (header.navContainer?.type !== "glass" || navStyle !== "minimal") return;
52576
+ style.borderRadius = "full";
52577
+ style.effects = {
52578
+ ...style.effects,
52579
+ hover: glassStateEffects(10),
52580
+ active: glassStateEffects(18)
52581
+ };
52582
+ }
52583
+ function glassStateEffects(opacity) {
52584
+ return [{
52585
+ effectId: "background-on-hover-alpha",
52586
+ options: {
52587
+ colorToken: "neutral-50",
52588
+ opacity
52589
+ }
52590
+ }, {
52591
+ effectId: "text-color-change",
52592
+ options: { hoverColorToken: "neutral-50" }
52593
+ }];
52594
+ }
52386
52595
  //#endregion
52387
52596
  //#region ../theme-core/src/header/generateHeaderCss.ts
52388
52597
  const HEADER_BLUR = "blur(12px)";
@@ -52412,8 +52621,8 @@ function generateHeaderCss(options) {
52412
52621
  const cssChunks = [];
52413
52622
  const headerContrastTreatment = resolveHeaderContrastTreatment(header);
52414
52623
  const headerNavTextSize = resolveHeaderNavTextSize(header);
52415
- cssChunks.push(generateHeaderRootStyles(header, themeId, tokens, theme));
52416
- cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId));
52624
+ cssChunks.push(generateHeaderRootStyles(header, themeId, tokens));
52625
+ cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId, header.variant));
52417
52626
  cssChunks.push(generateLogoStyles({
52418
52627
  logo: header.logo,
52419
52628
  themeId,
@@ -52451,56 +52660,33 @@ function isClearSplitHeaderShape(header) {
52451
52660
  function isDetachedFloatingHeaderShape(header) {
52452
52661
  return header.variant === "floating" && !header.container;
52453
52662
  }
52454
- function generateMobileOverlayBackdropFilterFix(themeId) {
52455
- return `\n${`:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])::before`} {\n backdrop-filter: none !important;\n -webkit-backdrop-filter: none !important;\n}\n`;
52456
- }
52457
52663
  /**
52458
52664
  * Generate root header container styles
52459
52665
  */
52460
- function generateHeaderRootStyles(header, themeId, tokens, _theme) {
52666
+ function generateHeaderRootStyles(header, themeId, tokens) {
52461
52667
  const selector = `:where([data-theme-scope="${themeId}"]) .header-root`;
52462
- const backgroundSelector = `:where([data-theme-scope="${themeId}"]) .header-root::before`;
52463
52668
  const rules = [];
52464
- const backgroundRules = [];
52465
52669
  const navContainerType = header.navContainer?.type ?? "none";
52466
52670
  const isContainedNav = navContainerType === "pill" || navContainerType === "glass";
52467
52671
  rules.push("position: relative;");
52468
52672
  rules.push("isolation: isolate;");
52469
- if (!isContainedNav) {
52470
- const bg = header.background;
52471
- if (bg.type === "color") {
52472
- const bgColor = tokens.getColor(bg.color || "surface");
52473
- backgroundRules.push(`background-color: ${bgColor};`);
52474
- } else if (bg.type === "gradient" && bg.gradient) {
52475
- const stops = bg.gradient.stops.map((s) => tokens.getColor(s.color)).join(", ");
52476
- const angle = bg.gradient.angle ?? 180;
52477
- backgroundRules.push(`background-image: linear-gradient(${angle}deg, ${stops});`);
52478
- }
52479
- backgroundRules.push(`backdrop-filter: ${HEADER_BLUR};`);
52480
- backgroundRules.push(`-webkit-backdrop-filter: ${HEADER_BLUR};`);
52481
- if (header.border) {
52482
- const borderWidth = getComponentBorderWidthPx(header.border.width);
52483
- if (borderWidth !== "0") {
52484
- const borderToken = header.border?.colorToken?.trim() || "border";
52485
- const borderColor = tokens.getColor(borderToken);
52486
- const borderStyle = header.border.style === "dashed" ? "dashed" : "solid";
52487
- if (header.border.position === "bottom") rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
52488
- else if (header.border.position === "top") rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
52489
- else if (header.border.position === "both") {
52490
- rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
52491
- rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
52492
- }
52493
- }
52494
- }
52495
- }
52673
+ const surfaceRules = isContainedNav ? {
52674
+ base: [],
52675
+ border: []
52676
+ } : buildHeaderSurfaceRules(header, tokens);
52677
+ const floatingSurfaceBorder = header.variant === "floating";
52678
+ if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
52679
+ const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
52680
+ const scrolledPaintRules = floatingSurfaceBorder ? surfaceRules.border : [];
52496
52681
  if (header.positioning === "sticky" || header.positioning === "fixed") {
52497
52682
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
52498
52683
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
52499
52684
  }
52500
52685
  const baseBlock = `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
52501
52686
  const overlayFix = `\n${`${selector}:has([data-nav-mobile-overlay][aria-hidden="false"])`} {\n backdrop-filter: none !important;\n -webkit-backdrop-filter: none !important;\n}\n`;
52502
- if (isContainedNav || backgroundRules.length === 0) return `${baseBlock}\n${overlayFix}`;
52503
- return `${baseBlock}\n${`\n${backgroundSelector} {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n border-radius: inherit;\n z-index: -1;\n ${backgroundRules.join("\n ")}\n}\n`}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}`;
52687
+ const scrollTreatmentStyles = generateHeaderScrollTreatmentStyles(header.scrollTreatment, themeId, header.variant, scrolledPaintRules);
52688
+ if (isContainedNav || basePaintRules.length === 0) return `${baseBlock}\n${overlayFix}${scrollTreatmentStyles}`;
52689
+ return `${baseBlock}\n${renderHeaderPaintTargetRules(getHeaderPaintTargets(header.variant, themeId), basePaintRules)}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}${scrollTreatmentStyles}`;
52504
52690
  }
52505
52691
  /**
52506
52692
  * Reshapes the full-bleed header paint layer into a contained brand capsule at
@@ -52545,10 +52731,10 @@ function generateLogoStyles(input) {
52545
52731
  else rules.push(`font-family: var(--font-heading);`);
52546
52732
  if (logo) {
52547
52733
  if (logo.letterSpacing && logo.letterSpacing !== "normal") rules.push(`letter-spacing: ${{
52548
- "normal": "0em",
52549
- "wide": "0.05em",
52550
- "wider": "0.1em",
52551
- "widest": "0.15em"
52734
+ normal: "0em",
52735
+ wide: "0.05em",
52736
+ wider: "0.1em",
52737
+ widest: "0.15em"
52552
52738
  }[logo.letterSpacing]};`);
52553
52739
  if (logo.gradient) {
52554
52740
  rules.push(`background: linear-gradient(to right, ${primaryColor}, ${accentColor});`);
@@ -52621,71 +52807,11 @@ function generateNavLinkStyles(header, themeId, tokens, theme, contrastTreatment
52621
52807
  } : header.navLinkStyle, navPreferences),
52622
52808
  className: "header-nav-link"
52623
52809
  });
52624
- const navStyle = header.navStyle ?? "minimal";
52625
- const basePreset = getNavLinkPreset(navStyle);
52626
- if (!basePreset) {
52627
- console.warn(`[generateHeaderCss] Nav link preset not found: ${navStyle}`);
52810
+ const mergedStyle = buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize);
52811
+ if (!mergedStyle) {
52812
+ console.warn(`[generateHeaderCss] Nav link preset not found: ${header.navStyle}`);
52628
52813
  return "";
52629
52814
  }
52630
- const mergedStyle = {
52631
- ...basePreset,
52632
- fontWeight: header.navWeight ?? basePreset.fontWeight,
52633
- colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
52634
- ...contrastTreatment ? { contrastTreatment } : {},
52635
- ...navTextSize ? { textSize: navTextSize } : {}
52636
- };
52637
- if (header.navWeight === "bold" && navStyle === "solid") mergedStyle.textTransform = "uppercase";
52638
- if (header.navEffects) {
52639
- const effects = mergedStyle.effects = {
52640
- ...mergedStyle.effects,
52641
- hover: [...mergedStyle.effects?.hover || []],
52642
- active: [...mergedStyle.effects?.active || []]
52643
- };
52644
- if (header.navEffects.glow) effects.hover.push({
52645
- effectId: "outer-glow",
52646
- options: { spread: 5 }
52647
- });
52648
- if (header.navEffects.neumorphic) {
52649
- effects.hover.push({
52650
- effectId: "neumorphic-shadow",
52651
- options: { mode: "pressed" }
52652
- });
52653
- effects.hover.push({
52654
- effectId: "text-color-change",
52655
- options: { hoverColorToken: "primary" }
52656
- });
52657
- }
52658
- if (header.navEffects.underlineGradient) effects.hover.push({
52659
- effectId: "border-bottom-grow",
52660
- options: { origin: "center" }
52661
- });
52662
- }
52663
- if ((header.navContainer?.type ?? "none") === "glass" && navStyle === "minimal") {
52664
- mergedStyle.borderRadius = "full";
52665
- mergedStyle.effects = {
52666
- ...mergedStyle.effects,
52667
- hover: [{
52668
- effectId: "background-on-hover-alpha",
52669
- options: {
52670
- colorToken: "neutral-50",
52671
- opacity: 10
52672
- }
52673
- }, {
52674
- effectId: "text-color-change",
52675
- options: { hoverColorToken: "neutral-50" }
52676
- }],
52677
- active: [{
52678
- effectId: "background-on-hover-alpha",
52679
- options: {
52680
- colorToken: "neutral-50",
52681
- opacity: 18
52682
- }
52683
- }, {
52684
- effectId: "text-color-change",
52685
- options: { hoverColorToken: "neutral-50" }
52686
- }]
52687
- };
52688
- }
52689
52815
  return generateNavLinkCSS({
52690
52816
  themeId,
52691
52817
  tokens,
@@ -52713,10 +52839,10 @@ function generateDropdownContainerStyles(header, themeId, tokens) {
52713
52839
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
52714
52840
  const borderRadius = dropdownStyle?.borderRadius ?? "md";
52715
52841
  rules.push(`border-radius: ${{
52716
- "none": "0",
52717
- "sm": "0.25rem",
52718
- "md": "0.5rem",
52719
- "lg": "0.75rem"
52842
+ none: "0",
52843
+ sm: "0.25rem",
52844
+ md: "0.5rem",
52845
+ lg: "0.75rem"
52720
52846
  }[borderRadius]};`);
52721
52847
  rules.push(`padding: 0.5rem 0;`);
52722
52848
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
@@ -52771,16 +52897,16 @@ function generateDropdownLinkStyles(header, themeId, tokens, theme) {
52771
52897
  const additionalRules = [];
52772
52898
  const letterSpacing = configuredDropdownStyle?.letterSpacing ?? "normal";
52773
52899
  if (letterSpacing !== "normal") additionalRules.push(`letter-spacing: ${{
52774
- "normal": "0em",
52775
- "wide": "0.05em",
52776
- "wider": "0.1em"
52900
+ normal: "0em",
52901
+ wide: "0.05em",
52902
+ wider: "0.1em"
52777
52903
  }[letterSpacing]};`);
52778
52904
  const textSize = configuredDropdownStyle?.textSize ?? "sm";
52779
52905
  additionalRules.push(`font-size: ${{
52780
- "xs": "0.75rem",
52781
- "sm": "0.875rem",
52782
- "base": "1rem",
52783
- "lg": "1.125rem"
52906
+ xs: "0.75rem",
52907
+ sm: "0.875rem",
52908
+ base: "1rem",
52909
+ lg: "1.125rem"
52784
52910
  }[textSize]};`);
52785
52911
  if (additionalRules.length > 0) return baseCSS + `\n${`:where([data-theme-scope="${themeId}"]) .nav-dropdown-link`} {\n ${additionalRules.join("\n ")}\n}\n`;
52786
52912
  return baseCSS;
@@ -52876,18 +53002,18 @@ function generateFloatingContainerStyles(header, themeId, tokens) {
52876
53002
  rules.push(`-webkit-backdrop-filter: ${FLOATING_BLUR};`);
52877
53003
  if (container.border) rules.push(`border: 1px solid rgb(255 255 255 / 0.2);`);
52878
53004
  rules.push(`border-radius: ${{
52879
- "none": "0",
52880
- "sm": "0.375rem",
52881
- "md": "0.5rem",
52882
- "lg": "0.75rem",
52883
- "xl": "1rem",
53005
+ none: "0",
53006
+ sm: "0.375rem",
53007
+ md: "0.5rem",
53008
+ lg: "0.75rem",
53009
+ xl: "1rem",
52884
53010
  "2xl": "1.5rem"
52885
53011
  }[container.rounded]};`);
52886
53012
  if (container.shadow) rules.push(`box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);`);
52887
53013
  rules.push(`padding: ${{
52888
- "sm": "1rem 1.5rem",
52889
- "md": "1.5rem 2rem",
52890
- "lg": "2rem 2.5rem"
53014
+ sm: "1rem 1.5rem",
53015
+ md: "1.5rem 2rem",
53016
+ lg: "2rem 2.5rem"
52891
53017
  }[container.padding]};`);
52892
53018
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
52893
53019
  }
@@ -69175,8 +69301,7 @@ function toBlocksBlockOverrides(overrides) {
69175
69301
  };
69176
69302
  return result;
69177
69303
  }
69178
- function toBlocksDataContext(dataContext) {
69179
- if (!dataContext) return void 0;
69304
+ function toBlocksPageRendererDataContext(dataContext) {
69180
69305
  return {
69181
69306
  ...dataContext,
69182
69307
  mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
@@ -69189,7 +69314,7 @@ function PageRenderer(props) {
69189
69314
  const blocksProps = {
69190
69315
  ...props,
69191
69316
  theme: blocksTheme,
69192
- dataContext: toBlocksDataContext(props.dataContext),
69317
+ dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
69193
69318
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
69194
69319
  sdkConfig: blocksSdkConfig,
69195
69320
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
@@ -69916,7 +70041,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69916
70041
  try {
69917
70042
  apiBaseUrl = getRiverbankEnv().baseUrl;
69918
70043
  } catch {}
69919
- const viewModelOverrides = {
70044
+ const sharedViewModelOverrides = {
69920
70045
  $root: {
69921
70046
  siteId: site.id,
69922
70047
  apiBaseUrl,
@@ -69929,14 +70054,24 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69929
70054
  site,
69930
70055
  menu: menuViewModel,
69931
70056
  footerMenu: footerMenuViewModel,
69932
- legalFooterMenu: legalFooterMenuViewModel,
70057
+ legalFooterMenu: legalFooterMenuViewModel
70058
+ };
70059
+ const headerViewModelOverrides = {
70060
+ ...sharedViewModelOverrides,
69933
70061
  content: { logo: logoViewModel }
69934
70062
  };
70063
+ const footerViewModelOverrides = {
70064
+ ...sharedViewModelOverrides,
70065
+ content: {
70066
+ ...layout.footer,
70067
+ logo: logoViewModel
70068
+ }
70069
+ };
69935
70070
  let headerElement = null;
69936
70071
  if (header === true) headerElement = renderBlock(siteHeaderManifest, headerContent, {
69937
70072
  theme: builtThemeRuntime.tokens,
69938
70073
  themeConfig: blocksThemeWithVariant,
69939
- viewModelOverrides
70074
+ viewModelOverrides: headerViewModelOverrides
69940
70075
  });
69941
70076
  else if (typeof header === "function") headerElement = header(headerData);
69942
70077
  let footerElement = null;
@@ -69971,7 +70106,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69971
70106
  const defaultFooterElement = footerPlan.renderDefaultFooter ? renderBlock(siteFooterManifest, layout.footer, {
69972
70107
  theme: builtThemeRuntime.tokens,
69973
70108
  themeConfig: blocksTheme,
69974
- viewModelOverrides
70109
+ viewModelOverrides: footerViewModelOverrides
69975
70110
  }) : null;
69976
70111
  footerElement = footerPlan.mode === "default+blocks" ? /* @__PURE__ */ jsxs(Fragment, { children: [footerBlocksElement, defaultFooterElement] }) : footerPlan.mode === "blocks" ? footerBlocksElement : footerPlan.mode === "none" ? null : defaultFooterElement;
69977
70112
  } else if (typeof footer === "function") footerElement = footer(footerData);
@@ -70155,6 +70290,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
70155
70290
  "listPublicRecurringSchedule",
70156
70291
  "getPublicEventDetails",
70157
70292
  "listPublicWholeSeriesOfferings",
70293
+ "getPublicWholeSeriesOffering",
70158
70294
  "listPublicRouteCandidates",
70159
70295
  "listPublicTeamMembers",
70160
70296
  "listPublicProducts",