@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"
@@ -42213,9 +42254,6 @@ function parseSignedNewsletterDestinationRef(value) {
42213
42254
  const trimmed = parseTrimmedString$1(value);
42214
42255
  return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
42215
42256
  }
42216
- function parseNewsletterSignupDestinationProvider(value) {
42217
- return value === "riverbank" || value === "mailchimp" ? value : null;
42218
- }
42219
42257
  function buildNewsletterSignupBlockRef(blockId) {
42220
42258
  const parsed = parseNewsletterSignupBlockId(blockId);
42221
42259
  return parsed ? {
@@ -42382,19 +42420,9 @@ const newsletterFieldSchema = z$1.object({
42382
42420
  });
42383
42421
  const newsletterSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
42384
42422
  const signedNewsletterDestinationRefSchema = z$1.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
42385
- const newsletterPublicDestinationRefSchema = z$1.discriminatedUnion("tag", [z$1.object({
42386
- tag: z$1.literal("block_ref"),
42387
- blockId: newsletterSignupBlockIdSchema
42388
- }), z$1.object({
42389
- tag: z$1.literal("signed_destination_ref"),
42390
- token: signedNewsletterDestinationRefSchema
42391
- })]);
42392
- const newsletterSourceSchema = z$1.object({
42393
- blockId: z$1.string().nullable().optional(),
42423
+ const newsletterSourceCommonSchema = z$1.object({
42394
42424
  siteId: z$1.string().optional(),
42395
42425
  apiBaseUrl: z$1.string().optional(),
42396
- listId: z$1.string().nullable().optional(),
42397
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
42398
42426
  preset: newsletterPresetSchema.optional(),
42399
42427
  includePhone: z$1.boolean().optional(),
42400
42428
  buttonLabel: z$1.string().nullable().optional(),
@@ -42405,6 +42433,25 @@ const newsletterSourceSchema = z$1.object({
42405
42433
  spamProtectionEnabled: z$1.boolean().optional(),
42406
42434
  className: z$1.string().nullable().optional()
42407
42435
  });
42436
+ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
42437
+ newsletterSourceCommonSchema.extend({
42438
+ source: z$1.literal("block"),
42439
+ blockId: z$1.string().nullable().optional(),
42440
+ listId: z$1.string().nullable().optional(),
42441
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
42442
+ }),
42443
+ newsletterSourceCommonSchema.extend({
42444
+ source: z$1.literal("signed-footer"),
42445
+ destinationRef: z$1.object({
42446
+ tag: z$1.literal("signed_destination_ref"),
42447
+ token: signedNewsletterDestinationRefSchema
42448
+ })
42449
+ }),
42450
+ newsletterSourceCommonSchema.extend({
42451
+ source: z$1.literal("legacy-direct-list"),
42452
+ listId: z$1.string().nullable()
42453
+ })
42454
+ ]);
42408
42455
  const newsletterDisplaySchema = z$1.object({
42409
42456
  kind: z$1.literal("newsletter-form"),
42410
42457
  className: z$1.string().nullable(),
@@ -42415,8 +42462,26 @@ const newsletterDisplaySchema = z$1.object({
42415
42462
  fields: z$1.array(newsletterFieldSchema)
42416
42463
  });
42417
42464
  const newsletterHydrationSchema = z$1.object({
42418
- destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
42419
- listId: z$1.string().nullable().optional(),
42465
+ target: z$1.discriminatedUnion("tag", [
42466
+ z$1.object({
42467
+ tag: z$1.literal("block-source"),
42468
+ destinationRef: z$1.object({
42469
+ tag: z$1.literal("block_ref"),
42470
+ blockId: newsletterSignupBlockIdSchema
42471
+ }).nullable()
42472
+ }),
42473
+ z$1.object({
42474
+ tag: z$1.literal("signed-footer-source"),
42475
+ destinationRef: z$1.object({
42476
+ tag: z$1.literal("signed_destination_ref"),
42477
+ token: signedNewsletterDestinationRefSchema
42478
+ })
42479
+ }),
42480
+ z$1.object({
42481
+ tag: z$1.literal("legacy-direct-list"),
42482
+ listId: z$1.string().nullable()
42483
+ })
42484
+ ]),
42420
42485
  preset: newsletterPresetSchema,
42421
42486
  includePhone: z$1.boolean(),
42422
42487
  tags: z$1.string().nullable().optional(),
@@ -42450,20 +42515,43 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
42450
42515
  render: createZodCodec(newsletterRenderSchema)
42451
42516
  },
42452
42517
  buildRender: (source) => {
42453
- const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
42518
+ const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
42454
42519
  return {
42455
42520
  display: buildNewsletterDisplay(source),
42456
42521
  hydration: {
42457
- destinationRef: buildNewsletterSignupBlockRef(source.blockId),
42458
- listId: runtimeSource.listId,
42522
+ target: projectNewsletterFormHydrationTarget(source),
42459
42523
  preset: source.preset ?? "emailOnly",
42460
42524
  includePhone: source.includePhone ?? false,
42461
- tags: runtimeSource.tags,
42525
+ tags: runtimeSource ? runtimeSource.tags : source.tags,
42462
42526
  spamProtectionEnabled: source.spamProtectionEnabled
42463
42527
  }
42464
42528
  };
42465
42529
  }
42466
42530
  });
42531
+ function projectNewsletterFormHydrationTarget(source) {
42532
+ switch (source.source) {
42533
+ case "block": {
42534
+ const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
42535
+ if (destinationRef?.tag === "block_ref") return {
42536
+ tag: "block-source",
42537
+ destinationRef
42538
+ };
42539
+ return {
42540
+ tag: "legacy-direct-list",
42541
+ listId: source.listId ?? null
42542
+ };
42543
+ }
42544
+ case "signed-footer": return {
42545
+ tag: "signed-footer-source",
42546
+ destinationRef: source.destinationRef
42547
+ };
42548
+ case "legacy-direct-list": return {
42549
+ tag: "legacy-direct-list",
42550
+ listId: source.listId
42551
+ };
42552
+ default: return assertNever$24(source);
42553
+ }
42554
+ }
42467
42555
  function buildNewsletterFormInteractiveIslandProps(props) {
42468
42556
  return buildInteractiveIslandProps({
42469
42557
  runtime: newsletterFormBlockRuntime,
@@ -42579,7 +42667,7 @@ const newsletterSignupBlockDefinition = {
42579
42667
  //#endregion
42580
42668
  //#region ../blocks/src/system/blocks/team-members.ts
42581
42669
  const ITEM_NAME = "member";
42582
- const teamMemberPhotoSchema = mediaSchema.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
42670
+ const teamMemberPhotoSchema = mediaSchema$1.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
42583
42671
  const teamMemberDataSchema = z$1.object({
42584
42672
  _type: z$1.literal("teamMember"),
42585
42673
  id: z$1.string(),
@@ -44154,7 +44242,7 @@ function getBlockDefinition(name) {
44154
44242
  //#endregion
44155
44243
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
44156
44244
  function resolveBackgroundMedia(input) {
44157
- const parsedMedia = mediaSchema.safeParse(input.image);
44245
+ const parsedMedia = mediaSchema$1.safeParse(input.image);
44158
44246
  if (!parsedMedia.success) return null;
44159
44247
  switch (parsedMedia.data.type) {
44160
44248
  case "image":
@@ -45522,6 +45610,9 @@ function renderTrailingAffordanceIcon(affordance) {
45522
45610
  className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block"
45523
45611
  });
45524
45612
  }
45613
+ function isMissingRequiredLink(linkRequired, resolvedHref) {
45614
+ return linkRequired && resolvedHref.length === 0;
45615
+ }
45525
45616
  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 }) => {
45526
45617
  const content = value ?? children;
45527
45618
  if (!content) {
@@ -45530,12 +45621,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
45530
45621
  }
45531
45622
  const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({ trailingIcon }));
45532
45623
  const resolvedHref = typeof href === "string" ? href.trim() : "";
45533
- if (linkRequired && resolvedHref.length === 0) {
45624
+ if (isMissingRequiredLink(linkRequired, resolvedHref)) {
45534
45625
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
45535
45626
  return null;
45536
45627
  }
45537
45628
  const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
45538
- const resolvedVariantId = parseThemeButtonVariantId(canonicalizePersistedBlockButtonRole(variantId));
45629
+ const resolvedVariantId = parseThemeButtonVariantId(variantId);
45630
+ if (variantId && !resolvedVariantId) {
45631
+ console.error("[ButtonNode] Invalid button variant", { variantId });
45632
+ return null;
45633
+ }
45539
45634
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
45540
45635
  variant: resolvedVariantId,
45541
45636
  size,
@@ -45664,8 +45759,9 @@ function iconForMediaType(type) {
45664
45759
  });
45665
45760
  }
45666
45761
  }
45667
- function normalizeButtonVariant(value) {
45668
- return isBlockButtonRole(value) ? value : "primary";
45762
+ function parseButtonVariant(value) {
45763
+ if (value === null || value === void 0) return "primary";
45764
+ return isBlockButtonRole(value) ? value : null;
45669
45765
  }
45670
45766
  function FileDownloadNode({ value, title, description, buttonLabel, buttonVariant, className }) {
45671
45767
  if (!value || !isDownloadableMediaType(value.type)) return null;
@@ -45675,7 +45771,11 @@ function FileDownloadNode({ value, title, description, buttonLabel, buttonVarian
45675
45771
  const heading = title?.trim() || filename;
45676
45772
  const body = description?.trim();
45677
45773
  const label = buttonLabel?.trim() || "Download";
45678
- const variant = normalizeButtonVariant(buttonVariant);
45774
+ const variant = parseButtonVariant(buttonVariant);
45775
+ if (!variant) {
45776
+ console.error("[FileDownloadNode] Invalid button variant", { buttonVariant });
45777
+ return null;
45778
+ }
45679
45779
  return /* @__PURE__ */ jsx("div", {
45680
45780
  className,
45681
45781
  children: /* @__PURE__ */ jsxs("div", {
@@ -46850,6 +46950,33 @@ function uniqByOccurrenceId(events) {
46850
46950
  }
46851
46951
  return out;
46852
46952
  }
46953
+ function selectFromOccurrenceContext(events, occurrenceContext) {
46954
+ if (!occurrenceContext) return null;
46955
+ const byId = events.find((event) => event.occurrenceId === occurrenceContext.id || event.id === occurrenceContext.id);
46956
+ if (byId) return byId;
46957
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46958
+ startsAt: occurrenceContext.startsAt,
46959
+ timeZone: occurrenceContext.timeZone
46960
+ }));
46961
+ return events.find((event) => getBookingLocalDateKey(toScheduledBookingDateTime({
46962
+ startsAt: event.startsAt,
46963
+ timeZone: event.timeZone
46964
+ })) === contextDate) ?? null;
46965
+ }
46966
+ function selectNextUpcoming(events, nowIso) {
46967
+ return [...events].filter((event) => isFutureOrNow(event.startsAt, nowIso)).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt))[0] ?? null;
46968
+ }
46969
+ function selectCompletedWholeSeries(events) {
46970
+ if (events.length === 0 || !events.every((event) => event.bookingScope === "whole_series")) return null;
46971
+ return [...events].sort((left, right) => Date.parse(right.startsAt) - Date.parse(left.startsAt))[0] ?? null;
46972
+ }
46973
+ function selectRelatedDates(input) {
46974
+ if (!input.seriesId) return [];
46975
+ const isWholeSeries = input.selected?.bookingScope === "whole_series";
46976
+ const selectedOccurrenceId = input.selected ? input.selected.occurrenceId || input.selected.id : null;
46977
+ 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));
46978
+ return isWholeSeries ? dates : dates.slice(0, input.limit);
46979
+ }
46853
46980
  function selectEventDetails(args) {
46854
46981
  const all = uniqByOccurrenceId(resolveEventRegistrationScopedEvents((args.events ?? []).filter(Boolean), {
46855
46982
  occurrenceContext: args.occurrenceContext,
@@ -46857,37 +46984,22 @@ function selectEventDetails(args) {
46857
46984
  }));
46858
46985
  const occurrenceContext = args.occurrenceContext ?? null;
46859
46986
  const otherLimit = parseLimit$1(args.otherDatesLimit, 5);
46860
- const selectedFromContext = (() => {
46861
- if (!occurrenceContext) return null;
46862
- const byId = all.find((e) => e.occurrenceId === occurrenceContext.id || e.id === occurrenceContext.id) ?? null;
46863
- if (byId) return byId;
46864
- const ctxDate = getBookingLocalDateKey(toScheduledBookingDateTime({
46865
- startsAt: occurrenceContext.startsAt,
46866
- timeZone: occurrenceContext.timeZone
46867
- }));
46868
- return all.find((e) => getBookingLocalDateKey(toScheduledBookingDateTime({
46869
- startsAt: e.startsAt,
46870
- timeZone: e.timeZone
46871
- })) === ctxDate) ?? null;
46872
- })();
46873
- const nextUpcoming = (() => {
46874
- const upcoming = all.filter((e) => isFutureOrNow(e.startsAt, args.nowIso));
46875
- upcoming.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
46876
- return upcoming[0] ?? null;
46877
- })();
46878
- const mode = selectedFromContext ? "selected" : "next";
46879
- const selected = selectedFromContext ?? nextUpcoming;
46987
+ const selectedFromContext = selectFromOccurrenceContext(all, occurrenceContext);
46988
+ const nextUpcoming = selectNextUpcoming(all, args.nowIso);
46989
+ const completedWholeSeries = selectCompletedWholeSeries(all);
46990
+ const selected = selectedFromContext ?? nextUpcoming ?? completedWholeSeries;
46991
+ const mode = selectedFromContext ? "selected" : nextUpcoming ? "next" : completedWholeSeries ? "completed" : "next";
46880
46992
  const timeZone = toBookingTimeZone(selected?.timeZone ?? all[0]?.timeZone ?? null);
46881
- const seriesId = occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null;
46882
- const selectedOccurrenceId = selected?.occurrenceId ?? null;
46883
46993
  return {
46884
46994
  mode,
46885
46995
  selected,
46886
- otherDates: seriesId ? all.filter((e) => e.seriesId === seriesId).filter((e) => isFutureOrNow(e.startsAt, args.nowIso)).filter((e) => {
46887
- const occId = e.occurrenceId || e.id;
46888
- if (selectedOccurrenceId && occId === selectedOccurrenceId) return false;
46889
- return true;
46890
- }).slice(0, otherLimit) : [],
46996
+ otherDates: selectRelatedDates({
46997
+ events: all,
46998
+ seriesId: occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null,
46999
+ selected,
47000
+ nowIso: args.nowIso,
47001
+ limit: otherLimit
47002
+ }),
46891
47003
  timeZone
46892
47004
  };
46893
47005
  }
@@ -47009,7 +47121,7 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
47009
47121
  /* @__PURE__ */ jsxs("div", { children: [
47010
47122
  /* @__PURE__ */ jsx("div", {
47011
47123
  className: "rb-label rb-mb-2",
47012
- children: selection.mode === "next" ? "Next date" : "Date"
47124
+ children: selected.bookingScope === "whole_series" ? selection.mode === "next" ? "Next session" : "Selected session" : selection.mode === "next" ? "Next date" : "Date"
47013
47125
  }),
47014
47126
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: date }) }),
47015
47127
  /* @__PURE__ */ jsx("p", {
@@ -47047,18 +47159,27 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
47047
47159
  }) : null] }, member.id))
47048
47160
  })]
47049
47161
  }) : null,
