@riverbankcms/sdk 0.125.0 → 0.127.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 (177) hide show
  1. package/README.md +3 -1
  2. package/dist/{PreviewEditorSidebar-BezDOtQ7.mjs → PreviewEditorSidebar-BXtfF7tp.mjs} +122 -301
  3. package/dist/{PreviewEditorUI-CgSqmfo2.mjs → PreviewEditorUI-Dou73Q0K.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-BH-3-jSj.mjs → PreviewQueryProvider-DgFDIwvK.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-Co3AHfj0.mjs → SdkPreviewModeRuntime-B0HPXr-l.mjs} +141 -63
  6. package/dist/{SiteChromeCustomizeContext-BHF-KANn.mjs → SiteChromeCustomizeContext-DZiDBAYu.mjs} +5330 -5841
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +1552 -202
  8. package/dist/_dts/api/src/common/envelope.d.ts +1 -1
  9. package/dist/_dts/api/src/contentRuntime.d.ts +1 -7
  10. package/dist/_dts/api/src/endpoints.d.ts +0 -7
  11. package/dist/_dts/api/src/sdk-event-upsert.d.ts +42 -0
  12. package/dist/_dts/api/src/sdkContracts.d.ts +11 -9
  13. package/dist/_dts/api/src/siteOperations.d.ts +18 -1
  14. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +1 -14
  15. package/dist/_dts/block-form/src/backend/store-backend.d.ts +2 -1
  16. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +1 -0
  17. package/dist/_dts/blocks/src/index.d.ts +3 -2
  18. package/dist/_dts/blocks/src/lib/media.d.ts +267 -0
  19. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +0 -13
  20. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/useEventRegistrationStripeReturn.d.ts +15 -2
  21. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCollectionContract.d.ts +4 -4
  22. package/dist/_dts/blocks/src/system/runtime/nodes/mergeResolveImageUrlContexts.d.ts +7 -0
  23. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +2 -2
  24. package/dist/_dts/content-editor/src/ui/blockValidationManifestRegistry.d.ts +17 -0
  25. package/dist/_dts/content-editor/src/ui/blockValidationView.d.ts +1 -1
  26. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +4 -0
  27. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +322 -171
  28. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +4 -0
  29. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockValidationManifests.d.ts +26 -0
  30. package/dist/_dts/editor-blocks/src/widgets/rich-text/imageInsert.d.ts +3 -3
  31. package/dist/_dts/media-editor/src/MediaEditor.d.ts +2 -2
  32. package/dist/_dts/media-editor/src/context.d.ts +1 -2
  33. package/dist/_dts/media-editor/src/index.d.ts +3 -1
  34. package/dist/_dts/media-editor/src/mediaSelection.d.ts +32 -0
  35. package/dist/_dts/media-editor/src/types.d.ts +3 -1
  36. package/dist/_dts/media-editor/src/useMediaSelection.d.ts +26 -0
  37. package/dist/_dts/preview-next/src/client/index.d.ts +2 -0
  38. package/dist/_dts/preview-next/src/client/preview/HeaderMenuControls.d.ts +12 -0
  39. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +1 -2
  40. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +13 -3
  41. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +7 -2
  42. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +6 -60
  43. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +3 -13
  44. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +8 -100
  45. package/dist/_dts/preview-next/src/client/preview/headerInteractionPaletteSurfaceState.d.ts +8 -0
  46. package/dist/_dts/preview-next/src/client/preview/previewThemeRoles.d.ts +15 -0
  47. package/dist/_dts/preview-next/src/client/preview/siteChromeCustomizeTypes.d.ts +54 -0
  48. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +13 -3
  49. package/dist/_dts/preview-next/src/client/preview/siteChromeNavQuickControlHistory.d.ts +3 -0
  50. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +6 -3
  51. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +1 -4
  52. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -15
  53. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +11 -21
  54. package/dist/_dts/sdk/src/cli/commands/event.d.ts +2 -2
  55. package/dist/_dts/sdk/src/cli/commands/eventOccurrenceSchedule.d.ts +12 -0
  56. package/dist/_dts/sdk/src/cli/commands/push/pushAllExtras.d.ts +6 -0
  57. package/dist/_dts/sdk/src/cli/commands/style.d.ts +1 -1
  58. package/dist/_dts/sdk/src/cli/content/legacyEventScheduleShapeError.d.ts +5 -0
  59. package/dist/_dts/sdk/src/cli/content/localEventSchedule.d.ts +17 -0
  60. package/dist/_dts/sdk/src/cli/content/reader.d.ts +5 -10
  61. package/dist/_dts/sdk/src/cli/migrations/events.d.ts +1 -1
  62. package/dist/_dts/sdk/src/cli/site-commands/eventScheduleCompiler.d.ts +24 -0
  63. package/dist/_dts/sdk/src/client/management/http.d.ts +1 -1
  64. package/dist/_dts/sdk/src/client/management/types.d.ts +3 -28
  65. package/dist/_dts/sdk/src/config/index.d.ts +1 -1
  66. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -20
  67. package/dist/_dts/sdk/src/rendering/index.d.ts +1 -1
  68. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -2
  69. package/dist/_dts/sdk/src/version.d.ts +1 -1
  70. package/dist/_dts/site-commands/src/commandContract.d.ts +33 -5
  71. package/dist/_dts/site-commands/src/commandDomain.d.ts +2 -2
  72. package/dist/_dts/site-commands/src/commands.d.ts +38 -9
  73. package/dist/_dts/site-commands/src/siteStyleCommandSchema.d.ts +28 -1
  74. package/dist/_dts/site-commands/src/siteStyleSelectionSchemaBuilder.d.ts +4 -4
  75. package/dist/_dts/theme-core/src/buttons/effects/presets/background.d.ts +1 -1
  76. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +0 -18
  77. package/dist/_dts/theme-core/src/buttons/types.d.ts +1 -3
  78. package/dist/_dts/theme-core/src/header/containerSchema.d.ts +20 -0
  79. package/dist/_dts/theme-core/src/header/generateHeaderCss.d.ts +1 -1
  80. package/dist/_dts/theme-core/src/header/interactionPalette.d.ts +14 -0
  81. package/dist/_dts/theme-core/src/header/legacyNavLinkStyle.d.ts +3 -0
  82. package/dist/_dts/theme-core/src/header/paintTargets.d.ts +25 -0
  83. package/dist/_dts/theme-core/src/header/scrollTreatment.d.ts +11 -0
  84. package/dist/_dts/theme-core/src/header/surfaceRules.d.ts +9 -0
  85. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +15 -0
  86. package/dist/_dts/theme-core/src/palette/colors.d.ts +1 -1
  87. package/dist/_dts/theme-core/src/palette/concretePalette.d.ts +20 -0
  88. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +2 -17
  89. package/dist/_dts/theme-core/src/palette/index.d.ts +1 -6
  90. package/dist/_dts/theme-core/src/palette/schema.d.ts +39 -0
  91. package/dist/_dts/theme-core/src/schema.d.ts +105 -45
  92. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +3 -51
  93. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +4 -11
  94. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +3 -51
  95. package/dist/_dts/theme-core/src/site-styles/headerInteractionPalette.d.ts +32 -0
  96. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +19 -106
  97. package/dist/_dts/theme-core/src/site-styles/headerOpeningForeground.d.ts +22 -0
  98. package/dist/_dts/theme-core/src/site-styles/headerOpeningSection.d.ts +2 -0
  99. package/dist/_dts/theme-core/src/site-styles/headerStyleParts.d.ts +4 -0
  100. package/dist/_dts/theme-core/src/site-styles/index.d.ts +3 -0
  101. package/dist/_dts/theme-core/src/site-styles/lookOptionGroups.d.ts +24 -0
  102. package/dist/_dts/theme-core/src/site-styles/lookResolution.d.ts +1 -2
  103. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +4 -22
  104. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorOptions.d.ts +21 -0
  105. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +5 -7
  106. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +5 -6
  107. package/dist/_dts/theme-core/src/site-styles/siteChromeNavPreferences.d.ts +4 -1
  108. package/dist/cli/index.mjs +1583 -1601
  109. package/dist/cli/init-docs/content/cli-reference.md +6 -3
  110. package/dist/cli/init-docs/content/content-management.md +24 -13
  111. package/dist/client/{DiscountCodeDisclosure-CyPpekBp.mjs → DiscountCodeDisclosure-BDFRp8Y7.mjs} +1 -1
  112. package/dist/client/{EventCombined.client-zywit-60.mjs → EventCombined.client-DJgF1_lf.mjs} +2 -2
  113. package/dist/client/{EventListing.client-J2nLhkKT.mjs → EventListing.client-CnWGNjOr.mjs} +2 -2
  114. package/dist/client/{LeafletStaticMap-CSubXWt6.mjs → LeafletStaticMap-BISs9Bl7.mjs} +1 -1
  115. package/dist/client/{MagicLinkForm-DDLIfiq9.mjs → MagicLinkForm-b5E_HoG9.mjs} +1 -1
  116. package/dist/client/{StepIndicator-DE8EvHIp.mjs → StepIndicator-D8gVYkK-.mjs} +2 -2
  117. package/dist/client/{accordion-Ct5T5NiA.mjs → accordion-DFDajgDz.mjs} +1 -1
  118. package/dist/client/{bookingForm-DMxtLPxw.mjs → bookingForm-Bdqj9-52.mjs} +5 -6
  119. package/dist/client/bookings.mjs +315 -46
  120. package/dist/client/{carousel--FMqgvob.mjs → carousel-Cvqf-kN8.mjs} +1 -1
  121. package/dist/client/{cart-BKX1bWiU.mjs → cart-CuH2TJXP.mjs} +3 -3
  122. package/dist/client/{checkout-B_jxi4WW.mjs → checkout-CMNPpejZ.mjs} +3 -3
  123. package/dist/client/client.mjs +1381 -1427
  124. package/dist/client/{courseRegistration-DH4MlkRD.mjs → courseRegistration-DTEYWL6Z.mjs} +6 -7
  125. package/dist/client/{eventCalendar-BQILwAcL.mjs → eventCalendar-BW-XoxZ0.mjs} +4 -4
  126. package/dist/client/{eventCombined-DFFW_Vmo.mjs → eventCombined-Bpn7s0y9.mjs} +2 -2
  127. package/dist/client/{eventDetails-B045CTSJ.mjs → eventDetails-D2uUSTMH.mjs} +3 -3
  128. package/dist/client/{eventListing-BDMYNVzS.mjs → eventListing-CVr1c094.mjs} +2 -2
  129. package/dist/client/{eventRegistration-CQ2-BSnB.mjs → eventRegistration-Dv4AvkMw.mjs} +30 -22
  130. package/dist/client/{form-DJKuyZgN.mjs → form-DxdKf9fs.mjs} +1 -1
  131. package/dist/client/{headerSection-DeTjfiDo.mjs → headerSection-BaXI5Sro.mjs} +2 -2
  132. package/dist/client/hooks.mjs +851 -976
  133. package/dist/client/{locationMap-i2wDA8gB.mjs → locationMap-BEtW2fKz.mjs} +2 -2
  134. package/dist/client/{newsletterForm-DKiueauk.mjs → newsletterForm-BKKs0S4R.mjs} +1 -1
  135. package/dist/client/{pricing-C01J3Epx.mjs → pricing-ClkqcElA.mjs} +1 -1
  136. package/dist/client/{productDetail-Dfc1sZaX.mjs → productDetail-H-ru8dyy.mjs} +3 -3
  137. package/dist/client/{productList-BXbvXWTF.mjs → productList-Buyi5c0C.mjs} +3 -3
  138. package/dist/client/{propsDecoder-CIR5DQ1l.mjs → propsDecoder-BF7i6Ijg.mjs} +293 -65
  139. package/dist/client/rendering/client.mjs +1145 -1190
  140. package/dist/client/rendering/islands.mjs +18 -18
  141. package/dist/client/rendering.mjs +1257 -1298
  142. package/dist/client/{useDiscountCodeUi-Bcyh4508.mjs → scrollToBlock-D_7t8yWb.mjs} +18 -2
  143. package/dist/client/{shop-BbNwPKM-.mjs → shop-CF7SZQNX.mjs} +5 -6
  144. package/dist/client/{shop-commerce-XO-XMFEt.mjs → shop-commerce-DA7_Rq5p.mjs} +4 -4
  145. package/dist/client/{shop-commerce-store-Byh6OUGK.mjs → shop-commerce-store-BmLqW7Gh.mjs} +1 -1
  146. package/dist/client/{shopShared-Bbq39mwr.mjs → shopShared-WL-E1znM.mjs} +2 -2
  147. package/dist/client/{useEventFilters-C8OOJ3el.mjs → useEventFilters-rc8VLeLV.mjs} +2 -2
  148. package/dist/client/{usePolling-CyJVo9kF.mjs → usePolling-1ncrfd4S.mjs} +2 -2
  149. package/dist/preview-next/before-render.mjs +0 -7
  150. package/dist/preview-next/client/runtime.mjs +4 -4
  151. package/dist/preview-next/middleware.mjs +0 -7
  152. package/dist/{previewAuthStore-CJX21dGi.mjs → previewAuthStore-Dev9CdG9.mjs} +0 -7
  153. package/dist/{sdk-runtime-BGhyuE-E.mjs → sdk-runtime-BnrCCFJq.mjs} +2 -2
  154. package/dist/{separator-BFs-Kmv5.mjs → separator-CFvBx2yl.mjs} +1 -1
  155. package/dist/server/components.mjs +1389 -1489
  156. package/dist/server/config-validation.mjs +851 -976
  157. package/dist/server/config.mjs +851 -976
  158. package/dist/server/data.mjs +851 -976
  159. package/dist/server/index.mjs +1 -8
  160. package/dist/server/next.mjs +1393 -1500
  161. package/dist/server/page-converter.mjs +851 -976
  162. package/dist/server/prebuild.mjs +1 -1
  163. package/dist/server/rendering/server.mjs +1346 -1446
  164. package/dist/server/rendering.mjs +1390 -1490
  165. package/dist/server/routing.mjs +939 -1041
  166. package/dist/server/server.mjs +852 -984
  167. package/dist/server/theme-bridge.mjs +322 -279
  168. package/dist/server/theme.mjs +277 -33
  169. package/package.json +1 -1
  170. package/dist/_dts/editor-blocks/src/widgets/rich-text/ensureRichTextImageAssetIdentifier.d.ts +0 -8
  171. package/dist/_dts/theme-core/src/palette/editorState.d.ts +0 -75
  172. package/dist/_dts/theme-core/src/palette/libraryModel.d.ts +0 -64
  173. package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +0 -81
  174. package/dist/_dts/theme-core/src/palette/resolveSelection.d.ts +0 -75
  175. package/dist/_dts/theme-core/src/palette/selection.d.ts +0 -74
  176. package/dist/_dts/theme-core/src/palette/sitePalettePersistence.d.ts +0 -34
  177. package/dist/client/scrollToBlock-C86BYkyV.mjs +0 -17
@@ -3066,6 +3066,101 @@ function isRichTextDoc(value) {
3066
3066
  return RichTextDocSchema.safeParse(value).success;
3067
3067
  }
3068
3068
  //#endregion
