@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
@@ -498,6 +498,11 @@ function toLocationCoordinates(value) {
498
498
  };
499
499
  }
500
500
  //#endregion
501
+ //#region ../core/src/newsletter-signup-destination.ts
502
+ function parseNewsletterSignupDestinationProvider(value) {
503
+ return value === "riverbank" || value === "mailchimp" ? value : null;
504
+ }
505
+ //#endregion
501
506
  //#region ../core/src/planner.ts
502
507
  /** Default clock for production callers that do not inject time explicitly. */
503
508
  const systemPlanningClock = { now: () => Date.now() };
@@ -3066,6 +3071,101 @@ function isRichTextDoc(value) {
3066
3071
  return RichTextDocSchema.safeParse(value).success;
3067
3072
  }
3068
3073
  //#endregion
3074
+ //#region ../blocks/src/lib/media.ts
3075
+ const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
3076
+ "document",
3077
+ "spreadsheet",
3078
+ "archive",
3079
+ "audio"
3080
+ ];
3081
+ const hotspotSchema$1 = z.object({
3082
+ x: z.number().min(0).max(1),
3083
+ y: z.number().min(0).max(1),
3084
+ radius: z.number().optional()
3085
+ });
3086
+ const rotationSchema$1 = z.union([
3087
+ z.literal(0),
3088
+ z.literal(90),
3089
+ z.literal(180),
3090
+ z.literal(270)
3091
+ ]);
3092
+ const rectSchema$1 = z.tuple([
3093
+ z.number(),
3094
+ z.number(),
3095
+ z.number(),
3096
+ z.number()
3097
+ ]);
3098
+ const aspectCropSchema$1 = z.object({
3099
+ aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
3100
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
3101
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
3102
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
3103
+ });
3104
+ const transformSchema$1 = z.object({
3105
+ aspectCrops: z.preprocess((value) => {
3106
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
3107
+ return value;
3108
+ }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
3109
+ rect: rectSchema$1.optional(),
3110
+ hotspot: hotspotSchema$1.optional(),
3111
+ rotation: rotationSchema$1.optional()
3112
+ });
3113
+ const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
3114
+ tag: z.literal("storage"),
3115
+ assetId: z.string().optional(),
3116
+ storageBucket: z.string().min(1),
3117
+ storagePath: z.string().min(1)
3118
+ }), z.object({
3119
+ tag: z.literal("external-src"),
3120
+ assetId: z.string().optional(),
3121
+ src: z.string().url()
3122
+ })]);
3123
+ const mediaBaseSchema = z.object({
3124
+ purpose: z.string().optional(),
3125
+ placeholder: z.boolean().default(true).optional(),
3126
+ assetId: z.string().optional(),
3127
+ identifier: z.string().optional(),
3128
+ src: z.string().optional(),
3129
+ alt: z.string().optional(),
3130
+ filename: z.string().optional(),
3131
+ mimeType: z.string().optional(),
3132
+ width: z.number().optional(),
3133
+ height: z.number().optional(),
3134
+ storageBucket: z.string().optional(),
3135
+ storagePath: z.string().optional(),
3136
+ poster: mediaPosterSchema.optional(),
3137
+ transform: transformSchema$1.optional()
3138
+ });
3139
+ /**
3140
+ * Canonical identifier carried by media values that are safe to persist.
3141
+ * Parsing trims boundary input so downstream writers cannot retain whitespace-only
3142
+ * identifiers or independently disagree about normalization.
3143
+ */
3144
+ const mediaIdentifierSchema = z.string().trim().min(1).brand();
3145
+ const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
3146
+ const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
3147
+ const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
3148
+ const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
3149
+ const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
3150
+ const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
3151
+ const mediaSchema$1 = z.discriminatedUnion("type", [
3152
+ imageMediaSchema,
3153
+ videoMediaSchema,
3154
+ audioMediaSchema,
3155
+ documentMediaSchema,
3156
+ spreadsheetMediaSchema,
3157
+ archiveMediaSchema
3158
+ ]);
3159
+ const persistableMediaBaseSchema = mediaBaseSchema.extend({ identifier: mediaIdentifierSchema });
3160
+ z.discriminatedUnion("type", [
3161
+ persistableMediaBaseSchema.extend({ type: z.literal("image") }),
3162
+ persistableMediaBaseSchema.extend({ type: z.literal("video") }),
3163
+ persistableMediaBaseSchema.extend({ type: z.literal("audio") }),
3164
+ persistableMediaBaseSchema.extend({ type: z.literal("document") }),
3165
+ persistableMediaBaseSchema.extend({ type: z.literal("spreadsheet") }),
3166
+ persistableMediaBaseSchema.extend({ type: z.literal("archive") })
3167
+ ]);
3168
+ //#endregion
3069
3169
  //#region ../blocks/src/system/manifest/fieldValidation/index.ts
3070
3170
  const TEL_RE = /^[+()0-9\s-]{3,}$/;
3071
3171
  const SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