47050
- pricing
47162
+ pricing,
47163
+ selected.bookingScope === "whole_series" ? /* @__PURE__ */ jsxs("div", {
47164
+ className: "rb-mt-6",
47165
+ children: [/* @__PURE__ */ jsx("div", {
47166
+ className: "rb-label rb-mb-2",
47167
+ children: "Registration"
47168
+ }), /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: selected.wholeSeries?.enrollmentOpen ? "Open" : "Closed" }) })]
47169
+ }) : null
47051
47170
  ]
47052
47171
  });
47053
47172
  }
47054
47173
  function OtherEventDates({ selection }) {
47055
- if (selection.otherDates.length === 0) return null;
47174
+ const isWholeSeries = selection.selected?.bookingScope === "whole_series";
47175
+ const dates = isWholeSeries && selection.selected ? [selection.selected, ...selection.otherDates].sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt)) : selection.otherDates;
47176
+ if (dates.length === 0) return null;
47056
47177
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
47057
47178
  className: "rb-label",
47058
- children: "Other dates"
47179
+ children: isWholeSeries ? "Session schedule" : "Other dates"
47059
47180
  }), /* @__PURE__ */ jsx("div", {
47060
47181
  className: "rb-mt-2 rb-tiles-grid",
47061
- children: selection.otherDates.map((event) => /* @__PURE__ */ jsx("a", {
47182
+ children: dates.map((event) => /* @__PURE__ */ jsx("a", {
47062
47183
  className: "rb-tile rb-tile--interactive",
47063
47184
  ...resolveEventLinkProps(event),
47064
47185
  children: /* @__PURE__ */ jsx(DateTimeTile, {
@@ -50257,13 +50378,13 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
50257
50378
  * Renders the newsletter signup form for SSR with hydration support.
50258
50379
  * Uses the islands architecture pattern to hydrate on the client.
50259
50380
  */
50260
- function NewsletterFormSSR({ blockId, siteId, apiBaseUrl, listId, destinationProvider, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className }) {
50381
+ function NewsletterFormSSR(props) {
50382
+ const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
50383
+ const blockId = props.source === "block" ? props.blockId : null;
50261
50384
  const islandProps = buildNewsletterFormInteractiveIslandProps({
50262
- blockId,
50385
+ ...props,
50263
50386
  siteId,
50264
50387
  apiBaseUrl,
50265
- listId,
50266
- destinationProvider,
50267
50388
  preset,
50268
50389
  includePhone,
50269
50390
  buttonLabel,
@@ -52596,6 +52717,35 @@ function resolveColorTokenHex(theme, colorToken) {
52596
52717
  if (colorToken === "transparent") return null;
52597
52718
  return expandPalette(theme.palette)[colorToken] ?? null;
52598
52719
  }
52720
+ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
52721
+ `min-width: 12rem;`,
52722
+ `width: max-content;`,
52723
+ `max-width: min(22rem, calc(100vw - 2rem));`,
52724
+ `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
52725
+ ];
52726
+ //#endregion
52727
+ //#region ../theme-core/src/header/surfaceRules.ts
52728
+ /** Compile the at-rest surface independently of scroll treatment and paint geometry. */
52729
+ function buildHeaderSurfaceRules(header, tokens) {
52730
+ const base = [];
52731
+ const background = header.background;
52732
+ if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
52733
+ else if (background.type === "gradient" && background.gradient) {
52734
+ const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
52735
+ base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
52736
+ }
52737
+ const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
52738
+ if (!header.border || borderWidth === "0") return {
52739
+ base,
52740
+ border: []
52741
+ };
52742
+ const color = rgbColorValue(header.border.colorToken?.trim() || "border");
52743
+ const style = header.border.style === "dashed" ? "dashed" : "solid";
52744
+ return {
52745
+ base,
52746
+ border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
52747
+ };
52748
+ }
52599
52749
  //#endregion
52600
52750
  //#region ../theme-core/src/navigation/presets.ts
52601
52751
  /**
@@ -52757,12 +52907,71 @@ function getNavLinkPreset(presetId) {
52757
52907
  return NAV_LINK_PRESETS[presetId];
52758
52908
  }
52759
52909
  Object.keys(NAV_LINK_PRESETS);
52760
- const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
52761
- `min-width: 12rem;`,
52762
- `width: max-content;`,
52763
- `max-width: min(22rem, calc(100vw - 2rem));`,
52764
- `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
52765
- ];
52910
+ //#endregion
52911
+ //#region ../theme-core/src/header/legacyNavLinkStyle.ts
52912
+ function buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize) {
52913
+ const navStyle = header.navStyle ?? "minimal";
52914
+ const basePreset = getNavLinkPreset(navStyle);
52915
+ if (!basePreset) return null;
52916
+ const style = {
52917
+ ...basePreset,
52918
+ fontWeight: header.navWeight ?? basePreset.fontWeight,
52919
+ colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
52920
+ ...contrastTreatment ? { contrastTreatment } : {},
52921
+ ...navTextSize ? { textSize: navTextSize } : {}
52922
+ };
52923
+ if (header.navWeight === "bold" && navStyle === "solid") style.textTransform = "uppercase";
52924
+ applyLegacyNavEffects(style, header);
52925
+ applyLegacyGlassTreatment(style, header, navStyle);
52926
+ return style;
52927
+ }
52928
+ function applyLegacyNavEffects(style, header) {
52929
+ if (!header.navEffects) return;
52930
+ const effects = style.effects = {
52931
+ ...style.effects,
52932
+ hover: [...style.effects?.hover ?? []],
52933
+ active: [...style.effects?.active ?? []]
52934
+ };
52935
+ if (header.navEffects.glow) effects.hover.push({
52936
+ effectId: "outer-glow",
52937
+ options: { spread: 5 }
52938
+ });
52939
+ if (header.navEffects.neumorphic) {
52940
+ effects.hover.push({
52941
+ effectId: "neumorphic-shadow",
52942
+ options: { mode: "pressed" }
52943
+ });
52944
+ effects.hover.push({
52945
+ effectId: "text-color-change",
52946
+ options: { hoverColorToken: "primary" }
52947
+ });
52948
+ }
52949
+ if (header.navEffects.underlineGradient) effects.hover.push({
52950
+ effectId: "border-bottom-grow",
52951
+ options: { origin: "center" }
52952
+ });
52953
+ }
52954
+ function applyLegacyGlassTreatment(style, header, navStyle) {
52955
+ if (header.navContainer?.type !== "glass" || navStyle !== "minimal") return;
52956
+ style.borderRadius = "full";
52957
+ style.effects = {
52958
+ ...style.effects,
52959
+ hover: glassStateEffects(10),
52960
+ active: glassStateEffects(18)
52961
+ };
52962
+ }
52963
+ function glassStateEffects(opacity) {
52964
+ return [{
52965
+ effectId: "background-on-hover-alpha",
52966
+ options: {
52967
+ colorToken: "neutral-50",
52968
+ opacity
52969
+ }
52970
+ }, {
52971
+ effectId: "text-color-change",
52972
+ options: { hoverColorToken: "neutral-50" }
52973
+ }];
52974
+ }
52766
52975
  //#endregion
52767
52976
  //#region ../theme-core/src/header/generateHeaderCss.ts
52768
52977
  const HEADER_BLUR = "blur(12px)";
@@ -52792,8 +53001,8 @@ function generateHeaderCss(options) {
52792
53001
  const cssChunks = [];
52793
53002
  const headerContrastTreatment = resolveHeaderContrastTreatment(header);
52794
53003
  const headerNavTextSize = resolveHeaderNavTextSize(header);
52795
- cssChunks.push(generateHeaderRootStyles(header, themeId, tokens, theme));
52796
- cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId));
53004
+ cssChunks.push(generateHeaderRootStyles(header, themeId, tokens));
53005
+ cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId, header.variant));
52797
53006
  cssChunks.push(generateLogoStyles({
52798
53007
  logo: header.logo,
52799
53008
  themeId,
@@ -52831,56 +53040,33 @@ function isClearSplitHeaderShape(header) {
52831
53040
  function isDetachedFloatingHeaderShape(header) {
52832
53041
  return header.variant === "floating" && !header.container;
52833
53042
  }
52834
- function generateMobileOverlayBackdropFilterFix(themeId) {
52835
- 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`;
52836
- }
52837
53043
  /**
52838
53044
  * Generate root header container styles
52839
53045
  */
52840
- function generateHeaderRootStyles(header, themeId, tokens, _theme) {
53046
+ function generateHeaderRootStyles(header, themeId, tokens) {
52841
53047
  const selector = `:where([data-theme-scope="${themeId}"]) .header-root`;
52842
- const backgroundSelector = `:where([data-theme-scope="${themeId}"]) .header-root::before`;
52843
53048
  const rules = [];
52844
- const backgroundRules = [];
52845
53049
  const navContainerType = header.navContainer?.type ?? "none";
52846
53050
  const isContainedNav = navContainerType === "pill" || navContainerType === "glass";
52847
53051
  rules.push("position: relative;");
52848
53052
  rules.push("isolation: isolate;");
52849
- if (!isContainedNav) {
52850
- const bg = header.background;
52851
- if (bg.type === "color") {
52852
- const bgColor = tokens.getColor(bg.color || "surface");
52853
- backgroundRules.push(`background-color: ${bgColor};`);
52854
- } else if (bg.type === "gradient" && bg.gradient) {
52855
- const stops = bg.gradient.stops.map((s) => tokens.getColor(s.color)).join(", ");
52856
- const angle = bg.gradient.angle ?? 180;
52857
- backgroundRules.push(`background-image: linear-gradient(${angle}deg, ${stops});`);
52858
- }
52859
- backgroundRules.push(`backdrop-filter: ${HEADER_BLUR};`);
52860
- backgroundRules.push(`-webkit-backdrop-filter: ${HEADER_BLUR};`);
52861
- if (header.border) {
52862
- const borderWidth = getComponentBorderWidthPx(header.border.width);
52863
- if (borderWidth !== "0") {
52864
- const borderToken = header.border?.colorToken?.trim() || "border";
52865
- const borderColor = tokens.getColor(borderToken);
52866
- const borderStyle = header.border.style === "dashed" ? "dashed" : "solid";
52867
- if (header.border.position === "bottom") rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
52868
- else if (header.border.position === "top") rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
52869
- else if (header.border.position === "both") {
52870
- rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
52871
- rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
52872
- }
52873
- }
52874
- }
52875
- }
53053
+ const surfaceRules = isContainedNav ? {
53054
+ base: [],
53055
+ border: []
53056
+ } : buildHeaderSurfaceRules(header, tokens);
53057
+ const floatingSurfaceBorder = header.variant === "floating";
53058
+ if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
53059
+ const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
53060
+ const scrolledPaintRules = floatingSurfaceBorder ? surfaceRules.border : [];
52876
53061
  if (header.positioning === "sticky" || header.positioning === "fixed") {
52877
53062
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
52878
53063
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
52879
53064
  }
52880
53065
  const baseBlock = `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
52881
53066
  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`;
52882
- if (isContainedNav || backgroundRules.length === 0) return `${baseBlock}\n${overlayFix}`;
52883
- 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) : ""}`;
53067
+ const scrollTreatmentStyles = generateHeaderScrollTreatmentStyles(header.scrollTreatment, themeId, header.variant, scrolledPaintRules);
53068
+ if (isContainedNav || basePaintRules.length === 0) return `${baseBlock}\n${overlayFix}${scrollTreatmentStyles}`;
53069
+ return `${baseBlock}\n${renderHeaderPaintTargetRules(getHeaderPaintTargets(header.variant, themeId), basePaintRules)}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}${scrollTreatmentStyles}`;
52884
53070
  }
52885
53071
  /**
52886
53072
  * Reshapes the full-bleed header paint layer into a contained brand capsule at
@@ -52925,10 +53111,10 @@ function generateLogoStyles(input) {
52925
53111
  else rules.push(`font-family: var(--font-heading);`);
52926
53112
  if (logo) {
52927
53113
  if (logo.letterSpacing && logo.letterSpacing !== "normal") rules.push(`letter-spacing: ${{
52928
- "normal": "0em",
52929
- "wide": "0.05em",
52930
- "wider": "0.1em",
52931
- "widest": "0.15em"
53114
+ normal: "0em",
53115
+ wide: "0.05em",
53116
+ wider: "0.1em",
53117
+ widest: "0.15em"
52932
53118
  }[logo.letterSpacing]};`);
52933
53119
  if (logo.gradient) {
52934
53120
  rules.push(`background: linear-gradient(to right, ${primaryColor}, ${accentColor});`);
@@ -53001,71 +53187,11 @@ function generateNavLinkStyles(header, themeId, tokens, theme, contrastTreatment
53001
53187
  } : header.navLinkStyle, navPreferences),
53002
53188
  className: "header-nav-link"
53003
53189
  });
53004
- const navStyle = header.navStyle ?? "minimal";
53005
- const basePreset = getNavLinkPreset(navStyle);
53006
- if (!basePreset) {
53007
- console.warn(`[generateHeaderCss] Nav link preset not found: ${navStyle}`);
53190
+ const mergedStyle = buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize);
53191
+ if (!mergedStyle) {
53192
+ console.warn(`[generateHeaderCss] Nav link preset not found: ${header.navStyle}`);
53008
53193
  return "";
53009
53194
  }
53010
- const mergedStyle = {
53011
- ...basePreset,
53012
- fontWeight: header.navWeight ?? basePreset.fontWeight,
53013
- colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
53014
- ...contrastTreatment ? { contrastTreatment } : {},
53015
- ...navTextSize ? { textSize: navTextSize } : {}
53016
- };
53017
- if (header.navWeight === "bold" && navStyle === "solid") mergedStyle.textTransform = "uppercase";
53018
- if (header.navEffects) {
53019
- const effects = mergedStyle.effects = {
53020
- ...mergedStyle.effects,
53021
- hover: [...mergedStyle.effects?.hover || []],
53022
- active: [...mergedStyle.effects?.active || []]
53023
- };
53024
- if (header.navEffects.glow) effects.hover.push({
53025
- effectId: "outer-glow",
53026
- options: { spread: 5 }
53027
- });
53028
- if (header.navEffects.neumorphic) {
53029
- effects.hover.push({
53030
- effectId: "neumorphic-shadow",
53031
- options: { mode: "pressed" }
53032
- });
53033
- effects.hover.push({
53034
- effectId: "text-color-change",
53035
- options: { hoverColorToken: "primary" }
53036
- });
53037
- }
53038
- if (header.navEffects.underlineGradient) effects.hover.push({
53039
- effectId: "border-bottom-grow",
53040
- options: { origin: "center" }
53041
- });
53042
- }
53043
- if ((header.navContainer?.type ?? "none") === "glass" && navStyle === "minimal") {
53044
- mergedStyle.borderRadius = "full";
53045
- mergedStyle.effects = {
53046
- ...mergedStyle.effects,
53047
- hover: [{
53048
- effectId: "background-on-hover-alpha",
53049
- options: {
53050
- colorToken: "neutral-50",
53051
- opacity: 10
53052
- }
53053
- }, {
53054
- effectId: "text-color-change",
53055
- options: { hoverColorToken: "neutral-50" }
53056
- }],
53057
- active: [{
53058
- effectId: "background-on-hover-alpha",
53059
- options: {
53060
- colorToken: "neutral-50",
53061
- opacity: 18
53062
- }
53063
- }, {
53064
- effectId: "text-color-change",
53065
- options: { hoverColorToken: "neutral-50" }
53066
- }]
53067
- };
53068
- }
53069
53195
  return generateNavLinkCSS({
53070
53196
  themeId,
53071
53197
  tokens,
@@ -53093,10 +53219,10 @@ function generateDropdownContainerStyles(header, themeId, tokens) {
53093
53219
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
53094
53220
  const borderRadius = dropdownStyle?.borderRadius ?? "md";
53095
53221
  rules.push(`border-radius: ${{
53096
- "none": "0",
53097
- "sm": "0.25rem",
53098
- "md": "0.5rem",
53099
- "lg": "0.75rem"
53222
+ none: "0",
53223
+ sm: "0.25rem",
53224
+ md: "0.5rem",
53225
+ lg: "0.75rem"
53100
53226
  }[borderRadius]};`);
53101
53227
  rules.push(`padding: 0.5rem 0;`);
53102
53228
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
@@ -53151,16 +53277,16 @@ function generateDropdownLinkStyles(header, themeId, tokens, theme) {
53151
53277
  const additionalRules = [];
53152
53278
  const letterSpacing = configuredDropdownStyle?.letterSpacing ?? "normal";
53153
53279
  if (letterSpacing !== "normal") additionalRules.push(`letter-spacing: ${{
53154
- "normal": "0em",
53155
- "wide": "0.05em",
53156
- "wider": "0.1em"
53280
+ normal: "0em",
53281
+ wide: "0.05em",
53282
+ wider: "0.1em"
53157
53283
  }[letterSpacing]};`);
53158
53284
  const textSize = configuredDropdownStyle?.textSize ?? "sm";
53159
53285
  additionalRules.push(`font-size: ${{
53160
- "xs": "0.75rem",
53161
- "sm": "0.875rem",
53162
- "base": "1rem",
53163
- "lg": "1.125rem"
53286
+ xs: "0.75rem",
53287
+ sm: "0.875rem",
53288
+ base: "1rem",
53289
+ lg: "1.125rem"
53164
53290
  }[textSize]};`);
53165
53291
  if (additionalRules.length > 0) return baseCSS + `\n${`:where([data-theme-scope="${themeId}"]) .nav-dropdown-link`} {\n ${additionalRules.join("\n ")}\n}\n`;
53166
53292
  return baseCSS;
@@ -53256,18 +53382,18 @@ function generateFloatingContainerStyles(header, themeId, tokens) {
53256
53382
  rules.push(`-webkit-backdrop-filter: ${FLOATING_BLUR};`);
53257
53383
  if (container.border) rules.push(`border: 1px solid rgb(255 255 255 / 0.2);`);
53258
53384
  rules.push(`border-radius: ${{
53259
- "none": "0",
53260
- "sm": "0.375rem",
53261
- "md": "0.5rem",
53262
- "lg": "0.75rem",
53263
- "xl": "1rem",
53385
+ none: "0",
53386
+ sm: "0.375rem",
53387
+ md: "0.5rem",
53388
+ lg: "0.75rem",
53389
+ xl: "1rem",
53264
53390
  "2xl": "1.5rem"
53265
53391
  }[container.rounded]};`);
53266
53392
  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);`);
53267
53393
  rules.push(`padding: ${{
53268
- "sm": "1rem 1.5rem",
53269
- "md": "1.5rem 2rem",
53270
- "lg": "2rem 2.5rem"
53394
+ sm: "1rem 1.5rem",
53395
+ md: "1.5rem 2rem",
53396
+ lg: "2rem 2.5rem"
53271
53397
  }[container.padding]};`);
53272
53398
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
53273
53399
  }
@@ -69555,8 +69681,7 @@ function toBlocksBlockOverrides(overrides) {
69555
69681
  };
69556
69682
  return result;
69557
69683
  }
69558
- function toBlocksDataContext(dataContext) {
69559
- if (!dataContext) return void 0;
69684
+ function toBlocksPageRendererDataContext(dataContext) {
69560
69685
  return {
69561
69686
  ...dataContext,
69562
69687
  mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
@@ -69569,7 +69694,7 @@ function PageRenderer(props) {
69569
69694
  const blocksProps = {
69570
69695
  ...props,
69571
69696
  theme: blocksTheme,
69572
- dataContext: toBlocksDataContext(props.dataContext),
69697
+ dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
69573
69698
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
69574
69699
  sdkConfig: blocksSdkConfig,
69575
69700
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
@@ -70296,7 +70421,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
70296
70421
  try {
70297
70422
  apiBaseUrl = getRiverbankEnv().baseUrl;
70298
70423
  } catch {}
70299
- const viewModelOverrides = {
70424
+ const sharedViewModelOverrides = {
70300
70425
  $root: {
70301
70426
  siteId: site.id,
70302
70427
  apiBaseUrl,
@@ -70309,14 +70434,24 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
70309
70434
  site,
70310
70435
  menu: menuViewModel,
70311
70436
  footerMenu: footerMenuViewModel,
70312
- legalFooterMenu: legalFooterMenuViewModel,
70437
+ legalFooterMenu: legalFooterMenuViewModel
70438
+ };
70439
+ const headerViewModelOverrides = {
70440
+ ...sharedViewModelOverrides,
70313
70441
  content: { logo: logoViewModel }
70314
70442
  };
70443
+ const footerViewModelOverrides = {
70444
+ ...sharedViewModelOverrides,
70445
+ content: {
70446
+ ...layout.footer,
70447
+ logo: logoViewModel
70448
+ }
70449
+ };
70315
70450
  let headerElement = null;
70316
70451
  if (header === true) headerElement = renderBlock(siteHeaderManifest, headerContent, {
70317
70452
  theme: builtThemeRuntime.tokens,
70318
70453
  themeConfig: blocksThemeWithVariant,
70319
- viewModelOverrides
70454
+ viewModelOverrides: headerViewModelOverrides
70320
70455
  });
70321
70456
  else if (typeof header === "function") headerElement = header(headerData);
70322
70457
  let footerElement = null;
@@ -70351,7 +70486,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
70351
70486
  const defaultFooterElement = footerPlan.renderDefaultFooter ? renderBlock(siteFooterManifest, layout.footer, {
70352
70487
  theme: builtThemeRuntime.tokens,
70353
70488
  themeConfig: blocksTheme,
70354
- viewModelOverrides
70489
+ viewModelOverrides: footerViewModelOverrides
70355
70490
  }) : null;
70356
70491
  footerElement = footerPlan.mode === "default+blocks" ? /* @__PURE__ */ jsxs(Fragment, { children: [footerBlocksElement, defaultFooterElement] }) : footerPlan.mode === "blocks" ? footerBlocksElement : footerPlan.mode === "none" ? null : defaultFooterElement;
70357
70492
  } else if (typeof footer === "function") footerElement = footer(footerData);
@@ -70679,6 +70814,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
70679
70814
  "listPublicRecurringSchedule",
70680
70815
  "getPublicEventDetails",
70681
70816
  "listPublicWholeSeriesOfferings",
70817
+ "getPublicWholeSeriesOffering",
70682
70818
  "listPublicRouteCandidates",
70683
70819
  "listPublicTeamMembers",
70684
70820
  "listPublicProducts",
@@ -73414,6 +73550,7 @@ const loaderAdapters = {
73414
73550
  listPublicEvents,
73415
73551
  listPublicRecurringSchedule,
73416
73552
  getPublicEventDetails,
73553
+ getPublicWholeSeriesOffering,
73417
73554
  listPublicRouteCandidates,
73418
73555
  listPublicTeamMembers,
73419
73556
  listPublicProducts,
@@ -73508,6 +73645,13 @@ async function listPublicEvents({ client, params }) {
73508
73645
  async function listPublicRecurringSchedule(input) {
73509
73646
  return projectRecurringSchedule(await listPublicEvents(input));
73510
73647
  }
73648
+ async function getPublicWholeSeriesOffering({ client, params }) {
73649
+ return await client.getPublicWholeSeriesOffering({
73650
+ siteId: requireStringParam(params, "siteId", "getPublicWholeSeriesOffering"),
73651
+ eventSeriesId: requireStringParam(params, "eventSeriesId", "getPublicWholeSeriesOffering"),
73652
+ stage: readStringParam(params, "stage")
73653
+ });
73654
+ }
73511
73655
  async function getPublicEventDetails({ client, params }) {
73512
73656
  return await client.getPublicEventDetails({
73513
73657
  siteId: requireStringParam(params, "siteId", "getPublicEventDetails"),
@@ -77584,4 +77728,4 @@ function defineBlockOverrideRegistrations(registrations) {
77584
77728
  * ```
77585
77729
  */
77586
77730
  //#endregion
77587
- export { Block, ImagePresets, Layout, Page, PageRenderer, RichText, ThemeScope, buildThemeRuntime, defineBlockOverrideRegistrations, defineBlockOverrides, defineLazyBlockOverride, isEntryContent, isPageContent, isPageSurfaceContent, loadContent, loadPage, resolveImageSourceSetWithContext, resolveImageUrl, resolveImageUrlWithContext };
77731
+ export { Block, ImagePresets, Layout, Page, PageRenderer, RichText, ThemeScope, buildThemeRuntime, defineBlockOverrideRegistrations, defineBlockOverrides, defineLazyBlockOverride, isEntryContent, isPageContent, isPageSurfaceContent, loadContent, loadPage, resolveImageSourceSetWithContext, resolveImageUrl, resolveImageUrlWithContext, toBlocksImageResolveContextInput, toBlocksMediaAssets, toBlocksPageRendererDataContext };