3069
+ //#region ../blocks/src/lib/media.ts
3070
+ const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
3071
+ "document",
3072
+ "spreadsheet",
3073
+ "archive",
3074
+ "audio"
3075
+ ];
3076
+ const hotspotSchema$1 = z.object({
3077
+ x: z.number().min(0).max(1),
3078
+ y: z.number().min(0).max(1),
3079
+ radius: z.number().optional()
3080
+ });
3081
+ const rotationSchema$1 = z.union([
3082
+ z.literal(0),
3083
+ z.literal(90),
3084
+ z.literal(180),
3085
+ z.literal(270)
3086
+ ]);
3087
+ const rectSchema$1 = z.tuple([
3088
+ z.number(),
3089
+ z.number(),
3090
+ z.number(),
3091
+ z.number()
3092
+ ]);
3093
+ const aspectCropSchema$1 = z.object({
3094
+ aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
3095
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
3096
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
3097
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
3098
+ });
3099
+ const transformSchema$1 = z.object({
3100
+ aspectCrops: z.preprocess((value) => {
3101
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
3102
+ return value;
3103
+ }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
3104
+ rect: rectSchema$1.optional(),
3105
+ hotspot: hotspotSchema$1.optional(),
3106
+ rotation: rotationSchema$1.optional()
3107
+ });
3108
+ const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
3109
+ tag: z.literal("storage"),
3110
+ assetId: z.string().optional(),
3111
+ storageBucket: z.string().min(1),
3112
+ storagePath: z.string().min(1)
3113
+ }), z.object({
3114
+ tag: z.literal("external-src"),
3115
+ assetId: z.string().optional(),
3116
+ src: z.string().url()
3117
+ })]);
3118
+ const mediaBaseSchema = z.object({
3119
+ purpose: z.string().optional(),
3120
+ placeholder: z.boolean().default(true).optional(),
3121
+ assetId: z.string().optional(),
3122
+ identifier: z.string().optional(),
3123
+ src: z.string().optional(),
3124
+ alt: z.string().optional(),
3125
+ filename: z.string().optional(),
3126
+ mimeType: z.string().optional(),
3127
+ width: z.number().optional(),
3128
+ height: z.number().optional(),
3129
+ storageBucket: z.string().optional(),
3130
+ storagePath: z.string().optional(),
3131
+ poster: mediaPosterSchema.optional(),
3132
+ transform: transformSchema$1.optional()
3133
+ });
3134
+ /**
3135
+ * Canonical identifier carried by media values that are safe to persist.
3136
+ * Parsing trims boundary input so downstream writers cannot retain whitespace-only
3137
+ * identifiers or independently disagree about normalization.
3138
+ */
3139
+ const mediaIdentifierSchema = z.string().trim().min(1).brand();
3140
+ const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
3141
+ const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
3142
+ const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
3143
+ const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
3144
+ const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
3145
+ const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
3146
+ const mediaSchema$1 = z.discriminatedUnion("type", [
3147
+ imageMediaSchema,
3148
+ videoMediaSchema,
3149
+ audioMediaSchema,
3150
+ documentMediaSchema,
3151
+ spreadsheetMediaSchema,
3152
+ archiveMediaSchema
3153
+ ]);
3154
+ const persistableMediaBaseSchema = mediaBaseSchema.extend({ identifier: mediaIdentifierSchema });
3155
+ z.discriminatedUnion("type", [
3156
+ persistableMediaBaseSchema.extend({ type: z.literal("image") }),
3157
+ persistableMediaBaseSchema.extend({ type: z.literal("video") }),
3158
+ persistableMediaBaseSchema.extend({ type: z.literal("audio") }),
3159
+ persistableMediaBaseSchema.extend({ type: z.literal("document") }),
3160
+ persistableMediaBaseSchema.extend({ type: z.literal("spreadsheet") }),
3161
+ persistableMediaBaseSchema.extend({ type: z.literal("archive") })
3162
+ ]);
3163
+ //#endregion
3069
3164
  //#region ../blocks/src/system/manifest/fieldValidation/index.ts
3070
3165
  const TEL_RE = /^[+()0-9\s-]{3,}$/;
3071
3166
  const SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