@@ -3396,7 +3496,7 @@ function normalizeObjectChildren(children, value, ctx) {
3396
3496
  function normalizeInlineTextFallbacks(plans, values, ctx) {
3397
3497
  for (const plan of plans) {
3398
3498
  if (plan.kind !== "inlineText" || !plan.plainTextFallbackPath) continue;
3399
- if (!isMissingForPlan(plan, values[plan.fieldId])) continue;
3499
+ if (!isMissingForPlan(plan, values[plan.fieldId]) && !(ctx.allowIncomplete && !parseInlineTextFromUnknown(values[plan.fieldId]).ok)) continue;
3400
3500
  const fallback = getAtFieldPath(values, plan.plainTextFallbackPath);
3401
3501
  if (typeof fallback !== "string" || fallback.trim().length === 0) continue;
3402
3502
  values[plan.fieldId] = normalizeFieldValue(plan, plainTextToInlineText(fallback), ctx);
@@ -3437,7 +3537,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
3437
3537
  case "select": return validateSelectPlan(plan, value);
3438
3538
  case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
3439
3539
  case "inlineText": return validateInlineTextPlan(plan, value);
3440
- case "media": return isPlainObject$4(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")];
3540
+ case "media": return isPlainObject$4(value) && mediaIdentifierSchema.safeParse(value.identifier).success && (value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type)) ? [] : [issue(plan, "invalidMedia")];
3441
3541
  case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
3442
3542
  case "repeater": return validateRepeaterPlan(plan, value, ctx);
3443
3543
  case "group": return validateGroupPlan(plan, value, ctx);
@@ -4070,6 +4170,17 @@ function isOnColorBackgroundCandidateToken(token) {
4070
4170
  return BACKGROUND_ROLE_NAMES.has(role);
4071
4171
  }
4072
4172
  //#endregion
4173
+ //#region ../theme-core/src/site-styles/lookOptionGroups.ts
4174
+ function defineLookOptionGroup(group) {
4175
+ defaultOption(group);
4176
+ return group;
4177
+ }
4178
+ function defaultOption(group) {
4179
+ const option = group.options.find((candidate) => candidate.id === group.defaultOptionId);
4180
+ if (option) return option;
4181
+ throw new Error(`Look option group "${group.id}" defaults to missing option "${group.defaultOptionId}".`);
4182
+ }
4183
+ //#endregion
4073
4184
  //#region ../theme-core/src/site-styles/types.ts
4074
4185
  /**
4075
4186
  * Defines a literal-preserving catalog while rejecting top-level extra keys on
@@ -4215,767 +4326,655 @@ function defineBlockDesignCapability(capability) {
4215
4326
  //#region ../theme-core/src/site-styles/appearancePresetResolution.ts
4216
4327
  function assertValidOptionGroups(preset) {
4217
4328
  preset.optionGroups?.forEach((group) => {
4218
- 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}".`);
4329
+ defineLookOptionGroup(group);
4219
4330
  });
4220
4331
  }
4221
4332
  function defineBlockAppearancePreset(preset) {
4222
4333
  assertValidOptionGroups(preset);
4223
4334
  return preset;
4224
4335
  }
4225
- [...[
4226
- defineBlockAppearancePreset({
4227
- kind: "block-design",
4228
- id: "hero-immersive-image",
4229
- target: "hero",
4230
- label: "Immersive image hero",
4231
- blockKinds: ["block.hero"],
4232
- constraints: { layoutFamilies: ["centered", "compact"] },
4233
- layoutPatches: [{
4234
- constraints: { layoutVariantKeys: ["micro"] },
4235
- designPatch: {
4236
- sectionHeight: "banner",
4237
- heroTypographyScale: "display"
4238
- }
4239
- }],
4240
- design: {
4241
- sectionSurface: "hero-image",
4242
- contentFrame: plainFrame,
4243
- itemSurface: "none",
4244
- sectionHeight: "hero",
4245
- heroComposition: "center",
4246
- heroTypographyScale: "display",
4247
- imageSurfaceTreatment: { kind: "neutral-wash" }
4336
+ //#endregion
4337
+ //#region ../theme-core/src/site-styles/blockAppearancePresets.ts
4338
+ const brandScrimOptionGroups = [{
4339
+ id: "image-surface-treatment",
4340
+ label: "Treatment",
4341
+ defaultOptionId: "brand-scrim-primary",
4342
+ options: [{
4343
+ id: "brand-scrim-primary",
4344
+ label: "Brand scrim",
4345
+ designPatch: { imageSurfaceTreatment: {
4346
+ kind: "brand-scrim",
4347
+ token: "primary"
4348
+ } }
4349
+ }, {
4350
+ id: "neutral-scrim",
4351
+ label: "Neutral scrim",
4352
+ designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
4353
+ }]
4354
+ }];
4355
+ const microBannerLayoutPatches = [{
4356
+ constraints: { layoutVariantKeys: ["micro"] },
4357
+ designPatch: { sectionHeight: "banner" }
4358
+ }];
4359
+ defineBlockAppearancePreset({
4360
+ id: "hero-immersive-image",
4361
+ target: "hero",
4362
+ label: "Immersive image hero",
4363
+ blockKinds: ["block.hero"],
4364
+ constraints: { layoutFamilies: ["centered", "compact"] },
4365
+ layoutPatches: [{
4366
+ constraints: { layoutVariantKeys: ["micro"] },
4367
+ designPatch: {
4368
+ sectionHeight: "banner",
4369
+ heroTypographyScale: "display"
4248
4370
  }
4249
- }),
4250
- defineBlockAppearancePreset({
4251
- kind: "block-design",
4252
- id: "hero-bottom-left-panel",
4253
- target: "hero",
4254
- label: "Bottom-left panel hero",
4255
- blockKinds: ["block.hero"],
4256
- constraints: { layoutFamilies: ["centered", "compact"] },
4257
- optionGroups: [{
4258
- id: "image-surface-treatment",
4259
- label: "Treatment",
4260
- selectedOptionId: "neutral-scrim",
4261
- options: [{
4262
- id: "neutral-scrim",
4263
- label: "Neutral scrim",
4264
- designPatch: { imageSurfaceTreatment: {
4265
- kind: "neutral-scrim",
4266
- intensity: "balanced"
4267
- } }
4268
- }, {
4269
- id: "brand-scrim-primary",
4270
- label: "Brand scrim",
4271
- designPatch: { imageSurfaceTreatment: {
4272
- kind: "brand-scrim",
4273
- token: "primary",
4274
- intensity: "balanced"
4275
- } }
4276
- }]
4277
- }],
4278
- layoutPatches: [{
4279
- constraints: { layoutVariantKeys: ["micro"] },
4280
- designPatch: {
4281
- sectionHeight: "banner",
4282
- heroTypographyScale: "editorial"
4283
- }
4284
- }],
4285
- design: {
4286
- sectionSurface: "hero-image",
4287
- contentFrame: panelFrame("raised"),
4288
- itemSurface: "none",
4289
- sectionHeight: "immersive",
4290
- heroComposition: "bottom-left",
4291
- heroTypographyScale: "display",
4292
- imageSurfaceTreatment: {
4371
+ }],
4372
+ design: {
4373
+ sectionSurface: "hero-image",
4374
+ contentFrame: plainFrame,
4375
+ itemSurface: "none",
4376
+ sectionHeight: "hero",
4377
+ heroComposition: "center",
4378
+ heroTypographyScale: "display",
4379
+ imageSurfaceTreatment: { kind: "neutral-wash" }
4380
+ }
4381
+ }), defineBlockAppearancePreset({
4382
+ id: "hero-bottom-left-panel",
4383
+ target: "hero",
4384
+ label: "Bottom-left panel hero",
4385
+ blockKinds: ["block.hero"],
4386
+ constraints: { layoutFamilies: ["centered", "compact"] },
4387
+ optionGroups: [{
4388
+ id: "image-surface-treatment",
4389
+ label: "Treatment",
4390
+ defaultOptionId: "neutral-scrim",
4391
+ options: [{
4392
+ id: "neutral-scrim",
4393
+ label: "Neutral scrim",
4394
+ designPatch: { imageSurfaceTreatment: {
4293
4395
  kind: "neutral-scrim",
4294
4396
  intensity: "balanced"
4295
- }
4296
- }
4297
- }),
4298
- defineBlockAppearancePreset({
4299
- kind: "block-design",
4300
- id: "hero-poster-image",
4301
- target: "hero",
4302
- label: "Poster image hero",
4303
- blockKinds: ["block.hero"],
4304
- constraints: { layoutFamilies: ["centered", "compact"] },
4305
- layoutPatches: [{
4306
- constraints: { layoutVariantKeys: ["micro"] },
4307
- designPatch: {
4308
- sectionHeight: "banner",
4309
- heroTypographyScale: "display"
4310
- }
4311
- }],
4312
- design: {
4313
- sectionSurface: "hero-image",
4314
- contentFrame: plainFrame,
4315
- itemSurface: "none",
4316
- sectionHeight: "immersive",
4317
- heroComposition: "center",
4318
- heroTypographyScale: "poster",
4319
- imageSurfaceTreatment: {
4397
+ } }
4398
+ }, {
4399
+ id: "brand-scrim-primary",
4400
+ label: "Brand scrim",
4401
+ designPatch: { imageSurfaceTreatment: {
4320
4402
  kind: "brand-scrim",
4321
4403
  token: "primary",
4322
- intensity: "strong"
4323
- }
4324
- }
4325
- }),
4326
- defineBlockAppearancePreset({
4327
- kind: "block-design",
4328
- id: "hero-brand-scrim",
4329
- target: "hero",
4330
- label: "Brand scrim image hero",
4331
- blockKinds: ["block.hero"],
4332
- constraints: { layoutFamilies: ["centered", "compact"] },
4333
- optionGroups: [{
4334
- id: "image-surface-treatment",
4335
- label: "Treatment",
4336
- selectedOptionId: "brand-scrim-primary",
4337
- options: [{
4338
- id: "brand-scrim-primary",
4339
- label: "Brand scrim",
4340
- designPatch: { imageSurfaceTreatment: {
4341
- kind: "brand-scrim",
4342
- token: "primary"
4343
- } }
4344
- }, {
4345
- id: "neutral-scrim",
4346
- label: "Neutral scrim",
4347
- designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
4348
- }]
4349
- }],
4350
- layoutPatches: [{
4351
- constraints: { layoutVariantKeys: ["micro"] },
4352
- designPatch: { sectionHeight: "banner" }
4353
- }],
4354
- design: {
4355
- sectionSurface: "hero-image",
4356
- contentFrame: plainFrame,
4357
- itemSurface: "none",
4358
- sectionHeight: "immersive",
4359
- heroComposition: "center",
4360
- heroTypographyScale: "display",
4361
- imageSurfaceTreatment: {
4362
- kind: "brand-scrim",
4363
- token: "primary"
4364
- }
4365
- }
4366
- }),
4367
- defineBlockAppearancePreset({
4368
- kind: "block-design",
4369
- id: "hero-brand-scrim-fixed-frame",
4370
- target: "hero",
4371
- label: "Fixed-frame brand scrim hero",
4372
- blockKinds: ["block.hero"],
4373
- constraints: { layoutFamilies: ["centered", "compact"] },
4374
- optionGroups: [{
4375
- id: "image-surface-treatment",
4376
- label: "Treatment",
4377
- selectedOptionId: "brand-scrim-primary",
4378
- options: [{
4379
- id: "brand-scrim-primary",
4380
- label: "Brand scrim",
4381
- designPatch: { imageSurfaceTreatment: {
4382
- kind: "brand-scrim",
4383
- token: "primary"
4384
- } }
4385
- }, {
4386
- id: "neutral-scrim",
4387
- label: "Neutral scrim",
4388
- designPatch: { imageSurfaceTreatment: { kind: "neutral-scrim" } }
4389
- }]
4390
- }],
4391
- layoutPatches: [{
4392
- constraints: { layoutVariantKeys: ["micro"] },
4393
- designPatch: { sectionHeight: "banner" }
4394
- }],
4395
- design: {
4396
- sectionSurface: "hero-image",
4397
- contentFrame: plainFrame,
4398
- itemSurface: "none",
4399
- sectionHeight: "immersive",
4400
- heroComposition: "center",
4401
- heroTypographyScale: "display",
4402
- imageSurfaceTreatment: {
4403
- kind: "brand-scrim",
4404
- token: "primary"
4405
- },
4406
- imageSurfaceMotion: "fixed-frame",
4407
- eyebrowTreatment: "accent-pill-bounce"
4408
- }
4409
- }),
4410
- defineBlockAppearancePreset({
4411
- kind: "block-design",
4412
- id: "hero-brand-depth-expressive",
4413
- target: "hero",
4414
- label: "Expressive brand-depth hero",
4415
- blockKinds: ["block.hero"],
4416
- constraints: { layoutFamilies: ["centered", "compact"] },
4417
- design: {
4418
- sectionSurface: "brand-depth-band",
4419
- contentFrame: plainFrame,
4420
- itemSurface: "none",
4421
- heroComposition: "center",
4422
- heroTypographyScale: "editorial",
4423
- eyebrowTreatment: "accent-pill-bounce"
4424
- }
4425
- }),
4426
- defineBlockAppearancePreset({
4427
- kind: "block-design",
4428
- id: "hero-contained-intro",
4429
- target: "hero",
4430
- label: "Contained intro hero",
4431
- blockKinds: ["block.hero"],
4432
- design: {
4433
- sectionSurface: "muted-band",
4434
- contentFrame: panelFrame("inset"),
4435
- itemSurface: "none",
4436
- heroComposition: "center",
4437
- heroTypographyScale: "editorial"
4438
- }
4439
- }),
4440
- defineBlockAppearancePreset({
4441
- kind: "block-design",
4442
- id: "hero-split-editorial",
4443
- target: "hero",
4444
- label: "Editorial split hero",
4445
- blockKinds: ["block.hero"],
4446
- constraints: { layoutFamilies: ["split"] },
4447
- design: {
4448
- sectionSurface: "base",
4449
- contentFrame: plainFrame,
4450
- itemSurface: "none",
4404
+ intensity: "balanced"
4405
+ } }
4406
+ }]
4407
+ }],
4408
+ layoutPatches: [{
4409
+ constraints: { layoutVariantKeys: ["micro"] },
4410
+ designPatch: {
4411
+ sectionHeight: "banner",
4451
4412
  heroTypographyScale: "editorial"
4452
4413
  }
4453
- }),
4454
- defineBlockAppearancePreset({
4455
- kind: "block-design",
4456
- id: "hero-split-brand",
4457
- target: "hero",
4458
- label: "Brand split hero",
4459
- blockKinds: ["block.hero"],
4460
- constraints: { layoutFamilies: ["split"] },
4461
- design: {
4462
- sectionSurface: "brand-depth-band",
4463
- contentFrame: plainFrame,
4464
- itemSurface: "none",
4465
- heroTypographyScale: "display",
4466
- eyebrowTreatment: "accent-pill-bounce"
4467
- }
4468
- }),
4469
- defineBlockAppearancePreset({
4470
- kind: "block-design",
4471
- id: "hero-split-soft-panel",
4472
- target: "hero",
4473
- label: "Soft panel split hero",
4474
- blockKinds: ["block.hero"],
4475
- constraints: { layoutFamilies: ["split"] },
4476
- design: {
4477
- sectionSurface: "muted-band",
4478
- contentFrame: panelFrame("raised"),
4479
- itemSurface: "none",
4480
- heroTypographyScale: "editorial"
4414
+ }],
4415
+ design: {
4416
+ sectionSurface: "hero-image",
4417
+ contentFrame: panelFrame("raised"),
4418
+ itemSurface: "none",
4419
+ sectionHeight: "immersive",
4420
+ heroComposition: "bottom-left",
4421
+ heroTypographyScale: "display",
4422
+ imageSurfaceTreatment: {
4423
+ kind: "neutral-scrim",
4424
+ intensity: "balanced"
4481
4425
  }
4482
- }),
4483
- defineBlockAppearancePreset({
4484
- kind: "block-design",
4485
- id: "hero-split-accent",
4486
- target: "hero",
4487
- label: "Accent split hero",
4488
- blockKinds: ["block.hero"],
4489
- constraints: { layoutFamilies: ["split"] },
4490
- design: {
4491
- sectionSurface: "accent-band",
4492
- contentFrame: panelFrame("raised"),
4493
- itemSurface: "none",
4426
+ }
4427
+ }), defineBlockAppearancePreset({
4428
+ id: "hero-poster-image",
4429
+ target: "hero",
4430
+ label: "Poster image hero",
4431
+ blockKinds: ["block.hero"],
4432
+ constraints: { layoutFamilies: ["centered", "compact"] },
4433
+ layoutPatches: [{
4434
+ constraints: { layoutVariantKeys: ["micro"] },
4435
+ designPatch: {
4436
+ sectionHeight: "banner",
4494
4437
  heroTypographyScale: "display"
4495
4438
  }
4496
- }),
4497
- defineBlockAppearancePreset({
4498
- kind: "block-design",
4499
- id: "intro-editorial-statement",
4500
- target: "intro",
4501
- label: "Editorial intro statement",
4502
- blockKinds: ["block.intro"],
4503
- constraints: { layoutVariantKeys: ["centered-copy", "statement-copy"] },
4504
- design: {
4505
- sectionSurface: "base",
4506
- contentFrame: plainFrame,
4507
- itemSurface: "none",
4508
- composition: {
4509
- kind: "intro",
4510
- treatment: "editorial-statement"
4511
- }
4512
- }
4513
- }),
4514
- defineBlockAppearancePreset({
4515
- kind: "block-design",
4516
- id: "intro-portrait-bio",
4517
- target: "intro",
4518
- label: "Portrait and bio",
4519
- blockKinds: ["block.intro"],
4520
- constraints: { layoutVariantKeys: ["media-copy"] },
4521
- design: {
4522
- sectionSurface: "base",
4523
- contentFrame: plainFrame,
4524
- itemSurface: "none",
4525
- composition: {
4526
- kind: "intro",
4527
- treatment: "portrait-bio"
4528
- }
4529
- }
4530
- }),
4531
- defineBlockAppearancePreset({
4532
- kind: "block-design",
4533
- id: "offerings-preview-default-cards",
4534
- target: "offerings",
4535
- label: "Default offering cards",
4536
- blockKinds: ["block.offerings-preview"],
4537
- design: {
4538
- sectionSurface: "base",
4539
- contentFrame: plainFrame,
4540
- itemSurface: "default"
4541
- }
4542
- }),
4543
- defineBlockAppearancePreset({
4544
- kind: "block-design",
4545
- id: "offerings-preview-secondary-cards",
4546
- target: "offerings",
4547
- label: "Secondary offering cards",
4548
- blockKinds: ["block.offerings-preview"],
4549
- design: {
4550
- sectionSurface: "muted-band",
4551
- contentFrame: plainFrame,
4552
- itemSurface: "inset"
4553
- }
4554
- }),
4555
- defineBlockAppearancePreset({
4556
- kind: "block-design",
4557
- id: "offerings-preview-non-carded",
4558
- target: "offerings",
4559
- label: "Non-carded offerings",
4560
- blockKinds: ["block.offerings-preview"],
4561
- design: {
4562
- sectionSurface: "muted-band",
4563
- contentFrame: plainFrame,
4564
- itemSurface: "editorial"
4565
- }
4566
- }),
4567
- defineBlockAppearancePreset({
4568
- kind: "block-design",
4569
- id: "offerings-preview-paired-feature-cards",
4570
- target: "offerings",
4571
- label: "Paired feature cards",
4572
- blockKinds: ["block.offerings-preview"],
4573
- constraints: { layoutVariantKeys: ["cards"] },
4574
- design: {
4575
- sectionSurface: "base",
4576
- contentFrame: plainFrame,
4577
- itemSurface: "none"
4578
- }
4579
- }),
4580
- defineBlockAppearancePreset({
4581
- kind: "block-design",
4582
- id: "offerings-preview-open-editorial-columns",
4583
- target: "offerings",
4584
- label: "Open editorial columns",
4585
- blockKinds: ["block.offerings-preview"],
4586
- constraints: { layoutVariantKeys: ["cards"] },
4587
- design: {
4588
- sectionSurface: "base",
4589
- contentFrame: plainFrame,
4590
- itemSurface: "none"
4591
- }
4592
- }),
4593
- defineBlockAppearancePreset({
4594
- kind: "block-design",
4595
- id: "offerings-preview-joined-programme-panel",
4596
- target: "offerings",
4597
- label: "Joined programme panel",
4598
- blockKinds: ["block.offerings-preview"],
4599
- constraints: { layoutVariantKeys: ["cards"] },
4600
- design: {
4601
- sectionSurface: "base",
4602
- contentFrame: plainFrame,
4603
- itemSurface: "none"
4604
- }
4605
- }),
4606
- defineBlockAppearancePreset({
4607
- kind: "block-design",
4608
- id: "feature-cards-raised-rule",
4609
- target: "feature-cards",
4610
- label: "Raised cards with rule",
4611
- blockKinds: ["block.feature-cards"],
4612
- design: {
4613
- sectionSurface: "base",
4614
- contentFrame: plainFrame,
4615
- itemSurface: "raised"
4616
- }
4617
- }),
4618
- defineBlockAppearancePreset({
4619
- kind: "block-design",
4620
- id: "feature-cards-bold-colors",
4621
- target: "feature-cards",
4622
- label: "Bold colour-blocked cards",
4623
- blockKinds: ["block.feature-cards"],
4624
- design: {
4625
- sectionSurface: "base",
4626
- contentFrame: plainFrame,
4627
- itemSurface: "color-blocked"
4628
- }
4629
- }),
4630
- defineBlockAppearancePreset({
4631
- kind: "block-design",
4632
- id: "feature-cards-editorial-columns",
4633
- target: "feature-cards",
4634
- label: "Editorial open columns",
4635
- blockKinds: ["block.feature-cards"],
4636
- design: {
4637
- sectionSurface: "base",
4638
- contentFrame: plainFrame,
4639
- itemSurface: "editorial"
4640
- }
4641
- }),
4642
- defineBlockAppearancePreset({
4643
- kind: "block-design",
4644
- id: "feature-cards-asymmetric-emphasis",
4645
- target: "feature-cards",
4646
- label: "Asymmetric emphasis pair",
4647
- blockKinds: ["block.feature-cards"],
4648
- constraints: { layoutFamilies: ["grid"] },
4649
- design: {
4650
- sectionSurface: "base",
4651
- contentFrame: plainFrame,
4652
- itemSurface: "none",
4653
- composition: {
4654
- kind: "feature-cards",
4655
- treatment: "asymmetric-emphasis"
4656
- }
4657
- }
4658
- }),
4659
- defineBlockAppearancePreset({
4660
- kind: "block-design",
4661
- id: "feature-cards-framed-programme",
4662
- target: "feature-cards",
4663
- label: "Framed programme cards",
4664
- blockKinds: ["block.feature-cards"],
4665
- constraints: { layoutFamilies: ["grid"] },
4666
- design: {
4667
- sectionSurface: "brand-depth-band",
4668
- contentFrame: plainFrame,
4669
- itemSurface: "inset",
4670
- composition: {
4671
- kind: "feature-cards",
4672
- treatment: "framed-programme"
4673
- }
4674
- }
4675
- }),
4676
- defineBlockAppearancePreset({
4677
- kind: "block-design",
4678
- id: "feature-cards-soft-panels",
4679
- target: "feature-cards",
4680
- label: "Soft tinted panels",
4681
- blockKinds: ["block.feature-cards"],
4682
- design: {
4683
- sectionSurface: "base",
4684
- contentFrame: plainFrame,
4685
- itemSurface: "inset"
4686
- }
4687
- }),
4688
- defineBlockAppearancePreset({
4689
- kind: "block-design",
4690
- id: "feature-cards-editorial-diptych",
4691
- target: "feature-cards",
4692
- label: "Editorial diptych",
4693
- blockKinds: ["block.feature-cards"],
4694
- constraints: { layoutVariantKeys: ["editorial-diptych"] },
4695
- design: {
4696
- sectionSurface: "base",
4697
- contentFrame: plainFrame,
4698
- itemSurface: "flat"
4699
- }
4700
- }),
4701
- defineBlockAppearancePreset({
4702
- kind: "block-design",
4703
- id: "feature-cards-editorial-pathways",
4704
- target: "feature-cards",
4705
- label: "Editorial pathways",
4706
- blockKinds: ["block.feature-cards"],
4707
- constraints: { layoutVariantKeys: ["editorial-pathways"] },
4708
- design: {
4709
- sectionSurface: "base",
4710
- contentFrame: plainFrame,
4711
- itemSurface: "flat"
4712
- }
4713
- }),
4714
- defineBlockAppearancePreset({
4715
- kind: "block-design",
4716
- id: "feature-cards-photo-tiles",
4717
- target: "feature-cards",
4718
- label: "Photo tiles",
4719
- blockKinds: ["block.feature-cards"],
4720
- design: {
4721
- sectionSurface: "base",
4722
- contentFrame: plainFrame,
4723
- itemSurface: "raised"
4724
- }
4725
- }),
4726
- defineBlockAppearancePreset({
4727
- kind: "block-design",
4728
- id: "events-lined-panel",
4729
- target: "events",
4730
- label: "Raised event panel",
4731
- blockKinds: ["block.event-calendar", "block.event-listing"],
4732
- design: {
4733
- sectionSurface: "base",
4734
- contentFrame: panelFrame("raised"),
4735
- itemSurface: "none"
4736
- }
4737
- }),
4738
- defineBlockAppearancePreset({
4739
- kind: "block-design",
4740
- id: "events-ruled-register",
4741
- target: "events",
4742
- label: "Ruled event register",
4743
- blockKinds: ["block.event-calendar", "block.event-listing"],
4744
- design: {
4745
- sectionSurface: "brand-depth-band",
4746
- contentFrame: plainFrame,
4747
- itemSurface: "none",
4748
- eventListTreatment: "ruled-register"
4749
- }
4750
- }),
4751
- defineBlockAppearancePreset({
4752
- kind: "block-design",
4753
- id: "events-editorial-register",
4754
- target: "events",
4755
- label: "Editorial event register",
4756
- blockKinds: ["block.event-calendar", "block.event-listing"],
4757
- design: {
4758
- sectionSurface: "base",
4759
- contentFrame: plainFrame,
4760
- itemSurface: "none",
4761
- eventListTreatment: "editorial-register"
4762
- }
4763
- }),
4764
- defineBlockAppearancePreset({
4765
- kind: "block-design",
4766
- id: "events-dense-index",
4767
- target: "events",
4768
- label: "Dense event index",
4769
- blockKinds: ["block.event-calendar", "block.event-listing"],
4770
- design: {
4771
- sectionSurface: "accent-band",
4772
- contentFrame: plainFrame,
4773
- itemSurface: "none",
4774
- eventListTreatment: "dense-index"
4775
- }
4776
- }),
4777
- defineBlockAppearancePreset({
4778
- kind: "block-design",
4779
- id: "schedule-details-brand-depth",
4780
- target: "events",
4781
- label: "Brand-depth schedule details",
4782
- blockKinds: ["block.event-details", "block.course-details"],
4783
- design: {
4784
- sectionSurface: "brand-depth-band",
4785
- contentFrame: plainFrame,
4786
- itemSurface: "none",
4787
- tileTreatment: "brand-depth"
4788
- }
4789
- }),
4790
- defineBlockAppearancePreset({
4791
- kind: "block-design",
4792
- id: "media-text-flush-feature",
4793
- target: "media-text",
4794
- label: "Flush media feature",
4795
- blockKinds: ["block.media-text"],
4796
- design: {
4797
- sectionSurface: "muted-band",
4798
- contentFrame: flushPanelFrame({ bleed: "start" }),
4799
- itemSurface: "none"
4800
- }
4801
- }),
4802
- defineBlockAppearancePreset({
4803
- kind: "block-design",
4804
- id: "testimonials-simple-cards",
4805
- target: "testimonials",
4806
- label: "Simple testimonial cards",
4807
- blockKinds: ["block.testimonials"],
4808
- design: {
4809
- sectionSurface: "base",
4810
- contentFrame: plainFrame,
4811
- itemSurface: "default"
4812
- }
4813
- }),
4814
- defineBlockAppearancePreset({
4815
- kind: "block-design",
4816
- id: "testimonials-raised-panel",
4817
- target: "testimonials",
4818
- label: "Raised testimonial panel",
4819
- blockKinds: ["block.testimonials"],
4820
- design: {
4821
- sectionSurface: "muted-band",
4822
- contentFrame: panelFrame("raised"),
4823
- itemSurface: "raised"
4824
- }
4825
- }),
4826
- defineBlockAppearancePreset({
4827
- kind: "block-design",
4828
- id: "testimonials-accent-panel",
4829
- target: "testimonials",
4830
- label: "Accent testimonial panel",
4831
- blockKinds: ["block.testimonials"],
4832
- design: {
4833
- sectionSurface: "accent-band",
4834
- contentFrame: panelFrame("raised"),
4835
- itemSurface: "raised"
4836
- }
4837
- }),
4838
- defineBlockAppearancePreset({
4839
- kind: "block-design",
4840
- id: "testimonials-default-cards",
4841
- target: "testimonials",
4842
- label: "Default cards",
4843
- blockKinds: ["block.testimonials"],
4844
- design: {
4845
- sectionSurface: "base",
4846
- contentFrame: plainFrame,
4847
- itemSurface: "none",
4848
- testimonialCardTreatment: "default"
4849
- }
4850
- }),
4851
- defineBlockAppearancePreset({
4852
- kind: "block-design",
4853
- id: "testimonials-statement-cards",
4854
- target: "testimonials",
4855
- label: "Statement cards",
4856
- blockKinds: ["block.testimonials"],
4857
- design: {
4858
- sectionSurface: "accent-band",
4859
- contentFrame: plainFrame,
4860
- itemSurface: "raised",
4861
- testimonialCardTreatment: "statement"
4862
- }
4863
- }),
4864
- defineBlockAppearancePreset({
4865
- kind: "block-design",
4866
- id: "testimonials-brand-statement-cards",
4867
- target: "testimonials",
4868
- label: "Brand statement cards",
4869
- blockKinds: ["block.testimonials"],
4870
- design: {
4871
- sectionSurface: "brand-depth-band",
4872
- contentFrame: plainFrame,
4873
- itemSurface: "raised",
4874
- testimonialCardTreatment: "statement"
4875
- }
4876
- }),
4877
- defineBlockAppearancePreset({
4878
- kind: "block-design",
4879
- id: "testimonials-non-carded",
4880
- target: "testimonials",
4881
- label: "Non-carded",
4882
- blockKinds: ["block.testimonials"],
4883
- design: {
4884
- sectionSurface: "muted-band",
4885
- contentFrame: plainFrame,
4886
- itemSurface: "none",
4887
- testimonialCardTreatment: "non-carded"
4888
- }
4889
- }),
4890
- defineBlockAppearancePreset({
4891
- kind: "block-design",
4892
- id: "testimonials-evergreen-lead",
4893
- target: "testimonials",
4894
- label: "Evergreen lead",
4895
- blockKinds: ["block.testimonials"],
4896
- constraints: { layoutVariantKeys: ["featured-editorial"] },
4897
- design: {
4898
- sectionSurface: "base",
4899
- contentFrame: plainFrame,
4900
- itemSurface: "none"
4901
- }
4902
- }),
4903
- defineBlockAppearancePreset({
4904
- kind: "block-design",
4905
- id: "testimonials-room-and-response",
4906
- target: "testimonials",
4907
- label: "Room and response",
4908
- blockKinds: ["block.testimonials"],
4909
- constraints: { layoutVariantKeys: ["featured-editorial"] },
4910
- design: {
4911
- sectionSurface: "base",
4912
- contentFrame: plainFrame,
4913
- itemSurface: "none"
4439
+ }],
4440
+ design: {
4441
+ sectionSurface: "hero-image",
4442
+ contentFrame: plainFrame,
4443
+ itemSurface: "none",
4444
+ sectionHeight: "immersive",
4445
+ heroComposition: "center",
4446
+ heroTypographyScale: "poster",
4447
+ imageSurfaceTreatment: {
4448
+ kind: "brand-scrim",
4449
+ token: "primary",
4450
+ intensity: "strong"
4914
4451
  }
4915
- }),
4916
- defineBlockAppearancePreset({
4917
- kind: "block-design",
4918
- id: "testimonials-open-floor",
4919
- target: "testimonials",
4920
- label: "Open floor",
4921
- blockKinds: ["block.testimonials"],
4922
- constraints: { layoutVariantKeys: ["featured-editorial"] },
4923
- design: {
4924
- sectionSurface: "base",
4925
- contentFrame: plainFrame,
4926
- itemSurface: "none"
4452
+ }
4453
+ }), defineBlockAppearancePreset({
4454
+ id: "hero-brand-scrim",
4455
+ target: "hero",
4456
+ label: "Brand scrim image hero",
4457
+ blockKinds: ["block.hero"],
4458
+ constraints: { layoutFamilies: ["centered", "compact"] },
4459
+ optionGroups: brandScrimOptionGroups,
4460
+ layoutPatches: microBannerLayoutPatches,
4461
+ design: {
4462
+ sectionSurface: "hero-image",
4463
+ contentFrame: plainFrame,
4464
+ itemSurface: "none",
4465
+ sectionHeight: "immersive",
4466
+ heroComposition: "center",
4467
+ heroTypographyScale: "display",
4468
+ imageSurfaceTreatment: {
4469
+ kind: "brand-scrim",
4470
+ token: "primary"
4927
4471
  }
4928
- }),
4929
- defineBlockAppearancePreset({
4930
- kind: "block-design",
4931
- id: "faq-base-accordion",
4932
- target: "faq",
4933
- label: "Base accordion FAQ",
4934
- blockKinds: ["block.faq"],
4935
- design: {
4936
- sectionSurface: "base",
4937
- contentFrame: plainFrame,
4938
- itemSurface: "default"
4472
+ }
4473
+ }), defineBlockAppearancePreset({
4474
+ id: "hero-brand-scrim-fixed-frame",
4475
+ target: "hero",
4476
+ label: "Fixed-frame brand scrim hero",
4477
+ blockKinds: ["block.hero"],
4478
+ constraints: { layoutFamilies: ["centered", "compact"] },
4479
+ optionGroups: brandScrimOptionGroups,
4480
+ layoutPatches: microBannerLayoutPatches,
4481
+ design: {
4482
+ sectionSurface: "hero-image",
4483
+ contentFrame: plainFrame,
4484
+ itemSurface: "none",
4485
+ sectionHeight: "immersive",
4486
+ heroComposition: "center",
4487
+ heroTypographyScale: "display",
4488
+ imageSurfaceTreatment: {
4489
+ kind: "brand-scrim",
4490
+ token: "primary"
4491
+ },
4492
+ imageSurfaceMotion: "fixed-frame",
4493
+ eyebrowTreatment: "accent-pill-bounce"
4494
+ }
4495
+ }), defineBlockAppearancePreset({
4496
+ id: "hero-brand-depth-expressive",
4497
+ target: "hero",
4498
+ label: "Expressive brand-depth hero",
4499
+ blockKinds: ["block.hero"],
4500
+ constraints: { layoutFamilies: ["centered", "compact"] },
4501
+ design: {
4502
+ sectionSurface: "brand-depth-band",
4503
+ contentFrame: plainFrame,
4504
+ itemSurface: "none",
4505
+ heroComposition: "center",
4506
+ heroTypographyScale: "editorial",
4507
+ eyebrowTreatment: "accent-pill-bounce"
4508
+ }
4509
+ }), defineBlockAppearancePreset({
4510
+ id: "hero-contained-intro",
4511
+ target: "hero",
4512
+ label: "Contained intro hero",
4513
+ blockKinds: ["block.hero"],
4514
+ design: {
4515
+ sectionSurface: "muted-band",
4516
+ contentFrame: panelFrame("inset"),
4517
+ itemSurface: "none",
4518
+ heroComposition: "center",
4519
+ heroTypographyScale: "editorial"
4520
+ }
4521
+ }), defineBlockAppearancePreset({
4522
+ id: "hero-split-editorial",
4523
+ target: "hero",
4524
+ label: "Editorial split hero",
4525
+ blockKinds: ["block.hero"],
4526
+ constraints: { layoutFamilies: ["split"] },
4527
+ design: {
4528
+ sectionSurface: "base",
4529
+ contentFrame: plainFrame,
4530
+ itemSurface: "none",
4531
+ heroTypographyScale: "editorial"
4532
+ }
4533
+ }), defineBlockAppearancePreset({
4534
+ id: "hero-split-brand",
4535
+ target: "hero",
4536
+ label: "Brand split hero",
4537
+ blockKinds: ["block.hero"],
4538
+ constraints: { layoutFamilies: ["split"] },
4539
+ design: {
4540
+ sectionSurface: "brand-depth-band",
4541
+ contentFrame: plainFrame,
4542
+ itemSurface: "none",
4543
+ heroTypographyScale: "display",
4544
+ eyebrowTreatment: "accent-pill-bounce"
4545
+ }
4546
+ }), defineBlockAppearancePreset({
4547
+ id: "hero-split-soft-panel",
4548
+ target: "hero",
4549
+ label: "Soft panel split hero",
4550
+ blockKinds: ["block.hero"],
4551
+ constraints: { layoutFamilies: ["split"] },
4552
+ design: {
4553
+ sectionSurface: "muted-band",
4554
+ contentFrame: panelFrame("raised"),
4555
+ itemSurface: "none",
4556
+ heroTypographyScale: "editorial"
4557
+ }
4558
+ }), defineBlockAppearancePreset({
4559
+ id: "hero-split-accent",
4560
+ target: "hero",
4561
+ label: "Accent split hero",
4562
+ blockKinds: ["block.hero"],
4563
+ constraints: { layoutFamilies: ["split"] },
4564
+ design: {
4565
+ sectionSurface: "accent-band",
4566
+ contentFrame: panelFrame("raised"),
4567
+ itemSurface: "none",
4568
+ heroTypographyScale: "display"
4569
+ }
4570
+ }), defineBlockAppearancePreset({
4571
+ id: "intro-editorial-statement",
4572
+ target: "intro",
4573
+ label: "Editorial intro statement",
4574
+ blockKinds: ["block.intro"],
4575
+ constraints: { layoutVariantKeys: ["centered-copy", "statement-copy"] },
4576
+ design: {
4577
+ sectionSurface: "base",
4578
+ contentFrame: plainFrame,
4579
+ itemSurface: "none",
4580
+ composition: {
4581
+ kind: "intro",
4582
+ treatment: "editorial-statement"
4939
4583
  }
4940
- }),
4941
- defineBlockAppearancePreset({
4942
- kind: "block-design",
4943
- id: "faq-contained-help",
4944
- target: "faq",
4945
- label: "Contained help panel",
4946
- blockKinds: ["block.faq"],
4947
- design: {
4948
- sectionSurface: "muted-band",
4949
- contentFrame: panelFrame("inset"),
4950
- itemSurface: "default"
4584
+ }
4585
+ }), defineBlockAppearancePreset({
4586
+ id: "intro-portrait-bio",
4587
+ target: "intro",
4588
+ label: "Portrait and bio",
4589
+ blockKinds: ["block.intro"],
4590
+ constraints: { layoutVariantKeys: ["media-copy"] },
4591
+ design: {
4592
+ sectionSurface: "base",
4593
+ contentFrame: plainFrame,
4594
+ itemSurface: "none",
4595
+ composition: {
4596
+ kind: "intro",
4597
+ treatment: "portrait-bio"
4951
4598
  }
4952
- }),
4953
- defineBlockAppearancePreset({
4954
- kind: "block-design",
4955
- id: "contact-form-panel",
4956
- target: "contact-form",
4957
- label: "Raised form panel",
4958
- blockKinds: ["block.form"],
4959
- design: {
4960
- sectionSurface: "muted-band",
4961
- contentFrame: panelFrame("raised"),
4962
- itemSurface: "none"
4599
+ }
4600
+ }), defineBlockAppearancePreset({
4601
+ id: "offerings-preview-default-cards",
4602
+ target: "offerings",
4603
+ label: "Default offering cards",
4604
+ blockKinds: ["block.offerings-preview"],
4605
+ design: {
4606
+ sectionSurface: "base",
4607
+ contentFrame: plainFrame,
4608
+ itemSurface: "default"
4609
+ }
4610
+ }), defineBlockAppearancePreset({
4611
+ id: "offerings-preview-secondary-cards",
4612
+ target: "offerings",
4613
+ label: "Secondary offering cards",
4614
+ blockKinds: ["block.offerings-preview"],
4615
+ design: {
4616
+ sectionSurface: "muted-band",
4617
+ contentFrame: plainFrame,
4618
+ itemSurface: "inset"
4619
+ }
4620
+ }), defineBlockAppearancePreset({
4621
+ id: "offerings-preview-non-carded",
4622
+ target: "offerings",
4623
+ label: "Non-carded offerings",
4624
+ blockKinds: ["block.offerings-preview"],
4625
+ design: {
4626
+ sectionSurface: "muted-band",
4627
+ contentFrame: plainFrame,
4628
+ itemSurface: "editorial"
4629
+ }
4630
+ }), defineBlockAppearancePreset({
4631
+ id: "offerings-preview-paired-feature-cards",
4632
+ target: "offerings",
4633
+ label: "Paired feature cards",
4634
+ blockKinds: ["block.offerings-preview"],
4635
+ constraints: { layoutVariantKeys: ["cards"] },
4636
+ design: {
4637
+ sectionSurface: "base",
4638
+ contentFrame: plainFrame,
4639
+ itemSurface: "none"
4640
+ }
4641
+ }), defineBlockAppearancePreset({
4642
+ id: "offerings-preview-open-editorial-columns",
4643
+ target: "offerings",
4644
+ label: "Open editorial columns",
4645
+ blockKinds: ["block.offerings-preview"],
4646
+ constraints: { layoutVariantKeys: ["cards"] },
4647
+ design: {
4648
+ sectionSurface: "base",
4649
+ contentFrame: plainFrame,
4650
+ itemSurface: "none"
4651
+ }
4652
+ }), defineBlockAppearancePreset({
4653
+ id: "offerings-preview-joined-programme-panel",
4654
+ target: "offerings",
4655
+ label: "Joined programme panel",
4656
+ blockKinds: ["block.offerings-preview"],
4657
+ constraints: { layoutVariantKeys: ["cards"] },
4658
+ design: {
4659
+ sectionSurface: "base",
4660
+ contentFrame: plainFrame,
4661
+ itemSurface: "none"
4662
+ }
4663
+ }), defineBlockAppearancePreset({
4664
+ id: "feature-cards-raised-rule",
4665
+ target: "feature-cards",
4666
+ label: "Raised cards with rule",
4667
+ blockKinds: ["block.feature-cards"],
4668
+ design: {
4669
+ sectionSurface: "base",
4670
+ contentFrame: plainFrame,
4671
+ itemSurface: "raised"
4672
+ }
4673
+ }), defineBlockAppearancePreset({
4674
+ id: "feature-cards-bold-colors",
4675
+ target: "feature-cards",
4676
+ label: "Bold colour-blocked cards",
4677
+ blockKinds: ["block.feature-cards"],
4678
+ design: {
4679
+ sectionSurface: "base",
4680
+ contentFrame: plainFrame,
4681
+ itemSurface: "color-blocked"
4682
+ }
4683
+ }), defineBlockAppearancePreset({
4684
+ id: "feature-cards-editorial-columns",
4685
+ target: "feature-cards",
4686
+ label: "Editorial open columns",
4687
+ blockKinds: ["block.feature-cards"],
4688
+ design: {
4689
+ sectionSurface: "base",
4690
+ contentFrame: plainFrame,
4691
+ itemSurface: "editorial"
4692
+ }
4693
+ }), defineBlockAppearancePreset({
4694
+ id: "feature-cards-asymmetric-emphasis",
4695
+ target: "feature-cards",
4696
+ label: "Asymmetric emphasis pair",
4697
+ blockKinds: ["block.feature-cards"],
4698
+ constraints: { layoutFamilies: ["grid"] },
4699
+ design: {
4700
+ sectionSurface: "base",
4701
+ contentFrame: plainFrame,
4702
+ itemSurface: "none",
4703
+ composition: {
4704
+ kind: "feature-cards",
4705
+ treatment: "asymmetric-emphasis"
4963
4706
  }
4964
- }),
4965
- defineBlockAppearancePreset({
4966
- kind: "block-design",
4967
- id: "cta-accent-band",
4968
- target: "cta",
4969
- label: "Accent CTA band",
4970
- blockKinds: ["block.cta-full"],
4971
- design: {
4972
- sectionSurface: "accent-band",
4973
- contentFrame: plainFrame,
4974
- itemSurface: "none",
4975
- eyebrowTreatment: "accent"
4707
+ }
4708
+ }), defineBlockAppearancePreset({
4709
+ id: "feature-cards-framed-programme",
4710
+ target: "feature-cards",
4711
+ label: "Framed programme cards",
4712
+ blockKinds: ["block.feature-cards"],
4713
+ constraints: { layoutFamilies: ["grid"] },
4714
+ design: {
4715
+ sectionSurface: "brand-depth-band",
4716
+ contentFrame: plainFrame,
4717
+ itemSurface: "inset",
4718
+ composition: {
4719
+ kind: "feature-cards",
4720
+ treatment: "framed-programme"
4976
4721
  }
4977
- })
4978
- ]];
4722
+ }
4723
+ }), defineBlockAppearancePreset({
4724
+ id: "feature-cards-soft-panels",
4725
+ target: "feature-cards",
4726
+ label: "Soft tinted panels",
4727
+ blockKinds: ["block.feature-cards"],
4728
+ design: {
4729
+ sectionSurface: "base",
4730
+ contentFrame: plainFrame,
4731
+ itemSurface: "inset"
4732
+ }
4733
+ }), defineBlockAppearancePreset({
4734
+ id: "feature-cards-editorial-diptych",
4735
+ target: "feature-cards",
4736
+ label: "Editorial diptych",
4737
+ blockKinds: ["block.feature-cards"],
4738
+ constraints: { layoutVariantKeys: ["editorial-diptych"] },
4739
+ design: {
4740
+ sectionSurface: "base",
4741
+ contentFrame: plainFrame,
4742
+ itemSurface: "flat"
4743
+ }
4744
+ }), defineBlockAppearancePreset({
4745
+ id: "feature-cards-editorial-pathways",
4746
+ target: "feature-cards",
4747
+ label: "Editorial pathways",
4748
+ blockKinds: ["block.feature-cards"],
4749
+ constraints: { layoutVariantKeys: ["editorial-pathways"] },
4750
+ design: {
4751
+ sectionSurface: "base",
4752
+ contentFrame: plainFrame,
4753
+ itemSurface: "flat"
4754
+ }
4755
+ }), defineBlockAppearancePreset({
4756
+ id: "feature-cards-photo-tiles",
4757
+ target: "feature-cards",
4758
+ label: "Photo tiles",
4759
+ blockKinds: ["block.feature-cards"],
4760
+ design: {
4761
+ sectionSurface: "base",
4762
+ contentFrame: plainFrame,
4763
+ itemSurface: "raised"
4764
+ }
4765
+ }), defineBlockAppearancePreset({
4766
+ id: "events-lined-panel",
4767
+ target: "events",
4768
+ label: "Raised event panel",
4769
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4770
+ design: {
4771
+ sectionSurface: "base",
4772
+ contentFrame: panelFrame("raised"),
4773
+ itemSurface: "none"
4774
+ }
4775
+ }), defineBlockAppearancePreset({
4776
+ id: "events-ruled-register",
4777
+ target: "events",
4778
+ label: "Ruled event register",
4779
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4780
+ design: {
4781
+ sectionSurface: "brand-depth-band",
4782
+ contentFrame: plainFrame,
4783
+ itemSurface: "none",
4784
+ eventListTreatment: "ruled-register"
4785
+ }
4786
+ }), defineBlockAppearancePreset({
4787
+ id: "events-editorial-register",
4788
+ target: "events",
4789
+ label: "Editorial event register",
4790
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4791
+ design: {
4792
+ sectionSurface: "base",
4793
+ contentFrame: plainFrame,
4794
+ itemSurface: "none",
4795
+ eventListTreatment: "editorial-register"
4796
+ }
4797
+ }), defineBlockAppearancePreset({
4798
+ id: "events-dense-index",
4799
+ target: "events",
4800
+ label: "Dense event index",
4801
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4802
+ design: {
4803
+ sectionSurface: "accent-band",
4804
+ contentFrame: plainFrame,
4805
+ itemSurface: "none",
4806
+ eventListTreatment: "dense-index"
4807
+ }
4808
+ }), defineBlockAppearancePreset({
4809
+ id: "schedule-details-brand-depth",
4810
+ target: "events",
4811
+ label: "Brand-depth schedule details",
4812
+ blockKinds: ["block.event-details", "block.course-details"],
4813
+ design: {
4814
+ sectionSurface: "brand-depth-band",
4815
+ contentFrame: plainFrame,
4816
+ itemSurface: "none",
4817
+ tileTreatment: "brand-depth"
4818
+ }
4819
+ }), defineBlockAppearancePreset({
4820
+ id: "media-text-flush-feature",
4821
+ target: "media-text",
4822
+ label: "Flush media feature",
4823
+ blockKinds: ["block.media-text"],
4824
+ design: {
4825
+ sectionSurface: "muted-band",
4826
+ contentFrame: flushPanelFrame({ bleed: "start" }),
4827
+ itemSurface: "none"
4828
+ }
4829
+ }), defineBlockAppearancePreset({
4830
+ id: "testimonials-simple-cards",
4831
+ target: "testimonials",
4832
+ label: "Simple testimonial cards",
4833
+ blockKinds: ["block.testimonials"],
4834
+ design: {
4835
+ sectionSurface: "base",
4836
+ contentFrame: plainFrame,
4837
+ itemSurface: "default"
4838
+ }
4839
+ }), defineBlockAppearancePreset({
4840
+ id: "testimonials-raised-panel",
4841
+ target: "testimonials",
4842
+ label: "Raised testimonial panel",
4843
+ blockKinds: ["block.testimonials"],
4844
+ design: {
4845
+ sectionSurface: "muted-band",
4846
+ contentFrame: panelFrame("raised"),
4847
+ itemSurface: "raised"
4848
+ }
4849
+ }), defineBlockAppearancePreset({
4850
+ id: "testimonials-accent-panel",
4851
+ target: "testimonials",
4852
+ label: "Accent testimonial panel",
4853
+ blockKinds: ["block.testimonials"],
4854
+ design: {
4855
+ sectionSurface: "accent-band",
4856
+ contentFrame: panelFrame("raised"),
4857
+ itemSurface: "raised"
4858
+ }
4859
+ }), defineBlockAppearancePreset({
4860
+ id: "testimonials-default-cards",
4861
+ target: "testimonials",
4862
+ label: "Default cards",
4863
+ blockKinds: ["block.testimonials"],
4864
+ design: {
4865
+ sectionSurface: "base",
4866
+ contentFrame: plainFrame,
4867
+ itemSurface: "none",
4868
+ testimonialCardTreatment: "default"
4869
+ }
4870
+ }), defineBlockAppearancePreset({
4871
+ id: "testimonials-statement-cards",
4872
+ target: "testimonials",
4873
+ label: "Statement cards",
4874
+ blockKinds: ["block.testimonials"],
4875
+ design: {
4876
+ sectionSurface: "accent-band",
4877
+ contentFrame: plainFrame,
4878
+ itemSurface: "raised",
4879
+ testimonialCardTreatment: "statement"
4880
+ }
4881
+ }), defineBlockAppearancePreset({
4882
+ id: "testimonials-brand-statement-cards",
4883
+ target: "testimonials",
4884
+ label: "Brand statement cards",
4885
+ blockKinds: ["block.testimonials"],
4886
+ design: {
4887
+ sectionSurface: "brand-depth-band",
4888
+ contentFrame: plainFrame,
4889
+ itemSurface: "raised",
4890
+ testimonialCardTreatment: "statement"
4891
+ }
4892
+ }), defineBlockAppearancePreset({
4893
+ id: "testimonials-non-carded",
4894
+ target: "testimonials",
4895
+ label: "Non-carded",
4896
+ blockKinds: ["block.testimonials"],
4897
+ design: {
4898
+ sectionSurface: "muted-band",
4899
+ contentFrame: plainFrame,
4900
+ itemSurface: "none",
4901
+ testimonialCardTreatment: "non-carded"
4902
+ }
4903
+ }), defineBlockAppearancePreset({
4904
+ id: "testimonials-evergreen-lead",
4905
+ target: "testimonials",
4906
+ label: "Evergreen lead",
4907
+ blockKinds: ["block.testimonials"],
4908
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4909
+ design: {
4910
+ sectionSurface: "base",
4911
+ contentFrame: plainFrame,
4912
+ itemSurface: "none"
4913
+ }
4914
+ }), defineBlockAppearancePreset({
4915
+ id: "testimonials-room-and-response",
4916
+ target: "testimonials",
4917
+ label: "Room and response",
4918
+ blockKinds: ["block.testimonials"],
4919
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4920
+ design: {
4921
+ sectionSurface: "base",
4922
+ contentFrame: plainFrame,
4923
+ itemSurface: "none"
4924
+ }
4925
+ }), defineBlockAppearancePreset({
4926
+ id: "testimonials-open-floor",
4927
+ target: "testimonials",
4928
+ label: "Open floor",
4929
+ blockKinds: ["block.testimonials"],
4930
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4931
+ design: {
4932
+ sectionSurface: "base",
4933
+ contentFrame: plainFrame,
4934
+ itemSurface: "none"
4935
+ }
4936
+ }), defineBlockAppearancePreset({
4937
+ id: "faq-base-accordion",
4938
+ target: "faq",
4939
+ label: "Base accordion FAQ",
4940
+ blockKinds: ["block.faq"],
4941
+ design: {
4942
+ sectionSurface: "base",
4943
+ contentFrame: plainFrame,
4944
+ itemSurface: "default"
4945
+ }
4946
+ }), defineBlockAppearancePreset({
4947
+ id: "faq-contained-help",
4948
+ target: "faq",
4949
+ label: "Contained help panel",
4950
+ blockKinds: ["block.faq"],
4951
+ design: {
4952
+ sectionSurface: "muted-band",
4953
+ contentFrame: panelFrame("inset"),
4954
+ itemSurface: "default"
4955
+ }
4956
+ }), defineBlockAppearancePreset({
4957
+ id: "contact-form-panel",
4958
+ target: "contact-form",
4959
+ label: "Raised form panel",
4960
+ blockKinds: ["block.form"],
4961
+ design: {
4962
+ sectionSurface: "muted-band",
4963
+ contentFrame: panelFrame("raised"),
4964
+ itemSurface: "none"
4965
+ }
4966
+ }), defineBlockAppearancePreset({
4967
+ id: "cta-accent-band",
4968
+ target: "cta",
4969
+ label: "Accent CTA band",
4970
+ blockKinds: ["block.cta-full"],
4971
+ design: {
4972
+ sectionSurface: "accent-band",
4973
+ contentFrame: plainFrame,
4974
+ itemSurface: "none",
4975
+ eyebrowTreatment: "accent"
4976
+ }
4977
+ });
4979
4978
  //#endregion
4980
4979
  //#region ../theme-core/src/site-styles/headerCtaVariants.ts
4981
4980
  function hasButtonVariant(theme, variantId) {
@@ -6493,7 +6492,7 @@ function canonicalPaletteHashInput(colors, mode) {
6493
6492
  return `${mode}|${paletteColorFingerprint(colors)}`;
6494
6493
  }
6495
6494
  /**
6496
- * The shared TypeScript/SQL protocol. Do not reorder roles: the order comes
6495
+ * Stable curated-catalogue identity. Do not reorder roles: the order comes
6497
6496
  * from PALETTE_TOKEN_NAMES through canonicalPaletteHashInput.
6498
6497
  */
6499
6498
  function paletteValueKey(colors, mode) {
@@ -8067,6 +8066,32 @@ function parseBackgroundAppearanceColorToken(value) {
8067
8066
  function uniqueStrings(values) {
8068
8067
  return Array.from(new Set(values));
8069
8068
  }
8069
+ const headerInteractionPaletteSchema = z$1.enum([
8070
+ "primary",
8071
+ "secondary",
8072
+ "accent"
8073
+ ]);
8074
+ //#endregion
8075
+ //#region ../theme-core/src/site-styles/headerInteractionPalette.ts
8076
+ const clearSplitInteractionPalette = defineLookOptionGroup({
8077
+ id: "interaction-palette",
8078
+ label: "Hover colour",
8079
+ defaultOptionId: "accent",
8080
+ options: [
8081
+ {
8082
+ id: "accent",
8083
+ label: "Accent"
8084
+ },
8085
+ {
8086
+ id: "primary",
8087
+ label: "Primary"
8088
+ },
8089
+ {
8090
+ id: "secondary",
8091
+ label: "Secondary"
8092
+ }
8093
+ ]
8094
+ });
8070
8095
  //#endregion
8071
8096
  //#region ../theme-core/src/site-styles/logoBranding.ts
8072
8097
  const logoTextConfidenceValues = [
@@ -8291,7 +8316,7 @@ const overlayLogoAccommodations = [
8291
8316
  * optional nested styling fields that would otherwise leak from another Look.
8292
8317
  */
8293
8318
  function baseHeader(theme) {
8294
- 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;
8319
+ 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;
8295
8320
  return {
8296
8321
  ...header,
8297
8322
  navContainer: {
@@ -8306,7 +8331,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8306
8331
  id: asHeaderLayoutId("classic"),
8307
8332
  label: "Classic",
8308
8333
  description: "Logo and navigation in one practical horizontal row.",
8309
- structure: "inline-classic",
8310
8334
  variant: "classic",
8311
8335
  defaultPositioning: "sticky",
8312
8336
  shrinkOnScroll: false
@@ -8315,7 +8339,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8315
8339
  id: asHeaderLayoutId("centered"),
8316
8340
  label: "Centered",
8317
8341
  description: "Logo centered above a balanced navigation row.",
8318
- structure: "centered-stack",
8319
8342
  variant: "centered",
8320
8343
  defaultPositioning: "static",
8321
8344
  shrinkOnScroll: false,
@@ -8331,7 +8354,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8331
8354
  id: asHeaderLayoutId("floating"),
8332
8355
  label: "Floating",
8333
8356
  description: "Detached header chrome that sits over the opening section.",
8334
- structure: "floating-shell",
8335
8357
  variant: "floating",
8336
8358
  defaultPositioning: "sticky",
8337
8359
  shrinkOnScroll: true,
@@ -8493,10 +8515,13 @@ const headerStyleCatalog = defineExactCatalog()([
8493
8515
  label: "Clear Split",
8494
8516
  description: "Floating logo with transparent navigation and no shared shell.",
8495
8517
  supportedLayoutIds: supportedLayouts(["floating"]),
8496
- navInteraction: "color-change",
8518
+ navInteraction: "pill-background",
8497
8519
  surface: "floating",
8498
- defaultDepth: "none",
8520
+ defaultDepth: "line",
8499
8521
  navTypography: "plain",
8522
+ openingForegroundTarget: "all",
8523
+ scrollTreatment: "contrast-glass",
8524
+ interactionPalette: clearSplitInteractionPalette,
8500
8525
  moods: ["editorial", "calm"]
8501
8526
  },
8502
8527
  {
@@ -8519,6 +8544,7 @@ const headerStyleCatalog = defineExactCatalog()([
8519
8544
  surface: "floating",
8520
8545
  defaultDepth: "shadow",
8521
8546
  navTypography: "quiet-caps",
8547
+ openingForegroundTarget: "brand-only",
8522
8548
  moods: ["expressive"]
8523
8549
  },
8524
8550
  {
@@ -8530,6 +8556,7 @@ const headerStyleCatalog = defineExactCatalog()([
8530
8556
  surface: "floating",
8531
8557
  defaultDepth: "shadow",
8532
8558
  navTypography: "heading",
8559
+ openingForegroundTarget: "brand-only",
8533
8560
  moods: ["calm", "editorial"]
8534
8561
  }
8535
8562
  ]);
@@ -9031,13 +9058,6 @@ const headerLookCatalog = defineExactCatalog()([
9031
9058
  {
9032
9059
  id: asHeaderLookId("clean-base"),
9033
9060
  label: "Clean base",
9034
- visualTreatment: "solid-neutral",
9035
- layoutBehavior: "sticky",
9036
- configuration: {
9037
- structure: "inline-classic",
9038
- treatment: "solid-neutral",
9039
- behavior: "sticky"
9040
- },
9041
9061
  openingRequirement: "none",
9042
9062
  logoAccommodations: inlineClassicLogoAccommodations,
9043
9063
  compile: cleanBaseHeader
@@ -9045,13 +9065,6 @@ const headerLookCatalog = defineExactCatalog()([
9045
9065
  {
9046
9066
  id: asHeaderLookId("classic-centered-nav"),
9047
9067
  label: "Centered nav",
9048
- visualTreatment: "solid-neutral",
9049
- layoutBehavior: "sticky",
9050
- configuration: {
9051
- structure: "inline-classic",
9052
- treatment: "solid-neutral",
9053
- behavior: "sticky"
9054
- },
9055
9068
  openingRequirement: "none",
9056
9069
  maxRecommendedNavItems: 6,
9057
9070
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9060,13 +9073,6 @@ const headerLookCatalog = defineExactCatalog()([
9060
9073
  {
9061
9074
  id: asHeaderLookId("brand-solid"),
9062
9075
  label: "Brand solid",
9063
- visualTreatment: "solid-brand",
9064
- layoutBehavior: "sticky-shrink",
9065
- configuration: {
9066
- structure: "inline-classic",
9067
- treatment: "solid-brand",
9068
- behavior: "sticky-shrink"
9069
- },
9070
9076
  openingRequirement: "none",
9071
9077
  logoAccommodations: inlineClassicLogoAccommodations,
9072
9078
  compile: solidBrandHeader
@@ -9074,13 +9080,6 @@ const headerLookCatalog = defineExactCatalog()([
9074
9080
  {
9075
9081
  id: asHeaderLookId("serif-line"),
9076
9082
  label: "Serif line",
9077
- visualTreatment: "light-serif",
9078
- layoutBehavior: "sticky",
9079
- configuration: {
9080
- structure: "centered-stack",
9081
- treatment: "light-serif",
9082
- behavior: "sticky"
9083
- },
9084
9083
  openingRequirement: "none",
9085
9084
  maxRecommendedNavItems: 6,
9086
9085
  logoAccommodations: centeredLogoAccommodations,
@@ -9089,13 +9088,6 @@ const headerLookCatalog = defineExactCatalog()([
9089
9088
  {
9090
9089
  id: asHeaderLookId("centered-calm"),
9091
9090
  label: "Centered calm",
9092
- visualTreatment: "light-serif",
9093
- layoutBehavior: "normal-flow",
9094
- configuration: {
9095
- structure: "centered-stack",
9096
- treatment: "light-serif",
9097
- behavior: "normal-flow"
9098
- },
9099
9091
  openingRequirement: "none",
9100
9092
  maxRecommendedNavItems: 5,
9101
9093
  logoAccommodations: centeredLogoAccommodations,
@@ -9104,13 +9096,6 @@ const headerLookCatalog = defineExactCatalog()([
9104
9096
  {
9105
9097
  id: asHeaderLookId("practical-utility"),
9106
9098
  label: "Practical utility",
9107
- visualTreatment: "solid-neutral",
9108
- layoutBehavior: "sticky-shrink",
9109
- configuration: {
9110
- structure: "inline-classic",
9111
- treatment: "solid-neutral",
9112
- behavior: "sticky-shrink"
9113
- },
9114
9099
  openingRequirement: "none",
9115
9100
  requiresProminentCta: true,
9116
9101
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9119,13 +9104,6 @@ const headerLookCatalog = defineExactCatalog()([
9119
9104
  {
9120
9105
  id: asHeaderLookId("minimal-transparent"),
9121
9106
  label: "Minimal transparent",
9122
- visualTreatment: "minimal-transparent",
9123
- layoutBehavior: "normal-flow",
9124
- configuration: {
9125
- structure: "inline-classic",
9126
- treatment: "minimal-transparent",
9127
- behavior: "normal-flow"
9128
- },
9129
9107
  openingRequirement: "reserved-space-ok",
9130
9108
  logoAccommodations: inlineClassicLogoAccommodations,
9131
9109
  compile: minimalTransparentHeader
@@ -9133,13 +9111,6 @@ const headerLookCatalog = defineExactCatalog()([
9133
9111
  {
9134
9112
  id: asHeaderLookId("transparent-overlay"),
9135
9113
  label: "Transparent overlay",
9136
- visualTreatment: "transparent-overlay",
9137
- layoutBehavior: "fixed-overlay",
9138
- configuration: {
9139
- structure: "inline-classic",
9140
- treatment: "transparent-overlay",
9141
- behavior: "fixed-overlay"
9142
- },
9143
9114
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9144
9115
  maxRecommendedNavItems: 5,
9145
9116
  logoAccommodations: overlayLogoAccommodations,
@@ -9148,24 +9119,13 @@ const headerLookCatalog = defineExactCatalog()([
9148
9119
  {
9149
9120
  id: asHeaderLookId("floating-glass"),
9150
9121
  label: "Floating glass",
9151
- visualTreatment: "floating-glass",
9152
- layoutBehavior: "fixed-floating",
9153
- configuration: {
9154
- structure: "floating-shell",
9155
- treatment: "floating-glass",
9156
- behavior: "fixed-floating"
9157
- },
9158
9122
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9159
9123
  maxRecommendedNavItems: 5,
9160
9124
  logoAccommodations: overlayLogoAccommodations,
9161
9125
  compile: floatingGlassHeader
9162
9126
  }
9163
9127
  ]);
9164
- new Set(headerLookCatalog.map((look) => headerConfigurationKey(look.configuration)));
9165
9128
  new Map(headerLookCatalog.map((look) => [look.id, look]));
9166
- function headerConfigurationKey(configuration) {
9167
- return `${configuration.structure}:${configuration.treatment}:${configuration.behavior}`;
9168
- }
9169
9129
  //#endregion
9170
9130
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
9171
9131
  function boundaryRuntimeMetrics(family, size, heightExpression) {
@@ -9375,8 +9335,6 @@ const VARIANT_ROLES = [
9375
9335
  "secondary",
9376
9336
  "outline",
9377
9337
  "ghost",
9378
- "link",
9379
- "tertiary",
9380
9338
  "accent"
9381
9339
  ];
9382
9340
  function isVariantRole(value) {
@@ -9388,7 +9346,7 @@ function isVariantRole(value) {
9388
9346
  * IDs become class selectors, so keep the contract deliberately narrower than
9389
9347
  * an arbitrary string and shared with every authoring/runtime boundary.
9390
9348
  */
9391
- const buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only");
9349
+ 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" });
9392
9350
  function asSpecialVariantId(value) {
9393
9351
  const parsed = buttonVariantIdSchema.safeParse(value);
9394
9352
  if (!parsed.success) throw new Error("SpecialVariantId must be a CSS-safe button variant ID");
@@ -12581,39 +12539,39 @@ function defaultTypographyForRecipe(recipe) {
12581
12539
  }
12582
12540
  //#endregion
12583
12541
  //#region ../theme-core/src/lib/media.ts
12584
- const hotspotSchema$1 = z.object({
12542
+ const hotspotSchema = z.object({
12585
12543
  x: z.number().min(0).max(1),
12586
12544
  y: z.number().min(0).max(1),
12587
12545
  radius: z.number().optional()
12588
12546
  });
12589
- const rotationSchema$1 = z.union([
12547
+ const rotationSchema = z.union([
12590
12548
  z.literal(0),
12591
12549
  z.literal(90),
12592
12550
  z.literal(180),
12593
12551
  z.literal(270)
12594
12552
  ]);
12595
- const rectSchema$1 = z.tuple([
12553
+ const rectSchema = z.tuple([
12596
12554
  z.number(),
12597
12555
  z.number(),
12598
12556
  z.number(),
12599
12557
  z.number()
12600
12558
  ]);
12601
- const aspectCropSchema$1 = z.object({
12559
+ const aspectCropSchema = z.object({
12602
12560
  aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
12603
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
12604
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
12605
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
12561
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
12562
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
12563
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
12606
12564
  });
12607
- const transformSchema$1 = z.object({
12565
+ const transformSchema = z.object({
12608
12566
  aspectCrops: z.preprocess((value) => {
12609
12567
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
12610
12568
  return value;
12611
- }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
12612
- rect: rectSchema$1.optional(),
12613
- hotspot: hotspotSchema$1.optional(),
12614
- rotation: rotationSchema$1.optional()
12569
+ }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
12570
+ rect: rectSchema.optional(),
12571
+ hotspot: hotspotSchema.optional(),
12572
+ rotation: rotationSchema.optional()
12615
12573
  });
12616
- const mediaSchema$1 = z.object({
12574
+ const mediaSchema = z.object({
12617
12575
  type: z.enum([
12618
12576
  "image",
12619
12577
  "video",
@@ -12634,7 +12592,7 @@ const mediaSchema$1 = z.object({
12634
12592
  height: z.number().optional(),
12635
12593
  storageBucket: z.string().optional(),
12636
12594
  storagePath: z.string().optional(),
12637
- transform: transformSchema$1.optional()
12595
+ transform: transformSchema.optional()
12638
12596
  });
12639
12597
  //#endregion
12640
12598
  //#region ../theme-core/src/palette/schema.ts
@@ -13467,264 +13425,6 @@ function generateInteractiveChildInheritanceCSS(selector) {
13467
13425
  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`;
13468
13426
  }
13469
13427
  //#endregion
13470
- //#region ../theme-core/src/buttons/effects/presets/background.ts
13471
- /**
13472
- * Darken background on hover
13473
- *
13474
- * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
13475
- */
13476
- const darkenBackgroundEffect = {
13477
- id: "darken-background",
13478
- name: "Darken on Hover",
13479
- description: "Darkens the background color on hover",
13480
- category: "background",
13481
- pseudoElement: "none",
13482
- applicableTo: ["button"],
13483
- customizableOption: {
13484
- name: "amount",
13485
- type: "select",
13486
- label: "Darken Amount (shade step)",
13487
- default: 100,
13488
- options: [
13489
- 0,
13490
- 100,
13491
- 200,
13492
- 300,
13493
- 400,
13494
- 500,
13495
- 600,
13496
- 700,
13497
- 800,
13498
- 900
13499
- ]
13500
- },
13501
- isApplicable: (buttonConfig) => {
13502
- return buttonConfig.background.type === "solid";
13503
- },
13504
- generateCSS: (ctx) => {
13505
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13506
- if (buttonConfig.background.type !== "solid") return "";
13507
- const amount = options.amount || 100;
13508
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13509
- const darkerToken = tokens.adjustShade(baseToken, amount);
13510
- return `
13511
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13512
- background-color: ${tokens.getColor(darkerToken)};
13513
- }
13514
- `;
13515
- }
13516
- };
13517
- /**
13518
- * Lighten background on hover
13519
- *
13520
- * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
13521
- */
13522
- const lightenBackgroundEffect = {
13523
- id: "lighten-background",
13524
- name: "Lighten on Hover",
13525
- description: "Lightens the background color on hover",
13526
- category: "background",
13527
- pseudoElement: "none",
13528
- applicableTo: ["button"],
13529
- customizableOption: {
13530
- name: "amount",
13531
- type: "select",
13532
- label: "Lighten Amount (shade step)",
13533
- default: 100,
13534
- options: [
13535
- 0,
13536
- 100,
13537
- 200,
13538
- 300,
13539
- 400,
13540
- 500,
13541
- 600,
13542
- 700,
13543
- 800,
13544
- 900
13545
- ]
13546
- },
13547
- isApplicable: (buttonConfig) => {
13548
- return buttonConfig.background.type === "solid";
13549
- },
13550
- generateCSS: (ctx) => {
13551
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13552
- if (buttonConfig.background.type !== "solid") return "";
13553
- const amount = options.amount || 100;
13554
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13555
- const lighterToken = tokens.adjustShade(baseToken, -amount);
13556
- return `
13557
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13558
- background-color: ${tokens.getColor(lighterToken)};
13559
- }
13560
- `;
13561
- }
13562
- };
13563
- /**
13564
- * Fade background on hover (reduce opacity)
13565
- *
13566
- * Works with all background types.
13567
- */
13568
- const fadeBackgroundEffect = {
13569
- id: "fade-background",
13570
- name: "Fade on Hover",
13571
- description: "Reduces background opacity on hover",
13572
- category: "background",
13573
- pseudoElement: "none",
13574
- applicableTo: ["nav-link"],
13575
- customizableOption: {
13576
- name: "opacity",
13577
- type: "percentage",
13578
- label: "Hover Opacity",
13579
- default: 80
13580
- },
13581
- generateCSS: (ctx) => {
13582
- const { themeId, variantId, options } = ctx;
13583
- return `
13584
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13585
- opacity: ${(options.opacity || 80) / 100};
13586
- }
13587
- `;
13588
- }
13589
- };
13590
- /**
13591
- * Reduce opacity on hover (simple opacity reduction)
13592
- *
13593
- * Navigation-link effect that reduces opacity by a percentage (default 15%).
13594
- */
13595
- const opacityReduceEffect = {
13596
- id: "opacity-reduce",
13597
- name: "Reduce Opacity",
13598
- description: "Reduces navigation-link opacity on hover by a percentage",
13599
- category: "background",
13600
- pseudoElement: "none",
13601
- applicableTo: ["nav-link"],
13602
- customizableOption: {
13603
- name: "reduction",
13604
- type: "percentage",
13605
- label: "Opacity Reduction",
13606
- default: 15
13607
- },
13608
- generateCSS: (ctx) => {
13609
- const { themeId, variantId, options } = ctx;
13610
- return `
13611
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13612
- opacity: ${1 - (options.reduction || 15) / 100};
13613
- }
13614
- `;
13615
- }
13616
- };
13617
- /**
13618
- * Animated gradient background
13619
- *
13620
- * Animates a gradient background by shifting its position on hover.
13621
- * Works with gradient backgrounds only.
13622
- *
13623
- * Sets background-size to 200% and animates background-position from left to right.
13624
- */
13625
- const animatedGradientEffect = {
13626
- id: "animated-gradient",
13627
- name: "Animated Gradient",
13628
- description: "Animates gradient position on hover",
13629
- category: "background",
13630
- pseudoElement: "none",
13631
- applicableTo: ["button"],
13632
- customizableOption: {
13633
- name: "direction",
13634
- type: "select",
13635
- label: "Animation Direction",
13636
- default: "horizontal",
13637
- options: ["horizontal", "vertical"]
13638
- },
13639
- isApplicable: (buttonConfig) => {
13640
- return buttonConfig.background.type === "gradient";
13641
- },
13642
- generateCSS: (ctx) => {
13643
- const { themeId, variantId, options, buttonConfig } = ctx;
13644
- if (buttonConfig.background.type !== "gradient") return "";
13645
- const direction = options.direction || "horizontal";
13646
- return `
13647
- /* Setup animated gradient */
13648
- :where([data-theme-scope="${themeId}"]) .${variantId} {
13649
- background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
13650
- background-position: left center;
13651
- transition: background-position 0.3s ease;
13652
- }
13653
-
13654
- /* Animate gradient on hover */
13655
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13656
- background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
13657
- }
13658
- `;
13659
- }
13660
- };
13661
- /**
13662
- * Add background color on hover
13663
- *
13664
- * Works best with transparent backgrounds. Adds a solid background color on hover.
13665
- */
13666
- const backgroundOnHoverEffect = {
13667
- id: "background-on-hover",
13668
- name: "Background on Hover",
13669
- description: "Adds background color on hover",
13670
- category: "background",
13671
- pseudoElement: "none",
13672
- applicableTo: ["button", "nav-link"],
13673
- customizableOption: {
13674
- name: "colorToken",
13675
- type: "select",
13676
- label: "Background Color",
13677
- default: "neutral-800",
13678
- options: [
13679
- "neutral-700",
13680
- "neutral-800",
13681
- "neutral-900",
13682
- "primary"
13683
- ]
13684
- },
13685
- generateCSS: (ctx) => {
13686
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13687
- const colorToken = options.colorToken || "neutral-800";
13688
- return `
13689
- /* Add background on hover */
13690
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13691
- background-color: ${tokens.getColor(colorToken)};${"textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : ""}
13692
- }
13693
- `;
13694
- }
13695
- };
13696
- /**
13697
- * Add semi-transparent background color on hover
13698
- *
13699
- * Adds a background with opacity/alpha channel. Perfect for retro/arcade styles.
13700
- */
13701
- const backgroundOnHoverAlphaEffect = {
13702
- id: "background-on-hover-alpha",
13703
- name: "Background on Hover (Transparent)",
13704
- description: "Adds semi-transparent background on hover",
13705
- category: "background",
13706
- pseudoElement: "none",
13707
- applicableTo: ["nav-link"],
13708
- customizableOption: {
13709
- name: "opacity",
13710
- type: "percentage",
13711
- label: "Opacity",
13712
- default: 50
13713
- },
13714
- generateCSS: (ctx) => {
13715
- const { themeId, variantId, stateGroup, options } = ctx;
13716
- const rawOpacity = options.opacity;
13717
- const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
13718
- const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
13719
- return `
13720
- /* Add semi-transparent background (${stateGroup}) */
13721
- :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
13722
- background-color: rgb(${cssVar} / ${clampedOpacity}%);
13723
- }
13724
- `;
13725
- }
13726
- };
13727
- //#endregion
13728
13428
  //#region ../theme-core/src/buttons/effects/cssUtils.ts
13729
13429
  /**
13730
13430
  * CSS Utilities for Effect Presets
@@ -13776,6 +13476,71 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
13776
13476
  `;
13777
13477
  }
13778
13478
  //#endregion
13479
+ //#region ../theme-core/src/buttons/effects/presets/background.ts
13480
+ /**
13481
+ * Darken background on hover
13482
+ *
13483
+ * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
13484
+ */
13485
+ const darkenBackgroundEffect = shadeBackgroundEffect({
13486
+ id: "darken-background",
13487
+ name: "Darken on Hover",
13488
+ description: "Darkens the background color on hover",
13489
+ label: "Darken Amount (shade step)",
13490
+ shadeDirection: 1
13491
+ });
13492
+ /**
13493
+ * Lighten background on hover
13494
+ *
13495
+ * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
13496
+ */
13497
+ const lightenBackgroundEffect = shadeBackgroundEffect({
13498
+ id: "lighten-background",
13499
+ name: "Lighten on Hover",
13500
+ description: "Lightens the background color on hover",
13501
+ label: "Lighten Amount (shade step)",
13502
+ shadeDirection: -1
13503
+ });
13504
+ function shadeBackgroundEffect(config) {
13505
+ return {
13506
+ id: config.id,
13507
+ name: config.name,
13508
+ description: config.description,
13509
+ category: "background",
13510
+ pseudoElement: "none",
13511
+ applicableTo: ["button"],
13512
+ customizableOption: {
13513
+ name: "amount",
13514
+ type: "select",
13515
+ label: config.label,
13516
+ default: 100,
13517
+ options: [
13518
+ 0,
13519
+ 100,
13520
+ 200,
13521
+ 300,
13522
+ 400,
13523
+ 500,
13524
+ 600,
13525
+ 700,
13526
+ 800,
13527
+ 900
13528
+ ]
13529
+ },
13530
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
13531
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
13532
+ if (buttonConfig.background.type !== "solid") return "";
13533
+ const amount = (options.amount || 100) * config.shadeDirection;
13534
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13535
+ return `
13536
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13537
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
13538
+ }
13539
+ `;
13540
+ }
13541
+ };
13542
+ }
13543
+ //#endregion
13779
13544
  //#region ../theme-core/src/buttons/effects/registry.ts
13780
13545
  /**
13781
13546
  * Registry of all available effect presets
@@ -13783,11 +13548,144 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
13783
13548
  const EFFECT_PRESETS = [
13784
13549
  darkenBackgroundEffect,
13785
13550
  lightenBackgroundEffect,
13786
- fadeBackgroundEffect,
13787
- opacityReduceEffect,
13788
- animatedGradientEffect,
13789
- backgroundOnHoverEffect,
13790
- backgroundOnHoverAlphaEffect,
13551
+ {
13552
+ id: "fade-background",
13553
+ name: "Fade on Hover",
13554
+ description: "Reduces background opacity on hover",
13555
+ category: "background",
13556
+ pseudoElement: "none",
13557
+ applicableTo: ["nav-link"],
13558
+ customizableOption: {
13559
+ name: "opacity",
13560
+ type: "percentage",
13561
+ label: "Hover Opacity",
13562
+ default: 80
13563
+ },
13564
+ generateCSS: (ctx) => {
13565
+ const { themeId, variantId, options } = ctx;
13566
+ return `
13567
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13568
+ opacity: ${(options.opacity || 80) / 100};
13569
+ }
13570
+ `;
13571
+ }
13572
+ },
13573
+ {
13574
+ id: "opacity-reduce",
13575
+ name: "Reduce Opacity",
13576
+ description: "Reduces navigation-link opacity on hover by a percentage",
13577
+ category: "background",
13578
+ pseudoElement: "none",
13579
+ applicableTo: ["nav-link"],
13580
+ customizableOption: {
13581
+ name: "reduction",
13582
+ type: "percentage",
13583
+ label: "Opacity Reduction",
13584
+ default: 15
13585
+ },
13586
+ generateCSS: (ctx) => {
13587
+ const { themeId, variantId, options } = ctx;
13588
+ return `
13589
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13590
+ opacity: ${1 - (options.reduction || 15) / 100};
13591
+ }
13592
+ `;
13593
+ }
13594
+ },
13595
+ {
13596
+ id: "animated-gradient",
13597
+ name: "Animated Gradient",
13598
+ description: "Animates gradient position on hover",
13599
+ category: "background",
13600
+ pseudoElement: "none",
13601
+ applicableTo: ["button"],
13602
+ customizableOption: {
13603
+ name: "direction",
13604
+ type: "select",
13605
+ label: "Animation Direction",
13606
+ default: "horizontal",
13607
+ options: ["horizontal", "vertical"]
13608
+ },
13609
+ isApplicable: (buttonConfig) => {
13610
+ return buttonConfig.background.type === "gradient";
13611
+ },
13612
+ generateCSS: (ctx) => {
13613
+ const { themeId, variantId, options, buttonConfig } = ctx;
13614
+ if (buttonConfig.background.type !== "gradient") return "";
13615
+ const direction = options.direction || "horizontal";
13616
+ return `
13617
+ /* Setup animated gradient */
13618
+ :where([data-theme-scope="${themeId}"]) .${variantId} {
13619
+ background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
13620
+ background-position: left center;
13621
+ transition: background-position 0.3s ease;
13622
+ }
13623
+
13624
+ /* Animate gradient on hover */
13625
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13626
+ background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
13627
+ }
13628
+ `;
13629
+ }
13630
+ },
13631
+ {
13632
+ id: "background-on-hover",
13633
+ name: "Background on Hover",
13634
+ description: "Adds background color on hover",
13635
+ category: "background",
13636
+ pseudoElement: "none",
13637
+ applicableTo: ["button", "nav-link"],
13638
+ customizableOption: {
13639
+ name: "colorToken",
13640
+ type: "select",
13641
+ label: "Background Color",
13642
+ default: "neutral-800",
13643
+ options: [
13644
+ "neutral-700",
13645
+ "neutral-800",
13646
+ "neutral-900",
13647
+ "primary"
13648
+ ]
13649
+ },
13650
+ generateCSS: (ctx) => {
13651
+ const { themeId, variantId, stateGroup, options, tokens, buttonConfig } = ctx;
13652
+ const colorToken = options.colorToken || "neutral-800";
13653
+ const color = tokens.getColor(colorToken);
13654
+ const navForeground = "textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : "";
13655
+ return `
13656
+ /* Add background on hover */
13657
+ ${getStateSelector(themeId, variantId, stateGroup)} {
13658
+ background-color: ${color};${navForeground}
13659
+ }
13660
+ `;
13661
+ }
13662
+ },
13663
+ {
13664
+ id: "background-on-hover-alpha",
13665
+ name: "Background on Hover (Transparent)",
13666
+ description: "Adds semi-transparent background on hover",
13667
+ category: "background",
13668
+ pseudoElement: "none",
13669
+ applicableTo: ["nav-link"],
13670
+ customizableOption: {
13671
+ name: "opacity",
13672
+ type: "percentage",
13673
+ label: "Opacity",
13674
+ default: 50
13675
+ },
13676
+ generateCSS: (ctx) => {
13677
+ const { themeId, variantId, stateGroup, options } = ctx;
13678
+ const rawOpacity = options.opacity;
13679
+ const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
13680
+ const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
13681
+ return `
13682
+ /* Add semi-transparent background (${stateGroup}) */
13683
+ :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
13684
+ background-color: rgb(${cssVar} / ${clampedOpacity}%);
13685
+ }
13686
+ `;
13687
+ }
13688
+ },
13791
13689
  {
13792
13690
  id: "border-glow",
13793
13691
  name: "Border Glow",
@@ -16726,6 +16624,166 @@ function resolveOnColorForThemeToken(token) {
16726
16624
  return shade <= 400 ? "#000000" : "#FFFFFF";
16727
16625
  }
16728
16626
  //#endregion
16627
+ //#region ../theme-core/src/header/paintTargets.ts
16628
+ /** Resolve the element that owns the visible header surface for each layout. */
16629
+ function getHeaderPaintTargets(variant, themeId, state = "base") {
16630
+ const scope = `:where([data-theme-scope="${themeId}"])`;
16631
+ const scrolledRoot = state === "scrolled" ? ".header-root.header-scrolled " : "";
16632
+ if (variant === "floating") {
16633
+ if (state === "scrolled") {
16634
+ const desktopOwner = `${scope} ${scrolledRoot}.header-floating-container`;
16635
+ const mobileOwner = `${scope} ${scrolledRoot}.header-mobile-bar`;
16636
+ return [{
16637
+ kind: "viewport-band",
16638
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
16639
+ ownerSelector: desktopOwner,
16640
+ selector: `${desktopOwner}::before`,
16641
+ mediaQuery: MQ_MD_UP,
16642
+ extent: {
16643
+ top: {
16644
+ customProperty: "--rb-header-floating-top-gap",
16645
+ value: "1rem",
16646
+ ownerProperty: "top"
16647
+ },
16648
+ bottom: {
16649
+ customProperty: "--rb-header-floating-bottom-extension",
16650
+ value: "0.75rem"
16651
+ }
16652
+ },
16653
+ ownerNeedsPositioning: false
16654
+ }, {
16655
+ kind: "viewport-band",
16656
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
16657
+ ownerSelector: mobileOwner,
16658
+ selector: `${mobileOwner}::before`,
16659
+ mediaQuery: MQ_MD_DOWN,
16660
+ extent: {
16661
+ top: {
16662
+ customProperty: "--rb-header-floating-top-gap",
16663
+ value: "0.75rem",
16664
+ ownerProperty: "margin-top"
16665
+ },
16666
+ bottom: {
16667
+ customProperty: "--rb-header-floating-bottom-extension",
16668
+ value: "0.75rem"
16669
+ }
16670
+ },
16671
+ ownerNeedsPositioning: true
16672
+ }];
16673
+ }
16674
+ return [{
16675
+ kind: "element-box",
16676
+ selector: `${scope} ${scrolledRoot}.header-floating-container`,
16677
+ mediaQuery: MQ_MD_UP
16678
+ }, {
16679
+ kind: "element-box",
16680
+ selector: `${scope} ${scrolledRoot}.header-mobile-bar`,
16681
+ mediaQuery: MQ_MD_DOWN
16682
+ }];
16683
+ }
16684
+ return [{
16685
+ kind: "element-box",
16686
+ selector: `${scope} .header-root${state === "scrolled" ? ".header-scrolled" : ""}::before`,
16687
+ pseudoElement: "inset"
16688
+ }];
16689
+ }
16690
+ function renderHeaderPaintTargetRules(targets, rules) {
16691
+ return targets.map((target) => {
16692
+ const block = renderHeaderPaintTargetRule(target, rules);
16693
+ return target.mediaQuery ? `@media ${target.mediaQuery} {\n${block}\n}` : block;
16694
+ }).join("\n");
16695
+ }
16696
+ function renderHeaderPaintTargetRule(target, rules) {
16697
+ switch (target.kind) {
16698
+ case "element-box": {
16699
+ const pseudoElementSetup = target.pseudoElement === "inset" ? [
16700
+ "content: \"\";",
16701
+ "position: absolute;",
16702
+ "inset: 0;",
16703
+ "pointer-events: none;",
16704
+ "border-radius: inherit;",
16705
+ "z-index: -1;"
16706
+ ] : [];
16707
+ return `${target.selector} {\n ${[...pseudoElementSetup, ...rules].join("\n ")}\n}`;
16708
+ }
16709
+ case "viewport-band": {
16710
+ const { top, bottom } = target.extent;
16711
+ const ownerRules = [
16712
+ `${top.customProperty}: ${top.value};`,
16713
+ `${bottom.customProperty}: ${bottom.value};`,
16714
+ `${top.ownerProperty}: var(${top.customProperty});`,
16715
+ ...target.ownerNeedsPositioning ? ["position: relative;"] : [],
16716
+ "isolation: isolate;",
16717
+ "background: none;",
16718
+ "backdrop-filter: none;",
16719
+ "-webkit-backdrop-filter: none;",
16720
+ "border: 0;",
16721
+ "box-shadow: none;"
16722
+ ];
16723
+ const bandRules = [
16724
+ "content: \"\";",
16725
+ "position: absolute;",
16726
+ `top: calc(-1 * var(${top.customProperty}));`,
16727
+ `bottom: calc(-1 * var(${bottom.customProperty}));`,
16728
+ "left: 50%;",
16729
+ "width: 100vw;",
16730
+ "transform: translateX(-50%);",
16731
+ "pointer-events: none;",
16732
+ "border-radius: 0;",
16733
+ "z-index: -1;",
16734
+ ...rules
16735
+ ];
16736
+ return `${target.clipSelector} {\n overflow-x: clip;\n}\n${target.ownerSelector} {\n ${ownerRules.join("\n ")}\n}\n${target.selector} {\n ${bandRules.join("\n ")}\n}`;
16737
+ }
16738
+ }
16739
+ }
16740
+ //#endregion
16741
+ //#region ../theme-core/src/header/scrollTreatment.ts
16742
+ const headerScrollTreatmentSchema = z$1.discriminatedUnion("kind", [z$1.object({
16743
+ kind: z$1.literal("contrast-glass"),
16744
+ backgroundTone: z$1.enum(["light", "dark"])
16745
+ })]).optional();
16746
+ const CONTRAST_GLASS_BLUR = "blur(12px)";
16747
+ function generateMobileOverlayBackdropFilterFix(themeId, variant) {
16748
+ const root = `:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])`;
16749
+ 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`;
16750
+ }
16751
+ function generateHeaderScrollTreatmentStyles(treatment, themeId, variant, surfaceRules = []) {
16752
+ if (!treatment) return "";
16753
+ switch (treatment.kind) {
16754
+ case "contrast-glass": {
16755
+ const backgroundChannels = treatment.backgroundTone === "dark" ? "0 0 0" : "255 255 255";
16756
+ return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [
16757
+ `background-color: rgb(${backgroundChannels} / 0.60);`,
16758
+ `backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
16759
+ `-webkit-backdrop-filter: ${CONTRAST_GLASS_BLUR};`,
16760
+ ...surfaceRules
16761
+ ]);
16762
+ }
16763
+ }
16764
+ }
16765
+ //#endregion
16766
+ //#region ../theme-core/src/header/containerSchema.ts
16767
+ const headerContainerSchema = z$1.object({
16768
+ rounded: z$1.enum([
16769
+ "none",
16770
+ "sm",
16771
+ "md",
16772
+ "lg",
16773
+ "xl",
16774
+ "2xl"
16775
+ ]).default("xl"),
16776
+ border: z$1.boolean().default(true),
16777
+ shadow: z$1.boolean().default(true),
16778
+ padding: z$1.enum([
16779
+ "sm",
16780
+ "md",
16781
+ "lg"
16782
+ ]).default("md"),
16783
+ tint: z$1.string().nullable().optional(),
16784
+ opacity: z$1.number().min(0).max(1).default(.12)
16785
+ }).optional();
16786
+ //#endregion
16729
16787
  //#region ../theme-core/src/schema.ts
16730
16788
  const axesSchema = z$1.object({
16731
16789
  tone: z$1.enum([
@@ -16886,7 +16944,7 @@ const boxBackgroundSchema = z$1.object({
16886
16944
  color: tokenOrCssColorValueSchema.nullable().optional(),
16887
16945
  gradient: z$1.string().nullable().optional(),
16888
16946
  gradientPresetId: z$1.string().min(1).nullable().optional(),
16889
- image: mediaSchema$1.nullable().optional(),
16947
+ image: mediaSchema.nullable().optional(),
16890
16948
  objectFit: z$1.enum([
16891
16949
  "fill",
16892
16950
  "fit",
@@ -17134,25 +17192,6 @@ const navFontWeight = z$1.enum([
17134
17192
  ]);
17135
17193
  const headerMaxWidth = z$1.enum(["container", "full"]);
17136
17194
  const headerBarFrame = z$1.enum(["full-bleed", "inset-shell"]);
17137
- const headerContainerSchema = z$1.object({
17138
- rounded: z$1.enum([
17139
- "none",
17140
- "sm",
17141
- "md",
17142
- "lg",
17143
- "xl",
17144
- "2xl"
17145
- ]).default("xl"),
17146
- border: z$1.boolean().default(true),
17147
- shadow: z$1.boolean().default(true),
17148
- padding: z$1.enum([
17149
- "sm",
17150
- "md",
17151
- "lg"
17152
- ]).default("md"),
17153
- tint: z$1.string().nullable().optional(),
17154
- opacity: z$1.number().min(0).max(1).default(.12)
17155
- }).optional();
17156
17195
  const headerBorderSchema = componentBorderSchema.extend({ position: z$1.enum([
17157
17196
  "bottom",
17158
17197
  "top",
@@ -17270,7 +17309,7 @@ const headerBackgroundSchema = z$1.object({
17270
17309
  contentOwner: z$1.literal(siteChromeBackgroundOverrideOwner).optional(),
17271
17310
  color: tokenOrCssColorValueSchema.nullable().optional(),
17272
17311
  gradient: gradientConfigSchema.nullable().optional(),
17273
- image: mediaSchema$1.nullable().optional(),
17312
+ image: mediaSchema.nullable().optional(),
17274
17313
  textColor: tokenOrCssColorValueSchema.nullable().optional()
17275
17314
  });
17276
17315
  const headerSchema = z$1.object({
@@ -17279,7 +17318,8 @@ const headerSchema = z$1.object({
17279
17318
  shrinkOnScroll: z$1.boolean(),
17280
17319
  maxWidth: headerMaxWidth,
17281
17320
  barFrame: headerBarFrame.optional(),
17282
- logoOverride: mediaSchema$1.nullable().optional(),
17321
+ scrollTreatment: headerScrollTreatmentSchema,
17322
+ logoOverride: mediaSchema.nullable().optional(),
17283
17323
  background: headerBackgroundSchema.default({
17284
17324
  type: "color",
17285
17325
  color: "surface"
@@ -17291,6 +17331,7 @@ const headerSchema = z$1.object({
17291
17331
  navFontRole: z$1.enum(["body", "heading"]).optional(),
17292
17332
  navTypography: z$1.enum(["body", "heading"]).optional(),
17293
17333
  navTextSize: navLinkStyleSchema.shape.textSize,
17334
+ interactionPalette: headerInteractionPaletteSchema.optional(),
17294
17335
  navPlacement: z$1.enum(["end", "center"]).optional(),
17295
17336
  container: headerContainerSchema,
17296
17337
  border: headerBorderSchema,
@@ -22684,15 +22725,6 @@ const heroCopyFragment = defineFragment({
22684
22725
  */
22685
22726
  const BLOCK_BUTTON_ROLES = PUBLIC_BUTTON_ROLES;
22686
22727
  const blockButtonRoleSchema = z$1.enum(BLOCK_BUTTON_ROLES);
22687
- /**
22688
- * Temporary rollout boundary for persisted content written before issue #1220.
22689
- * Authoring remains strict through `blockButtonRoleSchema`; this parser exists
22690
- * only until the post-deploy role rewrite has been audited in production.
22691
- */
22692
- function canonicalizePersistedBlockButtonRole(value) {
22693
- return value === "link" || value === "tertiary" ? "ghost" : value;
22694
- }
22695
- const persistedBlockButtonRoleSchema = z$1.preprocess((value) => typeof value === "string" ? canonicalizePersistedBlockButtonRole(value) : value, blockButtonRoleSchema);
22696
22728
  const BLOCK_BUTTON_ROLE_LABELS = {
22697
22729
  primary: "Primary",
22698
22730
  secondary: "Secondary",
@@ -24356,6 +24388,7 @@ const newsletterFormFragment = defineFragment({
24356
24388
  }
24357
24389
  ],
24358
24390
  layout: [el("newsletter-form", withApiBindings({
24391
+ source: "block",
24359
24392
  destinationProvider: { $bind: { from: "destinationProvider" } },
24360
24393
  listId: { $bind: { from: "listId" } },
24361
24394
  preset: { $bind: { from: "preset" } },
@@ -26300,6 +26333,7 @@ const contactNewsletterLayout = styledSection({
26300
26333
  as: "h2",
26301
26334
  className: "newsletter-copy-title"
26302
26335
  }, when("newsletterTitle"), bind("newsletterTitle")), richText({ className: "newsletter-copy-subtitle rb-prose rb-max-w-none" }, when("newsletterSubtitle"), bind("newsletterSubtitle"))]), el("newsletter-form", withApiBindings({
26336
+ source: "block",
26303
26337
  listId: { $bind: { from: "listId" } },
26304
26338
  preset: { $bind: { from: "preset" } },
26305
26339
  includePhone: { $bind: { from: "includePhone" } },
@@ -28310,6 +28344,22 @@ const footerNavGroupsLayout = stack({
28310
28344
  }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], whenCollectionHasItems("footerMenu.groups"));
28311
28345
  //#endregion
28312
28346
  //#region ../blocks/src/system/blocks/site-footer.ts
28347
+ const footerStandardContactBindings = {
28348
+ value: { $bind: { from: "module.engagement.runtime.value" } },
28349
+ submitLabel: { $bind: { from: "module.engagement.runtime.submitLabel" } },
28350
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } }
28351
+ };
28352
+ const footerMailingListBindings = {
28353
+ source: { $bind: { from: "module.engagement.runtime.source" } },
28354
+ destinationRef: { $bind: { from: "module.engagement.runtime.destinationRef" } },
28355
+ listId: { $bind: { from: "module.engagement.runtime.listId" } },
28356
+ preset: { $bind: { from: "module.engagement.runtime.preset" } },
28357
+ includePhone: { $bind: { from: "module.engagement.runtime.includePhone" } },
28358
+ buttonLabel: { $bind: { from: "module.engagement.runtime.buttonLabel" } },
28359
+ successMessage: { $bind: { from: "module.engagement.runtime.successMessage" } },
28360
+ privacyNote: { $bind: { from: "module.engagement.runtime.privacyNote" } }
28361
+ };
28362
+ const footerSpamProtectionBinding = { spamProtectionEnabled: { $bind: { from: "$root.spamProtectionEnabled" } } };
28313
28363
  const brandLogo = link({
28314
28364
  href: "/",
28315
28365
  className: { $bind: {
@@ -28387,6 +28437,23 @@ const authoredCopy = richText({
28387
28437
  id: "content.interpolateRichTextTokens",
28388
28438
  options: { tokens: ["year", "site_name"] }
28389
28439
  }] }));
28440
+ const footerEngagement = stack({
28441
+ gap: "md",
28442
+ className: "rb-w-full"
28443
+ }, [
28444
+ text({
28445
+ as: "p",
28446
+ className: "rb-body rb-opacity-80"
28447
+ }, bind("module.engagement.intro"), when("module.engagement.intro")),
28448
+ form(withApiBindings({
28449
+ ...footerStandardContactBindings,
28450
+ ...footerSpamProtectionBinding
28451
+ }), [], when("module.engagement.kind", { equals: "standard-contact" })),
28452
+ el("newsletter-form", withApiBindings({
28453
+ ...footerMailingListBindings,
28454
+ ...footerSpamProtectionBinding
28455
+ }), [], when("module.engagement.kind", { equals: "mailing-list" }))
28456
+ ], when("module.kind", { equals: "engagement" }));
28390
28457
  const footerGroup = stack({
28391
28458
  gap: "md",
28392
28459
  align: "stretch",
@@ -28412,6 +28479,7 @@ const footerGroup = stack({
28412
28479
  contact,
28413
28480
  hours,
28414
28481
  socials,
28482
+ footerEngagement,
28415
28483
  stack({ className: "rb-w-full" }, [authoredCopy], when("module.kind", { equals: "supporting-text" })),
28416
28484
  stack({ className: "rb-w-full rb-lg-col-span-3" }, [authoredCopy], when("module.kind", { equals: "legal" }))
28417
28485
  ], repeat("group.modules", "module"))], repeat("region.groups", "group"));
@@ -28419,6 +28487,10 @@ const footerMainRegion = stack({
28419
28487
  className: { $bind: { from: "region.className" } },
28420
28488
  "data-footer-region": { $bind: { from: "region.kind" } }
28421
28489
  }, [footerGroup], when("region.kind", { equals: "main" }), repeat("content.footerRuntime.regions", "region"));
28490
+ const footerEngagementRegion = stack({
28491
+ className: { $bind: { from: "region.className" } },
28492
+ "data-footer-region": "engagement-row"
28493
+ }, [footerGroup], when("region.kind", { equals: "engagement-row" }), repeat("content.footerRuntime.regions", "region"));
28422
28494
  const footerBottomRegion = stack({ className: { $bind: {
28423
28495
  from: "$root.theme.footer",
28424
28496
  transforms: [{ id: "layout.footerBottomBarContainerClass" }],
@@ -28454,7 +28526,11 @@ const siteFooterManifest = createBlockManifest({
28454
28526
  fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
28455
28527
  } },
28456
28528
  "data-footer-membership": { $bind: { from: "content.footerRuntime.membershipKey" } }
28457
- }, [footerMainRegion, footerBottomRegion]),
28529
+ }, [
28530
+ footerEngagementRegion,
28531
+ footerMainRegion,
28532
+ footerBottomRegion
28533
+ ]),
28458
28534
  description: "Site-wide composed footer with canonical shared details.",
28459
28535
  styleTokens: { spacing: "md" },
28460
28536
  paletteHidden: true
@@ -30277,86 +30353,6 @@ const weeklySlotAvailabilityBlockDefinition = {
30277
30353
  } }
30278
30354
  };
30279
30355
  //#endregion
30280
- //#region ../blocks/src/lib/media.ts
30281
- const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
30282
- "document",
30283
- "spreadsheet",
30284
- "archive",
30285
- "audio"
30286
- ];
30287
- const hotspotSchema = z.object({
30288
- x: z.number().min(0).max(1),
30289
- y: z.number().min(0).max(1),
30290
- radius: z.number().optional()
30291
- });
30292
- const rotationSchema = z.union([
30293
- z.literal(0),
30294
- z.literal(90),
30295
- z.literal(180),
30296
- z.literal(270)
30297
- ]);
30298
- const rectSchema = z.tuple([
30299
- z.number(),
30300
- z.number(),
30301
- z.number(),
30302
- z.number()
30303
- ]);
30304
- const aspectCropSchema = z.object({
30305
- aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
30306
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
30307
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
30308
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
30309
- });
30310
- const transformSchema = z.object({
30311
- aspectCrops: z.preprocess((value) => {
30312
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
30313
- return value;
30314
- }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
30315
- rect: rectSchema.optional(),
30316
- hotspot: hotspotSchema.optional(),
30317
- rotation: rotationSchema.optional()
30318
- });
30319
- const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
30320
- tag: z.literal("storage"),
30321
- assetId: z.string().optional(),
30322
- storageBucket: z.string().min(1),
30323
- storagePath: z.string().min(1)
30324
- }), z.object({
30325
- tag: z.literal("external-src"),
30326
- assetId: z.string().optional(),
30327
- src: z.string().url()
30328
- })]);
30329
- const mediaBaseSchema = z.object({
30330
- purpose: z.string().optional(),
30331
- placeholder: z.boolean().default(true).optional(),
30332
- assetId: z.string().optional(),
30333
- identifier: z.string().optional(),
30334
- src: z.string().optional(),
30335
- alt: z.string().optional(),
30336
- filename: z.string().optional(),
30337
- mimeType: z.string().optional(),
30338
- width: z.number().optional(),
30339
- height: z.number().optional(),
30340
- storageBucket: z.string().optional(),
30341
- storagePath: z.string().optional(),
30342
- poster: mediaPosterSchema.optional(),
30343
- transform: transformSchema.optional()
30344
- });
30345
- const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
30346
- const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
30347
- const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
30348
- const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
30349
- const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
30350
- const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
30351
- const mediaSchema = z.discriminatedUnion("type", [
30352
- imageMediaSchema,
30353
- videoMediaSchema,
30354
- audioMediaSchema,
30355
- documentMediaSchema,
30356
- spreadsheetMediaSchema,
30357
- archiveMediaSchema
30358
- ]);
30359
- //#endregion
30360
30356
  //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
30361
30357
  const bookingDepositRefundPolicySchema = z$1.enum(["refundable", "non_refundable"]);
30362
30358
  const bookingInstalmentPlanSchema = z$1.union([
@@ -30795,7 +30791,7 @@ const publicEventSchema = z$1.object({
30795
30791
  presentation: z$1.object({
30796
30792
  cardTitleOverride: z$1.string().nullable().optional(),
30797
30793
  summary: z$1.string().nullable().optional(),
30798
- image: mediaSchema.nullable().optional()
30794
+ image: mediaSchema$1.nullable().optional()
30799
30795
  }).optional(),
30800
30796
  slug: z$1.string(),
30801
30797
  path: z$1.string().nullable(),
@@ -31108,7 +31104,7 @@ const publicMembershipProductCollectionSchema = z$1.object({ memberships: z$1.ar
31108
31104
  * Kept in a shared module so the block definition and runtime contracts can
31109
31105
  * depend on the same schema without creating an initialization cycle.
31110
31106
  */
31111
- const occurrenceContextSchema$1 = z$1.object({
31107
+ const occurrenceContextSchema = z$1.object({
31112
31108
  id: z$1.string(),
31113
31109
  seriesId: z$1.string(),
31114
31110
  startsAt: z$1.string(),
@@ -31422,7 +31418,7 @@ function isEventCalendarListLayout(value) {
31422
31418
  //#region ../blocks/src/system/runtime/nodes/shared/contract-schemas.ts
31423
31419
  const previewStageSchema = z$1.enum(["preview", "published"]);
31424
31420
  const registrationButtonVariantSchema = blockButtonRoleSchema;
31425
- const eventButtonVariantSchema = persistedBlockButtonRoleSchema;
31421
+ const eventButtonVariantSchema = blockButtonRoleSchema;
31426
31422
  const eventLayoutSchema = z$1.enum(eventCalendarListLayoutValues);
31427
31423
  const eventCalendarDisplayModeSchema = z$1.enum(eventCalendarDisplayModeValues);
31428
31424
  const eventCalendarDefaultViewSchema = z$1.enum(eventCalendarDefaultViewValues);
@@ -31511,28 +31507,37 @@ const EVENT_REGISTRATION_SHELL_STEP_LABELS = [
31511
31507
  "Payment"
31512
31508
  ];
31513
31509
  const eventRegistrationPublicEventSchema = z$1.preprocess(normalizeEventRegistrationEventInput, publicEventSchema);
31514
- const eventRegistrationSourceSchema = z$1.object({
31515
- siteId: z$1.string().optional(),
31516
- apiBaseUrl: z$1.string().optional(),
31517
- portalToken: z$1.string().nullable().optional(),
31518
- previewToken: z$1.string().nullable().optional(),
31519
- occurrenceContext: occurrenceContextSchema$1.optional(),
31510
+ const eventRegistrationHydrationSchemaShape = {
31511
+ occurrenceContext: occurrenceContextSchema.optional(),
31520
31512
  subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
31521
31513
  events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31522
- className: z$1.string().nullable().optional(),
31523
- buttonText: z$1.string().nullable().optional(),
31524
- maxTickets: z$1.string().nullable().optional(),
31514
+ wholeSeriesOfferings: publicCoursesArraySchema.nullable().optional(),
31515
+ wholeSeriesOffering: publicCourseSchema.nullable().optional(),
31516
+ maxTickets: z$1.string().optional(),
31525
31517
  showVenue: z$1.boolean().optional(),
31526
31518
  showCapacity: z$1.boolean().optional(),
31519
+ showSessions: z$1.boolean().optional(),
31520
+ showPrice: z$1.boolean().optional(),
31527
31521
  successMessage: z$1.string().optional(),
31528
31522
  waitlistMessage: z$1.string().optional(),
31523
+ membershipMessage: z$1.string().optional(),
31529
31524
  buttonVariant: registrationButtonVariantSchema.optional(),
31530
31525
  overlayEnabled: z$1.boolean().optional(),
31531
31526
  spamProtectionEnabled: z$1.boolean().optional(),
31532
- stage: previewStageSchema.optional(),
31533
31527
  supportEmail: z$1.string().optional(),
31534
31528
  sitePasses: publicPassProductCollectionSchema.nullable().optional(),
31535
31529
  siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
31530
+ };
31531
+ const eventRegistrationSourceSchema = z$1.object({
31532
+ siteId: z$1.string().optional(),
31533
+ apiBaseUrl: z$1.string().optional(),
31534
+ portalToken: z$1.string().nullable().optional(),
31535
+ previewToken: z$1.string().nullable().optional(),
31536
+ ...eventRegistrationHydrationSchemaShape,
31537
+ className: z$1.string().nullable().optional(),
31538
+ buttonText: z$1.string().nullable().optional(),
31539
+ maxTickets: z$1.string().nullable().optional(),
31540
+ stage: previewStageSchema.optional()
31536
31541
  });
31537
31542
  const eventRegistrationDisplaySchema = z$1.object({
31538
31543
  kind: z$1.literal("event-registration"),
@@ -31543,22 +31548,7 @@ const eventRegistrationDisplaySchema = z$1.object({
31543
31548
  stepLabels: z$1.array(z$1.enum(EVENT_REGISTRATION_SHELL_STEP_LABELS)).min(1),
31544
31549
  summaryButtonText: z$1.string()
31545
31550
  });
31546
- const eventRegistrationHydrationSchema = z$1.object({
31547
- occurrenceContext: occurrenceContextSchema$1.optional(),
31548
- subject: eventRegistrationPageSurfaceSubjectSchema.nullable().optional(),
31549
- events: z$1.array(eventRegistrationPublicEventSchema).nullable().optional(),
31550
- maxTickets: z$1.string().optional(),
31551
- showVenue: z$1.boolean().optional(),
31552
- showCapacity: z$1.boolean().optional(),
31553
- successMessage: z$1.string().optional(),
31554
- waitlistMessage: z$1.string().optional(),
31555
- buttonVariant: registrationButtonVariantSchema.optional(),
31556
- overlayEnabled: z$1.boolean().optional(),
31557
- spamProtectionEnabled: z$1.boolean().optional(),
31558
- supportEmail: z$1.string().optional(),
31559
- sitePasses: publicPassProductCollectionSchema.nullable().optional(),
31560
- siteMemberships: publicMembershipProductCollectionSchema.nullable().optional()
31561
- });
31551
+ const eventRegistrationHydrationSchema = z$1.object(eventRegistrationHydrationSchemaShape);
31562
31552
  const eventRegistrationRenderSchema = z$1.object({
31563
31553
  display: eventRegistrationDisplaySchema,
31564
31554
  hydration: eventRegistrationHydrationSchema
@@ -31638,11 +31628,16 @@ const eventRegistrationBlockRuntime = defineClientOwnedBlockRuntime({
31638
31628
  occurrenceContext: source.occurrenceContext ?? null,
31639
31629
  subject: source.subject ?? null,
31640
31630
  events: source.events ?? null,
31631
+ wholeSeriesOfferings: source.wholeSeriesOfferings ?? null,
31632
+ wholeSeriesOffering: source.wholeSeriesOffering ?? null,
31641
31633
  maxTickets: source.maxTickets ?? void 0,
31642
31634
  showVenue: source.showVenue,
31643
31635
  showCapacity: source.showCapacity,
31636
+ showSessions: source.showSessions,
31637
+ showPrice: source.showPrice,
31644
31638
  successMessage: source.successMessage,
31645
31639
  waitlistMessage: source.waitlistMessage,
31640
+ membershipMessage: source.membershipMessage,
31646
31641
  buttonVariant: source.buttonVariant,
31647
31642
  overlayEnabled: source.overlayEnabled,
31648
31643
  spamProtectionEnabled: source.spamProtectionEnabled,
@@ -31677,6 +31672,159 @@ function buildEventRegistrationInteractiveIslandProps(props) {
31677
31672
  source: props
31678
31673
  });
31679
31674
  }
31675
+ //#endregion
31676
+ //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
31677
+ function isSaleWindowOpen(option, now) {
31678
+ if (!option.isActive) return false;
31679
+ if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
31680
+ if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
31681
+ return true;
31682
+ }
31683
+ function toExactOrFreeDisplay(amount, currency) {
31684
+ if (amount <= 0) return {
31685
+ kind: "free",
31686
+ currency
31687
+ };
31688
+ return {
31689
+ kind: "exact",
31690
+ amount,
31691
+ currency
31692
+ };
31693
+ }
31694
+ function getSelectableCoursePricingOptionsForNow(course, now) {
31695
+ if (course.pricing.pricingStrategy !== "tiered") return [];
31696
+ return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
31697
+ if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
31698
+ if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
31699
+ return left.name.localeCompare(right.name);
31700
+ });
31701
+ }
31702
+ function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
31703
+ const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
31704
+ const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
31705
+ const currency = course.pricing.currency;
31706
+ switch (course.pricing.pricingStrategy) {
31707
+ case "free": return {
31708
+ currency,
31709
+ display: {
31710
+ kind: "free",
31711
+ currency
31712
+ },
31713
+ selectableOptions: [],
31714
+ requiresSelection: false,
31715
+ selectedOption: null,
31716
+ slidingScale: null,
31717
+ selectedSlidingAmount: null,
31718
+ selectedPriceAmount: 0,
31719
+ selectedRequiresPayment: false,
31720
+ hasPaidSelection: false,
31721
+ hasFreeSelection: true
31722
+ };
31723
+ case "single": {
31724
+ const amount = course.pricing.singlePriceAmount ?? 0;
31725
+ return {
31726
+ currency,
31727
+ display: toExactOrFreeDisplay(amount, currency),
31728
+ selectableOptions: [],
31729
+ requiresSelection: false,
31730
+ selectedOption: null,
31731
+ slidingScale: null,
31732
+ selectedSlidingAmount: null,
31733
+ selectedPriceAmount: amount,
31734
+ selectedRequiresPayment: amount > 0,
31735
+ hasPaidSelection: amount > 0,
31736
+ hasFreeSelection: amount <= 0
31737
+ };
31738
+ }
31739
+ case "tiered": {
31740
+ const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
31741
+ const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
31742
+ const lowestAmount = selectableOptions.reduce((lowest, option) => {
31743
+ if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
31744
+ return lowest;
31745
+ }, null);
31746
+ return {
31747
+ currency,
31748
+ display: lowestAmount === null ? {
31749
+ kind: "unavailable",
31750
+ currency
31751
+ } : selectableOptions.length > 1 && lowestAmount > 0 ? {
31752
+ kind: "from",
31753
+ amount: lowestAmount,
31754
+ currency
31755
+ } : toExactOrFreeDisplay(lowestAmount, currency),
31756
+ selectableOptions,
31757
+ requiresSelection: selectableOptions.length > 1,
31758
+ selectedOption,
31759
+ slidingScale: null,
31760
+ selectedSlidingAmount: null,
31761
+ selectedPriceAmount: selectedOption?.priceAmount ?? null,
31762
+ selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
31763
+ hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
31764
+ hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
31765
+ };
31766
+ }
31767
+ case "sliding_scale": {
31768
+ const minAmount = course.pricing.slidingMinAmount ?? null;
31769
+ const maxAmount = course.pricing.slidingMaxAmount ?? null;
31770
+ if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
31771
+ currency,
31772
+ display: {
31773
+ kind: "unavailable",
31774
+ currency
31775
+ },
31776
+ selectableOptions: [],
31777
+ requiresSelection: true,
31778
+ selectedOption: null,
31779
+ slidingScale: null,
31780
+ selectedSlidingAmount: null,
31781
+ selectedPriceAmount: null,
31782
+ selectedRequiresPayment: false,
31783
+ hasPaidSelection: false,
31784
+ hasFreeSelection: false
31785
+ };
31786
+ const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
31787
+ return {
31788
+ currency,
31789
+ display: {
31790
+ kind: "range",
31791
+ minAmount,
31792
+ maxAmount,
31793
+ currency
31794
+ },
31795
+ selectableOptions: [],
31796
+ requiresSelection: normalizedSelectedAmount === null,
31797
+ selectedOption: null,
31798
+ slidingScale: {
31799
+ minAmount,
31800
+ maxAmount,
31801
+ suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
31802
+ },
31803
+ selectedSlidingAmount: normalizedSelectedAmount,
31804
+ selectedPriceAmount: normalizedSelectedAmount,
31805
+ selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
31806
+ hasPaidSelection: maxAmount > 0,
31807
+ hasFreeSelection: minAmount === 0
31808
+ };
31809
+ }
31810
+ }
31811
+ }
31812
+ function formatCoursePriceDisplay(display, locale) {
31813
+ return formatBookingPriceDisplay(display, {
31814
+ decimals: "exact",
31815
+ locale
31816
+ });
31817
+ }
31818
+ function formatCoursePriceAmount(amount, currency, locale) {
31819
+ return formatCoursePriceDisplay(amount > 0 ? {
31820
+ kind: "exact",
31821
+ amount,
31822
+ currency
31823
+ } : {
31824
+ kind: "free",
31825
+ currency
31826
+ }, locale);
31827
+ }
31680
31828
  const eventRegistrationBlockDefinition = {
31681
31829
  manifest: createBlockManifest({
31682
31830
  id: "block.event-registration",
@@ -31772,6 +31920,24 @@ const eventRegistrationBlockDefinition = {
31772
31920
  defaultValue: true,
31773
31921
  ui: { intent: "display" }
31774
31922
  },
31923
+ {
31924
+ id: "showSessions",
31925
+ type: "boolean",
31926
+ label: "Show complete schedule",
31927
+ description: "Display every session for whole-series registrations",
31928
+ required: false,
31929
+ defaultValue: true,
31930
+ ui: { intent: "display" }
31931
+ },
31932
+ {
31933
+ id: "showPrice",
31934
+ type: "boolean",
31935
+ label: "Show price",
31936
+ description: "Display the whole-series price",
31937
+ required: false,
31938
+ defaultValue: true,
31939
+ ui: { intent: "display" }
31940
+ },
31775
31941
  {
31776
31942
  id: "successMessage",
31777
31943
  type: "text",
@@ -31782,6 +31948,26 @@ const eventRegistrationBlockDefinition = {
31782
31948
  defaultValue: "Thank you for registering! Check your email for confirmation details.",
31783
31949
  maxLength: 500
31784
31950
  },
31951
+ {
31952
+ id: "waitlistMessage",
31953
+ type: "text",
31954
+ label: "Waitlist message",
31955
+ description: "Message shown after joining a whole-series waitlist",
31956
+ required: false,
31957
+ multiline: true,
31958
+ defaultValue: "You've been added to the waitlist. We'll email you if a place becomes available.",
31959
+ maxLength: 500
31960
+ },
31961
+ {
31962
+ id: "membershipMessage",
31963
+ type: "text",
31964
+ label: "Membership registration message",
31965
+ description: "Message shown when a whole-series place is covered by membership",
31966
+ required: false,
31967
+ multiline: true,
31968
+ defaultValue: "Registered using your membership. Check your email for session details.",
31969
+ maxLength: 500
31970
+ },
31785
31971
  {
31786
31972
  id: "buttonText",
31787
31973
  type: "text",
@@ -31813,8 +31999,11 @@ const eventRegistrationBlockDefinition = {
31813
31999
  } },
31814
32000
  showVenue: { $bind: { from: "content.showVenue" } },
31815
32001
  showCapacity: { $bind: { from: "content.showCapacity" } },
32002
+ showSessions: { $bind: { from: "content.showSessions" } },
32003
+ showPrice: { $bind: { from: "content.showPrice" } },
31816
32004
  successMessage: { $bind: { from: "content.successMessage" } },
31817
32005
  waitlistMessage: { $bind: { from: "content.waitlistMessage" } },
32006
+ membershipMessage: { $bind: { from: "content.membershipMessage" } },
31818
32007
  buttonText: { $bind: {
31819
32008
  from: "content.buttonText",
31820
32009
  fallback: "Complete Registration"
@@ -31828,6 +32017,7 @@ const eventRegistrationBlockDefinition = {
31828
32017
  fallback: false
31829
32018
  } },
31830
32019
  events: { $bind: { from: "data.events" } },
32020
+ wholeSeriesOffering: { $bind: { from: "data.wholeSeriesOffering.offering" } },
31831
32021
  sitePasses: { $bind: { from: "data.sitePasses" } },
31832
32022
  siteMemberships: { $bind: { from: "data.siteMemberships" } },
31833
32023
  stage: { $bind: {
@@ -31841,9 +32031,10 @@ const eventRegistrationBlockDefinition = {
31841
32031
  runtime: eventRegistrationBlockRuntime,
31842
32032
  dataSchemas: {
31843
32033
  events: publicEventsArraySchema.optional(),
32034
+ wholeSeriesOffering: z$1.object({ offering: publicCourseSchema }).optional(),
31844
32035
  sitePasses: publicPassProductCollectionSchema.optional(),
31845
32036
  siteMemberships: publicMembershipProductCollectionSchema.optional(),
31846
- occurrenceContext: occurrenceContextSchema$1.optional()
32037
+ occurrenceContext: occurrenceContextSchema.optional()
31847
32038
  },
31848
32039
  dataLoaders: {
31849
32040
  events: {
@@ -31856,11 +32047,23 @@ const eventRegistrationBlockDefinition = {
31856
32047
  fallback: "published"
31857
32048
  } },
31858
32049
  readProfile: "registration",
31859
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
32050
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
31860
32051
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
31861
32052
  },
31862
32053
  mode: "server"
31863
32054
  },
32055
+ wholeSeriesOffering: {
32056
+ endpoint: "getPublicWholeSeriesOffering",
32057
+ params: {
32058
+ siteId: { $bind: { from: "$root.siteId" } },
32059
+ eventSeriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32060
+ stage: { $bind: {
32061
+ from: "$root.previewStage",
32062
+ fallback: "published"
32063
+ } }
32064
+ },
32065
+ mode: "server"
32066
+ },
31864
32067
  sitePasses: {
31865
32068
  endpoint: "listPublicPasses",
31866
32069
  params: { siteId: { $bind: { from: "$root.siteId" } } },
@@ -31874,159 +32077,6 @@ const eventRegistrationBlockDefinition = {
31874
32077
  }
31875
32078
  };
31876
32079
  //#endregion
31877
- //#region ../blocks/src/system/blocks/courses/shared/pricing.ts
31878
- function isSaleWindowOpen(option, now) {
31879
- if (!option.isActive) return false;
31880
- if (option.saleStartsAt && new Date(option.saleStartsAt) > now) return false;
31881
- if (option.saleEndsAt && new Date(option.saleEndsAt) < now) return false;
31882
- return true;
31883
- }
31884
- function toExactOrFreeDisplay(amount, currency) {
31885
- if (amount <= 0) return {
31886
- kind: "free",
31887
- currency
31888
- };
31889
- return {
31890
- kind: "exact",
31891
- amount,
31892
- currency
31893
- };
31894
- }
31895
- function getSelectableCoursePricingOptionsForNow(course, now) {
31896
- if (course.pricing.pricingStrategy !== "tiered") return [];
31897
- return [...course.pricing.options].filter((option) => isSaleWindowOpen(option, now)).sort((left, right) => {
31898
- if (left.sortOrder !== right.sortOrder) return left.sortOrder - right.sortOrder;
31899
- if (left.priceAmount !== right.priceAmount) return left.priceAmount - right.priceAmount;
31900
- return left.name.localeCompare(right.name);
31901
- });
31902
- }
31903
- function resolveCoursePricingState(course, selectedPricingOptionId, selectedSlidingAmountOrNowInput, nowInput = {}) {
31904
- const selectedSlidingAmount = typeof selectedSlidingAmountOrNowInput === "number" || selectedSlidingAmountOrNowInput === null ? selectedSlidingAmountOrNowInput : null;
31905
- const effectiveNowInput = typeof selectedSlidingAmountOrNowInput === "object" && selectedSlidingAmountOrNowInput !== null ? selectedSlidingAmountOrNowInput : nowInput;
31906
- const currency = course.pricing.currency;
31907
- switch (course.pricing.pricingStrategy) {
31908
- case "free": return {
31909
- currency,
31910
- display: {
31911
- kind: "free",
31912
- currency
31913
- },
31914
- selectableOptions: [],
31915
- requiresSelection: false,
31916
- selectedOption: null,
31917
- slidingScale: null,
31918
- selectedSlidingAmount: null,
31919
- selectedPriceAmount: 0,
31920
- selectedRequiresPayment: false,
31921
- hasPaidSelection: false,
31922
- hasFreeSelection: true
31923
- };
31924
- case "single": {
31925
- const amount = course.pricing.singlePriceAmount ?? 0;
31926
- return {
31927
- currency,
31928
- display: toExactOrFreeDisplay(amount, currency),
31929
- selectableOptions: [],
31930
- requiresSelection: false,
31931
- selectedOption: null,
31932
- slidingScale: null,
31933
- selectedSlidingAmount: null,
31934
- selectedPriceAmount: amount,
31935
- selectedRequiresPayment: amount > 0,
31936
- hasPaidSelection: amount > 0,
31937
- hasFreeSelection: amount <= 0
31938
- };
31939
- }
31940
- case "tiered": {
31941
- const selectableOptions = getSelectableCoursePricingOptionsForNow(course, resolvePlanningDateInput(effectiveNowInput));
31942
- const selectedOption = (selectedPricingOptionId ? selectableOptions.find((option) => option.id === selectedPricingOptionId) : null) ?? (selectableOptions.length === 1 ? selectableOptions[0] ?? null : null);
31943
- const lowestAmount = selectableOptions.reduce((lowest, option) => {
31944
- if (lowest === null || option.priceAmount < lowest) return option.priceAmount;
31945
- return lowest;
31946
- }, null);
31947
- return {
31948
- currency,
31949
- display: lowestAmount === null ? {
31950
- kind: "unavailable",
31951
- currency
31952
- } : selectableOptions.length > 1 && lowestAmount > 0 ? {
31953
- kind: "from",
31954
- amount: lowestAmount,
31955
- currency
31956
- } : toExactOrFreeDisplay(lowestAmount, currency),
31957
- selectableOptions,
31958
- requiresSelection: selectableOptions.length > 1,
31959
- selectedOption,
31960
- slidingScale: null,
31961
- selectedSlidingAmount: null,
31962
- selectedPriceAmount: selectedOption?.priceAmount ?? null,
31963
- selectedRequiresPayment: (selectedOption?.priceAmount ?? 0) > 0,
31964
- hasPaidSelection: selectableOptions.some((option) => option.priceAmount > 0),
31965
- hasFreeSelection: selectableOptions.some((option) => option.priceAmount === 0)
31966
- };
31967
- }
31968
- case "sliding_scale": {
31969
- const minAmount = course.pricing.slidingMinAmount ?? null;
31970
- const maxAmount = course.pricing.slidingMaxAmount ?? null;
31971
- if (minAmount === null || maxAmount === null || minAmount < 0 || maxAmount < minAmount) return {
31972
- currency,
31973
- display: {
31974
- kind: "unavailable",
31975
- currency
31976
- },
31977
- selectableOptions: [],
31978
- requiresSelection: true,
31979
- selectedOption: null,
31980
- slidingScale: null,
31981
- selectedSlidingAmount: null,
31982
- selectedPriceAmount: null,
31983
- selectedRequiresPayment: false,
31984
- hasPaidSelection: false,
31985
- hasFreeSelection: false
31986
- };
31987
- const normalizedSelectedAmount = typeof selectedSlidingAmount === "number" && Number.isFinite(selectedSlidingAmount) ? selectedSlidingAmount : null;
31988
- return {
31989
- currency,
31990
- display: {
31991
- kind: "range",
31992
- minAmount,
31993
- maxAmount,
31994
- currency
31995
- },
31996
- selectableOptions: [],
31997
- requiresSelection: normalizedSelectedAmount === null,
31998
- selectedOption: null,
31999
- slidingScale: {
32000
- minAmount,
32001
- maxAmount,
32002
- suggestedAmount: course.pricing.slidingSuggestedAmount ?? null
32003
- },
32004
- selectedSlidingAmount: normalizedSelectedAmount,
32005
- selectedPriceAmount: normalizedSelectedAmount,
32006
- selectedRequiresPayment: (normalizedSelectedAmount ?? 0) > 0,
32007
- hasPaidSelection: maxAmount > 0,
32008
- hasFreeSelection: minAmount === 0
32009
- };
32010
- }
32011
- }
32012
- }
32013
- function formatCoursePriceDisplay(display, locale) {
32014
- return formatBookingPriceDisplay(display, {
32015
- decimals: "exact",
32016
- locale
32017
- });
32018
- }
32019
- function formatCoursePriceAmount(amount, currency, locale) {
32020
- return formatCoursePriceDisplay(amount > 0 ? {
32021
- kind: "exact",
32022
- amount,
32023
- currency
32024
- } : {
32025
- kind: "free",
32026
- currency
32027
- }, locale);
32028
- }
32029
- //#endregion
32030
32080
  //#region ../blocks/src/system/runtime/nodes/course-registration.interactive.ts
32031
32081
  const courseRegistrationSourceSchema = z$1.object({
32032
32082
  siteId: z$1.string().optional(),
@@ -32461,15 +32511,6 @@ const eventDetailsManifest = createBlockManifest({
32461
32511
  })], { gap: "lg" })
32462
32512
  })]
32463
32513
  });
32464
- const occurrenceContextSchema = z$1.object({
32465
- id: z$1.string(),
32466
- seriesId: z$1.string(),
32467
- startsAt: z$1.string(),
32468
- endsAt: z$1.string(),
32469
- timeZone: z$1.string(),
32470
- capacityOverride: z$1.number().nullable().optional(),
32471
- overrides: z$1.record(z$1.string(), z$1.unknown()).nullable().optional()
32472
- }).nullable();
32473
32514
  const eventAutoApplyDiscountPreviewBaseSchema = z$1.object({
32474
32515
  id: z$1.string(),
32475
32516
  publicLabel: z$1.string(),
@@ -32504,8 +32545,9 @@ const eventDetailsBlockDefinition = {
32504
32545
  from: "$root.previewStage",
32505
32546
  fallback: "published"
32506
32547
  } },
32507
- limit: "25",
32508
- seriesId: { $bind: { from: "$root.occurrenceContext.seriesId" } },
32548
+ limit: "100",
32549
+ readProfile: "details",
32550
+ seriesId: { $bind: { from: "$root.subject.eventSeriesId" } },
32509
32551
  includeOccurrenceId: { $bind: { from: "$root.occurrenceContext.id" } }
32510
32552
  },
32511
32553
  mode: "server"
@@ -41242,9 +41284,6 @@ function parseSignedNewsletterDestinationRef(value) {
41242
41284
  const trimmed = parseTrimmedString(value);
41243
41285
  return trimmed && SIGNED_DESTINATION_REF_PATTERN.test(trimmed) ? trimmed : null;
41244
41286
  }
41245
- function parseNewsletterSignupDestinationProvider(value) {
41246
- return value === "riverbank" || value === "mailchimp" ? value : null;
41247
- }
41248
41287
  function buildNewsletterSignupBlockRef(blockId) {
41249
41288
  const parsed = parseNewsletterSignupBlockId(blockId);
41250
41289
  return parsed ? {
@@ -41391,19 +41430,9 @@ const newsletterFieldSchema = z$1.object({
41391
41430
  });
41392
41431
  const newsletterSignupBlockIdSchema = z$1.string().trim().min(1).transform(parseRequiredNewsletterSignupBlockId);
41393
41432
  const signedNewsletterDestinationRefSchema = z$1.string().trim().min(1).transform(parseRequiredSignedNewsletterDestinationRef);
41394
- const newsletterPublicDestinationRefSchema = z$1.discriminatedUnion("tag", [z$1.object({
41395
- tag: z$1.literal("block_ref"),
41396
- blockId: newsletterSignupBlockIdSchema
41397
- }), z$1.object({
41398
- tag: z$1.literal("signed_destination_ref"),
41399
- token: signedNewsletterDestinationRefSchema
41400
- })]);
41401
- const newsletterSourceSchema = z$1.object({
41402
- blockId: z$1.string().nullable().optional(),
41433
+ const newsletterSourceCommonSchema = z$1.object({
41403
41434
  siteId: z$1.string().optional(),
41404
41435
  apiBaseUrl: z$1.string().optional(),
41405
- listId: z$1.string().nullable().optional(),
41406
- destinationProvider: newsletterDestinationProviderSchema.nullable().optional(),
41407
41436
  preset: newsletterPresetSchema.optional(),
41408
41437
  includePhone: z$1.boolean().optional(),
41409
41438
  buttonLabel: z$1.string().nullable().optional(),
@@ -41414,6 +41443,25 @@ const newsletterSourceSchema = z$1.object({
41414
41443
  spamProtectionEnabled: z$1.boolean().optional(),
41415
41444
  className: z$1.string().nullable().optional()
41416
41445
  });
41446
+ const newsletterSourceSchema = z$1.discriminatedUnion("source", [
41447
+ newsletterSourceCommonSchema.extend({
41448
+ source: z$1.literal("block"),
41449
+ blockId: z$1.string().nullable().optional(),
41450
+ listId: z$1.string().nullable().optional(),
41451
+ destinationProvider: newsletterDestinationProviderSchema.nullable().optional()
41452
+ }),
41453
+ newsletterSourceCommonSchema.extend({
41454
+ source: z$1.literal("signed-footer"),
41455
+ destinationRef: z$1.object({
41456
+ tag: z$1.literal("signed_destination_ref"),
41457
+ token: signedNewsletterDestinationRefSchema
41458
+ })
41459
+ }),
41460
+ newsletterSourceCommonSchema.extend({
41461
+ source: z$1.literal("legacy-direct-list"),
41462
+ listId: z$1.string().nullable()
41463
+ })
41464
+ ]);
41417
41465
  const newsletterDisplaySchema = z$1.object({
41418
41466
  kind: z$1.literal("newsletter-form"),
41419
41467
  className: z$1.string().nullable(),
@@ -41424,8 +41472,26 @@ const newsletterDisplaySchema = z$1.object({
41424
41472
  fields: z$1.array(newsletterFieldSchema)
41425
41473
  });
41426
41474
  const newsletterHydrationSchema = z$1.object({
41427
- destinationRef: newsletterPublicDestinationRefSchema.nullable().optional(),
41428
- listId: z$1.string().nullable().optional(),
41475
+ target: z$1.discriminatedUnion("tag", [
41476
+ z$1.object({
41477
+ tag: z$1.literal("block-source"),
41478
+ destinationRef: z$1.object({
41479
+ tag: z$1.literal("block_ref"),
41480
+ blockId: newsletterSignupBlockIdSchema
41481
+ }).nullable()
41482
+ }),
41483
+ z$1.object({
41484
+ tag: z$1.literal("signed-footer-source"),
41485
+ destinationRef: z$1.object({
41486
+ tag: z$1.literal("signed_destination_ref"),
41487
+ token: signedNewsletterDestinationRefSchema
41488
+ })
41489
+ }),
41490
+ z$1.object({
41491
+ tag: z$1.literal("legacy-direct-list"),
41492
+ listId: z$1.string().nullable()
41493
+ })
41494
+ ]),
41429
41495
  preset: newsletterPresetSchema,
41430
41496
  includePhone: z$1.boolean(),
41431
41497
  tags: z$1.string().nullable().optional(),
@@ -41459,20 +41525,43 @@ const newsletterFormBlockRuntime = defineProgressiveBlockRuntime({
41459
41525
  render: createZodCodec(newsletterRenderSchema)
41460
41526
  },
41461
41527
  buildRender: (source) => {
41462
- const runtimeSource = deriveNewsletterSignupRuntimeSource(source);
41528
+ const runtimeSource = source.source === "block" ? deriveNewsletterSignupRuntimeSource(source) : null;
41463
41529
  return {
41464
41530
  display: buildNewsletterDisplay(source),
41465
41531
  hydration: {
41466
- destinationRef: buildNewsletterSignupBlockRef(source.blockId),
41467
- listId: runtimeSource.listId,
41532
+ target: projectNewsletterFormHydrationTarget(source),
41468
41533
  preset: source.preset ?? "emailOnly",
41469
41534
  includePhone: source.includePhone ?? false,
41470
- tags: runtimeSource.tags,
41535
+ tags: runtimeSource ? runtimeSource.tags : source.tags,
41471
41536
  spamProtectionEnabled: source.spamProtectionEnabled
41472
41537
  }
41473
41538
  };
41474
41539
  }
41475
41540
  });
41541
+ function projectNewsletterFormHydrationTarget(source) {
41542
+ switch (source.source) {
41543
+ case "block": {
41544
+ const destinationRef = buildNewsletterSignupBlockRef(source.blockId);
41545
+ if (destinationRef?.tag === "block_ref") return {
41546
+ tag: "block-source",
41547
+ destinationRef
41548
+ };
41549
+ return {
41550
+ tag: "legacy-direct-list",
41551
+ listId: source.listId ?? null
41552
+ };
41553
+ }
41554
+ case "signed-footer": return {
41555
+ tag: "signed-footer-source",
41556
+ destinationRef: source.destinationRef
41557
+ };
41558
+ case "legacy-direct-list": return {
41559
+ tag: "legacy-direct-list",
41560
+ listId: source.listId
41561
+ };
41562
+ default: return assertNever$4(source);
41563
+ }
41564
+ }
41476
41565
  function buildNewsletterFormInteractiveIslandProps(props) {
41477
41566
  return buildInteractiveIslandProps({
41478
41567
  runtime: newsletterFormBlockRuntime,
@@ -41588,7 +41677,7 @@ const newsletterSignupBlockDefinition = {
41588
41677
  //#endregion
41589
41678
  //#region ../blocks/src/system/blocks/team-members.ts
41590
41679
  const ITEM_NAME = "member";
41591
- const teamMemberPhotoSchema = mediaSchema.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
41680
+ const teamMemberPhotoSchema = mediaSchema$1.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
41592
41681
  const teamMemberDataSchema = z$1.object({
41593
41682
  _type: z$1.literal("teamMember"),
41594
41683
  id: z$1.string(),
@@ -43163,7 +43252,7 @@ function getBlockDefinition(name) {
43163
43252
  //#endregion
43164
43253
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
43165
43254
  function resolveBackgroundMedia(input) {
43166
- const parsedMedia = mediaSchema.safeParse(input.image);
43255
+ const parsedMedia = mediaSchema$1.safeParse(input.image);
43167
43256
  if (!parsedMedia.success) return null;
43168
43257
  switch (parsedMedia.data.type) {
43169
43258
  case "image":
@@ -44533,6 +44622,9 @@ function renderTrailingAffordanceIcon(affordance) {
44533
44622
  className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block"
44534
44623
  });
44535
44624
  }
44625
+ function isMissingRequiredLink(linkRequired, resolvedHref) {
44626
+ return linkRequired && resolvedHref.length === 0;
44627
+ }
44536
44628
  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 }) => {
44537
44629
  const content = value ?? children;
44538
44630
  if (!content) {
@@ -44541,12 +44633,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
44541
44633
  }
44542
44634
  const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({ trailingIcon }));
44543
44635
  const resolvedHref = typeof href === "string" ? href.trim() : "";
44544
- if (linkRequired && resolvedHref.length === 0) {
44636
+ if (isMissingRequiredLink(linkRequired, resolvedHref)) {
44545
44637
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
44546
44638
  return null;
44547
44639
  }
44548
44640
  const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
44549
- const resolvedVariantId = parseThemeButtonVariantId(canonicalizePersistedBlockButtonRole(variantId));
44641
+ const resolvedVariantId = parseThemeButtonVariantId(variantId);
44642
+ if (variantId && !resolvedVariantId) {
44643
+ console.error("[ButtonNode] Invalid button variant", { variantId });
44644
+ return null;
44645
+ }
44550
44646
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
44551
44647
  variant: resolvedVariantId,
44552
44648
  size,
@@ -44675,8 +44771,9 @@ function iconForMediaType(type) {
44675
44771
  });
44676
44772
  }
44677
44773
  }
44678
- function normalizeButtonVariant(value) {
44679
- return isBlockButtonRole(value) ? value : "primary";
44774
+ function parseButtonVariant(value) {
44775
+ if (value === null || value === void 0) return "primary";
44776
+ return isBlockButtonRole(value) ? value : null;
44680
44777
  }
44681
44778
  function FileDownloadNode({ value, title, description, buttonLabel, buttonVariant, className }) {
44682
44779
  if (!value || !isDownloadableMediaType(value.type)) return null;
@@ -44686,7 +44783,11 @@ function FileDownloadNode({ value, title, description, buttonLabel, buttonVarian
44686
44783
  const heading = title?.trim() || filename;
44687
44784
  const body = description?.trim();
44688
44785
  const label = buttonLabel?.trim() || "Download";
44689
- const variant = normalizeButtonVariant(buttonVariant);
44786
+ const variant = parseButtonVariant(buttonVariant);
44787
+ if (!variant) {
44788
+ console.error("[FileDownloadNode] Invalid button variant", { buttonVariant });
44789
+ return null;
44790
+ }
44690
44791
  return /* @__PURE__ */ jsx("div", {
44691
44792
  className,
44692
44793
  children: /* @__PURE__ */ jsxs("div", {
@@ -45845,6 +45946,33 @@ function uniqByOccurrenceId(events) {
45845
45946
  }
45846
45947
  return out;
45847
45948
  }
45949
+ function selectFromOccurrenceContext(events, occurrenceContext) {
45950
+ if (!occurrenceContext) return null;
45951
+ const byId = events.find((event) => event.occurrenceId === occurrenceContext.id || event.id === occurrenceContext.id);
45952
+ if (byId) return byId;
45953
+ const contextDate = getBookingLocalDateKey(toScheduledBookingDateTime({
45954
+ startsAt: occurrenceContext.startsAt,
45955
+ timeZone: occurrenceContext.timeZone
45956
+ }));
45957
+ return events.find((event) => getBookingLocalDateKey(toScheduledBookingDateTime({
45958
+ startsAt: event.startsAt,
45959
+ timeZone: event.timeZone
45960
+ })) === contextDate) ?? null;
45961
+ }
45962
+ function selectNextUpcoming(events, nowIso) {
45963
+ return [...events].filter((event) => isFutureOrNow(event.startsAt, nowIso)).sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt))[0] ?? null;
45964
+ }
45965
+ function selectCompletedWholeSeries(events) {
45966
+ if (events.length === 0 || !events.every((event) => event.bookingScope === "whole_series")) return null;
45967
+ return [...events].sort((left, right) => Date.parse(right.startsAt) - Date.parse(left.startsAt))[0] ?? null;
45968
+ }
45969
+ function selectRelatedDates(input) {
45970
+ if (!input.seriesId) return [];
45971
+ const isWholeSeries = input.selected?.bookingScope === "whole_series";
45972
+ const selectedOccurrenceId = input.selected ? input.selected.occurrenceId || input.selected.id : null;
45973
+ 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));
45974
+ return isWholeSeries ? dates : dates.slice(0, input.limit);
45975
+ }
45848
45976
  function selectEventDetails(args) {
45849
45977
  const all = uniqByOccurrenceId(resolveEventRegistrationScopedEvents((args.events ?? []).filter(Boolean), {
45850
45978
  occurrenceContext: args.occurrenceContext,
@@ -45852,37 +45980,22 @@ function selectEventDetails(args) {
45852
45980
  }));
45853
45981
  const occurrenceContext = args.occurrenceContext ?? null;
45854
45982
  const otherLimit = parseLimit$1(args.otherDatesLimit, 5);
45855
- const selectedFromContext = (() => {
45856
- if (!occurrenceContext) return null;
45857
- const byId = all.find((e) => e.occurrenceId === occurrenceContext.id || e.id === occurrenceContext.id) ?? null;
45858
- if (byId) return byId;
45859
- const ctxDate = getBookingLocalDateKey(toScheduledBookingDateTime({
45860
- startsAt: occurrenceContext.startsAt,
45861
- timeZone: occurrenceContext.timeZone
45862
- }));
45863
- return all.find((e) => getBookingLocalDateKey(toScheduledBookingDateTime({
45864
- startsAt: e.startsAt,
45865
- timeZone: e.timeZone
45866
- })) === ctxDate) ?? null;
45867
- })();
45868
- const nextUpcoming = (() => {
45869
- const upcoming = all.filter((e) => isFutureOrNow(e.startsAt, args.nowIso));
45870
- upcoming.sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
45871
- return upcoming[0] ?? null;
45872
- })();
45873
- const mode = selectedFromContext ? "selected" : "next";
45874
- const selected = selectedFromContext ?? nextUpcoming;
45983
+ const selectedFromContext = selectFromOccurrenceContext(all, occurrenceContext);
45984
+ const nextUpcoming = selectNextUpcoming(all, args.nowIso);
45985
+ const completedWholeSeries = selectCompletedWholeSeries(all);
45986
+ const selected = selectedFromContext ?? nextUpcoming ?? completedWholeSeries;
45987
+ const mode = selectedFromContext ? "selected" : nextUpcoming ? "next" : completedWholeSeries ? "completed" : "next";
45875
45988
  const timeZone = toBookingTimeZone(selected?.timeZone ?? all[0]?.timeZone ?? null);
45876
- const seriesId = occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null;
45877
- const selectedOccurrenceId = selected?.occurrenceId ?? null;
45878
45989
  return {
45879
45990
  mode,
45880
45991
  selected,
45881
- otherDates: seriesId ? all.filter((e) => e.seriesId === seriesId).filter((e) => isFutureOrNow(e.startsAt, args.nowIso)).filter((e) => {
45882
- const occId = e.occurrenceId || e.id;
45883
- if (selectedOccurrenceId && occId === selectedOccurrenceId) return false;
45884
- return true;
45885
- }).slice(0, otherLimit) : [],
45992
+ otherDates: selectRelatedDates({
45993
+ events: all,
45994
+ seriesId: occurrenceContext?.seriesId ?? selected?.seriesId ?? all[0]?.seriesId ?? null,
45995
+ selected,
45996
+ nowIso: args.nowIso,
45997
+ limit: otherLimit
45998
+ }),
45886
45999
  timeZone
45887
46000
  };
45888
46001
  }
@@ -46027,7 +46140,7 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46027
46140
  /* @__PURE__ */ jsxs("div", { children: [
46028
46141
  /* @__PURE__ */ jsx("div", {
46029
46142
  className: "rb-label rb-mb-2",
46030
- children: selection.mode === "next" ? "Next date" : "Date"
46143
+ children: selected.bookingScope === "whole_series" ? selection.mode === "next" ? "Next session" : "Selected session" : selection.mode === "next" ? "Next date" : "Date"
46031
46144
  }),
46032
46145
  /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: date }) }),
46033
46146
  /* @__PURE__ */ jsx("p", {
@@ -46065,18 +46178,27 @@ function EventFacts({ selection, selected, venue, teamMembers, pricing }) {
46065
46178
  }) : null] }, member.id))
46066
46179
  })]
46067
46180
  }) : null,
46068
- pricing
46181
+ pricing,
46182
+ selected.bookingScope === "whole_series" ? /* @__PURE__ */ jsxs("div", {
46183
+ className: "rb-mt-6",
46184
+ children: [/* @__PURE__ */ jsx("div", {
46185
+ className: "rb-label rb-mb-2",
46186
+ children: "Registration"
46187
+ }), /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("strong", { children: selected.wholeSeries?.enrollmentOpen ? "Open" : "Closed" }) })]
46188
+ }) : null
46069
46189
  ]
46070
46190
  });
46071
46191
  }
46072
46192
  function OtherEventDates({ selection }) {
46073
- if (selection.otherDates.length === 0) return null;
46193
+ const isWholeSeries = selection.selected?.bookingScope === "whole_series";
46194
+ const dates = isWholeSeries && selection.selected ? [selection.selected, ...selection.otherDates].sort((left, right) => Date.parse(left.startsAt) - Date.parse(right.startsAt)) : selection.otherDates;
46195
+ if (dates.length === 0) return null;
46074
46196
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
46075
46197
  className: "rb-label",
46076
- children: "Other dates"
46198
+ children: isWholeSeries ? "Session schedule" : "Other dates"
46077
46199
  }), /* @__PURE__ */ jsx("div", {
46078
46200
  className: "rb-mt-2 rb-tiles-grid",
46079
- children: selection.otherDates.map((event) => /* @__PURE__ */ jsx("a", {
46201
+ children: dates.map((event) => /* @__PURE__ */ jsx("a", {
46080
46202
  className: "rb-tile rb-tile--interactive",
46081
46203
  ...resolveEventLinkProps(event),
46082
46204
  children: /* @__PURE__ */ jsx(DateTimeTile, {
@@ -49275,13 +49397,13 @@ const FormNodeSSR = ({ blockId, value, submitLabel, successMessage, className, o
49275
49397
  * Renders the newsletter signup form for SSR with hydration support.
49276
49398
  * Uses the islands architecture pattern to hydrate on the client.
49277
49399
  */
49278
- function NewsletterFormSSR({ blockId, siteId, apiBaseUrl, listId, destinationProvider, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className }) {
49400
+ function NewsletterFormSSR(props) {
49401
+ const { siteId, apiBaseUrl, preset = "emailOnly", includePhone, buttonLabel = "Subscribe", buttonVariant = "primary", successMessage, privacyNote, tags, spamProtectionEnabled, className } = props;
49402
+ const blockId = props.source === "block" ? props.blockId : null;
49279
49403
  const islandProps = buildNewsletterFormInteractiveIslandProps({
49280
- blockId,
49404
+ ...props,
49281
49405
  siteId,
49282
49406
  apiBaseUrl,
49283
- listId,
49284
- destinationProvider,
49285
49407
  preset,
49286
49408
  includePhone,
49287
49409
  buttonLabel,
@@ -51529,6 +51651,35 @@ function resolveColorTokenHex(theme, colorToken) {
51529
51651
  if (colorToken === "transparent") return null;
51530
51652
  return expandPalette(theme.palette)[colorToken] ?? null;
51531
51653
  }
51654
+ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
51655
+ `min-width: 12rem;`,
51656
+ `width: max-content;`,
51657
+ `max-width: min(22rem, calc(100vw - 2rem));`,
51658
+ `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
51659
+ ];
51660
+ //#endregion
51661
+ //#region ../theme-core/src/header/surfaceRules.ts
51662
+ /** Compile the at-rest surface independently of scroll treatment and paint geometry. */
51663
+ function buildHeaderSurfaceRules(header, tokens) {
51664
+ const base = [];
51665
+ const background = header.background;
51666
+ if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
51667
+ else if (background.type === "gradient" && background.gradient) {
51668
+ const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
51669
+ base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
51670
+ }
51671
+ const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
51672
+ if (!header.border || borderWidth === "0") return {
51673
+ base,
51674
+ border: []
51675
+ };
51676
+ const color = rgbColorValue(header.border.colorToken?.trim() || "border");
51677
+ const style = header.border.style === "dashed" ? "dashed" : "solid";
51678
+ return {
51679
+ base,
51680
+ border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
51681
+ };
51682
+ }
51532
51683
  //#endregion
51533
51684
  //#region ../theme-core/src/navigation/presets.ts
51534
51685
  /**
@@ -51690,12 +51841,71 @@ function getNavLinkPreset(presetId) {
51690
51841
  return NAV_LINK_PRESETS[presetId];
51691
51842
  }
51692
51843
  Object.keys(NAV_LINK_PRESETS);
51693
- const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
51694
- `min-width: 12rem;`,
51695
- `width: max-content;`,
51696
- `max-width: min(22rem, calc(100vw - 2rem));`,
51697
- `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
51698
- ];
51844
+ //#endregion
51845
+ //#region ../theme-core/src/header/legacyNavLinkStyle.ts
51846
+ function buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize) {
51847
+ const navStyle = header.navStyle ?? "minimal";
51848
+ const basePreset = getNavLinkPreset(navStyle);
51849
+ if (!basePreset) return null;
51850
+ const style = {
51851
+ ...basePreset,
51852
+ fontWeight: header.navWeight ?? basePreset.fontWeight,
51853
+ colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
51854
+ ...contrastTreatment ? { contrastTreatment } : {},
51855
+ ...navTextSize ? { textSize: navTextSize } : {}
51856
+ };
51857
+ if (header.navWeight === "bold" && navStyle === "solid") style.textTransform = "uppercase";
51858
+ applyLegacyNavEffects(style, header);
51859
+ applyLegacyGlassTreatment(style, header, navStyle);
51860
+ return style;
51861
+ }
51862
+ function applyLegacyNavEffects(style, header) {
51863
+ if (!header.navEffects) return;
51864
+ const effects = style.effects = {
51865
+ ...style.effects,
51866
+ hover: [...style.effects?.hover ?? []],
51867
+ active: [...style.effects?.active ?? []]
51868
+ };
51869
+ if (header.navEffects.glow) effects.hover.push({
51870
+ effectId: "outer-glow",
51871
+ options: { spread: 5 }
51872
+ });
51873
+ if (header.navEffects.neumorphic) {
51874
+ effects.hover.push({
51875
+ effectId: "neumorphic-shadow",
51876
+ options: { mode: "pressed" }
51877
+ });
51878
+ effects.hover.push({
51879
+ effectId: "text-color-change",
51880
+ options: { hoverColorToken: "primary" }
51881
+ });
51882
+ }
51883
+ if (header.navEffects.underlineGradient) effects.hover.push({
51884
+ effectId: "border-bottom-grow",
51885
+ options: { origin: "center" }
51886
+ });
51887
+ }
51888
+ function applyLegacyGlassTreatment(style, header, navStyle) {
51889
+ if (header.navContainer?.type !== "glass" || navStyle !== "minimal") return;
51890
+ style.borderRadius = "full";
51891
+ style.effects = {
51892
+ ...style.effects,
51893
+ hover: glassStateEffects(10),
51894
+ active: glassStateEffects(18)
51895
+ };
51896
+ }
51897
+ function glassStateEffects(opacity) {
51898
+ return [{
51899
+ effectId: "background-on-hover-alpha",
51900
+ options: {
51901
+ colorToken: "neutral-50",
51902
+ opacity
51903
+ }
51904
+ }, {
51905
+ effectId: "text-color-change",
51906
+ options: { hoverColorToken: "neutral-50" }
51907
+ }];
51908
+ }
51699
51909
  //#endregion
51700
51910
  //#region ../theme-core/src/header/generateHeaderCss.ts
51701
51911
  const HEADER_BLUR = "blur(12px)";
@@ -51725,8 +51935,8 @@ function generateHeaderCss(options) {
51725
51935
  const cssChunks = [];
51726
51936
  const headerContrastTreatment = resolveHeaderContrastTreatment(header);
51727
51937
  const headerNavTextSize = resolveHeaderNavTextSize(header);
51728
- cssChunks.push(generateHeaderRootStyles(header, themeId, tokens, theme));
51729
- cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId));
51938
+ cssChunks.push(generateHeaderRootStyles(header, themeId, tokens));
51939
+ cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId, header.variant));
51730
51940
  cssChunks.push(generateLogoStyles({
51731
51941
  logo: header.logo,
51732
51942
  themeId,
@@ -51764,56 +51974,33 @@ function isClearSplitHeaderShape(header) {
51764
51974
  function isDetachedFloatingHeaderShape(header) {
51765
51975
  return header.variant === "floating" && !header.container;
51766
51976
  }
51767
- function generateMobileOverlayBackdropFilterFix(themeId) {
51768
- 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`;
51769
- }
51770
51977
  /**
51771
51978
  * Generate root header container styles
51772
51979
  */
51773
- function generateHeaderRootStyles(header, themeId, tokens, _theme) {
51980
+ function generateHeaderRootStyles(header, themeId, tokens) {
51774
51981
  const selector = `:where([data-theme-scope="${themeId}"]) .header-root`;
51775
- const backgroundSelector = `:where([data-theme-scope="${themeId}"]) .header-root::before`;
51776
51982
  const rules = [];
51777
- const backgroundRules = [];
51778
51983
  const navContainerType = header.navContainer?.type ?? "none";
51779
51984
  const isContainedNav = navContainerType === "pill" || navContainerType === "glass";
51780
51985
  rules.push("position: relative;");
51781
51986
  rules.push("isolation: isolate;");
51782
- if (!isContainedNav) {
51783
- const bg = header.background;
51784
- if (bg.type === "color") {
51785
- const bgColor = tokens.getColor(bg.color || "surface");
51786
- backgroundRules.push(`background-color: ${bgColor};`);
51787
- } else if (bg.type === "gradient" && bg.gradient) {
51788
- const stops = bg.gradient.stops.map((s) => tokens.getColor(s.color)).join(", ");
51789
- const angle = bg.gradient.angle ?? 180;
51790
- backgroundRules.push(`background-image: linear-gradient(${angle}deg, ${stops});`);
51791
- }
51792
- backgroundRules.push(`backdrop-filter: ${HEADER_BLUR};`);
51793
- backgroundRules.push(`-webkit-backdrop-filter: ${HEADER_BLUR};`);
51794
- if (header.border) {
51795
- const borderWidth = getComponentBorderWidthPx(header.border.width);
51796
- if (borderWidth !== "0") {
51797
- const borderToken = header.border?.colorToken?.trim() || "border";
51798
- const borderColor = tokens.getColor(borderToken);
51799
- const borderStyle = header.border.style === "dashed" ? "dashed" : "solid";
51800
- if (header.border.position === "bottom") rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
51801
- else if (header.border.position === "top") rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
51802
- else if (header.border.position === "both") {
51803
- rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
51804
- rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
51805
- }
51806
- }
51807
- }
51808
- }
51987
+ const surfaceRules = isContainedNav ? {
51988
+ base: [],
51989
+ border: []
51990
+ } : buildHeaderSurfaceRules(header, tokens);
51991
+ const floatingSurfaceBorder = header.variant === "floating";
51992
+ if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
51993
+ const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
51994
+ const scrolledPaintRules = floatingSurfaceBorder ? surfaceRules.border : [];
51809
51995
  if (header.positioning === "sticky" || header.positioning === "fixed") {
51810
51996
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
51811
51997
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
51812
51998
  }
51813
51999
  const baseBlock = `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
51814
52000
  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`;
51815
- if (isContainedNav || backgroundRules.length === 0) return `${baseBlock}\n${overlayFix}`;
51816
- 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) : ""}`;
52001
+ const scrollTreatmentStyles = generateHeaderScrollTreatmentStyles(header.scrollTreatment, themeId, header.variant, scrolledPaintRules);
52002
+ if (isContainedNav || basePaintRules.length === 0) return `${baseBlock}\n${overlayFix}${scrollTreatmentStyles}`;
52003
+ return `${baseBlock}\n${renderHeaderPaintTargetRules(getHeaderPaintTargets(header.variant, themeId), basePaintRules)}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}${scrollTreatmentStyles}`;
51817
52004
  }
51818
52005
  /**
51819
52006
  * Reshapes the full-bleed header paint layer into a contained brand capsule at
@@ -51858,10 +52045,10 @@ function generateLogoStyles(input) {
51858
52045
  else rules.push(`font-family: var(--font-heading);`);
51859
52046
  if (logo) {
51860
52047
  if (logo.letterSpacing && logo.letterSpacing !== "normal") rules.push(`letter-spacing: ${{
51861
- "normal": "0em",
51862
- "wide": "0.05em",
51863
- "wider": "0.1em",
51864
- "widest": "0.15em"
52048
+ normal: "0em",
52049
+ wide: "0.05em",
52050
+ wider: "0.1em",
52051
+ widest: "0.15em"
51865
52052
  }[logo.letterSpacing]};`);
51866
52053
  if (logo.gradient) {
51867
52054
  rules.push(`background: linear-gradient(to right, ${primaryColor}, ${accentColor});`);
@@ -51934,71 +52121,11 @@ function generateNavLinkStyles(header, themeId, tokens, theme, contrastTreatment
51934
52121
  } : header.navLinkStyle, navPreferences),
51935
52122
  className: "header-nav-link"
51936
52123
  });
51937
- const navStyle = header.navStyle ?? "minimal";
51938
- const basePreset = getNavLinkPreset(navStyle);
51939
- if (!basePreset) {
51940
- console.warn(`[generateHeaderCss] Nav link preset not found: ${navStyle}`);
52124
+ const mergedStyle = buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize);
52125
+ if (!mergedStyle) {
52126
+ console.warn(`[generateHeaderCss] Nav link preset not found: ${header.navStyle}`);
51941
52127
  return "";
51942
52128
  }
51943
- const mergedStyle = {
51944
- ...basePreset,
51945
- fontWeight: header.navWeight ?? basePreset.fontWeight,
51946
- colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
51947
- ...contrastTreatment ? { contrastTreatment } : {},
51948
- ...navTextSize ? { textSize: navTextSize } : {}
51949
- };
51950
- if (header.navWeight === "bold" && navStyle === "solid") mergedStyle.textTransform = "uppercase";
51951
- if (header.navEffects) {
51952
- const effects = mergedStyle.effects = {
51953
- ...mergedStyle.effects,
51954
- hover: [...mergedStyle.effects?.hover || []],
51955
- active: [...mergedStyle.effects?.active || []]
51956
- };
51957
- if (header.navEffects.glow) effects.hover.push({
51958
- effectId: "outer-glow",
51959
- options: { spread: 5 }
51960
- });
51961
- if (header.navEffects.neumorphic) {
51962
- effects.hover.push({
51963
- effectId: "neumorphic-shadow",
51964
- options: { mode: "pressed" }
51965
- });
51966
- effects.hover.push({
51967
- effectId: "text-color-change",
51968
- options: { hoverColorToken: "primary" }
51969
- });
51970
- }
51971
- if (header.navEffects.underlineGradient) effects.hover.push({
51972
- effectId: "border-bottom-grow",
51973
- options: { origin: "center" }
51974
- });
51975
- }
51976
- if ((header.navContainer?.type ?? "none") === "glass" && navStyle === "minimal") {
51977
- mergedStyle.borderRadius = "full";
51978
- mergedStyle.effects = {
51979
- ...mergedStyle.effects,
51980
- hover: [{
51981
- effectId: "background-on-hover-alpha",
51982
- options: {
51983
- colorToken: "neutral-50",
51984
- opacity: 10
51985
- }
51986
- }, {
51987
- effectId: "text-color-change",
51988
- options: { hoverColorToken: "neutral-50" }
51989
- }],
51990
- active: [{
51991
- effectId: "background-on-hover-alpha",
51992
- options: {
51993
- colorToken: "neutral-50",
51994
- opacity: 18
51995
- }
51996
- }, {
51997
- effectId: "text-color-change",
51998
- options: { hoverColorToken: "neutral-50" }
51999
- }]
52000
- };
52001
- }
52002
52129
  return generateNavLinkCSS({
52003
52130
  themeId,
52004
52131
  tokens,
@@ -52026,10 +52153,10 @@ function generateDropdownContainerStyles(header, themeId, tokens) {
52026
52153
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
52027
52154
  const borderRadius = dropdownStyle?.borderRadius ?? "md";
52028
52155
  rules.push(`border-radius: ${{
52029
- "none": "0",
52030
- "sm": "0.25rem",
52031
- "md": "0.5rem",
52032
- "lg": "0.75rem"
52156
+ none: "0",
52157
+ sm: "0.25rem",
52158
+ md: "0.5rem",
52159
+ lg: "0.75rem"
52033
52160
  }[borderRadius]};`);
52034
52161
  rules.push(`padding: 0.5rem 0;`);
52035
52162
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
@@ -52084,16 +52211,16 @@ function generateDropdownLinkStyles(header, themeId, tokens, theme) {
52084
52211
  const additionalRules = [];
52085
52212
  const letterSpacing = configuredDropdownStyle?.letterSpacing ?? "normal";
52086
52213
  if (letterSpacing !== "normal") additionalRules.push(`letter-spacing: ${{
52087
- "normal": "0em",
52088
- "wide": "0.05em",
52089
- "wider": "0.1em"
52214
+ normal: "0em",
52215
+ wide: "0.05em",
52216
+ wider: "0.1em"
52090
52217
  }[letterSpacing]};`);
52091
52218
  const textSize = configuredDropdownStyle?.textSize ?? "sm";
52092
52219
  additionalRules.push(`font-size: ${{
52093
- "xs": "0.75rem",
52094
- "sm": "0.875rem",
52095
- "base": "1rem",
52096
- "lg": "1.125rem"
52220
+ xs: "0.75rem",
52221
+ sm: "0.875rem",
52222
+ base: "1rem",
52223
+ lg: "1.125rem"
52097
52224
  }[textSize]};`);
52098
52225
  if (additionalRules.length > 0) return baseCSS + `\n${`:where([data-theme-scope="${themeId}"]) .nav-dropdown-link`} {\n ${additionalRules.join("\n ")}\n}\n`;
52099
52226
  return baseCSS;
@@ -52189,18 +52316,18 @@ function generateFloatingContainerStyles(header, themeId, tokens) {
52189
52316
  rules.push(`-webkit-backdrop-filter: ${FLOATING_BLUR};`);
52190
52317
  if (container.border) rules.push(`border: 1px solid rgb(255 255 255 / 0.2);`);
52191
52318
  rules.push(`border-radius: ${{
52192
- "none": "0",
52193
- "sm": "0.375rem",
52194
- "md": "0.5rem",
52195
- "lg": "0.75rem",
52196
- "xl": "1rem",
52319
+ none: "0",
52320
+ sm: "0.375rem",
52321
+ md: "0.5rem",
52322
+ lg: "0.75rem",
52323
+ xl: "1rem",
52197
52324
  "2xl": "1.5rem"
52198
52325
  }[container.rounded]};`);
52199
52326
  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);`);
52200
52327
  rules.push(`padding: ${{
52201
- "sm": "1rem 1.5rem",
52202
- "md": "1.5rem 2rem",
52203
- "lg": "2rem 2.5rem"
52328
+ sm: "1rem 1.5rem",
52329
+ md: "1.5rem 2rem",
52330
+ lg: "2rem 2.5rem"
52204
52331
  }[container.padding]};`);
52205
52332
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
52206
52333
  }
@@ -68490,8 +68617,7 @@ function toBlocksBlockOverrides(overrides) {
68490
68617
  };
68491
68618
  return result;
68492
68619
  }
68493
- function toBlocksDataContext(dataContext) {
68494
- if (!dataContext) return void 0;
68620
+ function toBlocksPageRendererDataContext(dataContext) {
68495
68621
  return {
68496
68622
  ...dataContext,
68497
68623
  mediaAssets: toBlocksMediaAssets(dataContext.mediaAssets),
@@ -68504,7 +68630,7 @@ function PageRenderer(props) {
68504
68630
  const blocksProps = {
68505
68631
  ...props,
68506
68632
  theme: blocksTheme,
68507
- dataContext: toBlocksDataContext(props.dataContext),
68633
+ dataContext: props.dataContext ? toBlocksPageRendererDataContext(props.dataContext) : void 0,
68508
68634
  blockOverrides: toBlocksBlockOverrides(props.blockOverrides),
68509
68635
  sdkConfig: blocksSdkConfig,
68510
68636
  customBlocks: normalizeSdkCustomBlocks(props.customBlocks)
@@ -69180,7 +69306,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69180
69306
  try {
69181
69307
  apiBaseUrl = getRiverbankEnv().baseUrl;
69182
69308
  } catch {}
69183
- const viewModelOverrides = {
69309
+ const sharedViewModelOverrides = {
69184
69310
  $root: {
69185
69311
  siteId: site.id,
69186
69312
  apiBaseUrl,
@@ -69193,14 +69319,24 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69193
69319
  site,
69194
69320
  menu: menuViewModel,
69195
69321
  footerMenu: footerMenuViewModel,
69196
- legalFooterMenu: legalFooterMenuViewModel,
69322
+ legalFooterMenu: legalFooterMenuViewModel
69323
+ };
69324
+ const headerViewModelOverrides = {
69325
+ ...sharedViewModelOverrides,
69197
69326
  content: { logo: logoViewModel }
69198
69327
  };
69328
+ const footerViewModelOverrides = {
69329
+ ...sharedViewModelOverrides,
69330
+ content: {
69331
+ ...layout.footer,
69332
+ logo: logoViewModel
69333
+ }
69334
+ };
69199
69335
  let headerElement = null;
69200
69336
  if (header === true) headerElement = renderBlock(siteHeaderManifest, headerContent, {
69201
69337
  theme: builtThemeRuntime.tokens,
69202
69338
  themeConfig: blocksThemeWithVariant,
69203
- viewModelOverrides
69339
+ viewModelOverrides: headerViewModelOverrides
69204
69340
  });
69205
69341
  else if (typeof header === "function") headerElement = header(headerData);
69206
69342
  let footerElement = null;
@@ -69235,7 +69371,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69235
69371
  const defaultFooterElement = footerPlan.renderDefaultFooter ? renderBlock(siteFooterManifest, layout.footer, {
69236
69372
  theme: builtThemeRuntime.tokens,
69237
69373
  themeConfig: blocksTheme,
69238
- viewModelOverrides
69374
+ viewModelOverrides: footerViewModelOverrides
69239
69375
  }) : null;
69240
69376
  footerElement = footerPlan.mode === "default+blocks" ? /* @__PURE__ */ jsxs(Fragment, { children: [footerBlocksElement, defaultFooterElement] }) : footerPlan.mode === "blocks" ? footerBlocksElement : footerPlan.mode === "none" ? null : defaultFooterElement;
69241
69377
  } else if (typeof footer === "function") footerElement = footer(footerData);
@@ -69545,6 +69681,7 @@ const SUPPORTED_LOADER_ENDPOINTS$1 = [
69545
69681
  "listPublicRecurringSchedule",
69546
69682
  "getPublicEventDetails",
69547
69683
  "listPublicWholeSeriesOfferings",
69684
+ "getPublicWholeSeriesOffering",
69548
69685
  "listPublicRouteCandidates",
69549
69686
  "listPublicTeamMembers",
69550
69687
  "listPublicProducts",
@@ -71970,6 +72107,7 @@ const loaderAdapters = {
71970
72107
  listPublicEvents,
71971
72108
  listPublicRecurringSchedule,
71972
72109
  getPublicEventDetails,
72110
+ getPublicWholeSeriesOffering,
71973
72111
  listPublicRouteCandidates,
71974
72112
  listPublicTeamMembers,
71975
72113
  listPublicProducts,
@@ -72064,6 +72202,13 @@ async function listPublicEvents({ client, params }) {
72064
72202
  async function listPublicRecurringSchedule(input) {
72065
72203
  return projectRecurringSchedule(await listPublicEvents(input));
72066
72204
  }
72205
+ async function getPublicWholeSeriesOffering({ client, params }) {
72206
+ return await client.getPublicWholeSeriesOffering({
72207
+ siteId: requireStringParam(params, "siteId", "getPublicWholeSeriesOffering"),
72208
+ eventSeriesId: requireStringParam(params, "eventSeriesId", "getPublicWholeSeriesOffering"),
72209
+ stage: readStringParam(params, "stage")
72210
+ });
72211
+ }
72067
72212
  async function getPublicEventDetails({ client, params }) {
72068
72213
  return await client.getPublicEventDetails({
72069
72214
  siteId: requireStringParam(params, "siteId", "getPublicEventDetails"),