@@ -3396,7 +3491,7 @@ function normalizeObjectChildren(children, value, ctx) {
3396
3491
  function normalizeInlineTextFallbacks(plans, values, ctx) {
3397
3492
  for (const plan of plans) {
3398
3493
  if (plan.kind !== "inlineText" || !plan.plainTextFallbackPath) continue;
3399
- if (!isMissingForPlan(plan, values[plan.fieldId])) continue;
3494
+ if (!isMissingForPlan(plan, values[plan.fieldId]) && !(ctx.allowIncomplete && !parseInlineTextFromUnknown(values[plan.fieldId]).ok)) continue;
3400
3495
  const fallback = getAtFieldPath(values, plan.plainTextFallbackPath);
3401
3496
  if (typeof fallback !== "string" || fallback.trim().length === 0) continue;
3402
3497
  values[plan.fieldId] = normalizeFieldValue(plan, plainTextToInlineText(fallback), ctx);
@@ -3437,7 +3532,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
3437
3532
  case "select": return validateSelectPlan(plan, value);
3438
3533
  case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
3439
3534
  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")];
3535
+ 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
3536
  case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
3442
3537
  case "repeater": return validateRepeaterPlan(plan, value, ctx);
3443
3538
  case "group": return validateGroupPlan(plan, value, ctx);
@@ -4070,6 +4165,17 @@ function isOnColorBackgroundCandidateToken(token) {
4070
4165
  return BACKGROUND_ROLE_NAMES.has(role);
4071
4166
  }
4072
4167
  //#endregion
4168
+ //#region ../theme-core/src/site-styles/lookOptionGroups.ts
4169
+ function defineLookOptionGroup(group) {
4170
+ defaultOption(group);
4171
+ return group;
4172
+ }
4173
+ function defaultOption(group) {
4174
+ const option = group.options.find((candidate) => candidate.id === group.defaultOptionId);
4175
+ if (option) return option;
4176
+ throw new Error(`Look option group "${group.id}" defaults to missing option "${group.defaultOptionId}".`);
4177
+ }
4178
+ //#endregion
4073
4179
  //#region ../theme-core/src/site-styles/types.ts
4074
4180
  /**
4075
4181
  * Defines a literal-preserving catalog while rejecting top-level extra keys on
@@ -4215,767 +4321,655 @@ function defineBlockDesignCapability(capability) {
4215
4321
  //#region ../theme-core/src/site-styles/appearancePresetResolution.ts
4216
4322
  function assertValidOptionGroups(preset) {
4217
4323
  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}".`);
4324
+ defineLookOptionGroup(group);
4219
4325
  });
4220
4326
  }
4221
4327
  function defineBlockAppearancePreset(preset) {
4222
4328
  assertValidOptionGroups(preset);
4223
4329
  return preset;
4224
4330
  }
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" }
4331
+ //#endregion
4332
+ //#region ../theme-core/src/site-styles/blockAppearancePresets.ts
4333
+ const brandScrimOptionGroups = [{
4334
+ id: "image-surface-treatment",
4335
+ label: "Treatment",
4336
+ defaultOptionId: "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
+ const microBannerLayoutPatches = [{
4351
+ constraints: { layoutVariantKeys: ["micro"] },
4352
+ designPatch: { sectionHeight: "banner" }
4353
+ }];
4354
+ defineBlockAppearancePreset({
4355
+ id: "hero-immersive-image",
4356
+ target: "hero",
4357
+ label: "Immersive image hero",
4358
+ blockKinds: ["block.hero"],
4359
+ constraints: { layoutFamilies: ["centered", "compact"] },
4360
+ layoutPatches: [{
4361
+ constraints: { layoutVariantKeys: ["micro"] },
4362
+ designPatch: {
4363
+ sectionHeight: "banner",
4364
+ heroTypographyScale: "display"
4248
4365
  }
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: {
4366
+ }],
4367
+ design: {
4368
+ sectionSurface: "hero-image",
4369
+ contentFrame: plainFrame,
4370
+ itemSurface: "none",
4371
+ sectionHeight: "hero",
4372
+ heroComposition: "center",
4373
+ heroTypographyScale: "display",
4374
+ imageSurfaceTreatment: { kind: "neutral-wash" }
4375
+ }
4376
+ }), defineBlockAppearancePreset({
4377
+ id: "hero-bottom-left-panel",
4378
+ target: "hero",
4379
+ label: "Bottom-left panel hero",
4380
+ blockKinds: ["block.hero"],
4381
+ constraints: { layoutFamilies: ["centered", "compact"] },
4382
+ optionGroups: [{
4383
+ id: "image-surface-treatment",
4384
+ label: "Treatment",
4385
+ defaultOptionId: "neutral-scrim",
4386
+ options: [{
4387
+ id: "neutral-scrim",
4388
+ label: "Neutral scrim",
4389
+ designPatch: { imageSurfaceTreatment: {
4293
4390
  kind: "neutral-scrim",
4294
4391
  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: {
4392
+ } }
4393
+ }, {
4394
+ id: "brand-scrim-primary",
4395
+ label: "Brand scrim",
4396
+ designPatch: { imageSurfaceTreatment: {
4320
4397
  kind: "brand-scrim",
4321
4398
  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",
4399
+ intensity: "balanced"
4400
+ } }
4401
+ }]
4402
+ }],
4403
+ layoutPatches: [{
4404
+ constraints: { layoutVariantKeys: ["micro"] },
4405
+ designPatch: {
4406
+ sectionHeight: "banner",
4451
4407
  heroTypographyScale: "editorial"
4452
4408
  }
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"
4409
+ }],
4410
+ design: {
4411
+ sectionSurface: "hero-image",
4412
+ contentFrame: panelFrame("raised"),
4413
+ itemSurface: "none",
4414
+ sectionHeight: "immersive",
4415
+ heroComposition: "bottom-left",
4416
+ heroTypographyScale: "display",
4417
+ imageSurfaceTreatment: {
4418
+ kind: "neutral-scrim",
4419
+ intensity: "balanced"
4481
4420
  }
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",
4421
+ }
4422
+ }), defineBlockAppearancePreset({
4423
+ id: "hero-poster-image",
4424
+ target: "hero",
4425
+ label: "Poster image hero",
4426
+ blockKinds: ["block.hero"],
4427
+ constraints: { layoutFamilies: ["centered", "compact"] },
4428
+ layoutPatches: [{
4429
+ constraints: { layoutVariantKeys: ["micro"] },
4430
+ designPatch: {
4431
+ sectionHeight: "banner",
4494
4432
  heroTypographyScale: "display"
4495
4433
  }
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"
4434
+ }],
4435
+ design: {
4436
+ sectionSurface: "hero-image",
4437
+ contentFrame: plainFrame,
4438
+ itemSurface: "none",
4439
+ sectionHeight: "immersive",
4440
+ heroComposition: "center",
4441
+ heroTypographyScale: "poster",
4442
+ imageSurfaceTreatment: {
4443
+ kind: "brand-scrim",
4444
+ token: "primary",
4445
+ intensity: "strong"
4914
4446
  }
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"
4447
+ }
4448
+ }), defineBlockAppearancePreset({
4449
+ id: "hero-brand-scrim",
4450
+ target: "hero",
4451
+ label: "Brand scrim image hero",
4452
+ blockKinds: ["block.hero"],
4453
+ constraints: { layoutFamilies: ["centered", "compact"] },
4454
+ optionGroups: brandScrimOptionGroups,
4455
+ layoutPatches: microBannerLayoutPatches,
4456
+ design: {
4457
+ sectionSurface: "hero-image",
4458
+ contentFrame: plainFrame,
4459
+ itemSurface: "none",
4460
+ sectionHeight: "immersive",
4461
+ heroComposition: "center",
4462
+ heroTypographyScale: "display",
4463
+ imageSurfaceTreatment: {
4464
+ kind: "brand-scrim",
4465
+ token: "primary"
4927
4466
  }
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"
4467
+ }
4468
+ }), defineBlockAppearancePreset({
4469
+ id: "hero-brand-scrim-fixed-frame",
4470
+ target: "hero",
4471
+ label: "Fixed-frame brand scrim hero",
4472
+ blockKinds: ["block.hero"],
4473
+ constraints: { layoutFamilies: ["centered", "compact"] },
4474
+ optionGroups: brandScrimOptionGroups,
4475
+ layoutPatches: microBannerLayoutPatches,
4476
+ design: {
4477
+ sectionSurface: "hero-image",
4478
+ contentFrame: plainFrame,
4479
+ itemSurface: "none",
4480
+ sectionHeight: "immersive",
4481
+ heroComposition: "center",
4482
+ heroTypographyScale: "display",
4483
+ imageSurfaceTreatment: {
4484
+ kind: "brand-scrim",
4485
+ token: "primary"
4486
+ },
4487
+ imageSurfaceMotion: "fixed-frame",
4488
+ eyebrowTreatment: "accent-pill-bounce"
4489
+ }
4490
+ }), defineBlockAppearancePreset({
4491
+ id: "hero-brand-depth-expressive",
4492
+ target: "hero",
4493
+ label: "Expressive brand-depth hero",
4494
+ blockKinds: ["block.hero"],
4495
+ constraints: { layoutFamilies: ["centered", "compact"] },
4496
+ design: {
4497
+ sectionSurface: "brand-depth-band",
4498
+ contentFrame: plainFrame,
4499
+ itemSurface: "none",
4500
+ heroComposition: "center",
4501
+ heroTypographyScale: "editorial",
4502
+ eyebrowTreatment: "accent-pill-bounce"
4503
+ }
4504
+ }), defineBlockAppearancePreset({
4505
+ id: "hero-contained-intro",
4506
+ target: "hero",
4507
+ label: "Contained intro hero",
4508
+ blockKinds: ["block.hero"],
4509
+ design: {
4510
+ sectionSurface: "muted-band",
4511
+ contentFrame: panelFrame("inset"),
4512
+ itemSurface: "none",
4513
+ heroComposition: "center",
4514
+ heroTypographyScale: "editorial"
4515
+ }
4516
+ }), defineBlockAppearancePreset({
4517
+ id: "hero-split-editorial",
4518
+ target: "hero",
4519
+ label: "Editorial split hero",
4520
+ blockKinds: ["block.hero"],
4521
+ constraints: { layoutFamilies: ["split"] },
4522
+ design: {
4523
+ sectionSurface: "base",
4524
+ contentFrame: plainFrame,
4525
+ itemSurface: "none",
4526
+ heroTypographyScale: "editorial"
4527
+ }
4528
+ }), defineBlockAppearancePreset({
4529
+ id: "hero-split-brand",
4530
+ target: "hero",
4531
+ label: "Brand split hero",
4532
+ blockKinds: ["block.hero"],
4533
+ constraints: { layoutFamilies: ["split"] },
4534
+ design: {
4535
+ sectionSurface: "brand-depth-band",
4536
+ contentFrame: plainFrame,
4537
+ itemSurface: "none",
4538
+ heroTypographyScale: "display",
4539
+ eyebrowTreatment: "accent-pill-bounce"
4540
+ }
4541
+ }), defineBlockAppearancePreset({
4542
+ id: "hero-split-soft-panel",
4543
+ target: "hero",
4544
+ label: "Soft panel split hero",
4545
+ blockKinds: ["block.hero"],
4546
+ constraints: { layoutFamilies: ["split"] },
4547
+ design: {
4548
+ sectionSurface: "muted-band",
4549
+ contentFrame: panelFrame("raised"),
4550
+ itemSurface: "none",
4551
+ heroTypographyScale: "editorial"
4552
+ }
4553
+ }), defineBlockAppearancePreset({
4554
+ id: "hero-split-accent",
4555
+ target: "hero",
4556
+ label: "Accent split hero",
4557
+ blockKinds: ["block.hero"],
4558
+ constraints: { layoutFamilies: ["split"] },
4559
+ design: {
4560
+ sectionSurface: "accent-band",
4561
+ contentFrame: panelFrame("raised"),
4562
+ itemSurface: "none",
4563
+ heroTypographyScale: "display"
4564
+ }
4565
+ }), defineBlockAppearancePreset({
4566
+ id: "intro-editorial-statement",
4567
+ target: "intro",
4568
+ label: "Editorial intro statement",
4569
+ blockKinds: ["block.intro"],
4570
+ constraints: { layoutVariantKeys: ["centered-copy", "statement-copy"] },
4571
+ design: {
4572
+ sectionSurface: "base",
4573
+ contentFrame: plainFrame,
4574
+ itemSurface: "none",
4575
+ composition: {
4576
+ kind: "intro",
4577
+ treatment: "editorial-statement"
4939
4578
  }
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"
4579
+ }
4580
+ }), defineBlockAppearancePreset({
4581
+ id: "intro-portrait-bio",
4582
+ target: "intro",
4583
+ label: "Portrait and bio",
4584
+ blockKinds: ["block.intro"],
4585
+ constraints: { layoutVariantKeys: ["media-copy"] },
4586
+ design: {
4587
+ sectionSurface: "base",
4588
+ contentFrame: plainFrame,
4589
+ itemSurface: "none",
4590
+ composition: {
4591
+ kind: "intro",
4592
+ treatment: "portrait-bio"
4951
4593
  }
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"
4594
+ }
4595
+ }), defineBlockAppearancePreset({
4596
+ id: "offerings-preview-default-cards",
4597
+ target: "offerings",
4598
+ label: "Default offering cards",
4599
+ blockKinds: ["block.offerings-preview"],
4600
+ design: {
4601
+ sectionSurface: "base",
4602
+ contentFrame: plainFrame,
4603
+ itemSurface: "default"
4604
+ }
4605
+ }), defineBlockAppearancePreset({
4606
+ id: "offerings-preview-secondary-cards",
4607
+ target: "offerings",
4608
+ label: "Secondary offering cards",
4609
+ blockKinds: ["block.offerings-preview"],
4610
+ design: {
4611
+ sectionSurface: "muted-band",
4612
+ contentFrame: plainFrame,
4613
+ itemSurface: "inset"
4614
+ }
4615
+ }), defineBlockAppearancePreset({
4616
+ id: "offerings-preview-non-carded",
4617
+ target: "offerings",
4618
+ label: "Non-carded offerings",
4619
+ blockKinds: ["block.offerings-preview"],
4620
+ design: {
4621
+ sectionSurface: "muted-band",
4622
+ contentFrame: plainFrame,
4623
+ itemSurface: "editorial"
4624
+ }
4625
+ }), defineBlockAppearancePreset({
4626
+ id: "offerings-preview-paired-feature-cards",
4627
+ target: "offerings",
4628
+ label: "Paired feature cards",
4629
+ blockKinds: ["block.offerings-preview"],
4630
+ constraints: { layoutVariantKeys: ["cards"] },
4631
+ design: {
4632
+ sectionSurface: "base",
4633
+ contentFrame: plainFrame,
4634
+ itemSurface: "none"
4635
+ }
4636
+ }), defineBlockAppearancePreset({
4637
+ id: "offerings-preview-open-editorial-columns",
4638
+ target: "offerings",
4639
+ label: "Open editorial columns",
4640
+ blockKinds: ["block.offerings-preview"],
4641
+ constraints: { layoutVariantKeys: ["cards"] },
4642
+ design: {
4643
+ sectionSurface: "base",
4644
+ contentFrame: plainFrame,
4645
+ itemSurface: "none"
4646
+ }
4647
+ }), defineBlockAppearancePreset({
4648
+ id: "offerings-preview-joined-programme-panel",
4649
+ target: "offerings",
4650
+ label: "Joined programme panel",
4651
+ blockKinds: ["block.offerings-preview"],
4652
+ constraints: { layoutVariantKeys: ["cards"] },
4653
+ design: {
4654
+ sectionSurface: "base",
4655
+ contentFrame: plainFrame,
4656
+ itemSurface: "none"
4657
+ }
4658
+ }), defineBlockAppearancePreset({
4659
+ id: "feature-cards-raised-rule",
4660
+ target: "feature-cards",
4661
+ label: "Raised cards with rule",
4662
+ blockKinds: ["block.feature-cards"],
4663
+ design: {
4664
+ sectionSurface: "base",
4665
+ contentFrame: plainFrame,
4666
+ itemSurface: "raised"
4667
+ }
4668
+ }), defineBlockAppearancePreset({
4669
+ id: "feature-cards-bold-colors",
4670
+ target: "feature-cards",
4671
+ label: "Bold colour-blocked cards",
4672
+ blockKinds: ["block.feature-cards"],
4673
+ design: {
4674
+ sectionSurface: "base",
4675
+ contentFrame: plainFrame,
4676
+ itemSurface: "color-blocked"
4677
+ }
4678
+ }), defineBlockAppearancePreset({
4679
+ id: "feature-cards-editorial-columns",
4680
+ target: "feature-cards",
4681
+ label: "Editorial open columns",
4682
+ blockKinds: ["block.feature-cards"],
4683
+ design: {
4684
+ sectionSurface: "base",
4685
+ contentFrame: plainFrame,
4686
+ itemSurface: "editorial"
4687
+ }
4688
+ }), defineBlockAppearancePreset({
4689
+ id: "feature-cards-asymmetric-emphasis",
4690
+ target: "feature-cards",
4691
+ label: "Asymmetric emphasis pair",
4692
+ blockKinds: ["block.feature-cards"],
4693
+ constraints: { layoutFamilies: ["grid"] },
4694
+ design: {
4695
+ sectionSurface: "base",
4696
+ contentFrame: plainFrame,
4697
+ itemSurface: "none",
4698
+ composition: {
4699
+ kind: "feature-cards",
4700
+ treatment: "asymmetric-emphasis"
4963
4701
  }
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"
4702
+ }
4703
+ }), defineBlockAppearancePreset({
4704
+ id: "feature-cards-framed-programme",
4705
+ target: "feature-cards",
4706
+ label: "Framed programme cards",
4707
+ blockKinds: ["block.feature-cards"],
4708
+ constraints: { layoutFamilies: ["grid"] },
4709
+ design: {
4710
+ sectionSurface: "brand-depth-band",
4711
+ contentFrame: plainFrame,
4712
+ itemSurface: "inset",
4713
+ composition: {
4714
+ kind: "feature-cards",
4715
+ treatment: "framed-programme"
4976
4716
  }
4977
- })
4978
- ]];
4717
+ }
4718
+ }), defineBlockAppearancePreset({
4719
+ id: "feature-cards-soft-panels",
4720
+ target: "feature-cards",
4721
+ label: "Soft tinted panels",
4722
+ blockKinds: ["block.feature-cards"],
4723
+ design: {
4724
+ sectionSurface: "base",
4725
+ contentFrame: plainFrame,
4726
+ itemSurface: "inset"
4727
+ }
4728
+ }), defineBlockAppearancePreset({
4729
+ id: "feature-cards-editorial-diptych",
4730
+ target: "feature-cards",
4731
+ label: "Editorial diptych",
4732
+ blockKinds: ["block.feature-cards"],
4733
+ constraints: { layoutVariantKeys: ["editorial-diptych"] },
4734
+ design: {
4735
+ sectionSurface: "base",
4736
+ contentFrame: plainFrame,
4737
+ itemSurface: "flat"
4738
+ }
4739
+ }), defineBlockAppearancePreset({
4740
+ id: "feature-cards-editorial-pathways",
4741
+ target: "feature-cards",
4742
+ label: "Editorial pathways",
4743
+ blockKinds: ["block.feature-cards"],
4744
+ constraints: { layoutVariantKeys: ["editorial-pathways"] },
4745
+ design: {
4746
+ sectionSurface: "base",
4747
+ contentFrame: plainFrame,
4748
+ itemSurface: "flat"
4749
+ }
4750
+ }), defineBlockAppearancePreset({
4751
+ id: "feature-cards-photo-tiles",
4752
+ target: "feature-cards",
4753
+ label: "Photo tiles",
4754
+ blockKinds: ["block.feature-cards"],
4755
+ design: {
4756
+ sectionSurface: "base",
4757
+ contentFrame: plainFrame,
4758
+ itemSurface: "raised"
4759
+ }
4760
+ }), defineBlockAppearancePreset({
4761
+ id: "events-lined-panel",
4762
+ target: "events",
4763
+ label: "Raised event panel",
4764
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4765
+ design: {
4766
+ sectionSurface: "base",
4767
+ contentFrame: panelFrame("raised"),
4768
+ itemSurface: "none"
4769
+ }
4770
+ }), defineBlockAppearancePreset({
4771
+ id: "events-ruled-register",
4772
+ target: "events",
4773
+ label: "Ruled event register",
4774
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4775
+ design: {
4776
+ sectionSurface: "brand-depth-band",
4777
+ contentFrame: plainFrame,
4778
+ itemSurface: "none",
4779
+ eventListTreatment: "ruled-register"
4780
+ }
4781
+ }), defineBlockAppearancePreset({
4782
+ id: "events-editorial-register",
4783
+ target: "events",
4784
+ label: "Editorial event register",
4785
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4786
+ design: {
4787
+ sectionSurface: "base",
4788
+ contentFrame: plainFrame,
4789
+ itemSurface: "none",
4790
+ eventListTreatment: "editorial-register"
4791
+ }
4792
+ }), defineBlockAppearancePreset({
4793
+ id: "events-dense-index",
4794
+ target: "events",
4795
+ label: "Dense event index",
4796
+ blockKinds: ["block.event-calendar", "block.event-listing"],
4797
+ design: {
4798
+ sectionSurface: "accent-band",
4799
+ contentFrame: plainFrame,
4800
+ itemSurface: "none",
4801
+ eventListTreatment: "dense-index"
4802
+ }
4803
+ }), defineBlockAppearancePreset({
4804
+ id: "schedule-details-brand-depth",
4805
+ target: "events",
4806
+ label: "Brand-depth schedule details",
4807
+ blockKinds: ["block.event-details", "block.course-details"],
4808
+ design: {
4809
+ sectionSurface: "brand-depth-band",
4810
+ contentFrame: plainFrame,
4811
+ itemSurface: "none",
4812
+ tileTreatment: "brand-depth"
4813
+ }
4814
+ }), defineBlockAppearancePreset({
4815
+ id: "media-text-flush-feature",
4816
+ target: "media-text",
4817
+ label: "Flush media feature",
4818
+ blockKinds: ["block.media-text"],
4819
+ design: {
4820
+ sectionSurface: "muted-band",
4821
+ contentFrame: flushPanelFrame({ bleed: "start" }),
4822
+ itemSurface: "none"
4823
+ }
4824
+ }), defineBlockAppearancePreset({
4825
+ id: "testimonials-simple-cards",
4826
+ target: "testimonials",
4827
+ label: "Simple testimonial cards",
4828
+ blockKinds: ["block.testimonials"],
4829
+ design: {
4830
+ sectionSurface: "base",
4831
+ contentFrame: plainFrame,
4832
+ itemSurface: "default"
4833
+ }
4834
+ }), defineBlockAppearancePreset({
4835
+ id: "testimonials-raised-panel",
4836
+ target: "testimonials",
4837
+ label: "Raised testimonial panel",
4838
+ blockKinds: ["block.testimonials"],
4839
+ design: {
4840
+ sectionSurface: "muted-band",
4841
+ contentFrame: panelFrame("raised"),
4842
+ itemSurface: "raised"
4843
+ }
4844
+ }), defineBlockAppearancePreset({
4845
+ id: "testimonials-accent-panel",
4846
+ target: "testimonials",
4847
+ label: "Accent testimonial panel",
4848
+ blockKinds: ["block.testimonials"],
4849
+ design: {
4850
+ sectionSurface: "accent-band",
4851
+ contentFrame: panelFrame("raised"),
4852
+ itemSurface: "raised"
4853
+ }
4854
+ }), defineBlockAppearancePreset({
4855
+ id: "testimonials-default-cards",
4856
+ target: "testimonials",
4857
+ label: "Default cards",
4858
+ blockKinds: ["block.testimonials"],
4859
+ design: {
4860
+ sectionSurface: "base",
4861
+ contentFrame: plainFrame,
4862
+ itemSurface: "none",
4863
+ testimonialCardTreatment: "default"
4864
+ }
4865
+ }), defineBlockAppearancePreset({
4866
+ id: "testimonials-statement-cards",
4867
+ target: "testimonials",
4868
+ label: "Statement cards",
4869
+ blockKinds: ["block.testimonials"],
4870
+ design: {
4871
+ sectionSurface: "accent-band",
4872
+ contentFrame: plainFrame,
4873
+ itemSurface: "raised",
4874
+ testimonialCardTreatment: "statement"
4875
+ }
4876
+ }), defineBlockAppearancePreset({
4877
+ id: "testimonials-brand-statement-cards",
4878
+ target: "testimonials",
4879
+ label: "Brand statement cards",
4880
+ blockKinds: ["block.testimonials"],
4881
+ design: {
4882
+ sectionSurface: "brand-depth-band",
4883
+ contentFrame: plainFrame,
4884
+ itemSurface: "raised",
4885
+ testimonialCardTreatment: "statement"
4886
+ }
4887
+ }), defineBlockAppearancePreset({
4888
+ id: "testimonials-non-carded",
4889
+ target: "testimonials",
4890
+ label: "Non-carded",
4891
+ blockKinds: ["block.testimonials"],
4892
+ design: {
4893
+ sectionSurface: "muted-band",
4894
+ contentFrame: plainFrame,
4895
+ itemSurface: "none",
4896
+ testimonialCardTreatment: "non-carded"
4897
+ }
4898
+ }), defineBlockAppearancePreset({
4899
+ id: "testimonials-evergreen-lead",
4900
+ target: "testimonials",
4901
+ label: "Evergreen lead",
4902
+ blockKinds: ["block.testimonials"],
4903
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4904
+ design: {
4905
+ sectionSurface: "base",
4906
+ contentFrame: plainFrame,
4907
+ itemSurface: "none"
4908
+ }
4909
+ }), defineBlockAppearancePreset({
4910
+ id: "testimonials-room-and-response",
4911
+ target: "testimonials",
4912
+ label: "Room and response",
4913
+ blockKinds: ["block.testimonials"],
4914
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4915
+ design: {
4916
+ sectionSurface: "base",
4917
+ contentFrame: plainFrame,
4918
+ itemSurface: "none"
4919
+ }
4920
+ }), defineBlockAppearancePreset({
4921
+ id: "testimonials-open-floor",
4922
+ target: "testimonials",
4923
+ label: "Open floor",
4924
+ blockKinds: ["block.testimonials"],
4925
+ constraints: { layoutVariantKeys: ["featured-editorial"] },
4926
+ design: {
4927
+ sectionSurface: "base",
4928
+ contentFrame: plainFrame,
4929
+ itemSurface: "none"
4930
+ }
4931
+ }), defineBlockAppearancePreset({
4932
+ id: "faq-base-accordion",
4933
+ target: "faq",
4934
+ label: "Base accordion FAQ",
4935
+ blockKinds: ["block.faq"],
4936
+ design: {
4937
+ sectionSurface: "base",
4938
+ contentFrame: plainFrame,
4939
+ itemSurface: "default"
4940
+ }
4941
+ }), defineBlockAppearancePreset({
4942
+ id: "faq-contained-help",
4943
+ target: "faq",
4944
+ label: "Contained help panel",
4945
+ blockKinds: ["block.faq"],
4946
+ design: {
4947
+ sectionSurface: "muted-band",
4948
+ contentFrame: panelFrame("inset"),
4949
+ itemSurface: "default"
4950
+ }
4951
+ }), defineBlockAppearancePreset({
4952
+ id: "contact-form-panel",
4953
+ target: "contact-form",
4954
+ label: "Raised form panel",
4955
+ blockKinds: ["block.form"],
4956
+ design: {
4957
+ sectionSurface: "muted-band",
4958
+ contentFrame: panelFrame("raised"),
4959
+ itemSurface: "none"
4960
+ }
4961
+ }), defineBlockAppearancePreset({
4962
+ id: "cta-accent-band",
4963
+ target: "cta",
4964
+ label: "Accent CTA band",
4965
+ blockKinds: ["block.cta-full"],
4966
+ design: {
4967
+ sectionSurface: "accent-band",
4968
+ contentFrame: plainFrame,
4969
+ itemSurface: "none",
4970
+ eyebrowTreatment: "accent"
4971
+ }
4972
+ });
4979
4973
  //#endregion
4980
4974
  //#region ../theme-core/src/site-styles/headerCtaVariants.ts
4981
4975
  function hasButtonVariant(theme, variantId) {
@@ -6388,6 +6382,21 @@ const themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isTh
6388
6382
  //#region ../theme-core/src/palette/colors.ts
6389
6383
  const HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
6390
6384
  const NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
6385
+ const THEME_PALETTE_COLOR_ORDER = [
6386
+ "primary",
6387
+ "secondary",
6388
+ "accent",
6389
+ "success",
6390
+ "warning",
6391
+ "destructive",
6392
+ "background",
6393
+ "surface",
6394
+ "surfaceAlt",
6395
+ "muted",
6396
+ "text",
6397
+ "primaryForeground",
6398
+ "border"
6399
+ ];
6391
6400
  const hexColorSchema = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
6392
6401
  const paletteModeSchema = z$1.enum(["light", "dark"]);
6393
6402
  const PALETTE_VALUE_KEY_PREFIX = "palette-value:v1|";
@@ -6465,6 +6474,12 @@ function requirePaletteColorsFromEntries(entries) {
6465
6474
  if (result.ok) return result.colors;
6466
6475
  throw new Error(`Invalid complete palette: ${result.error.kind}`);
6467
6476
  }
6477
+ function paletteColorEntries(colors) {
6478
+ return THEME_PALETTE_COLOR_ORDER.map((name) => ({
6479
+ name,
6480
+ hex: colors[name]
6481
+ }));
6482
+ }
6468
6483
  function paletteColorFingerprint(colors) {
6469
6484
  return PALETTE_TOKEN_NAMES.map((name) => `${name}:${colors[name]}`).join("|");
6470
6485
  }
@@ -6472,7 +6487,7 @@ function canonicalPaletteHashInput(colors, mode) {
6472
6487
  return `${mode}|${paletteColorFingerprint(colors)}`;
6473
6488
  }
6474
6489
  /**
6475
- * The shared TypeScript/SQL protocol. Do not reorder roles: the order comes
6490
+ * Stable curated-catalogue identity. Do not reorder roles: the order comes
6476
6491
  * from PALETTE_TOKEN_NAMES through canonicalPaletteHashInput.
6477
6492
  */
6478
6493
  function paletteValueKey(colors, mode) {
@@ -7798,13 +7813,6 @@ const warmDarkKirtanGold = defineCuratedPalette({
7798
7813
  });
7799
7814
  //#endregion
7800
7815
  //#region ../theme-core/src/palette/curated/index.ts
7801
- /**
7802
- * Curated palette library.
7803
- *
7804
- * Authoring keys are readable source aliases. Value keys are derived from the
7805
- * complete mode and semantic colours and are the only curated identity used at
7806
- * persistence and runtime boundaries.
7807
- */
7808
7816
  function admitCuratedPaletteDefinition(definition) {
7809
7817
  return {
7810
7818
  ...definition,
@@ -7831,11 +7839,8 @@ const curatedPalettes = [
7831
7839
  admitCuratedPaletteDefinition(warmDarkEmber),
7832
7840
  admitCuratedPaletteDefinition(warmDarkKirtanGold)
7833
7841
  ];
7834
- const curatedPalettesByValueKey = new Map(curatedPalettes.map((palette) => [palette.valueKey, palette]));
7842
+ new Map(curatedPalettes.map((palette) => [palette.valueKey, palette]));
7835
7843
  const curatedPalettesByAuthoringKey = new Map(curatedPalettes.map((palette) => [palette.authoringKey, palette]));
7836
- function findCuratedPalette(valueKey) {
7837
- return curatedPalettesByValueKey.get(valueKey);
7838
- }
7839
7844
  function findCuratedPaletteByAuthoringKey(authoringKey) {
7840
7845
  return curatedPalettesByAuthoringKey.get(authoringKey);
7841
7846
  }
@@ -7844,87 +7849,6 @@ function requireCuratedPaletteValueKey(authoringKey) {
7844
7849
  if (!palette) throw new Error(`Unknown curated palette authoring key "${authoringKey}"`);
7845
7850
  return palette.valueKey;
7846
7851
  }
7847
- /** Parses a raw persisted key into catalogue-proven curated membership. */
7848
- const knownCuratedPaletteValueKeySchema = z$1.string().transform((value, ctx) => {
7849
- const valueKey = parsePaletteValueKey(value);
7850
- if (!valueKey) {
7851
- ctx.addIssue({
7852
- code: "custom",
7853
- message: "Invalid canonical palette value key"
7854
- });
7855
- return z$1.NEVER;
7856
- }
7857
- const palette = findCuratedPalette(valueKey);
7858
- if (!palette) {
7859
- ctx.addIssue({
7860
- code: "custom",
7861
- message: "Unknown curated palette value key"
7862
- });
7863
- return z$1.NEVER;
7864
- }
7865
- return palette.valueKey;
7866
- });
7867
- //#endregion
7868
- //#region ../theme-core/src/palette/selection.ts
7869
- const sitePaletteIdSchema = z$1.string().uuid().transform((value) => value);
7870
- const sitePaletteVersionSchema = z$1.number().int().nonnegative().transform((value) => value);
7871
- const paletteSelectionSchema = z$1.discriminatedUnion("kind", [z$1.object({
7872
- kind: z$1.literal("curated"),
7873
- valueKey: knownCuratedPaletteValueKeySchema
7874
- }), z$1.object({
7875
- kind: z$1.literal("site"),
7876
- paletteId: sitePaletteIdSchema
7877
- })]);
7878
- const onboardingPaletteOriginSchema = z$1.object({
7879
- kind: z$1.literal("onboarding"),
7880
- sourceKey: z$1.string().min(1).nullable()
7881
- });
7882
- const curatedForkPaletteOriginSchema = z$1.object({
7883
- kind: z$1.literal("curated-fork"),
7884
- sourceValueKey: paletteValueKeySchema
7885
- });
7886
- const manualPaletteOriginSchema = z$1.object({ kind: z$1.literal("manual") });
7887
- const legacyCustomizedPaletteOriginSchema = z$1.object({
7888
- kind: z$1.literal("legacy-customized"),
7889
- sourceKey: z$1.string().min(1).nullable()
7890
- });
7891
- const sitePaletteOriginSchema = z$1.discriminatedUnion("kind", [
7892
- onboardingPaletteOriginSchema,
7893
- curatedForkPaletteOriginSchema,
7894
- manualPaletteOriginSchema,
7895
- legacyCustomizedPaletteOriginSchema
7896
- ]);
7897
- const editorSitePaletteOriginSchema = z$1.discriminatedUnion("kind", [z$1.object({
7898
- kind: z$1.literal("curated-fork"),
7899
- sourceValueKey: knownCuratedPaletteValueKeySchema
7900
- }), manualPaletteOriginSchema]);
7901
- z$1.object({
7902
- id: sitePaletteIdSchema,
7903
- colors: paletteColorsSchema,
7904
- mode: paletteModeSchema,
7905
- origin: sitePaletteOriginSchema,
7906
- version: sitePaletteVersionSchema
7907
- });
7908
- z$1.discriminatedUnion("kind", [
7909
- z$1.object({ kind: z$1.literal("preserve") }),
7910
- z$1.object({
7911
- kind: z$1.literal("select"),
7912
- selection: paletteSelectionSchema
7913
- }),
7914
- z$1.object({
7915
- kind: z$1.literal("create-site"),
7916
- colors: paletteColorsSchema,
7917
- mode: paletteModeSchema,
7918
- origin: editorSitePaletteOriginSchema
7919
- }),
7920
- z$1.object({
7921
- kind: z$1.literal("update-site"),
7922
- paletteId: sitePaletteIdSchema,
7923
- expectedVersion: sitePaletteVersionSchema,
7924
- colors: paletteColorsSchema,
7925
- mode: paletteModeSchema
7926
- })
7927
- ]);
7928
7852
  //#endregion
7929
7853
  //#region ../theme-core/src/tokens/tokens.ts
7930
7854
  const defaultThemeTokens = {
@@ -8137,6 +8061,32 @@ function parseBackgroundAppearanceColorToken(value) {
8137
8061
  function uniqueStrings(values) {
8138
8062
  return Array.from(new Set(values));
8139
8063
  }
8064
+ const headerInteractionPaletteSchema = z$1.enum([
8065
+ "primary",
8066
+ "secondary",
8067
+ "accent"
8068
+ ]);
8069
+ //#endregion
8070
+ //#region ../theme-core/src/site-styles/headerInteractionPalette.ts
8071
+ const clearSplitInteractionPalette = defineLookOptionGroup({
8072
+ id: "interaction-palette",
8073
+ label: "Hover colour",
8074
+ defaultOptionId: "accent",
8075
+ options: [
8076
+ {
8077
+ id: "accent",
8078
+ label: "Accent"
8079
+ },
8080
+ {
8081
+ id: "primary",
8082
+ label: "Primary"
8083
+ },
8084
+ {
8085
+ id: "secondary",
8086
+ label: "Secondary"
8087
+ }
8088
+ ]
8089
+ });
8140
8090
  //#endregion
8141
8091
  //#region ../theme-core/src/site-styles/logoBranding.ts
8142
8092
  const logoTextConfidenceValues = [
@@ -8361,7 +8311,7 @@ const overlayLogoAccommodations = [
8361
8311
  * optional nested styling fields that would otherwise leak from another Look.
8362
8312
  */
8363
8313
  function baseHeader(theme) {
8364
- 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;
8314
+ 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;
8365
8315
  return {
8366
8316
  ...header,
8367
8317
  navContainer: {
@@ -8376,7 +8326,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8376
8326
  id: asHeaderLayoutId("classic"),
8377
8327
  label: "Classic",
8378
8328
  description: "Logo and navigation in one practical horizontal row.",
8379
- structure: "inline-classic",
8380
8329
  variant: "classic",
8381
8330
  defaultPositioning: "sticky",
8382
8331
  shrinkOnScroll: false
@@ -8385,7 +8334,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8385
8334
  id: asHeaderLayoutId("centered"),
8386
8335
  label: "Centered",
8387
8336
  description: "Logo centered above a balanced navigation row.",
8388
- structure: "centered-stack",
8389
8337
  variant: "centered",
8390
8338
  defaultPositioning: "static",
8391
8339
  shrinkOnScroll: false,
@@ -8401,7 +8349,6 @@ const headerLayoutCatalog = defineExactCatalog()([
8401
8349
  id: asHeaderLayoutId("floating"),
8402
8350
  label: "Floating",
8403
8351
  description: "Detached header chrome that sits over the opening section.",
8404
- structure: "floating-shell",
8405
8352
  variant: "floating",
8406
8353
  defaultPositioning: "sticky",
8407
8354
  shrinkOnScroll: true,
@@ -8563,10 +8510,13 @@ const headerStyleCatalog = defineExactCatalog()([
8563
8510
  label: "Clear Split",
8564
8511
  description: "Floating logo with transparent navigation and no shared shell.",
8565
8512
  supportedLayoutIds: supportedLayouts(["floating"]),
8566
- navInteraction: "color-change",
8513
+ navInteraction: "pill-background",
8567
8514
  surface: "floating",
8568
- defaultDepth: "none",
8515
+ defaultDepth: "line",
8569
8516
  navTypography: "plain",
8517
+ openingForegroundTarget: "all",
8518
+ scrollTreatment: "contrast-glass",
8519
+ interactionPalette: clearSplitInteractionPalette,
8570
8520
  moods: ["editorial", "calm"]
8571
8521
  },
8572
8522
  {
@@ -8589,6 +8539,7 @@ const headerStyleCatalog = defineExactCatalog()([
8589
8539
  surface: "floating",
8590
8540
  defaultDepth: "shadow",
8591
8541
  navTypography: "quiet-caps",
8542
+ openingForegroundTarget: "brand-only",
8592
8543
  moods: ["expressive"]
8593
8544
  },
8594
8545
  {
@@ -8600,6 +8551,7 @@ const headerStyleCatalog = defineExactCatalog()([
8600
8551
  surface: "floating",
8601
8552
  defaultDepth: "shadow",
8602
8553
  navTypography: "heading",
8554
+ openingForegroundTarget: "brand-only",
8603
8555
  moods: ["calm", "editorial"]
8604
8556
  }
8605
8557
  ]);
@@ -9101,13 +9053,6 @@ const headerLookCatalog = defineExactCatalog()([
9101
9053
  {
9102
9054
  id: asHeaderLookId("clean-base"),
9103
9055
  label: "Clean base",
9104
- visualTreatment: "solid-neutral",
9105
- layoutBehavior: "sticky",
9106
- configuration: {
9107
- structure: "inline-classic",
9108
- treatment: "solid-neutral",
9109
- behavior: "sticky"
9110
- },
9111
9056
  openingRequirement: "none",
9112
9057
  logoAccommodations: inlineClassicLogoAccommodations,
9113
9058
  compile: cleanBaseHeader
@@ -9115,13 +9060,6 @@ const headerLookCatalog = defineExactCatalog()([
9115
9060
  {
9116
9061
  id: asHeaderLookId("classic-centered-nav"),
9117
9062
  label: "Centered nav",
9118
- visualTreatment: "solid-neutral",
9119
- layoutBehavior: "sticky",
9120
- configuration: {
9121
- structure: "inline-classic",
9122
- treatment: "solid-neutral",
9123
- behavior: "sticky"
9124
- },
9125
9063
  openingRequirement: "none",
9126
9064
  maxRecommendedNavItems: 6,
9127
9065
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9130,13 +9068,6 @@ const headerLookCatalog = defineExactCatalog()([
9130
9068
  {
9131
9069
  id: asHeaderLookId("brand-solid"),
9132
9070
  label: "Brand solid",
9133
- visualTreatment: "solid-brand",
9134
- layoutBehavior: "sticky-shrink",
9135
- configuration: {
9136
- structure: "inline-classic",
9137
- treatment: "solid-brand",
9138
- behavior: "sticky-shrink"
9139
- },
9140
9071
  openingRequirement: "none",
9141
9072
  logoAccommodations: inlineClassicLogoAccommodations,
9142
9073
  compile: solidBrandHeader
@@ -9144,13 +9075,6 @@ const headerLookCatalog = defineExactCatalog()([
9144
9075
  {
9145
9076
  id: asHeaderLookId("serif-line"),
9146
9077
  label: "Serif line",
9147
- visualTreatment: "light-serif",
9148
- layoutBehavior: "sticky",
9149
- configuration: {
9150
- structure: "centered-stack",
9151
- treatment: "light-serif",
9152
- behavior: "sticky"
9153
- },
9154
9078
  openingRequirement: "none",
9155
9079
  maxRecommendedNavItems: 6,
9156
9080
  logoAccommodations: centeredLogoAccommodations,
@@ -9159,13 +9083,6 @@ const headerLookCatalog = defineExactCatalog()([
9159
9083
  {
9160
9084
  id: asHeaderLookId("centered-calm"),
9161
9085
  label: "Centered calm",
9162
- visualTreatment: "light-serif",
9163
- layoutBehavior: "normal-flow",
9164
- configuration: {
9165
- structure: "centered-stack",
9166
- treatment: "light-serif",
9167
- behavior: "normal-flow"
9168
- },
9169
9086
  openingRequirement: "none",
9170
9087
  maxRecommendedNavItems: 5,
9171
9088
  logoAccommodations: centeredLogoAccommodations,
@@ -9174,13 +9091,6 @@ const headerLookCatalog = defineExactCatalog()([
9174
9091
  {
9175
9092
  id: asHeaderLookId("practical-utility"),
9176
9093
  label: "Practical utility",
9177
- visualTreatment: "solid-neutral",
9178
- layoutBehavior: "sticky-shrink",
9179
- configuration: {
9180
- structure: "inline-classic",
9181
- treatment: "solid-neutral",
9182
- behavior: "sticky-shrink"
9183
- },
9184
9094
  openingRequirement: "none",
9185
9095
  requiresProminentCta: true,
9186
9096
  logoAccommodations: inlineClassicLogoAccommodations,
@@ -9189,13 +9099,6 @@ const headerLookCatalog = defineExactCatalog()([
9189
9099
  {
9190
9100
  id: asHeaderLookId("minimal-transparent"),
9191
9101
  label: "Minimal transparent",
9192
- visualTreatment: "minimal-transparent",
9193
- layoutBehavior: "normal-flow",
9194
- configuration: {
9195
- structure: "inline-classic",
9196
- treatment: "minimal-transparent",
9197
- behavior: "normal-flow"
9198
- },
9199
9102
  openingRequirement: "reserved-space-ok",
9200
9103
  logoAccommodations: inlineClassicLogoAccommodations,
9201
9104
  compile: minimalTransparentHeader
@@ -9203,13 +9106,6 @@ const headerLookCatalog = defineExactCatalog()([
9203
9106
  {
9204
9107
  id: asHeaderLookId("transparent-overlay"),
9205
9108
  label: "Transparent overlay",
9206
- visualTreatment: "transparent-overlay",
9207
- layoutBehavior: "fixed-overlay",
9208
- configuration: {
9209
- structure: "inline-classic",
9210
- treatment: "transparent-overlay",
9211
- behavior: "fixed-overlay"
9212
- },
9213
9109
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9214
9110
  maxRecommendedNavItems: 5,
9215
9111
  logoAccommodations: overlayLogoAccommodations,
@@ -9218,24 +9114,13 @@ const headerLookCatalog = defineExactCatalog()([
9218
9114
  {
9219
9115
  id: asHeaderLookId("floating-glass"),
9220
9116
  label: "Floating glass",
9221
- visualTreatment: "floating-glass",
9222
- layoutBehavior: "fixed-floating",
9223
- configuration: {
9224
- structure: "floating-shell",
9225
- treatment: "floating-glass",
9226
- behavior: "fixed-floating"
9227
- },
9228
9117
  openingRequirement: "requires-image-hero-with-contrast-overlay",
9229
9118
  maxRecommendedNavItems: 5,
9230
9119
  logoAccommodations: overlayLogoAccommodations,
9231
9120
  compile: floatingGlassHeader
9232
9121
  }
9233
9122
  ]);
9234
- new Set(headerLookCatalog.map((look) => headerConfigurationKey(look.configuration)));
9235
9123
  new Map(headerLookCatalog.map((look) => [look.id, look]));
9236
- function headerConfigurationKey(configuration) {
9237
- return `${configuration.structure}:${configuration.treatment}:${configuration.behavior}`;
9238
- }
9239
9124
  //#endregion
9240
9125
  //#region ../theme-core/src/site-styles/sectionTransitions.ts
9241
9126
  function boundaryRuntimeMetrics(family, size, heightExpression) {
@@ -9445,8 +9330,6 @@ const VARIANT_ROLES = [
9445
9330
  "secondary",
9446
9331
  "outline",
9447
9332
  "ghost",
9448
- "link",
9449
- "tertiary",
9450
9333
  "accent"
9451
9334
  ];
9452
9335
  function isVariantRole(value) {
@@ -9458,7 +9341,7 @@ function isVariantRole(value) {
9458
9341
  * IDs become class selectors, so keep the contract deliberately narrower than
9459
9342
  * an arbitrary string and shared with every authoring/runtime boundary.
9460
9343
  */
9461
- const buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only");
9344
+ 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" });
9462
9345
  function asSpecialVariantId(value) {
9463
9346
  const parsed = buttonVariantIdSchema.safeParse(value);
9464
9347
  if (!parsed.success) throw new Error("SpecialVariantId must be a CSS-safe button variant ID");
@@ -12651,39 +12534,39 @@ function defaultTypographyForRecipe(recipe) {
12651
12534
  }
12652
12535
  //#endregion
12653
12536
  //#region ../theme-core/src/lib/media.ts
12654
- const hotspotSchema$1 = z.object({
12537
+ const hotspotSchema = z.object({
12655
12538
  x: z.number().min(0).max(1),
12656
12539
  y: z.number().min(0).max(1),
12657
12540
  radius: z.number().optional()
12658
12541
  });
12659
- const rotationSchema$1 = z.union([
12542
+ const rotationSchema = z.union([
12660
12543
  z.literal(0),
12661
12544
  z.literal(90),
12662
12545
  z.literal(180),
12663
12546
  z.literal(270)
12664
12547
  ]);
12665
- const rectSchema$1 = z.tuple([
12548
+ const rectSchema = z.tuple([
12666
12549
  z.number(),
12667
12550
  z.number(),
12668
12551
  z.number(),
12669
12552
  z.number()
12670
12553
  ]);
12671
- const aspectCropSchema$1 = z.object({
12554
+ const aspectCropSchema = z.object({
12672
12555
  aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
12673
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
12674
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
12675
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
12556
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
12557
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
12558
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
12676
12559
  });
12677
- const transformSchema$1 = z.object({
12560
+ const transformSchema = z.object({
12678
12561
  aspectCrops: z.preprocess((value) => {
12679
12562
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
12680
12563
  return value;
12681
- }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
12682
- rect: rectSchema$1.optional(),
12683
- hotspot: hotspotSchema$1.optional(),
12684
- rotation: rotationSchema$1.optional()
12564
+ }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
12565
+ rect: rectSchema.optional(),
12566
+ hotspot: hotspotSchema.optional(),
12567
+ rotation: rotationSchema.optional()
12685
12568
  });
12686
- const mediaSchema$1 = z.object({
12569
+ const mediaSchema = z.object({
12687
12570
  type: z.enum([
12688
12571
  "image",
12689
12572
  "video",
@@ -12704,7 +12587,35 @@ const mediaSchema$1 = z.object({
12704
12587
  height: z.number().optional(),
12705
12588
  storageBucket: z.string().optional(),
12706
12589
  storagePath: z.string().optional(),
12707
- transform: transformSchema$1.optional()
12590
+ transform: transformSchema.optional()
12591
+ });
12592
+ //#endregion
12593
+ //#region ../theme-core/src/palette/schema.ts
12594
+ const colourHexString = z$1.string().regex(/^#([0-9A-Fa-f]{3}){1,2}$/);
12595
+ const paletteColorSchema = z$1.object({
12596
+ name: z$1.string().min(1),
12597
+ hex: colourHexString
12598
+ });
12599
+ const paletteMetaSchema = z$1.object({ mode: z$1.enum(["light", "dark"]) });
12600
+ const paletteSchema = z$1.object({
12601
+ colors: z$1.array(paletteColorSchema),
12602
+ meta: paletteMetaSchema
12603
+ }).transform((palette, ctx) => {
12604
+ const colors = paletteColorsFromEntries(palette.colors);
12605
+ if (!colors.ok) {
12606
+ ctx.addIssue({
12607
+ code: "custom",
12608
+ message: `Invalid complete palette: ${colors.error.kind}`
12609
+ });
12610
+ return z$1.NEVER;
12611
+ }
12612
+ return {
12613
+ colors: paletteColorEntries(colors.colors).map(({ name, hex }) => ({
12614
+ name: String(name),
12615
+ hex: String(hex)
12616
+ })),
12617
+ meta: palette.meta
12618
+ };
12708
12619
  });
12709
12620
  //#endregion
12710
12621
  //#region ../theme-core/src/surfaces/foregroundRoles.ts
@@ -13509,264 +13420,6 @@ function generateInteractiveChildInheritanceCSS(selector) {
13509
13420
  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`;
13510
13421
  }
13511
13422
  //#endregion
13512
- //#region ../theme-core/src/buttons/effects/presets/background.ts
13513
- /**
13514
- * Darken background on hover
13515
- *
13516
- * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
13517
- */
13518
- const darkenBackgroundEffect = {
13519
- id: "darken-background",
13520
- name: "Darken on Hover",
13521
- description: "Darkens the background color on hover",
13522
- category: "background",
13523
- pseudoElement: "none",
13524
- applicableTo: ["button"],
13525
- customizableOption: {
13526
- name: "amount",
13527
- type: "select",
13528
- label: "Darken Amount (shade step)",
13529
- default: 100,
13530
- options: [
13531
- 0,
13532
- 100,
13533
- 200,
13534
- 300,
13535
- 400,
13536
- 500,
13537
- 600,
13538
- 700,
13539
- 800,
13540
- 900
13541
- ]
13542
- },
13543
- isApplicable: (buttonConfig) => {
13544
- return buttonConfig.background.type === "solid";
13545
- },
13546
- generateCSS: (ctx) => {
13547
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13548
- if (buttonConfig.background.type !== "solid") return "";
13549
- const amount = options.amount || 100;
13550
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13551
- const darkerToken = tokens.adjustShade(baseToken, amount);
13552
- return `
13553
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13554
- background-color: ${tokens.getColor(darkerToken)};
13555
- }
13556
- `;
13557
- }
13558
- };
13559
- /**
13560
- * Lighten background on hover
13561
- *
13562
- * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
13563
- */
13564
- const lightenBackgroundEffect = {
13565
- id: "lighten-background",
13566
- name: "Lighten on Hover",
13567
- description: "Lightens the background color on hover",
13568
- category: "background",
13569
- pseudoElement: "none",
13570
- applicableTo: ["button"],
13571
- customizableOption: {
13572
- name: "amount",
13573
- type: "select",
13574
- label: "Lighten Amount (shade step)",
13575
- default: 100,
13576
- options: [
13577
- 0,
13578
- 100,
13579
- 200,
13580
- 300,
13581
- 400,
13582
- 500,
13583
- 600,
13584
- 700,
13585
- 800,
13586
- 900
13587
- ]
13588
- },
13589
- isApplicable: (buttonConfig) => {
13590
- return buttonConfig.background.type === "solid";
13591
- },
13592
- generateCSS: (ctx) => {
13593
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13594
- if (buttonConfig.background.type !== "solid") return "";
13595
- const amount = options.amount || 100;
13596
- const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13597
- const lighterToken = tokens.adjustShade(baseToken, -amount);
13598
- return `
13599
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13600
- background-color: ${tokens.getColor(lighterToken)};
13601
- }
13602
- `;
13603
- }
13604
- };
13605
- /**
13606
- * Fade background on hover (reduce opacity)
13607
- *
13608
- * Works with all background types.
13609
- */
13610
- const fadeBackgroundEffect = {
13611
- id: "fade-background",
13612
- name: "Fade on Hover",
13613
- description: "Reduces background opacity on hover",
13614
- category: "background",
13615
- pseudoElement: "none",
13616
- applicableTo: ["nav-link"],
13617
- customizableOption: {
13618
- name: "opacity",
13619
- type: "percentage",
13620
- label: "Hover Opacity",
13621
- default: 80
13622
- },
13623
- generateCSS: (ctx) => {
13624
- const { themeId, variantId, options } = ctx;
13625
- return `
13626
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13627
- opacity: ${(options.opacity || 80) / 100};
13628
- }
13629
- `;
13630
- }
13631
- };
13632
- /**
13633
- * Reduce opacity on hover (simple opacity reduction)
13634
- *
13635
- * Navigation-link effect that reduces opacity by a percentage (default 15%).
13636
- */
13637
- const opacityReduceEffect = {
13638
- id: "opacity-reduce",
13639
- name: "Reduce Opacity",
13640
- description: "Reduces navigation-link opacity on hover by a percentage",
13641
- category: "background",
13642
- pseudoElement: "none",
13643
- applicableTo: ["nav-link"],
13644
- customizableOption: {
13645
- name: "reduction",
13646
- type: "percentage",
13647
- label: "Opacity Reduction",
13648
- default: 15
13649
- },
13650
- generateCSS: (ctx) => {
13651
- const { themeId, variantId, options } = ctx;
13652
- return `
13653
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13654
- opacity: ${1 - (options.reduction || 15) / 100};
13655
- }
13656
- `;
13657
- }
13658
- };
13659
- /**
13660
- * Animated gradient background
13661
- *
13662
- * Animates a gradient background by shifting its position on hover.
13663
- * Works with gradient backgrounds only.
13664
- *
13665
- * Sets background-size to 200% and animates background-position from left to right.
13666
- */
13667
- const animatedGradientEffect = {
13668
- id: "animated-gradient",
13669
- name: "Animated Gradient",
13670
- description: "Animates gradient position on hover",
13671
- category: "background",
13672
- pseudoElement: "none",
13673
- applicableTo: ["button"],
13674
- customizableOption: {
13675
- name: "direction",
13676
- type: "select",
13677
- label: "Animation Direction",
13678
- default: "horizontal",
13679
- options: ["horizontal", "vertical"]
13680
- },
13681
- isApplicable: (buttonConfig) => {
13682
- return buttonConfig.background.type === "gradient";
13683
- },
13684
- generateCSS: (ctx) => {
13685
- const { themeId, variantId, options, buttonConfig } = ctx;
13686
- if (buttonConfig.background.type !== "gradient") return "";
13687
- const direction = options.direction || "horizontal";
13688
- return `
13689
- /* Setup animated gradient */
13690
- :where([data-theme-scope="${themeId}"]) .${variantId} {
13691
- background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
13692
- background-position: left center;
13693
- transition: background-position 0.3s ease;
13694
- }
13695
-
13696
- /* Animate gradient on hover */
13697
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13698
- background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
13699
- }
13700
- `;
13701
- }
13702
- };
13703
- /**
13704
- * Add background color on hover
13705
- *
13706
- * Works best with transparent backgrounds. Adds a solid background color on hover.
13707
- */
13708
- const backgroundOnHoverEffect = {
13709
- id: "background-on-hover",
13710
- name: "Background on Hover",
13711
- description: "Adds background color on hover",
13712
- category: "background",
13713
- pseudoElement: "none",
13714
- applicableTo: ["button", "nav-link"],
13715
- customizableOption: {
13716
- name: "colorToken",
13717
- type: "select",
13718
- label: "Background Color",
13719
- default: "neutral-800",
13720
- options: [
13721
- "neutral-700",
13722
- "neutral-800",
13723
- "neutral-900",
13724
- "primary"
13725
- ]
13726
- },
13727
- generateCSS: (ctx) => {
13728
- const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13729
- const colorToken = options.colorToken || "neutral-800";
13730
- return `
13731
- /* Add background on hover */
13732
- :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13733
- background-color: ${tokens.getColor(colorToken)};${"textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : ""}
13734
- }
13735
- `;
13736
- }
13737
- };
13738
- /**
13739
- * Add semi-transparent background color on hover
13740
- *
13741
- * Adds a background with opacity/alpha channel. Perfect for retro/arcade styles.
13742
- */
13743
- const backgroundOnHoverAlphaEffect = {
13744
- id: "background-on-hover-alpha",
13745
- name: "Background on Hover (Transparent)",
13746
- description: "Adds semi-transparent background on hover",
13747
- category: "background",
13748
- pseudoElement: "none",
13749
- applicableTo: ["nav-link"],
13750
- customizableOption: {
13751
- name: "opacity",
13752
- type: "percentage",
13753
- label: "Opacity",
13754
- default: 50
13755
- },
13756
- generateCSS: (ctx) => {
13757
- const { themeId, variantId, stateGroup, options } = ctx;
13758
- const rawOpacity = options.opacity;
13759
- const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
13760
- const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
13761
- return `
13762
- /* Add semi-transparent background (${stateGroup}) */
13763
- :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
13764
- background-color: rgb(${cssVar} / ${clampedOpacity}%);
13765
- }
13766
- `;
13767
- }
13768
- };
13769
- //#endregion
13770
13423
  //#region ../theme-core/src/buttons/effects/cssUtils.ts
13771
13424
  /**
13772
13425
  * CSS Utilities for Effect Presets
@@ -13818,6 +13471,71 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
13818
13471
  `;
13819
13472
  }
13820
13473
  //#endregion
13474
+ //#region ../theme-core/src/buttons/effects/presets/background.ts
13475
+ /**
13476
+ * Darken background on hover
13477
+ *
13478
+ * Works with solid backgrounds only. Darkens the background color by adjusting the shade.
13479
+ */
13480
+ const darkenBackgroundEffect = shadeBackgroundEffect({
13481
+ id: "darken-background",
13482
+ name: "Darken on Hover",
13483
+ description: "Darkens the background color on hover",
13484
+ label: "Darken Amount (shade step)",
13485
+ shadeDirection: 1
13486
+ });
13487
+ /**
13488
+ * Lighten background on hover
13489
+ *
13490
+ * Works with solid backgrounds only. Lightens the background color by adjusting the shade.
13491
+ */
13492
+ const lightenBackgroundEffect = shadeBackgroundEffect({
13493
+ id: "lighten-background",
13494
+ name: "Lighten on Hover",
13495
+ description: "Lightens the background color on hover",
13496
+ label: "Lighten Amount (shade step)",
13497
+ shadeDirection: -1
13498
+ });
13499
+ function shadeBackgroundEffect(config) {
13500
+ return {
13501
+ id: config.id,
13502
+ name: config.name,
13503
+ description: config.description,
13504
+ category: "background",
13505
+ pseudoElement: "none",
13506
+ applicableTo: ["button"],
13507
+ customizableOption: {
13508
+ name: "amount",
13509
+ type: "select",
13510
+ label: config.label,
13511
+ default: 100,
13512
+ options: [
13513
+ 0,
13514
+ 100,
13515
+ 200,
13516
+ 300,
13517
+ 400,
13518
+ 500,
13519
+ 600,
13520
+ 700,
13521
+ 800,
13522
+ 900
13523
+ ]
13524
+ },
13525
+ isApplicable: (buttonConfig) => buttonConfig.background.type === "solid",
13526
+ generateCSS: ({ themeId, variantId, options, tokens, buttonConfig }) => {
13527
+ if (buttonConfig.background.type !== "solid") return "";
13528
+ const amount = (options.amount || 100) * config.shadeDirection;
13529
+ const baseToken = buttonConfig.background.colorToken ?? "primary-500";
13530
+ return `
13531
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13532
+ background-color: ${tokens.getColor(tokens.adjustShade(baseToken, amount))};
13533
+ }
13534
+ `;
13535
+ }
13536
+ };
13537
+ }
13538
+ //#endregion
13821
13539
  //#region ../theme-core/src/buttons/effects/registry.ts
13822
13540
  /**
13823
13541
  * Registry of all available effect presets
@@ -13825,11 +13543,144 @@ function generateStateCSS(themeId, variantId, state, cssProperties) {
13825
13543
  const EFFECT_PRESETS = [
13826
13544
  darkenBackgroundEffect,
13827
13545
  lightenBackgroundEffect,
13828
- fadeBackgroundEffect,
13829
- opacityReduceEffect,
13830
- animatedGradientEffect,
13831
- backgroundOnHoverEffect,
13832
- backgroundOnHoverAlphaEffect,
13546
+ {
13547
+ id: "fade-background",
13548
+ name: "Fade on Hover",
13549
+ description: "Reduces background opacity on hover",
13550
+ category: "background",
13551
+ pseudoElement: "none",
13552
+ applicableTo: ["nav-link"],
13553
+ customizableOption: {
13554
+ name: "opacity",
13555
+ type: "percentage",
13556
+ label: "Hover Opacity",
13557
+ default: 80
13558
+ },
13559
+ generateCSS: (ctx) => {
13560
+ const { themeId, variantId, options } = ctx;
13561
+ return `
13562
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13563
+ opacity: ${(options.opacity || 80) / 100};
13564
+ }
13565
+ `;
13566
+ }
13567
+ },
13568
+ {
13569
+ id: "opacity-reduce",
13570
+ name: "Reduce Opacity",
13571
+ description: "Reduces navigation-link opacity on hover by a percentage",
13572
+ category: "background",
13573
+ pseudoElement: "none",
13574
+ applicableTo: ["nav-link"],
13575
+ customizableOption: {
13576
+ name: "reduction",
13577
+ type: "percentage",
13578
+ label: "Opacity Reduction",
13579
+ default: 15
13580
+ },
13581
+ generateCSS: (ctx) => {
13582
+ const { themeId, variantId, options } = ctx;
13583
+ return `
13584
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13585
+ opacity: ${1 - (options.reduction || 15) / 100};
13586
+ }
13587
+ `;
13588
+ }
13589
+ },
13590
+ {
13591
+ id: "animated-gradient",
13592
+ name: "Animated Gradient",
13593
+ description: "Animates gradient position on hover",
13594
+ category: "background",
13595
+ pseudoElement: "none",
13596
+ applicableTo: ["button"],
13597
+ customizableOption: {
13598
+ name: "direction",
13599
+ type: "select",
13600
+ label: "Animation Direction",
13601
+ default: "horizontal",
13602
+ options: ["horizontal", "vertical"]
13603
+ },
13604
+ isApplicable: (buttonConfig) => {
13605
+ return buttonConfig.background.type === "gradient";
13606
+ },
13607
+ generateCSS: (ctx) => {
13608
+ const { themeId, variantId, options, buttonConfig } = ctx;
13609
+ if (buttonConfig.background.type !== "gradient") return "";
13610
+ const direction = options.direction || "horizontal";
13611
+ return `
13612
+ /* Setup animated gradient */
13613
+ :where([data-theme-scope="${themeId}"]) .${variantId} {
13614
+ background-size: ${direction === "horizontal" ? "200% auto" : "auto 200%"};
13615
+ background-position: left center;
13616
+ transition: background-position 0.3s ease;
13617
+ }
13618
+
13619
+ /* Animate gradient on hover */
13620
+ :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13621
+ background-position: ${direction === "horizontal" ? "right center" : "center bottom"};
13622
+ }
13623
+ `;
13624
+ }
13625
+ },
13626
+ {
13627
+ id: "background-on-hover",
13628
+ name: "Background on Hover",
13629
+ description: "Adds background color on hover",
13630
+ category: "background",
13631
+ pseudoElement: "none",
13632
+ applicableTo: ["button", "nav-link"],
13633
+ customizableOption: {
13634
+ name: "colorToken",
13635
+ type: "select",
13636
+ label: "Background Color",
13637
+ default: "neutral-800",
13638
+ options: [
13639
+ "neutral-700",
13640
+ "neutral-800",
13641
+ "neutral-900",
13642
+ "primary"
13643
+ ]
13644
+ },
13645
+ generateCSS: (ctx) => {
13646
+ const { themeId, variantId, stateGroup, options, tokens, buttonConfig } = ctx;
13647
+ const colorToken = options.colorToken || "neutral-800";
13648
+ const color = tokens.getColor(colorToken);
13649
+ const navForeground = "textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : "";
13650
+ return `
13651
+ /* Add background on hover */
13652
+ ${getStateSelector(themeId, variantId, stateGroup)} {
13653
+ background-color: ${color};${navForeground}
13654
+ }
13655
+ `;
13656
+ }
13657
+ },
13658
+ {
13659
+ id: "background-on-hover-alpha",
13660
+ name: "Background on Hover (Transparent)",
13661
+ description: "Adds semi-transparent background on hover",
13662
+ category: "background",
13663
+ pseudoElement: "none",
13664
+ applicableTo: ["nav-link"],
13665
+ customizableOption: {
13666
+ name: "opacity",
13667
+ type: "percentage",
13668
+ label: "Opacity",
13669
+ default: 50
13670
+ },
13671
+ generateCSS: (ctx) => {
13672
+ const { themeId, variantId, stateGroup, options } = ctx;
13673
+ const rawOpacity = options.opacity;
13674
+ const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
13675
+ const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
13676
+ return `
13677
+ /* Add semi-transparent background (${stateGroup}) */
13678
+ :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
13679
+ background-color: rgb(${cssVar} / ${clampedOpacity}%);
13680
+ }
13681
+ `;
13682
+ }
13683
+ },
13833
13684
  {
13834
13685
  id: "border-glow",
13835
13686
  name: "Border Glow",
@@ -16768,6 +16619,147 @@ function resolveOnColorForThemeToken(token) {
16768
16619
  return shade <= 400 ? "#000000" : "#FFFFFF";
16769
16620
  }
16770
16621
  //#endregion
16622
+ //#region ../theme-core/src/header/paintTargets.ts
16623
+ /** Resolve the element that owns the visible header surface for each layout. */
16624
+ function getHeaderPaintTargets(variant, themeId, state = "base") {
16625
+ const scope = `:where([data-theme-scope="${themeId}"])`;
16626
+ const scrolledRoot = state === "scrolled" ? ".header-root.header-scrolled " : "";
16627
+ if (variant === "floating") {
16628
+ if (state === "scrolled") {
16629
+ const desktopOwner = `${scope} ${scrolledRoot}.header-floating-container`;
16630
+ const mobileOwner = `${scope} ${scrolledRoot}.header-mobile-bar`;
16631
+ return [{
16632
+ kind: "viewport-band",
16633
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
16634
+ ownerSelector: desktopOwner,
16635
+ selector: `${desktopOwner}::before`,
16636
+ mediaQuery: MQ_MD_UP,
16637
+ topExtension: {
16638
+ customProperty: "--rb-header-floating-top-gap",
16639
+ value: "1rem",
16640
+ ownerProperty: "top"
16641
+ },
16642
+ ownerNeedsPositioning: false
16643
+ }, {
16644
+ kind: "viewport-band",
16645
+ clipSelector: `${scope}:has(.header-root.header-scrolled)`,
16646
+ ownerSelector: mobileOwner,
16647
+ selector: `${mobileOwner}::before`,
16648
+ mediaQuery: MQ_MD_DOWN,
16649
+ topExtension: {
16650
+ customProperty: "--rb-header-floating-top-gap",
16651
+ value: "0.75rem",
16652
+ ownerProperty: "margin-top"
16653
+ },
16654
+ ownerNeedsPositioning: true
16655
+ }];
16656
+ }
16657
+ return [{
16658
+ kind: "element-box",
16659
+ selector: `${scope} ${scrolledRoot}.header-floating-container`,
16660
+ mediaQuery: MQ_MD_UP
16661
+ }, {
16662
+ kind: "element-box",
16663
+ selector: `${scope} ${scrolledRoot}.header-mobile-bar`,
16664
+ mediaQuery: MQ_MD_DOWN
16665
+ }];
16666
+ }
16667
+ return [{
16668
+ kind: "element-box",
16669
+ selector: `${scope} .header-root${state === "scrolled" ? ".header-scrolled" : ""}::before`,
16670
+ pseudoElement: "inset"
16671
+ }];
16672
+ }
16673
+ function renderHeaderPaintTargetRules(targets, rules) {
16674
+ return targets.map((target) => {
16675
+ const block = renderHeaderPaintTargetRule(target, rules);
16676
+ return target.mediaQuery ? `@media ${target.mediaQuery} {\n${block}\n}` : block;
16677
+ }).join("\n");
16678
+ }
16679
+ function renderHeaderPaintTargetRule(target, rules) {
16680
+ switch (target.kind) {
16681
+ case "element-box": {
16682
+ const pseudoElementSetup = target.pseudoElement === "inset" ? [
16683
+ "content: \"\";",
16684
+ "position: absolute;",
16685
+ "inset: 0;",
16686
+ "pointer-events: none;",
16687
+ "border-radius: inherit;",
16688
+ "z-index: -1;"
16689
+ ] : [];
16690
+ return `${target.selector} {\n ${[...pseudoElementSetup, ...rules].join("\n ")}\n}`;
16691
+ }
16692
+ case "viewport-band": {
16693
+ const gap = target.topExtension;
16694
+ const ownerRules = [
16695
+ `${gap.customProperty}: ${gap.value};`,
16696
+ `${gap.ownerProperty}: var(${gap.customProperty});`,
16697
+ ...target.ownerNeedsPositioning ? ["position: relative;"] : [],
16698
+ "isolation: isolate;",
16699
+ "background: none;",
16700
+ "backdrop-filter: none;",
16701
+ "-webkit-backdrop-filter: none;",
16702
+ "border: 0;",
16703
+ "box-shadow: none;"
16704
+ ];
16705
+ const bandRules = [
16706
+ "content: \"\";",
16707
+ "position: absolute;",
16708
+ `top: calc(-1 * var(${gap.customProperty}));`,
16709
+ "bottom: 0;",
16710
+ "left: 50%;",
16711
+ "width: 100vw;",
16712
+ "transform: translateX(-50%);",
16713
+ "pointer-events: none;",
16714
+ "border-radius: 0;",
16715
+ "z-index: -1;",
16716
+ ...rules
16717
+ ];
16718
+ return `${target.clipSelector} {\n overflow-x: clip;\n}\n${target.ownerSelector} {\n ${ownerRules.join("\n ")}\n}\n${target.selector} {\n ${bandRules.join("\n ")}\n}`;
16719
+ }
16720
+ }
16721
+ }
16722
+ //#endregion
16723
+ //#region ../theme-core/src/header/scrollTreatment.ts
16724
+ const headerScrollTreatmentSchema = z$1.discriminatedUnion("kind", [z$1.object({
16725
+ kind: z$1.literal("contrast-glass"),
16726
+ backgroundTone: z$1.enum(["light", "dark"])
16727
+ })]).optional();
16728
+ function generateMobileOverlayBackdropFilterFix(themeId, variant) {
16729
+ const root = `:where([data-theme-scope="${themeId}"]) .header-root:has([data-nav-mobile-overlay][aria-hidden="false"])`;
16730
+ 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`;
16731
+ }
16732
+ function generateHeaderScrollTreatmentStyles(treatment, themeId, variant, surfaceRules = []) {
16733
+ if (!treatment) return "";
16734
+ switch (treatment.kind) {
16735
+ case "contrast-glass": {
16736
+ const backgroundChannels = treatment.backgroundTone === "dark" ? "0 0 0" : "255 255 255";
16737
+ return renderHeaderPaintTargetRules(getHeaderPaintTargets(variant, themeId, "scrolled"), [`background-color: rgb(${backgroundChannels} / 0.60);`, ...surfaceRules]);
16738
+ }
16739
+ }
16740
+ }
16741
+ //#endregion
16742
+ //#region ../theme-core/src/header/containerSchema.ts
16743
+ const headerContainerSchema = z$1.object({
16744
+ rounded: z$1.enum([
16745
+ "none",
16746
+ "sm",
16747
+ "md",
16748
+ "lg",
16749
+ "xl",
16750
+ "2xl"
16751
+ ]).default("xl"),
16752
+ border: z$1.boolean().default(true),
16753
+ shadow: z$1.boolean().default(true),
16754
+ padding: z$1.enum([
16755
+ "sm",
16756
+ "md",
16757
+ "lg"
16758
+ ]).default("md"),
16759
+ tint: z$1.string().nullable().optional(),
16760
+ opacity: z$1.number().min(0).max(1).default(.12)
16761
+ }).optional();
16762
+ //#endregion
16771
16763
  //#region ../theme-core/src/schema.ts
16772
16764
  const axesSchema = z$1.object({
16773
16765
  tone: z$1.enum([
@@ -16797,16 +16789,6 @@ const axesSchema = z$1.object({
16797
16789
  "expressive"
16798
16790
  ])
16799
16791
  });
16800
- const colourHexString = z$1.string().regex(/^#([0-9A-Fa-f]{3}){1,2}$/);
16801
- const paletteColorSchema = z$1.object({
16802
- name: z$1.string().min(1),
16803
- hex: colourHexString
16804
- });
16805
- const paletteMetaSchema = z$1.object({ mode: z$1.enum(["light", "dark"]) });
16806
- const paletteSchema = z$1.object({
16807
- colors: z$1.array(paletteColorSchema),
16808
- meta: paletteMetaSchema
16809
- });
16810
16792
  const typographyStyleSchema = z$1.object({
16811
16793
  family: z$1.string().min(1),
16812
16794
  weight: z$1.enum([
@@ -16938,7 +16920,7 @@ const boxBackgroundSchema = z$1.object({
16938
16920
  color: tokenOrCssColorValueSchema.nullable().optional(),
16939
16921
  gradient: z$1.string().nullable().optional(),
16940
16922
  gradientPresetId: z$1.string().min(1).nullable().optional(),
16941
- image: mediaSchema$1.nullable().optional(),
16923
+ image: mediaSchema.nullable().optional(),
16942
16924
  objectFit: z$1.enum([
16943
16925
  "fill",
16944
16926
  "fit",
@@ -17186,25 +17168,6 @@ const navFontWeight = z$1.enum([
17186
17168
  ]);
17187
17169
  const headerMaxWidth = z$1.enum(["container", "full"]);
17188
17170
  const headerBarFrame = z$1.enum(["full-bleed", "inset-shell"]);
17189
- const headerContainerSchema = z$1.object({
17190
- rounded: z$1.enum([
17191
- "none",
17192
- "sm",
17193
- "md",
17194
- "lg",
17195
- "xl",
17196
- "2xl"
17197
- ]).default("xl"),
17198
- border: z$1.boolean().default(true),
17199
- shadow: z$1.boolean().default(true),
17200
- padding: z$1.enum([
17201
- "sm",
17202
- "md",
17203
- "lg"
17204
- ]).default("md"),
17205
- tint: z$1.string().nullable().optional(),
17206
- opacity: z$1.number().min(0).max(1).default(.12)
17207
- }).optional();
17208
17171
  const headerBorderSchema = componentBorderSchema.extend({ position: z$1.enum([
17209
17172
  "bottom",
17210
17173
  "top",
@@ -17322,7 +17285,7 @@ const headerBackgroundSchema = z$1.object({
17322
17285
  contentOwner: z$1.literal(siteChromeBackgroundOverrideOwner).optional(),
17323
17286
  color: tokenOrCssColorValueSchema.nullable().optional(),
17324
17287
  gradient: gradientConfigSchema.nullable().optional(),
17325
- image: mediaSchema$1.nullable().optional(),
17288
+ image: mediaSchema.nullable().optional(),
17326
17289
  textColor: tokenOrCssColorValueSchema.nullable().optional()
17327
17290
  });
17328
17291
  const headerSchema = z$1.object({
@@ -17331,7 +17294,8 @@ const headerSchema = z$1.object({
17331
17294
  shrinkOnScroll: z$1.boolean(),
17332
17295
  maxWidth: headerMaxWidth,
17333
17296
  barFrame: headerBarFrame.optional(),
17334
- logoOverride: mediaSchema$1.nullable().optional(),
17297
+ scrollTreatment: headerScrollTreatmentSchema,
17298
+ logoOverride: mediaSchema.nullable().optional(),
17335
17299
  background: headerBackgroundSchema.default({
17336
17300
  type: "color",
17337
17301
  color: "surface"
@@ -17343,6 +17307,7 @@ const headerSchema = z$1.object({
17343
17307
  navFontRole: z$1.enum(["body", "heading"]).optional(),
17344
17308
  navTypography: z$1.enum(["body", "heading"]).optional(),
17345
17309
  navTextSize: navLinkStyleSchema.shape.textSize,
17310
+ interactionPalette: headerInteractionPaletteSchema.optional(),
17346
17311
  navPlacement: z$1.enum(["end", "center"]).optional(),
17347
17312
  container: headerContainerSchema,
17348
17313
  border: headerBorderSchema,
@@ -22736,15 +22701,6 @@ const heroCopyFragment = defineFragment({
22736
22701
  */
22737
22702
  const BLOCK_BUTTON_ROLES = PUBLIC_BUTTON_ROLES;
22738
22703
  const blockButtonRoleSchema = z$1.enum(BLOCK_BUTTON_ROLES);
22739
- /**
22740
- * Temporary rollout boundary for persisted content written before issue #1220.
22741
- * Authoring remains strict through `blockButtonRoleSchema`; this parser exists
22742
- * only until the post-deploy role rewrite has been audited in production.
22743
- */
22744
- function canonicalizePersistedBlockButtonRole(value) {
22745
- return value === "link" || value === "tertiary" ? "ghost" : value;
22746
- }
22747
- const persistedBlockButtonRoleSchema = z$1.preprocess((value) => typeof value === "string" ? canonicalizePersistedBlockButtonRole(value) : value, blockButtonRoleSchema);
22748
22704
  const BLOCK_BUTTON_ROLE_LABELS = {
22749
22705
  primary: "Primary",
22750
22706
  secondary: "Secondary",
@@ -30329,86 +30285,6 @@ const weeklySlotAvailabilityBlockDefinition = {
30329
30285
  } }
30330
30286
  };
30331
30287
  //#endregion
30332
- //#region ../blocks/src/lib/media.ts
30333
- const PUBLIC_DOWNLOAD_MEDIA_TYPES = [
30334
- "document",
30335
- "spreadsheet",
30336
- "archive",
30337
- "audio"
30338
- ];
30339
- const hotspotSchema = z.object({
30340
- x: z.number().min(0).max(1),
30341
- y: z.number().min(0).max(1),
30342
- radius: z.number().optional()
30343
- });
30344
- const rotationSchema = z.union([
30345
- z.literal(0),
30346
- z.literal(90),
30347
- z.literal(180),
30348
- z.literal(270)
30349
- ]);
30350
- const rectSchema = z.tuple([
30351
- z.number(),
30352
- z.number(),
30353
- z.number(),
30354
- z.number()
30355
- ]);
30356
- const aspectCropSchema = z.object({
30357
- aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
30358
- rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema.optional()),
30359
- hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema.optional()),
30360
- rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema.optional())
30361
- });
30362
- const transformSchema = z.object({
30363
- aspectCrops: z.preprocess((value) => {
30364
- if (!value || typeof value !== "object" || Array.isArray(value)) return;
30365
- return value;
30366
- }, z.record(z.string(), aspectCropSchema.catch({}))).optional(),
30367
- rect: rectSchema.optional(),
30368
- hotspot: hotspotSchema.optional(),
30369
- rotation: rotationSchema.optional()
30370
- });
30371
- const mediaPosterSchema = z.discriminatedUnion("tag", [z.object({
30372
- tag: z.literal("storage"),
30373
- assetId: z.string().optional(),
30374
- storageBucket: z.string().min(1),
30375
- storagePath: z.string().min(1)
30376
- }), z.object({
30377
- tag: z.literal("external-src"),
30378
- assetId: z.string().optional(),
30379
- src: z.string().url()
30380
- })]);
30381
- const mediaBaseSchema = z.object({
30382
- purpose: z.string().optional(),
30383
- placeholder: z.boolean().default(true).optional(),
30384
- assetId: z.string().optional(),
30385
- identifier: z.string().optional(),
30386
- src: z.string().optional(),
30387
- alt: z.string().optional(),
30388
- filename: z.string().optional(),
30389
- mimeType: z.string().optional(),
30390
- width: z.number().optional(),
30391
- height: z.number().optional(),
30392
- storageBucket: z.string().optional(),
30393
- storagePath: z.string().optional(),
30394
- poster: mediaPosterSchema.optional(),
30395
- transform: transformSchema.optional()
30396
- });
30397
- const imageMediaSchema = mediaBaseSchema.extend({ type: z.literal("image") });
30398
- const videoMediaSchema = mediaBaseSchema.extend({ type: z.literal("video") });
30399
- const audioMediaSchema = mediaBaseSchema.extend({ type: z.literal("audio") });
30400
- const documentMediaSchema = mediaBaseSchema.extend({ type: z.literal("document") });
30401
- const spreadsheetMediaSchema = mediaBaseSchema.extend({ type: z.literal("spreadsheet") });
30402
- const archiveMediaSchema = mediaBaseSchema.extend({ type: z.literal("archive") });
30403
- const mediaSchema = z.discriminatedUnion("type", [
30404
- imageMediaSchema,
30405
- videoMediaSchema,
30406
- audioMediaSchema,
30407
- documentMediaSchema,
30408
- spreadsheetMediaSchema,
30409
- archiveMediaSchema
30410
- ]);
30411
- //#endregion
30412
30288
  //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
30413
30289
  const bookingDepositRefundPolicySchema = z$1.enum(["refundable", "non_refundable"]);
30414
30290
  const bookingInstalmentPlanSchema = z$1.union([
@@ -30847,7 +30723,7 @@ const publicEventSchema = z$1.object({
30847
30723
  presentation: z$1.object({
30848
30724
  cardTitleOverride: z$1.string().nullable().optional(),
30849
30725
  summary: z$1.string().nullable().optional(),
30850
- image: mediaSchema.nullable().optional()
30726
+ image: mediaSchema$1.nullable().optional()
30851
30727
  }).optional(),
30852
30728
  slug: z$1.string(),
30853
30729
  path: z$1.string().nullable(),
@@ -31474,7 +31350,7 @@ function isEventCalendarListLayout(value) {
31474
31350
  //#region ../blocks/src/system/runtime/nodes/shared/contract-schemas.ts
31475
31351
  const previewStageSchema = z$1.enum(["preview", "published"]);
31476
31352
  const registrationButtonVariantSchema = blockButtonRoleSchema;
31477
- const eventButtonVariantSchema = persistedBlockButtonRoleSchema;
31353
+ const eventButtonVariantSchema = blockButtonRoleSchema;
31478
31354
  const eventLayoutSchema = z$1.enum(eventCalendarListLayoutValues);
31479
31355
  const eventCalendarDisplayModeSchema = z$1.enum(eventCalendarDisplayModeValues);
31480
31356
  const eventCalendarDefaultViewSchema = z$1.enum(eventCalendarDefaultViewValues);
@@ -41640,7 +41516,7 @@ const newsletterSignupBlockDefinition = {
41640
41516
  //#endregion
41641
41517
  //#region ../blocks/src/system/blocks/team-members.ts
41642
41518
  const ITEM_NAME = "member";
41643
- const teamMemberPhotoSchema = mediaSchema.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
41519
+ const teamMemberPhotoSchema = mediaSchema$1.refine((media) => media.type === "image", { message: "Team member photos must be image media" }).nullable();
41644
41520
  const teamMemberDataSchema = z$1.object({
41645
41521
  _type: z$1.literal("teamMember"),
41646
41522
  id: z$1.string(),
@@ -43215,7 +43091,7 @@ function getBlockDefinition(name) {
43215
43091
  //#endregion
43216
43092
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
43217
43093
  function resolveBackgroundMedia(input) {
43218
- const parsedMedia = mediaSchema.safeParse(input.image);
43094
+ const parsedMedia = mediaSchema$1.safeParse(input.image);
43219
43095
  if (!parsedMedia.success) return null;
43220
43096
  switch (parsedMedia.data.type) {
43221
43097
  case "image":
@@ -44585,6 +44461,9 @@ function renderTrailingAffordanceIcon(affordance) {
44585
44461
  className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block"
44586
44462
  });
44587
44463
  }
44464
+ function isMissingRequiredLink(linkRequired, resolvedHref) {
44465
+ return linkRequired && resolvedHref.length === 0;
44466
+ }
44588
44467
  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 }) => {
44589
44468
  const content = value ?? children;
44590
44469
  if (!content) {
@@ -44593,12 +44472,16 @@ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md",
44593
44472
  }
44594
44473
  const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({ trailingIcon }));
44595
44474
  const resolvedHref = typeof href === "string" ? href.trim() : "";
44596
- if (linkRequired && resolvedHref.length === 0) {
44475
+ if (isMissingRequiredLink(linkRequired, resolvedHref)) {
44597
44476
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
44598
44477
  return null;
44599
44478
  }
44600
44479
  const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
44601
- const resolvedVariantId = parseThemeButtonVariantId(canonicalizePersistedBlockButtonRole(variantId));
44480
+ const resolvedVariantId = parseThemeButtonVariantId(variantId);
44481
+ if (variantId && !resolvedVariantId) {
44482
+ console.error("[ButtonNode] Invalid button variant", { variantId });
44483
+ return null;
44484
+ }
44602
44485
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
44603
44486
  variant: resolvedVariantId,
44604
44487
  size,
@@ -44727,8 +44610,9 @@ function iconForMediaType(type) {
44727
44610
  });
44728
44611
  }
44729
44612
  }
44730
- function normalizeButtonVariant(value) {
44731
- return isBlockButtonRole(value) ? value : "primary";
44613
+ function parseButtonVariant(value) {
44614
+ if (value === null || value === void 0) return "primary";
44615
+ return isBlockButtonRole(value) ? value : null;
44732
44616
  }
44733
44617
  function FileDownloadNode({ value, title, description, buttonLabel, buttonVariant, className }) {
44734
44618
  if (!value || !isDownloadableMediaType(value.type)) return null;
@@ -44738,7 +44622,11 @@ function FileDownloadNode({ value, title, description, buttonLabel, buttonVarian
44738
44622
  const heading = title?.trim() || filename;
44739
44623
  const body = description?.trim();
44740
44624
  const label = buttonLabel?.trim() || "Download";
44741
- const variant = normalizeButtonVariant(buttonVariant);
44625
+ const variant = parseButtonVariant(buttonVariant);
44626
+ if (!variant) {
44627
+ console.error("[FileDownloadNode] Invalid button variant", { buttonVariant });
44628
+ return null;
44629
+ }
44742
44630
  return /* @__PURE__ */ jsx("div", {
44743
44631
  className,
44744
44632
  children: /* @__PURE__ */ jsxs("div", {
@@ -51581,6 +51469,41 @@ function resolveColorTokenHex(theme, colorToken) {
51581
51469
  if (colorToken === "transparent") return null;
51582
51470
  return expandPalette(theme.palette)[colorToken] ?? null;
51583
51471
  }
51472
+ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
51473
+ `min-width: 12rem;`,
51474
+ `width: max-content;`,
51475
+ `max-width: min(22rem, calc(100vw - 2rem));`,
51476
+ `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
51477
+ ];
51478
+ //#endregion
51479
+ //#region ../theme-core/src/header/surfaceRules.ts
51480
+ /** Compile the visual surface declarations independently of paint geometry. */
51481
+ function buildHeaderSurfaceRules(header, tokens, blur) {
51482
+ const base = [];
51483
+ const scrolled = [];
51484
+ const background = header.background;
51485
+ if (background.type === "color") base.push(`background-color: ${tokens.getColor(background.color || "surface")};`);
51486
+ else if (background.type === "gradient" && background.gradient) {
51487
+ const stops = background.gradient.stops.map((stop) => tokens.getColor(stop.color)).join(", ");
51488
+ base.push(`background-image: linear-gradient(${background.gradient.angle ?? 180}deg, ${stops});`);
51489
+ }
51490
+ const blurRules = [`backdrop-filter: ${blur};`, `-webkit-backdrop-filter: ${blur};`];
51491
+ base.push(...blurRules);
51492
+ scrolled.push(...blurRules);
51493
+ const borderWidth = getComponentBorderWidthPx(header.border?.width ?? "none");
51494
+ if (!header.border || borderWidth === "0") return {
51495
+ base,
51496
+ scrolled,
51497
+ border: []
51498
+ };
51499
+ const color = rgbColorValue(header.border.colorToken?.trim() || "border");
51500
+ const style = header.border.style === "dashed" ? "dashed" : "solid";
51501
+ return {
51502
+ base,
51503
+ scrolled,
51504
+ border: header.border.position === "both" ? [`border-top: ${borderWidth} ${style} ${color};`, `border-bottom: ${borderWidth} ${style} ${color};`] : [`border-${header.border.position}: ${borderWidth} ${style} ${color};`]
51505
+ };
51506
+ }
51584
51507
  //#endregion
51585
51508
  //#region ../theme-core/src/navigation/presets.ts
51586
51509
  /**
@@ -51742,12 +51665,71 @@ function getNavLinkPreset(presetId) {
51742
51665
  return NAV_LINK_PRESETS[presetId];
51743
51666
  }
51744
51667
  Object.keys(NAV_LINK_PRESETS);
51745
- const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
51746
- `min-width: 12rem;`,
51747
- `width: max-content;`,
51748
- `max-width: min(22rem, calc(100vw - 2rem));`,
51749
- `transform: translateX(var(--nav-dropdown-shift-x, 0px));`
51750
- ];
51668
+ //#endregion
51669
+ //#region ../theme-core/src/header/legacyNavLinkStyle.ts
51670
+ function buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize) {
51671
+ const navStyle = header.navStyle ?? "minimal";
51672
+ const basePreset = getNavLinkPreset(navStyle);
51673
+ if (!basePreset) return null;
51674
+ const style = {
51675
+ ...basePreset,
51676
+ fontWeight: header.navWeight ?? basePreset.fontWeight,
51677
+ colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
51678
+ ...contrastTreatment ? { contrastTreatment } : {},
51679
+ ...navTextSize ? { textSize: navTextSize } : {}
51680
+ };
51681
+ if (header.navWeight === "bold" && navStyle === "solid") style.textTransform = "uppercase";
51682
+ applyLegacyNavEffects(style, header);
51683
+ applyLegacyGlassTreatment(style, header, navStyle);
51684
+ return style;
51685
+ }
51686
+ function applyLegacyNavEffects(style, header) {
51687
+ if (!header.navEffects) return;
51688
+ const effects = style.effects = {
51689
+ ...style.effects,
51690
+ hover: [...style.effects?.hover ?? []],
51691
+ active: [...style.effects?.active ?? []]
51692
+ };
51693
+ if (header.navEffects.glow) effects.hover.push({
51694
+ effectId: "outer-glow",
51695
+ options: { spread: 5 }
51696
+ });
51697
+ if (header.navEffects.neumorphic) {
51698
+ effects.hover.push({
51699
+ effectId: "neumorphic-shadow",
51700
+ options: { mode: "pressed" }
51701
+ });
51702
+ effects.hover.push({
51703
+ effectId: "text-color-change",
51704
+ options: { hoverColorToken: "primary" }
51705
+ });
51706
+ }
51707
+ if (header.navEffects.underlineGradient) effects.hover.push({
51708
+ effectId: "border-bottom-grow",
51709
+ options: { origin: "center" }
51710
+ });
51711
+ }
51712
+ function applyLegacyGlassTreatment(style, header, navStyle) {
51713
+ if (header.navContainer?.type !== "glass" || navStyle !== "minimal") return;
51714
+ style.borderRadius = "full";
51715
+ style.effects = {
51716
+ ...style.effects,
51717
+ hover: glassStateEffects(10),
51718
+ active: glassStateEffects(18)
51719
+ };
51720
+ }
51721
+ function glassStateEffects(opacity) {
51722
+ return [{
51723
+ effectId: "background-on-hover-alpha",
51724
+ options: {
51725
+ colorToken: "neutral-50",
51726
+ opacity
51727
+ }
51728
+ }, {
51729
+ effectId: "text-color-change",
51730
+ options: { hoverColorToken: "neutral-50" }
51731
+ }];
51732
+ }
51751
51733
  //#endregion
51752
51734
  //#region ../theme-core/src/header/generateHeaderCss.ts
51753
51735
  const HEADER_BLUR = "blur(12px)";
@@ -51777,8 +51759,8 @@ function generateHeaderCss(options) {
51777
51759
  const cssChunks = [];
51778
51760
  const headerContrastTreatment = resolveHeaderContrastTreatment(header);
51779
51761
  const headerNavTextSize = resolveHeaderNavTextSize(header);
51780
- cssChunks.push(generateHeaderRootStyles(header, themeId, tokens, theme));
51781
- cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId));
51762
+ cssChunks.push(generateHeaderRootStyles(header, themeId, tokens));
51763
+ cssChunks.push(generateMobileOverlayBackdropFilterFix(themeId, header.variant));
51782
51764
  cssChunks.push(generateLogoStyles({
51783
51765
  logo: header.logo,
51784
51766
  themeId,
@@ -51816,56 +51798,34 @@ function isClearSplitHeaderShape(header) {
51816
51798
  function isDetachedFloatingHeaderShape(header) {
51817
51799
  return header.variant === "floating" && !header.container;
51818
51800
  }
51819
- function generateMobileOverlayBackdropFilterFix(themeId) {
51820
- 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`;
51821
- }
51822
51801
  /**
51823
51802
  * Generate root header container styles
51824
51803
  */
51825
- function generateHeaderRootStyles(header, themeId, tokens, _theme) {
51804
+ function generateHeaderRootStyles(header, themeId, tokens) {
51826
51805
  const selector = `:where([data-theme-scope="${themeId}"]) .header-root`;
51827
- const backgroundSelector = `:where([data-theme-scope="${themeId}"]) .header-root::before`;
51828
51806
  const rules = [];
51829
- const backgroundRules = [];
51830
51807
  const navContainerType = header.navContainer?.type ?? "none";
51831
51808
  const isContainedNav = navContainerType === "pill" || navContainerType === "glass";
51832
51809
  rules.push("position: relative;");
51833
51810
  rules.push("isolation: isolate;");
51834
- if (!isContainedNav) {
51835
- const bg = header.background;
51836
- if (bg.type === "color") {
51837
- const bgColor = tokens.getColor(bg.color || "surface");
51838
- backgroundRules.push(`background-color: ${bgColor};`);
51839
- } else if (bg.type === "gradient" && bg.gradient) {
51840
- const stops = bg.gradient.stops.map((s) => tokens.getColor(s.color)).join(", ");
51841
- const angle = bg.gradient.angle ?? 180;
51842
- backgroundRules.push(`background-image: linear-gradient(${angle}deg, ${stops});`);
51843
- }
51844
- backgroundRules.push(`backdrop-filter: ${HEADER_BLUR};`);
51845
- backgroundRules.push(`-webkit-backdrop-filter: ${HEADER_BLUR};`);
51846
- if (header.border) {
51847
- const borderWidth = getComponentBorderWidthPx(header.border.width);
51848
- if (borderWidth !== "0") {
51849
- const borderToken = header.border?.colorToken?.trim() || "border";
51850
- const borderColor = tokens.getColor(borderToken);
51851
- const borderStyle = header.border.style === "dashed" ? "dashed" : "solid";
51852
- if (header.border.position === "bottom") rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
51853
- else if (header.border.position === "top") rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
51854
- else if (header.border.position === "both") {
51855
- rules.push(`border-top: ${borderWidth} ${borderStyle} ${borderColor};`);
51856
- rules.push(`border-bottom: ${borderWidth} ${borderStyle} ${borderColor};`);
51857
- }
51858
- }
51859
- }
51860
- }
51811
+ const surfaceRules = isContainedNav ? {
51812
+ base: [],
51813
+ scrolled: [],
51814
+ border: []
51815
+ } : buildHeaderSurfaceRules(header, tokens, HEADER_BLUR);
51816
+ const floatingSurfaceBorder = header.variant === "floating";
51817
+ if (!floatingSurfaceBorder) rules.push(...surfaceRules.border);
51818
+ const basePaintRules = floatingSurfaceBorder ? [...surfaceRules.base, ...surfaceRules.border] : surfaceRules.base;
51819
+ const scrolledPaintRules = floatingSurfaceBorder ? [...surfaceRules.scrolled, ...surfaceRules.border] : surfaceRules.scrolled;
51861
51820
  if (header.positioning === "sticky" || header.positioning === "fixed") {
51862
51821
  const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
51863
51822
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
51864
51823
  }
51865
51824
  const baseBlock = `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
51866
51825
  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`;
51867
- if (isContainedNav || backgroundRules.length === 0) return `${baseBlock}\n${overlayFix}`;
51868
- 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) : ""}`;
51826
+ const scrollTreatmentStyles = generateHeaderScrollTreatmentStyles(header.scrollTreatment, themeId, header.variant, scrolledPaintRules);
51827
+ if (isContainedNav || basePaintRules.length === 0) return `${baseBlock}\n${overlayFix}${scrollTreatmentStyles}`;
51828
+ return `${baseBlock}\n${renderHeaderPaintTargetRules(getHeaderPaintTargets(header.variant, themeId), basePaintRules)}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}${scrollTreatmentStyles}`;
51869
51829
  }
51870
51830
  /**
51871
51831
  * Reshapes the full-bleed header paint layer into a contained brand capsule at
@@ -51910,10 +51870,10 @@ function generateLogoStyles(input) {
51910
51870
  else rules.push(`font-family: var(--font-heading);`);
51911
51871
  if (logo) {
51912
51872
  if (logo.letterSpacing && logo.letterSpacing !== "normal") rules.push(`letter-spacing: ${{
51913
- "normal": "0em",
51914
- "wide": "0.05em",
51915
- "wider": "0.1em",
51916
- "widest": "0.15em"
51873
+ normal: "0em",
51874
+ wide: "0.05em",
51875
+ wider: "0.1em",
51876
+ widest: "0.15em"
51917
51877
  }[logo.letterSpacing]};`);
51918
51878
  if (logo.gradient) {
51919
51879
  rules.push(`background: linear-gradient(to right, ${primaryColor}, ${accentColor});`);
@@ -51986,71 +51946,11 @@ function generateNavLinkStyles(header, themeId, tokens, theme, contrastTreatment
51986
51946
  } : header.navLinkStyle, navPreferences),
51987
51947
  className: "header-nav-link"
51988
51948
  });
51989
- const navStyle = header.navStyle ?? "minimal";
51990
- const basePreset = getNavLinkPreset(navStyle);
51991
- if (!basePreset) {
51992
- console.warn(`[generateHeaderCss] Nav link preset not found: ${navStyle}`);
51949
+ const mergedStyle = buildLegacyHeaderNavLinkStyle(header, contrastTreatment, navTextSize);
51950
+ if (!mergedStyle) {
51951
+ console.warn(`[generateHeaderCss] Nav link preset not found: ${header.navStyle}`);
51993
51952
  return "";
51994
51953
  }
51995
- const mergedStyle = {
51996
- ...basePreset,
51997
- fontWeight: header.navWeight ?? basePreset.fontWeight,
51998
- colorToken: (header.navColor ?? header.textColor)?.trim() || basePreset.colorToken,
51999
- ...contrastTreatment ? { contrastTreatment } : {},
52000
- ...navTextSize ? { textSize: navTextSize } : {}
52001
- };
52002
- if (header.navWeight === "bold" && navStyle === "solid") mergedStyle.textTransform = "uppercase";
52003
- if (header.navEffects) {
52004
- const effects = mergedStyle.effects = {
52005
- ...mergedStyle.effects,
52006
- hover: [...mergedStyle.effects?.hover || []],
52007
- active: [...mergedStyle.effects?.active || []]
52008
- };
52009
- if (header.navEffects.glow) effects.hover.push({
52010
- effectId: "outer-glow",
52011
- options: { spread: 5 }
52012
- });
52013
- if (header.navEffects.neumorphic) {
52014
- effects.hover.push({
52015
- effectId: "neumorphic-shadow",
52016
- options: { mode: "pressed" }
52017
- });
52018
- effects.hover.push({
52019
- effectId: "text-color-change",
52020
- options: { hoverColorToken: "primary" }
52021
- });
52022
- }
52023
- if (header.navEffects.underlineGradient) effects.hover.push({
52024
- effectId: "border-bottom-grow",
52025
- options: { origin: "center" }
52026
- });
52027
- }
52028
- if ((header.navContainer?.type ?? "none") === "glass" && navStyle === "minimal") {
52029
- mergedStyle.borderRadius = "full";
52030
- mergedStyle.effects = {
52031
- ...mergedStyle.effects,
52032
- hover: [{
52033
- effectId: "background-on-hover-alpha",
52034
- options: {
52035
- colorToken: "neutral-50",
52036
- opacity: 10
52037
- }
52038
- }, {
52039
- effectId: "text-color-change",
52040
- options: { hoverColorToken: "neutral-50" }
52041
- }],
52042
- active: [{
52043
- effectId: "background-on-hover-alpha",
52044
- options: {
52045
- colorToken: "neutral-50",
52046
- opacity: 18
52047
- }
52048
- }, {
52049
- effectId: "text-color-change",
52050
- options: { hoverColorToken: "neutral-50" }
52051
- }]
52052
- };
52053
- }
52054
51954
  return generateNavLinkCSS({
52055
51955
  themeId,
52056
51956
  tokens,
@@ -52078,10 +51978,10 @@ function generateDropdownContainerStyles(header, themeId, tokens) {
52078
51978
  if (shadowVar) rules.push(`box-shadow: ${shadowVar};`);
52079
51979
  const borderRadius = dropdownStyle?.borderRadius ?? "md";
52080
51980
  rules.push(`border-radius: ${{
52081
- "none": "0",
52082
- "sm": "0.25rem",
52083
- "md": "0.5rem",
52084
- "lg": "0.75rem"
51981
+ none: "0",
51982
+ sm: "0.25rem",
51983
+ md: "0.5rem",
51984
+ lg: "0.75rem"
52085
51985
  }[borderRadius]};`);
52086
51986
  rules.push(`padding: 0.5rem 0;`);
52087
51987
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
@@ -52136,16 +52036,16 @@ function generateDropdownLinkStyles(header, themeId, tokens, theme) {
52136
52036
  const additionalRules = [];
52137
52037
  const letterSpacing = configuredDropdownStyle?.letterSpacing ?? "normal";
52138
52038
  if (letterSpacing !== "normal") additionalRules.push(`letter-spacing: ${{
52139
- "normal": "0em",
52140
- "wide": "0.05em",
52141
- "wider": "0.1em"
52039
+ normal: "0em",
52040
+ wide: "0.05em",
52041
+ wider: "0.1em"
52142
52042
  }[letterSpacing]};`);
52143
52043
  const textSize = configuredDropdownStyle?.textSize ?? "sm";
52144
52044
  additionalRules.push(`font-size: ${{
52145
- "xs": "0.75rem",
52146
- "sm": "0.875rem",
52147
- "base": "1rem",
52148
- "lg": "1.125rem"
52045
+ xs: "0.75rem",
52046
+ sm: "0.875rem",
52047
+ base: "1rem",
52048
+ lg: "1.125rem"
52149
52049
  }[textSize]};`);
52150
52050
  if (additionalRules.length > 0) return baseCSS + `\n${`:where([data-theme-scope="${themeId}"]) .nav-dropdown-link`} {\n ${additionalRules.join("\n ")}\n}\n`;
52151
52051
  return baseCSS;
@@ -52241,18 +52141,18 @@ function generateFloatingContainerStyles(header, themeId, tokens) {
52241
52141
  rules.push(`-webkit-backdrop-filter: ${FLOATING_BLUR};`);
52242
52142
  if (container.border) rules.push(`border: 1px solid rgb(255 255 255 / 0.2);`);
52243
52143
  rules.push(`border-radius: ${{
52244
- "none": "0",
52245
- "sm": "0.375rem",
52246
- "md": "0.5rem",
52247
- "lg": "0.75rem",
52248
- "xl": "1rem",
52144
+ none: "0",
52145
+ sm: "0.375rem",
52146
+ md: "0.5rem",
52147
+ lg: "0.75rem",
52148
+ xl: "1rem",
52249
52149
  "2xl": "1.5rem"
52250
52150
  }[container.rounded]};`);
52251
52151
  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);`);
52252
52152
  rules.push(`padding: ${{
52253
- "sm": "1rem 1.5rem",
52254
- "md": "1.5rem 2rem",
52255
- "lg": "2rem 2.5rem"
52153
+ sm: "1rem 1.5rem",
52154
+ md: "1.5rem 2rem",
52155
+ lg: "2rem 2.5rem"
52256
52156
  }[container.padding]};`);
52257
52157
  return `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
52258
52158
  }