riverbankcms 0.4.0 → 0.4.3

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { At as ok, B as parseUtcIsoDateTimeString, Ct as unsafeAsSiteScopedStoragePath, D as mapNonEmptyArray, Dt as unsafeAsUploadSessionId, E as fromArray, Et as unsafeAsStoragePath, O as hasText, Ot as unsafeAsUserId, St as unsafeAsSiteId, Tt as unsafeAsStorageBucketName, Z as assertNever, _ as parseFooterCompositionV1, _t as unsafeAsPositiveByteCount, a as parseVerticalPresetId, at as unsafeAsBookingRequirementId, bt as unsafeAsSafeDownloadFilename, c as EVENT_PRESET_VALUES, dt as unsafeAsEventOfferingId, f as createSecret, ft as unsafeAsEventSeriesId, g as footerNavigationLayouts, gt as unsafeAsOriginalFilename, h as stableJsonStringify, ht as unsafeAsOccurrenceId, i as parseVerticalId, k as isPresent, kt as err, l as ORDINARY_EVENT_PRESET_VALUES, lt as unsafeAsDetectedMimeType, m as parseManagementKey, mt as unsafeAsMediaAssetId, n as canonicalizeConfiguredBookingVerticalConfig, nt as parseSiteId, o as resolveSiteVerticalBookingConfig, ot as unsafeAsBookingSessionId, p as exposeSecret, pt as unsafeAsFileChecksumSha256, st as unsafeAsDeclaredMimeType, ut as unsafeAsEntitlementId, vt as unsafeAsPositiveSeconds, w as isCanonicalRichTextDoc, xt as unsafeAsSiteFontId, yt as unsafeAsProductId } from "./src-BRAF1Dee.mjs";
3
- import { a as classifySdkEventPricing, n as sdkEventOccurrenceInputSchema, o as classifySdkEventPaymentTerms } from "./sdk-event-upsert-C6zsxDcf.mjs";
4
- import { t as CliSdkPeerError } from "./sdk-peer-DZNUBvf5.mjs";
2
+ import { At as ok, B as parseUtcIsoDateTimeString, Ct as unsafeAsSiteScopedStoragePath, D as mapNonEmptyArray, Dt as unsafeAsUploadSessionId, E as fromArray, Et as unsafeAsStoragePath, O as hasText, Ot as unsafeAsUserId, St as unsafeAsSiteId, Tt as unsafeAsStorageBucketName, Z as assertNever, _ as parseFooterCompositionV1, _t as unsafeAsPositiveByteCount, a as parseVerticalPresetId, at as unsafeAsBookingRequirementId, bt as unsafeAsSafeDownloadFilename, c as EVENT_PRESET_VALUES, dt as unsafeAsEventOfferingId, f as createSecret, ft as unsafeAsEventSeriesId, g as footerNavigationLayouts, gt as unsafeAsOriginalFilename, h as stableJsonStringify, ht as unsafeAsOccurrenceId, i as parseVerticalId, k as isPresent, kt as err, l as ORDINARY_EVENT_PRESET_VALUES, lt as unsafeAsDetectedMimeType, m as parseManagementKey, mt as unsafeAsMediaAssetId, n as canonicalizeConfiguredBookingVerticalConfig, nt as parseSiteId, o as resolveSiteVerticalBookingConfig, ot as unsafeAsBookingSessionId, p as exposeSecret, pt as unsafeAsFileChecksumSha256, st as unsafeAsDeclaredMimeType, ut as unsafeAsEntitlementId, vt as unsafeAsPositiveSeconds, w as isCanonicalRichTextDoc, xt as unsafeAsSiteFontId, yt as unsafeAsProductId } from "./src-DKm0bLEA.mjs";
3
+ import { a as classifySdkEventPricing, n as sdkEventOccurrenceInputSchema, o as classifySdkEventPaymentTerms } from "./sdk-event-upsert-Dy08IXYL.mjs";
4
+ import { t as CliSdkPeerError } from "./sdk-peer-CeNepTFW.mjs";
5
5
  import "node:module";
6
6
  import { Command } from "commander";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -214,6 +214,96 @@ const sdkEventOccurrenceResponseSchema = z.object({ occurrence: sdkManagementEve
214
214
  const sdkDeleteEventOccurrenceResponseSchema = z.object({ deleted: z.literal(true) });
215
215
  const sdkReorderResponseSchema = z.object({ reordered: z.literal(true) });
216
216
 
217
+ //#endregion
218
+ //#region ../blocks/src/system/types/link.ts
219
+ const nullableString = z.union([z.string().min(1), z.null()]);
220
+ const RESOLVED_INTERNAL_LINK_ENTITY_TYPES = [
221
+ "page",
222
+ "content",
223
+ "pageSurface"
224
+ ];
225
+ function isResolvedInternalLinkEntityType(value) {
226
+ return typeof value === "string" && RESOLVED_INTERNAL_LINK_ENTITY_TYPES.includes(value);
227
+ }
228
+ const resolvedInternalLinkKeys = [
229
+ "entityId",
230
+ "entityType",
231
+ "href",
232
+ "title",
233
+ "typeLabel"
234
+ ];
235
+ const internalRouteOnlyLinkSchema = z.object({
236
+ kind: z.literal("internal"),
237
+ routeId: z.string().min(1)
238
+ }).passthrough().superRefine((value, ctx) => {
239
+ const hasResolvedMetadata = resolvedInternalLinkKeys.some((key) => value[key] != null);
240
+ if (!hasResolvedMetadata) return;
241
+ ctx.addIssue({
242
+ code: "custom",
243
+ message: "Internal links with resolved metadata must include entityId, entityType, href, title, and typeLabel"
244
+ });
245
+ });
246
+ const internalResolvedLinkSchema = z.object({
247
+ kind: z.literal("internal"),
248
+ routeId: z.string().min(1),
249
+ entityId: z.string().min(1),
250
+ entityType: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
251
+ href: z.string().min(1),
252
+ title: z.string().min(1),
253
+ typeLabel: z.string().min(1),
254
+ contentTypeKey: nullableString.optional(),
255
+ contentTypeName: nullableString.optional(),
256
+ updatedAt: nullableString.optional()
257
+ }).passthrough();
258
+ const internalLinkSchema = z.union([internalResolvedLinkSchema, internalRouteOnlyLinkSchema]);
259
+ const externalLinkSchema$1 = z.object({
260
+ kind: z.literal("external"),
261
+ href: z.string().min(1)
262
+ }).passthrough();
263
+ const customLinkSchema$1 = z.object({
264
+ kind: z.literal("url"),
265
+ href: z.string().min(1)
266
+ }).passthrough();
267
+ const pageLinkSchema$1 = z.object({
268
+ kind: z.literal("page"),
269
+ identifier: z.string().min(1)
270
+ }).passthrough();
271
+ const entryLinkSchema$1 = z.object({
272
+ kind: z.literal("entry"),
273
+ contentType: z.string().min(1),
274
+ identifier: z.string().min(1)
275
+ }).passthrough();
276
+ const linkSchema = z.union([
277
+ internalLinkSchema,
278
+ externalLinkSchema$1,
279
+ customLinkSchema$1,
280
+ pageLinkSchema$1,
281
+ entryLinkSchema$1
282
+ ]);
283
+ function visitLinkValueReferences(value, visitor) {
284
+ const parsed = linkSchema.safeParse(value);
285
+ if (!parsed.success) {
286
+ return;
287
+ }
288
+ const link = parsed.data;
289
+ switch (link.kind) {
290
+ case "internal":
291
+ visitor.routeIds.add(link.routeId);
292
+ return;
293
+ case "page":
294
+ visitor.pageIdentifiers.add(link.identifier);
295
+ return;
296
+ case "entry":
297
+ visitor.entryIdentifiers.add(link.contentType, link.identifier);
298
+ return;
299
+ case "external":
300
+ case "url": return;
301
+ }
302
+ }
303
+ function isInternalResolvedLinkValue(value) {
304
+ return value?.kind === "internal" && "entityId" in value && "entityType" in value && "href" in value && "title" in value && "typeLabel" in value && typeof value.entityId === "string" && isResolvedInternalLinkEntityType(value.entityType) && typeof value.href === "string" && typeof value.title === "string" && typeof value.typeLabel === "string";
305
+ }
306
+
217
307
  //#endregion
218
308
  //#region ../api/src/navigation/contracts.ts
219
309
  /**
@@ -244,7 +334,7 @@ const internalLinkPayloadSchema = z.object({
244
334
  kind: z.literal("internal"),
245
335
  routeId: z.string().uuid(),
246
336
  entityId: z.string().uuid(),
247
- entityType: z.enum(["page", "content"]),
337
+ entityType: z.enum(RESOLVED_INTERNAL_LINK_ENTITY_TYPES),
248
338
  href: z.string().min(1),
249
339
  title: z.string().min(1),
250
340
  typeLabel: z.string().min(1),
@@ -10164,12 +10254,8 @@ const legacyHeaderVariantValues = Object.keys(legacyHeaderVariants);
10164
10254
  * `@riverbankcms/api` is `z.input<typeof themeSchema>`, so a widened input here
10165
10255
  * would leak straight into a public type.
10166
10256
  *
10167
- * Not every read of a persisted theme goes through the schema:
10168
- * `resolveRuntimeTheme` in
10169
- * `apps/dashboard/src/server/services/sites/runtimeSiteResponse.ts` returns the
10170
- * raw database JSON asserted as `Theme` with no parse, so a theme still
10171
- * carrying a legacy spelling reaches the theme editor un-aliased. That gap
10172
- * predates this alias and is harmless while persisted usage is zero.
10257
+ * Persisted runtime themes are admitted through `parseThemeForPersistence`
10258
+ * before reaching consumers, so legacy spellings normalize at that boundary.
10173
10259
  */
10174
10260
  const headerVariantWithLegacyAliasSchema = z.enum([...headerVariantValues, ...legacyHeaderVariantValues]).transform((value) => value in legacyHeaderVariants ? legacyHeaderVariants[value] : value);
10175
10261
 
@@ -10814,7 +10900,6 @@ const navFontWeight = z.enum([
10814
10900
  "bold"
10815
10901
  ]);
10816
10902
  const headerMaxWidth = z.enum(["container", "full"]);
10817
- const headerBarFrame = z.enum(["full-bleed", "inset-shell"]);
10818
10903
  const headerBorderSchema = componentBorderSchema.extend({ position: z.enum([
10819
10904
  "bottom",
10820
10905
  "top",
@@ -10843,12 +10928,6 @@ const headerLogoTextSchema = z.object({
10843
10928
  ]).optional(),
10844
10929
  hideOnShrink: z.boolean().optional()
10845
10930
  }).optional();
10846
- const navEffectsSchema = z.object({
10847
- underlineGradient: z.boolean().default(false),
10848
- glow: z.boolean().default(false),
10849
- glowColor: z.string().optional(),
10850
- neumorphic: z.boolean().default(false)
10851
- }).optional();
10852
10931
  const dropdownStyleSchema = z.object({
10853
10932
  background: themeColorTokenSchema.default("surface"),
10854
10933
  textColor: themeColorTokenSchema.default("text"),
@@ -10940,9 +11019,7 @@ const headerSchema = z.object({
10940
11019
  positioning: headerPositioning,
10941
11020
  shrinkOnScroll: z.boolean(),
10942
11021
  maxWidth: headerMaxWidth,
10943
- barFrame: headerBarFrame.optional(),
10944
11022
  scrollTreatment: headerScrollTreatmentSchema,
10945
- logoOverride: mediaSchema.nullable().optional(),
10946
11023
  background: headerBackgroundSchema.default({
10947
11024
  type: "color",
10948
11025
  color: "surface"
@@ -10954,13 +11031,11 @@ const headerSchema = z.object({
10954
11031
  navFontRole: z.enum(["body", "heading"]).optional(),
10955
11032
  navTextSize: navLinkStyleSchema.shape.textSize,
10956
11033
  interactionPalette: headerInteractionPaletteSchema.optional(),
10957
- navPlacement: z.enum(["end", "center"]).optional(),
10958
11034
  container: headerContainerSchema,
10959
11035
  border: headerBorderSchema,
10960
11036
  shadow: componentShadowSchema.optional(),
10961
11037
  logo: logoStyleSchema,
10962
11038
  logoText: headerLogoTextSchema,
10963
- navEffects: navEffectsSchema,
10964
11039
  navContainer: navContainerSchema,
10965
11040
  navLinkStyle: navLinkStyleSchema.optional(),
10966
11041
  ctaGap: headerCtaGapSchema.optional(),
@@ -12548,7 +12623,7 @@ const blockAppearancePresets = [
12548
12623
  id: "schedule-details-brand-depth",
12549
12624
  target: "events",
12550
12625
  label: "Brand-depth schedule details",
12551
- blockKinds: ["block.event-details", "block.course-details"],
12626
+ blockKinds: ["block.event-details"],
12552
12627
  design: {
12553
12628
  sectionSurface: "brand-depth-band",
12554
12629
  contentFrame: plainFrame,
@@ -16270,90 +16345,6 @@ function deriveHeaderLogoShapeFromDimensions({ width, height }) {
16270
16345
  }
16271
16346
  const defaultHeaderLogoContext = { shape: "text-only" };
16272
16347
 
16273
- //#endregion
16274
- //#region ../theme-core/src/site-styles/headerInteractionPalette.ts
16275
- const clearSplitInteractionPalette = defineLookOptionGroup({
16276
- id: "interaction-palette",
16277
- label: "Hover colour",
16278
- defaultOptionId: "accent",
16279
- options: [
16280
- {
16281
- id: "accent",
16282
- label: "Accent"
16283
- },
16284
- {
16285
- id: "primary",
16286
- label: "Primary"
16287
- },
16288
- {
16289
- id: "secondary",
16290
- label: "Secondary"
16291
- }
16292
- ]
16293
- });
16294
- function resolveHeaderInteractionPaletteControl(group, preference) {
16295
- if (!group) return { kind: "unavailable" };
16296
- if (preference === "recommended") {
16297
- const resolution$1 = resolveLookOption(group, undefined);
16298
- return availableControlState(group, preference, resolution$1.option.id, null);
16299
- }
16300
- const resolution = resolveHeaderInteractionPalette(group, preference);
16301
- return availableControlState(group, preference, resolution.option.id, resolution.kind === "repaired" ? {
16302
- requested: preference,
16303
- fallback: resolution.option.id,
16304
- reason: resolution.reason
16305
- } : null);
16306
- }
16307
- function availableControlState(group, preference, effectivePalette, repair$1) {
16308
- return {
16309
- kind: "available",
16310
- preference,
16311
- effectivePalette,
16312
- options: [{
16313
- value: "recommended",
16314
- label: `Recommended (${defaultOptionLabel(group)})`
16315
- }, ...group.options.map((option) => ({
16316
- value: option.id,
16317
- label: option.label
16318
- }))],
16319
- repair: repair$1
16320
- };
16321
- }
16322
- function applyHeaderInteractionPalette(header, group, preference) {
16323
- if (!group) return header;
16324
- if (!header.navLinkStyle) {
16325
- throw new Error(`Header interaction palette "${group.id}" requires a nav link style.`);
16326
- }
16327
- const palette = resolveHeaderInteractionPalette(group, preference).option.id;
16328
- const pair = headerInteractionPalettePair(palette);
16329
- const pillEffect = {
16330
- effectId: "background-on-hover",
16331
- options: {
16332
- colorToken: pair.backgroundToken,
16333
- textColorToken: pair.foregroundToken
16334
- }
16335
- };
16336
- return {
16337
- ...header,
16338
- navLinkStyle: {
16339
- ...header.navLinkStyle,
16340
- hoverColorToken: null,
16341
- borderRadius: "full",
16342
- effects: {
16343
- ...header.navLinkStyle.effects,
16344
- hover: [pillEffect],
16345
- focus: [pillEffect]
16346
- }
16347
- }
16348
- };
16349
- }
16350
- function resolveHeaderInteractionPalette(group, preference) {
16351
- return resolveLookOption(group, preference === "recommended" ? undefined : preference);
16352
- }
16353
- function defaultOptionLabel(group) {
16354
- return resolveLookOption(group, undefined).option.label;
16355
- }
16356
-
16357
16348
  //#endregion
16358
16349
  //#region ../theme-core/src/site-styles/headerLayoutCatalog.ts
16359
16350
  const titleOnlyLogoAccommodation = {
@@ -16570,43 +16561,37 @@ const headerStyleCatalog = defineExactCatalog()([
16570
16561
  id: asHeaderStyleId("minimal"),
16571
16562
  label: "Minimal",
16572
16563
  description: "Quiet surface with simple color-change navigation.",
16573
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16574
- navTypography: "plain"
16564
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16575
16565
  },
16576
16566
  {
16577
16567
  id: asHeaderStyleId("fine-line"),
16578
16568
  label: "Seamless",
16579
16569
  description: "Borderless surface with underline hover for a quieter page transition.",
16580
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16581
- navTypography: "plain"
16570
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16582
16571
  },
16583
16572
  {
16584
16573
  id: asHeaderStyleId("soft-bar"),
16585
16574
  label: "Soft Bar",
16586
16575
  description: "Soft tinted surface with gentle pill hover states.",
16587
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16588
- navTypography: "plain"
16576
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16589
16577
  },
16590
16578
  {
16591
16579
  id: asHeaderStyleId("pill-nav"),
16592
16580
  label: "Pill Nav",
16593
16581
  description: "A calm pill navigation rail over a neutral header.",
16594
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16595
- navTypography: "plain"
16582
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16596
16583
  },
16597
16584
  {
16598
16585
  id: asHeaderStyleId("brand-bar"),
16599
16586
  label: "Brand Bar",
16600
16587
  description: "Solid brand surface with high-contrast navigation.",
16601
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16602
- navTypography: "brand-caps"
16588
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16603
16589
  },
16604
16590
  {
16605
16591
  id: asHeaderStyleId("brand-underline"),
16606
16592
  label: "Brand Underline",
16607
16593
  description: "Brand surface with underline-grow navigation.",
16608
- supportedLayoutIds: supportedLayouts(["classic"]),
16609
- navTypography: "brand-caps"
16594
+ supportedLayoutIds: supportedLayouts(["classic"])
16610
16595
  },
16611
16596
  {
16612
16597
  id: asHeaderStyleId("brand-pill"),
@@ -16616,69 +16601,55 @@ const headerStyleCatalog = defineExactCatalog()([
16616
16601
  "classic",
16617
16602
  "centered",
16618
16603
  "floating"
16619
- ]),
16620
- navTypography: "brand-caps"
16604
+ ])
16621
16605
  },
16622
16606
  {
16623
16607
  id: asHeaderStyleId("brand-capsule"),
16624
16608
  label: "Brand Capsule",
16625
16609
  description: "Solid brand chrome designed as a floating capsule, with quiet-caps nav, a soft pill active state, and an inverted CTA pill.",
16626
- supportedLayoutIds: supportedLayouts(["classic"]),
16627
- navTypography: "quiet-caps"
16610
+ supportedLayoutIds: supportedLayouts(["classic"])
16628
16611
  },
16629
16612
  {
16630
16613
  id: asHeaderStyleId("serif-line"),
16631
16614
  label: "Serif Line",
16632
16615
  description: "Typographic logo treatment with understated underline navigation.",
16633
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16634
- navTypography: "heading"
16616
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16635
16617
  },
16636
16618
  {
16637
16619
  id: asHeaderStyleId("flat-tabs"),
16638
16620
  label: "Flat Tabs",
16639
16621
  description: "Flat block hover and active states with a Swiss utility feel.",
16640
- supportedLayoutIds: supportedLayouts(["classic", "centered"]),
16641
- navTypography: "quiet-caps"
16622
+ supportedLayoutIds: supportedLayouts(["classic", "centered"])
16642
16623
  },
16643
16624
  {
16644
16625
  id: asHeaderStyleId("glass"),
16645
16626
  label: "Glass",
16646
16627
  description: "Translucent chrome with frosted navigation backing.",
16647
- supportedLayoutIds: supportedLayouts(["floating"]),
16648
- navTypography: "plain"
16628
+ supportedLayoutIds: supportedLayouts(["floating"])
16649
16629
  },
16650
16630
  {
16651
16631
  id: asHeaderStyleId("minimal-surface"),
16652
16632
  label: "Clear Split",
16653
16633
  description: "Floating logo with transparent navigation and no shared shell.",
16654
- supportedLayoutIds: supportedLayouts(["floating"]),
16655
- navTypography: "plain",
16656
- openingForegroundTarget: "all",
16657
- scrollTreatment: "contrast-glass",
16658
- interactionPalette: clearSplitInteractionPalette
16634
+ supportedLayoutIds: supportedLayouts(["floating"])
16659
16635
  },
16660
16636
  {
16661
16637
  id: asHeaderStyleId("soft-shell"),
16662
16638
  label: "Soft Shell",
16663
16639
  description: "Floating rounded shell with soft pill navigation states.",
16664
- supportedLayoutIds: supportedLayouts(["floating"]),
16665
- navTypography: "plain"
16640
+ supportedLayoutIds: supportedLayouts(["floating"])
16666
16641
  },
16667
16642
  {
16668
16643
  id: asHeaderStyleId("split-glass"),
16669
16644
  label: "Split Glass",
16670
16645
  description: "Logo floats independently while the navigation sits in a glass rail.",
16671
- supportedLayoutIds: supportedLayouts(["floating"]),
16672
- navTypography: "quiet-caps",
16673
- openingForegroundTarget: "brand-only"
16646
+ supportedLayoutIds: supportedLayouts(["floating"])
16674
16647
  },
16675
16648
  {
16676
16649
  id: asHeaderStyleId("split-pill"),
16677
16650
  label: "Split Pill",
16678
16651
  description: "Logo floats independently with a soft pill-backed navigation rail.",
16679
- supportedLayoutIds: supportedLayouts(["floating"]),
16680
- navTypography: "heading",
16681
- openingForegroundTarget: "brand-only"
16652
+ supportedLayoutIds: supportedLayouts(["floating"])
16682
16653
  }
16683
16654
  ]);
16684
16655
  const headerLayoutsById = new Map(headerLayoutCatalog.map((layout) => [layout.id, layout]));
@@ -16865,6 +16836,449 @@ function resolveHeaderLayoutStyleSelection(selection) {
16865
16836
  };
16866
16837
  }
16867
16838
 
16839
+ //#endregion
16840
+ //#region ../theme-core/src/site-styles/headerInteractionPalette.ts
16841
+ const clearSplitInteractionPalette = defineLookOptionGroup({
16842
+ id: "interaction-palette",
16843
+ label: "Hover colour",
16844
+ defaultOptionId: "accent",
16845
+ options: [
16846
+ {
16847
+ id: "accent",
16848
+ label: "Accent"
16849
+ },
16850
+ {
16851
+ id: "primary",
16852
+ label: "Primary"
16853
+ },
16854
+ {
16855
+ id: "secondary",
16856
+ label: "Secondary"
16857
+ }
16858
+ ]
16859
+ });
16860
+ function resolveHeaderInteractionPaletteControl(group, preference) {
16861
+ if (!group) return { kind: "unavailable" };
16862
+ if (preference === "recommended") {
16863
+ const resolution$1 = resolveLookOption(group, undefined);
16864
+ return availableControlState(group, preference, resolution$1.option.id, null);
16865
+ }
16866
+ const resolution = resolveHeaderInteractionPalette(group, preference);
16867
+ return availableControlState(group, preference, resolution.option.id, resolution.kind === "repaired" ? {
16868
+ requested: preference,
16869
+ fallback: resolution.option.id,
16870
+ reason: resolution.reason
16871
+ } : null);
16872
+ }
16873
+ function availableControlState(group, preference, effectivePalette, repair$1) {
16874
+ return {
16875
+ kind: "available",
16876
+ preference,
16877
+ effectivePalette,
16878
+ options: [{
16879
+ value: "recommended",
16880
+ label: `Recommended (${defaultOptionLabel(group)})`
16881
+ }, ...group.options.map((option) => ({
16882
+ value: option.id,
16883
+ label: option.label
16884
+ }))],
16885
+ repair: repair$1
16886
+ };
16887
+ }
16888
+ function applyHeaderInteractionPalette(header, group, preference) {
16889
+ if (!group) return header;
16890
+ if (!header.navLinkStyle) {
16891
+ throw new Error(`Header interaction palette "${group.id}" requires a nav link style.`);
16892
+ }
16893
+ const palette = resolveHeaderInteractionPalette(group, preference).option.id;
16894
+ const pair = headerInteractionPalettePair(palette);
16895
+ const pillEffect = {
16896
+ effectId: "background-on-hover",
16897
+ options: {
16898
+ colorToken: pair.backgroundToken,
16899
+ textColorToken: pair.foregroundToken
16900
+ }
16901
+ };
16902
+ return {
16903
+ ...header,
16904
+ navLinkStyle: {
16905
+ ...header.navLinkStyle,
16906
+ hoverColorToken: null,
16907
+ borderRadius: "full",
16908
+ effects: {
16909
+ ...header.navLinkStyle.effects,
16910
+ hover: [pillEffect],
16911
+ focus: [pillEffect]
16912
+ }
16913
+ }
16914
+ };
16915
+ }
16916
+ function resolveHeaderInteractionPalette(group, preference) {
16917
+ return resolveLookOption(group, preference === "recommended" ? undefined : preference);
16918
+ }
16919
+ function defaultOptionLabel(group) {
16920
+ return resolveLookOption(group, undefined).option.label;
16921
+ }
16922
+
16923
+ //#endregion
16924
+ //#region ../theme-core/src/site-styles/headerStyleDefaults.ts
16925
+ /**
16926
+ * A style either takes the default recipe or authors a complete one. This is
16927
+ * deliberately not a deep merge: the same "declare the variant or fall back"
16928
+ * rule cards use, so a half-authored recipe cannot exist.
16929
+ */
16930
+ function resolveHeaderStyleRecipe(siteStyle, styleId) {
16931
+ return siteStyle?.headerStyleRecipes?.[styleId] ?? defaultHeaderStyleRecipes[styleId];
16932
+ }
16933
+ /**
16934
+ * The default header appearance for every catalogue style id (#1318).
16935
+ *
16936
+ * This is the only id-keyed structure in the header appearance pipeline, and it
16937
+ * is data rather than dispatch — the same shape `cards/siteStyleDefaults.ts`
16938
+ * uses. A site style that wants a different header takes over an entry here
16939
+ * with its own recipe; it does not add a branch anywhere.
16940
+ *
16941
+ * `navWeight` (the bar) and `navLinkWeight` (the link text) are separate fields
16942
+ * and they disagree on five styles. That disagreement is real and pre-existing;
16943
+ * it is spelled out here rather than left implicit in a helper default. See the
16944
+ * note on `HeaderStyleRecipeCore.navLinkWeight`.
16945
+ */
16946
+ const defaultHeaderStyleRecipes = {
16947
+ minimal: {
16948
+ tone: "neutral",
16949
+ background: {
16950
+ kind: "token",
16951
+ token: "surface"
16952
+ },
16953
+ nav: {
16954
+ kind: "minimal",
16955
+ hoverColorToken: "primary"
16956
+ },
16957
+ navWeight: "medium",
16958
+ navLinkWeight: "medium",
16959
+ navTypography: "plain",
16960
+ border: "none",
16961
+ shadow: { kind: "absent" },
16962
+ frame: { kind: "none" },
16963
+ cta: { treatment: "default" }
16964
+ },
16965
+ "fine-line": {
16966
+ tone: "neutral",
16967
+ background: {
16968
+ kind: "token",
16969
+ token: "surface"
16970
+ },
16971
+ nav: {
16972
+ kind: "underline",
16973
+ hover: "underline"
16974
+ },
16975
+ navWeight: "medium",
16976
+ navLinkWeight: "medium",
16977
+ navTypography: "plain",
16978
+ border: "none",
16979
+ shadow: { kind: "absent" },
16980
+ frame: { kind: "none" },
16981
+ cta: { treatment: "outline" }
16982
+ },
16983
+ "soft-bar": {
16984
+ tone: "neutral",
16985
+ background: {
16986
+ kind: "token",
16987
+ token: "surfaceAlt"
16988
+ },
16989
+ nav: {
16990
+ kind: "pill",
16991
+ backing: "capsule",
16992
+ hoverColorToken: "primary",
16993
+ hoverAlpha: 8
16994
+ },
16995
+ navWeight: "medium",
16996
+ navLinkWeight: "medium",
16997
+ navTypography: "plain",
16998
+ border: "bottom",
16999
+ shadow: { kind: "absent" },
17000
+ frame: { kind: "none" },
17001
+ cta: { treatment: "default" }
17002
+ },
17003
+ "pill-nav": {
17004
+ tone: "neutral",
17005
+ background: {
17006
+ kind: "token",
17007
+ token: "surface"
17008
+ },
17009
+ nav: {
17010
+ kind: "pill",
17011
+ backing: "capsule",
17012
+ hoverColorToken: "primary",
17013
+ hoverAlpha: 10
17014
+ },
17015
+ navWeight: "medium",
17016
+ navLinkWeight: "medium",
17017
+ navTypography: "plain",
17018
+ border: "none",
17019
+ shadow: { kind: "absent" },
17020
+ frame: {
17021
+ kind: "nav-container",
17022
+ type: "pill",
17023
+ tint: "surfaceAlt",
17024
+ opacity: .7
17025
+ },
17026
+ cta: { treatment: "default" }
17027
+ },
17028
+ "brand-bar": {
17029
+ tone: "brand",
17030
+ background: {
17031
+ kind: "token",
17032
+ token: "primary"
17033
+ },
17034
+ nav: {
17035
+ kind: "minimal",
17036
+ hoverColorToken: "secondary"
17037
+ },
17038
+ navWeight: "semibold",
17039
+ navLinkWeight: "medium",
17040
+ navTypography: "brand-caps",
17041
+ border: "none",
17042
+ shadow: { kind: "absent" },
17043
+ frame: { kind: "none" },
17044
+ cta: { treatment: "inverted" }
17045
+ },
17046
+ "brand-underline": {
17047
+ tone: "brand",
17048
+ background: {
17049
+ kind: "token",
17050
+ token: "primary"
17051
+ },
17052
+ nav: {
17053
+ kind: "underline",
17054
+ hover: "both",
17055
+ hoverColorToken: "secondary",
17056
+ underlineColorToken: "secondary"
17057
+ },
17058
+ navWeight: "bold",
17059
+ navLinkWeight: "bold",
17060
+ navTypography: "brand-caps",
17061
+ border: "none",
17062
+ shadow: { kind: "absent" },
17063
+ frame: { kind: "none" },
17064
+ cta: {
17065
+ treatment: "inverted",
17066
+ gap: "compact"
17067
+ }
17068
+ },
17069
+ "brand-pill": {
17070
+ tone: "brand",
17071
+ background: {
17072
+ kind: "token",
17073
+ token: "primary"
17074
+ },
17075
+ nav: {
17076
+ kind: "pill",
17077
+ backing: "capsule",
17078
+ hoverColorToken: "primaryForeground",
17079
+ hoverAlpha: 14
17080
+ },
17081
+ navWeight: "semibold",
17082
+ navLinkWeight: "medium",
17083
+ navTypography: "brand-caps",
17084
+ border: "none",
17085
+ shadow: { kind: "absent" },
17086
+ frame: { kind: "none" },
17087
+ cta: { treatment: "inverted" },
17088
+ onFloating: {
17089
+ background: { kind: "transparent" },
17090
+ frame: {
17091
+ kind: "container",
17092
+ rounded: "2xl",
17093
+ padding: "sm",
17094
+ tint: "primary",
17095
+ opacity: .95
17096
+ }
17097
+ }
17098
+ },
17099
+ "brand-capsule": {
17100
+ tone: "brand",
17101
+ background: {
17102
+ kind: "token",
17103
+ token: "primary"
17104
+ },
17105
+ nav: {
17106
+ kind: "pill",
17107
+ backing: "capsule",
17108
+ hoverColorToken: "primaryForeground",
17109
+ hoverAlpha: 16
17110
+ },
17111
+ navWeight: "semibold",
17112
+ navLinkWeight: "medium",
17113
+ navTypography: "quiet-caps",
17114
+ border: "none",
17115
+ shadow: {
17116
+ kind: "fixed",
17117
+ elevation: "md"
17118
+ },
17119
+ frame: { kind: "none" },
17120
+ cta: { treatment: "inverted" }
17121
+ },
17122
+ "serif-line": {
17123
+ tone: "neutral",
17124
+ background: {
17125
+ kind: "token",
17126
+ token: "background"
17127
+ },
17128
+ nav: {
17129
+ kind: "underline",
17130
+ hover: "underline"
17131
+ },
17132
+ navWeight: "medium",
17133
+ navLinkWeight: "medium",
17134
+ navTypography: "heading",
17135
+ border: "none",
17136
+ shadow: { kind: "explicit-none" },
17137
+ frame: { kind: "none" },
17138
+ cta: {
17139
+ treatment: "outline",
17140
+ gap: "relaxed"
17141
+ },
17142
+ logo: {
17143
+ fontFamily: "heading",
17144
+ letterSpacing: "wide",
17145
+ gradient: false
17146
+ }
17147
+ },
17148
+ "flat-tabs": {
17149
+ tone: "neutral",
17150
+ background: {
17151
+ kind: "token",
17152
+ token: "surface"
17153
+ },
17154
+ nav: { kind: "flat-tab" },
17155
+ navWeight: "semibold",
17156
+ navLinkWeight: "semibold",
17157
+ navTypography: "quiet-caps",
17158
+ border: "bottom",
17159
+ shadow: { kind: "themed" },
17160
+ frame: { kind: "none" },
17161
+ cta: {
17162
+ treatment: "primary",
17163
+ gap: "compact"
17164
+ }
17165
+ },
17166
+ glass: {
17167
+ tone: "neutral",
17168
+ background: { kind: "transparent" },
17169
+ nav: {
17170
+ kind: "pill",
17171
+ backing: "frosted",
17172
+ hoverColorToken: "primary",
17173
+ hoverAlpha: 8
17174
+ },
17175
+ navWeight: "semibold",
17176
+ navLinkWeight: "medium",
17177
+ navTypography: "plain",
17178
+ border: "none",
17179
+ shadow: { kind: "absent" },
17180
+ frame: {
17181
+ kind: "container",
17182
+ rounded: "2xl",
17183
+ padding: "sm",
17184
+ tint: "surface",
17185
+ opacity: .4
17186
+ },
17187
+ cta: { treatment: "default" }
17188
+ },
17189
+ "minimal-surface": {
17190
+ tone: "neutral",
17191
+ background: { kind: "transparent" },
17192
+ nav: {
17193
+ kind: "minimal",
17194
+ hoverColorToken: "primary"
17195
+ },
17196
+ navWeight: "medium",
17197
+ navLinkWeight: "medium",
17198
+ navTypography: "plain",
17199
+ border: "none",
17200
+ shadow: { kind: "absent" },
17201
+ frame: { kind: "none" },
17202
+ cta: { treatment: "default" },
17203
+ navLinkExtras: {
17204
+ textSize: "lg",
17205
+ contrastTreatment: "soft-glow"
17206
+ },
17207
+ openingForeground: "all",
17208
+ scrollTreatment: "contrast-glass",
17209
+ interactionPalette: clearSplitInteractionPalette
17210
+ },
17211
+ "soft-shell": {
17212
+ tone: "neutral",
17213
+ background: { kind: "transparent" },
17214
+ nav: {
17215
+ kind: "pill",
17216
+ backing: "capsule",
17217
+ hoverColorToken: "primary",
17218
+ hoverAlpha: 8
17219
+ },
17220
+ navWeight: "medium",
17221
+ navLinkWeight: "medium",
17222
+ navTypography: "plain",
17223
+ border: "none",
17224
+ shadow: { kind: "absent" },
17225
+ frame: {
17226
+ kind: "container",
17227
+ rounded: "2xl",
17228
+ padding: "md",
17229
+ tint: "surfaceAlt",
17230
+ opacity: .95
17231
+ },
17232
+ cta: { treatment: "default" }
17233
+ },
17234
+ "split-glass": {
17235
+ tone: "neutral",
17236
+ background: { kind: "transparent" },
17237
+ nav: {
17238
+ kind: "pill",
17239
+ backing: "frosted",
17240
+ hoverColorToken: "primary",
17241
+ hoverAlpha: 8
17242
+ },
17243
+ navWeight: "semibold",
17244
+ navLinkWeight: "medium",
17245
+ navTypography: "quiet-caps",
17246
+ border: "none",
17247
+ shadow: { kind: "absent" },
17248
+ frame: {
17249
+ kind: "nav-container",
17250
+ type: "glass",
17251
+ tint: "surface",
17252
+ opacity: .4
17253
+ },
17254
+ cta: { treatment: "default" },
17255
+ openingForeground: "brand-only"
17256
+ },
17257
+ "split-pill": {
17258
+ tone: "neutral",
17259
+ background: { kind: "transparent" },
17260
+ nav: {
17261
+ kind: "pill",
17262
+ backing: "capsule",
17263
+ hoverColorToken: "primary",
17264
+ hoverAlpha: 10
17265
+ },
17266
+ navWeight: "medium",
17267
+ navLinkWeight: "medium",
17268
+ navTypography: "heading",
17269
+ border: "none",
17270
+ shadow: { kind: "absent" },
17271
+ frame: {
17272
+ kind: "nav-container",
17273
+ type: "pill",
17274
+ tint: "surface",
17275
+ opacity: .94
17276
+ },
17277
+ cta: { treatment: "default" },
17278
+ openingForeground: "brand-only"
17279
+ }
17280
+ };
17281
+
16868
17282
  //#endregion
16869
17283
  //#region ../theme-core/src/site-styles/headerNavStyles.ts
16870
17284
  function applyNavTypography(style, typography) {
@@ -16988,95 +17402,133 @@ function flatTabNavLinkStyle(colorToken, typography = "plain") {
16988
17402
  }
16989
17403
 
16990
17404
  //#endregion
16991
- //#region ../theme-core/src/site-styles/headerStyleCompiler.ts
16992
- function headerForLayout(theme, layout) {
16993
- return {
16994
- ...baseHeader(theme),
16995
- variant: layout.variant,
16996
- positioning: layout.defaultPositioning,
16997
- shrinkOnScroll: layout.shrinkOnScroll,
16998
- ctaGap: layout.id === asHeaderLayoutId("floating") ? "compact" : "default",
16999
- logoText: layout.id === asHeaderLayoutId("classic") ? {
17000
- mobileMaxWidth: "sm",
17001
- mobileWrapLines: 1,
17002
- hideOnShrink: false
17003
- } : undefined
17004
- };
17405
+ //#region ../theme-core/src/site-styles/headerStyleRecipe.ts
17406
+ function effectiveRecipe(layout, recipe) {
17407
+ return layout.id === asHeaderLayoutId("floating") && recipe.onFloating ? {
17408
+ ...recipe,
17409
+ ...recipe.onFloating
17410
+ } : recipe;
17005
17411
  }
17006
- function brandHeaderForeground() {
17007
- return {
17008
- textColor: "primaryForeground",
17009
- navColor: "primaryForeground"
17010
- };
17412
+ /**
17413
+ * One token drives the header text, the nav text and the nav link colour: they
17414
+ * are the same decision, and splitting them was how they could disagree.
17415
+ */
17416
+ function toneColorToken(tone) {
17417
+ switch (tone) {
17418
+ case "neutral": return "text";
17419
+ case "brand": return "primaryForeground";
17420
+ default: return assertNever$5(tone, "Unhandled header tone recipe");
17421
+ }
17011
17422
  }
17012
- function neutralDropdownStyle() {
17013
- return {
17014
- background: "surface",
17015
- textColor: "text",
17016
- borderColor: "border",
17017
- shadow: "md",
17018
- borderRadius: "md",
17019
- textTransform: "none",
17020
- letterSpacing: "normal"
17021
- };
17423
+ function toneDropdownStyle(tone) {
17424
+ switch (tone) {
17425
+ case "neutral": return {
17426
+ background: "surface",
17427
+ textColor: "text",
17428
+ borderColor: "border",
17429
+ shadow: "md",
17430
+ borderRadius: "md",
17431
+ textTransform: "none",
17432
+ letterSpacing: "normal"
17433
+ };
17434
+ case "brand": return {
17435
+ background: "primary-700",
17436
+ textColor: "primaryForeground",
17437
+ borderColor: null,
17438
+ shadow: "md",
17439
+ borderRadius: "md",
17440
+ hoverBackground: "primary-900",
17441
+ hoverTextColor: "secondary",
17442
+ textTransform: "uppercase",
17443
+ letterSpacing: "wider",
17444
+ fontWeight: "bold",
17445
+ textSize: "sm"
17446
+ };
17447
+ default: return assertNever$5(tone, "Unhandled header tone recipe");
17448
+ }
17022
17449
  }
17023
- function brandDropdownStyle() {
17024
- return {
17025
- background: "primary-700",
17026
- textColor: "primaryForeground",
17027
- borderColor: null,
17028
- shadow: "md",
17029
- borderRadius: "md",
17030
- hoverBackground: "primary-900",
17031
- hoverTextColor: "secondary",
17032
- textTransform: "uppercase",
17033
- letterSpacing: "wider",
17034
- fontWeight: "bold",
17035
- textSize: "sm"
17036
- };
17450
+ function recipeBackground(background) {
17451
+ switch (background.kind) {
17452
+ case "token": return {
17453
+ type: "color",
17454
+ color: background.token
17455
+ };
17456
+ case "transparent": return {
17457
+ type: "color",
17458
+ color: "transparent"
17459
+ };
17460
+ default: return assertNever$5(background, "Unhandled header background recipe");
17461
+ }
17037
17462
  }
17038
- function noHeaderBorder() {
17039
- return {
17040
- style: "solid",
17041
- width: "none",
17042
- position: "none"
17043
- };
17463
+ function recipeBorder(border$1) {
17464
+ switch (border$1) {
17465
+ case "none": return {
17466
+ style: "solid",
17467
+ width: "none",
17468
+ position: "none"
17469
+ };
17470
+ case "bottom": return {
17471
+ style: "solid",
17472
+ width: "thin",
17473
+ position: "bottom",
17474
+ colorToken: "border"
17475
+ };
17476
+ default: return assertNever$5(border$1, "Unhandled header border recipe");
17477
+ }
17044
17478
  }
17045
- function bottomHeaderBorder() {
17046
- return {
17047
- style: "solid",
17048
- width: "thin",
17049
- position: "bottom",
17050
- colorToken: "border"
17051
- };
17479
+ function recipeNavStyle(nav) {
17480
+ switch (nav.kind) {
17481
+ case "minimal": return "minimal";
17482
+ case "underline": return "underline-grow";
17483
+ case "pill": return nav.backing;
17484
+ case "flat-tab": return "solid";
17485
+ default: return assertNever$5(nav, "Unhandled header nav recipe");
17486
+ }
17052
17487
  }
17053
- function colorHeaderBackground(color) {
17054
- return {
17055
- type: "color",
17056
- color
17488
+ function underlineHoverEffects(nav) {
17489
+ const underline = {
17490
+ effectId: "nav-underline",
17491
+ options: {
17492
+ style: "grow",
17493
+ ...nav.underlineColorToken ? { colorToken: nav.underlineColorToken } : {}
17494
+ }
17057
17495
  };
17496
+ switch (nav.hover) {
17497
+ case "underline": return [underline];
17498
+ case "colour": return [{
17499
+ effectId: "text-color-change",
17500
+ options: { hoverColorToken: nav.hoverColorToken }
17501
+ }];
17502
+ case "both": return [{
17503
+ effectId: "text-color-change",
17504
+ options: { hoverColorToken: nav.hoverColorToken }
17505
+ }, underline];
17506
+ default: return assertNever$5(nav, "Unhandled underline nav hover affordance");
17507
+ }
17058
17508
  }
17059
- function neutralHeaderBase() {
17509
+ function underlineNavLink(nav, colorToken, typography) {
17510
+ const base = underlineNavLinkStyle(colorToken, nav.underlineColorToken, typography);
17060
17511
  return {
17061
- textColor: "text",
17062
- navColor: "text",
17063
- dropdownStyle: neutralDropdownStyle()
17512
+ ...base,
17513
+ ...nav.hover === "underline" ? {} : { hoverColorToken: nav.hoverColorToken },
17514
+ effects: {
17515
+ ...base.effects,
17516
+ hover: underlineHoverEffects(nav)
17517
+ }
17064
17518
  };
17065
17519
  }
17066
- function transparentHeaderBackground() {
17067
- return colorHeaderBackground("transparent");
17068
- }
17069
- function floatingContainer(input) {
17070
- return {
17071
- rounded: input.rounded,
17072
- border: true,
17073
- shadow: true,
17074
- padding: input.padding,
17075
- tint: input.tint,
17076
- opacity: input.opacity
17077
- };
17520
+ function recipeNavLinkStyle(recipe) {
17521
+ const colorToken = toneColorToken(recipe.tone);
17522
+ const nav = recipe.nav;
17523
+ switch (nav.kind) {
17524
+ case "minimal": return minimalNavLinkStyle(colorToken, nav.hoverColorToken, recipe.navTypography);
17525
+ case "underline": return underlineNavLink(nav, colorToken, recipe.navTypography);
17526
+ case "pill": return pillNavLinkStyle(colorToken, nav.hoverColorToken, nav.hoverAlpha, recipe.navTypography);
17527
+ case "flat-tab": return flatTabNavLinkStyle(colorToken, recipe.navTypography);
17528
+ default: return assertNever$5(nav, "Unhandled header nav recipe");
17529
+ }
17078
17530
  }
17079
- function themedHeaderShadow(theme) {
17531
+ function themedShadow(theme) {
17080
17532
  switch (theme.shadow.elevation) {
17081
17533
  case "none": return undefined;
17082
17534
  case "low": return { elevation: "sm" };
@@ -17085,248 +17537,120 @@ function themedHeaderShadow(theme) {
17085
17537
  default: return assertNever$5(theme.shadow.elevation, "Unhandled theme shadow elevation");
17086
17538
  }
17087
17539
  }
17088
- function brandSurfaceBase(theme, header) {
17089
- const ctaVariant = resolveHeaderCtaVariant(theme, "inverted");
17540
+ function recipeShadow(shadow$1, theme) {
17541
+ switch (shadow$1.kind) {
17542
+ case "absent": return {};
17543
+ case "explicit-none": return { shadow: { elevation: "none" } };
17544
+ case "fixed": return { shadow: { elevation: shadow$1.elevation } };
17545
+ case "themed": {
17546
+ const resolved = themedShadow(theme);
17547
+ return resolved ? { shadow: resolved } : {};
17548
+ }
17549
+ default: return assertNever$5(shadow$1, "Unhandled header shadow recipe");
17550
+ }
17551
+ }
17552
+ /**
17553
+ * `{kind: 'none'}` writes nothing: the base header already carries the
17554
+ * `{type: 'none', tint: null, opacity: 0.15}` nav container default, and
17555
+ * omitting the key would be a different JSON.
17556
+ */
17557
+ function recipeFrame(frame) {
17558
+ switch (frame.kind) {
17559
+ case "none": return {};
17560
+ case "container": return { container: {
17561
+ rounded: frame.rounded,
17562
+ border: true,
17563
+ shadow: true,
17564
+ padding: frame.padding,
17565
+ tint: frame.tint,
17566
+ opacity: frame.opacity
17567
+ } };
17568
+ case "nav-container": return { navContainer: {
17569
+ type: frame.type,
17570
+ tint: frame.tint,
17571
+ opacity: frame.opacity
17572
+ } };
17573
+ default: return assertNever$5(frame, "Unhandled header frame recipe");
17574
+ }
17575
+ }
17576
+ /**
17577
+ * `ctaVariant` is spread conditionally everywhere, which is byte-safe for the
17578
+ * nine `'default'` styles only because `resolveHeaderCtaVariant(theme,
17579
+ * 'default')` returns `undefined`. The compiler used to mix a conditional
17580
+ * spread with three direct assignments; the difference was invisible in
17581
+ * persisted JSON and visible to an in-memory `toEqual`, so it is normalised
17582
+ * here (ledger D1).
17583
+ */
17584
+ function recipeCta(cta, theme) {
17585
+ const variant = resolveHeaderCtaVariant(theme, cta.treatment);
17090
17586
  return {
17091
- ...header,
17092
- ...brandHeaderForeground(),
17093
- background: colorHeaderBackground("primary"),
17094
- dropdownStyle: brandDropdownStyle(),
17095
- border: noHeaderBorder(),
17096
- ctaTreatment: "inverted",
17097
- ...ctaVariant ? { ctaVariant } : {}
17587
+ ctaTreatment: cta.treatment,
17588
+ ...variant ? { ctaVariant: variant } : {},
17589
+ ...cta.gap ? { ctaGap: cta.gap } : {}
17098
17590
  };
17099
17591
  }
17100
- function floatingSurfaceBase(header) {
17592
+ /** Layout-derived structure. The only part of the header a recipe cannot reach. */
17593
+ function headerForLayout(theme, layout) {
17101
17594
  return {
17102
- ...header,
17103
- background: transparentHeaderBackground(),
17104
- border: noHeaderBorder()
17105
- };
17106
- }
17107
- function applyBasicHeaderStyle(id, theme, header, style) {
17108
- switch (id) {
17109
- case "minimal": return {
17110
- ...header,
17111
- ...neutralHeaderBase(),
17112
- background: colorHeaderBackground("surface"),
17113
- navStyle: "minimal",
17114
- navWeight: "medium",
17115
- navLinkStyle: minimalNavLinkStyle("text", "primary", style.navTypography),
17116
- border: noHeaderBorder(),
17117
- ctaTreatment: "default"
17118
- };
17119
- case "fine-line": return {
17120
- ...header,
17121
- ...neutralHeaderBase(),
17122
- background: colorHeaderBackground("surface"),
17123
- navStyle: "underline-grow",
17124
- navWeight: "medium",
17125
- navLinkStyle: underlineNavLinkStyle("text", undefined, style.navTypography),
17126
- border: noHeaderBorder(),
17127
- ctaTreatment: "outline",
17128
- ctaVariant: resolveHeaderCtaVariant(theme, "outline")
17129
- };
17130
- case "soft-bar": return {
17131
- ...header,
17132
- ...neutralHeaderBase(),
17133
- background: colorHeaderBackground("surfaceAlt"),
17134
- navStyle: "capsule",
17135
- navWeight: "medium",
17136
- navLinkStyle: pillNavLinkStyle("text", "primary", 8, style.navTypography),
17137
- border: bottomHeaderBorder(),
17138
- ctaTreatment: "default"
17139
- };
17140
- case "pill-nav": return {
17141
- ...header,
17142
- ...neutralHeaderBase(),
17143
- background: colorHeaderBackground("surface"),
17144
- navStyle: "capsule",
17145
- navWeight: "medium",
17146
- navLinkStyle: pillNavLinkStyle("text", "primary", 10, style.navTypography),
17147
- navContainer: {
17148
- type: "pill",
17149
- tint: "surfaceAlt",
17150
- opacity: .7
17151
- },
17152
- border: noHeaderBorder(),
17153
- ctaTreatment: "default"
17154
- };
17155
- default: return assertNever$5(id, "Unhandled basic header style id");
17156
- }
17157
- }
17158
- function applyBrandHeaderStyle(id, theme, header, style) {
17159
- switch (id) {
17160
- case "brand-bar": return {
17161
- ...brandSurfaceBase(theme, header),
17162
- navStyle: "minimal",
17163
- navWeight: "semibold",
17164
- navLinkStyle: minimalNavLinkStyle("primaryForeground", "secondary", style.navTypography)
17165
- };
17166
- case "brand-underline": return {
17167
- ...brandSurfaceBase(theme, header),
17168
- navStyle: "underline-grow",
17169
- navWeight: "bold",
17170
- navLinkStyle: underlineNavLinkStyle("primaryForeground", "secondary", style.navTypography)
17171
- };
17172
- case "brand-pill": return {
17173
- ...brandSurfaceBase(theme, header),
17174
- ...header.variant === "floating" ? {
17175
- background: transparentHeaderBackground(),
17176
- container: floatingContainer({
17177
- rounded: "2xl",
17178
- padding: "sm",
17179
- tint: "primary",
17180
- opacity: .95
17181
- })
17182
- } : {},
17183
- navStyle: "capsule",
17184
- navWeight: "semibold",
17185
- navLinkStyle: pillNavLinkStyle("primaryForeground", "primaryForeground", 14, style.navTypography)
17186
- };
17187
- case "brand-capsule": return {
17188
- ...brandSurfaceBase(theme, header),
17189
- navStyle: "capsule",
17190
- navWeight: "semibold",
17191
- navLinkStyle: pillNavLinkStyle("primaryForeground", "primaryForeground", 16, style.navTypography),
17192
- shadow: { elevation: "md" }
17193
- };
17194
- default: return assertNever$5(id, "Unhandled brand header style id");
17195
- }
17196
- }
17197
- function applyEditorialHeaderStyle(id, theme, header, style) {
17198
- switch (id) {
17199
- case "serif-line": return {
17200
- ...header,
17201
- ...neutralHeaderBase(),
17202
- background: colorHeaderBackground("background"),
17203
- navStyle: "underline-grow",
17204
- navWeight: "medium",
17205
- navLinkStyle: underlineNavLinkStyle("text", undefined, style.navTypography),
17206
- border: noHeaderBorder(),
17207
- shadow: { elevation: "none" },
17208
- logo: {
17209
- fontFamily: "heading",
17210
- letterSpacing: "wide",
17211
- gradient: false
17212
- },
17213
- ctaTreatment: "outline",
17214
- ctaVariant: resolveHeaderCtaVariant(theme, "outline"),
17215
- ctaGap: "relaxed"
17216
- };
17217
- case "flat-tabs": return {
17218
- ...header,
17219
- ...neutralHeaderBase(),
17220
- background: colorHeaderBackground("surface"),
17221
- navStyle: "solid",
17222
- navWeight: "semibold",
17223
- navLinkStyle: flatTabNavLinkStyle("text", style.navTypography),
17224
- border: bottomHeaderBorder(),
17225
- shadow: themedHeaderShadow(theme),
17226
- ctaTreatment: "primary",
17227
- ctaVariant: resolveHeaderCtaVariant(theme, "primary"),
17228
- ctaGap: "compact"
17229
- };
17230
- default: return assertNever$5(id, "Unhandled editorial header style id");
17231
- }
17232
- }
17233
- function applyFloatingHeaderStyle(id, header, style) {
17234
- switch (id) {
17235
- case "glass": return {
17236
- ...floatingSurfaceBase(header),
17237
- ...neutralHeaderBase(),
17238
- navStyle: "frosted",
17239
- navWeight: "semibold",
17240
- navLinkStyle: pillNavLinkStyle("text", "primary", 8, style.navTypography),
17241
- container: floatingContainer({
17242
- rounded: "2xl",
17243
- padding: "sm",
17244
- tint: "surface",
17245
- opacity: .4
17246
- }),
17247
- ctaTreatment: "default"
17248
- };
17249
- case "minimal-surface": return {
17250
- ...floatingSurfaceBase(header),
17251
- ...neutralHeaderBase(),
17252
- navStyle: "minimal",
17253
- navWeight: "medium",
17254
- navLinkStyle: {
17255
- ...minimalNavLinkStyle("text", "primary", style.navTypography),
17256
- textSize: "lg",
17257
- contrastTreatment: "soft-glow"
17258
- },
17259
- ctaTreatment: "default"
17260
- };
17261
- case "soft-shell": return {
17262
- ...floatingSurfaceBase(header),
17263
- ...neutralHeaderBase(),
17264
- navStyle: "capsule",
17265
- navWeight: "medium",
17266
- navLinkStyle: pillNavLinkStyle("text", "primary", 8, style.navTypography),
17267
- container: floatingContainer({
17268
- rounded: "2xl",
17269
- padding: "md",
17270
- tint: "surfaceAlt",
17271
- opacity: .95
17272
- }),
17273
- ctaTreatment: "default"
17274
- };
17275
- case "split-glass": return {
17276
- ...floatingSurfaceBase(header),
17277
- ...neutralHeaderBase(),
17278
- navStyle: "frosted",
17279
- navWeight: "semibold",
17280
- navLinkStyle: pillNavLinkStyle("text", "primary", 8, style.navTypography),
17281
- navContainer: {
17282
- type: "glass",
17283
- tint: "surface",
17284
- opacity: .4
17285
- },
17286
- ctaTreatment: "default"
17287
- };
17288
- case "split-pill": return {
17289
- ...floatingSurfaceBase(header),
17290
- ...neutralHeaderBase(),
17291
- navStyle: "capsule",
17292
- navWeight: "medium",
17293
- navLinkStyle: pillNavLinkStyle("text", "primary", 10, style.navTypography),
17294
- navContainer: {
17295
- type: "pill",
17296
- tint: "surface",
17297
- opacity: .94
17298
- },
17299
- ctaTreatment: "default"
17300
- };
17301
- default: return assertNever$5(id, "Unhandled floating header style id");
17302
- }
17303
- }
17304
- const headerStyleCompilers = {
17305
- minimal: (theme, header, style) => applyBasicHeaderStyle("minimal", theme, header, style),
17306
- "fine-line": (theme, header, style) => applyBasicHeaderStyle("fine-line", theme, header, style),
17307
- "soft-bar": (theme, header, style) => applyBasicHeaderStyle("soft-bar", theme, header, style),
17308
- "pill-nav": (theme, header, style) => applyBasicHeaderStyle("pill-nav", theme, header, style),
17309
- "brand-bar": (theme, header, style) => applyBrandHeaderStyle("brand-bar", theme, header, style),
17310
- "brand-underline": (theme, header, style) => applyBrandHeaderStyle("brand-underline", theme, header, style),
17311
- "brand-pill": (theme, header, style) => applyBrandHeaderStyle("brand-pill", theme, header, style),
17312
- "brand-capsule": (theme, header, style) => applyBrandHeaderStyle("brand-capsule", theme, header, style),
17313
- "serif-line": (theme, header, style) => applyEditorialHeaderStyle("serif-line", theme, header, style),
17314
- "flat-tabs": (theme, header, style) => applyEditorialHeaderStyle("flat-tabs", theme, header, style),
17315
- glass: (_theme, header, style) => applyFloatingHeaderStyle("glass", header, style),
17316
- "minimal-surface": (_theme, header, style) => applyFloatingHeaderStyle("minimal-surface", header, style),
17317
- "soft-shell": (_theme, header, style) => applyFloatingHeaderStyle("soft-shell", header, style),
17318
- "split-glass": (_theme, header, style) => applyFloatingHeaderStyle("split-glass", header, style),
17319
- "split-pill": (_theme, header, style) => applyFloatingHeaderStyle("split-pill", header, style)
17320
- };
17321
- function applyHeaderStyle(theme, header, style) {
17322
- return headerStyleCompilers[headerStyleIdValue(style.id)](theme, header, style);
17595
+ ...baseHeader(theme),
17596
+ variant: layout.variant,
17597
+ positioning: layout.defaultPositioning,
17598
+ shrinkOnScroll: layout.shrinkOnScroll,
17599
+ ctaGap: layout.id === asHeaderLayoutId("floating") ? "compact" : "default",
17600
+ logoText: layout.id === asHeaderLayoutId("classic") ? {
17601
+ mobileMaxWidth: "sm",
17602
+ mobileWrapLines: 1,
17603
+ hideOnShrink: false
17604
+ } : undefined
17605
+ };
17323
17606
  }
17324
- function headerStyleIdValue(id) {
17325
- return id;
17607
+ /**
17608
+ * The single header interpreter. Pure and total: same `(theme, layout, recipe)`
17609
+ * in, same object out, no throws of its own.
17610
+ */
17611
+ function compileHeaderRecipe(theme, layout, recipe) {
17612
+ const effective = effectiveRecipe(layout, recipe);
17613
+ const navLinkStyle = recipeNavLinkStyle(effective);
17614
+ return {
17615
+ ...headerForLayout(theme, layout),
17616
+ textColor: toneColorToken(effective.tone),
17617
+ navColor: toneColorToken(effective.tone),
17618
+ dropdownStyle: toneDropdownStyle(effective.tone),
17619
+ background: recipeBackground(effective.background),
17620
+ border: recipeBorder(effective.border),
17621
+ navStyle: recipeNavStyle(effective.nav),
17622
+ navWeight: effective.navWeight,
17623
+ navLinkStyle: {
17624
+ ...navLinkStyle,
17625
+ fontWeight: effective.navLinkWeight,
17626
+ ...effective.navLinkExtras ?? {}
17627
+ },
17628
+ ...recipeShadow(effective.shadow, theme),
17629
+ ...recipeFrame(effective.frame),
17630
+ ...effective.logo ? { logo: effective.logo } : {},
17631
+ ...recipeCta(effective.cta, theme)
17632
+ };
17326
17633
  }
17327
- function compileHeaderLayoutStyleSelection(theme, resolution) {
17328
- const header = applyHeaderStyle(theme, headerForLayout(theme, resolution.layout), resolution.style);
17329
- return applyHeaderInteractionPalette(header, resolution.style.interactionPalette, theme.header.interactionPalette ?? "recommended");
17634
+
17635
+ //#endregion
17636
+ //#region ../theme-core/src/site-styles/headerStyleCompiler.ts
17637
+ /**
17638
+ * The header compilation pipeline: pick the recipe, interpret it, then apply
17639
+ * the user's interaction-palette preference.
17640
+ *
17641
+ * Appearance decisions live in `headerStyleDefaults.ts` (data), optionally
17642
+ * taken over per site style, and `headerStyleRecipe.ts` (one pure interpreter).
17643
+ * Nothing here switches on a header style id.
17644
+ *
17645
+ * `siteStyle` is required rather than optional: a caller that has no resolved
17646
+ * site style has to say so, because silently falling back to the catalogue
17647
+ * default is exactly the ownership leak this slice closes. Pass `null` when
17648
+ * there genuinely is no site style (initial site provisioning).
17649
+ */
17650
+ function compileHeaderLayoutStyleSelection(theme, resolution, siteStyle) {
17651
+ const recipe = resolveHeaderStyleRecipe(siteStyle, resolution.style.id);
17652
+ const header = compileHeaderRecipe(theme, resolution.layout, recipe);
17653
+ return applyHeaderInteractionPalette(header, recipe.interactionPalette, theme.header.interactionPalette ?? "recommended");
17330
17654
  }
17331
17655
 
17332
17656
  //#endregion
@@ -18138,7 +18462,6 @@ const modernMinimalTheme = {
18138
18462
  positioning: "static",
18139
18463
  shrinkOnScroll: false,
18140
18464
  maxWidth: "container",
18141
- logoOverride: null,
18142
18465
  background: {
18143
18466
  type: "color",
18144
18467
  color: "surface"
@@ -20995,6 +21318,19 @@ const curatedSiteStyles = [
20995
21318
  })
20996
21319
  ];
20997
21320
  const curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
21321
+ /**
21322
+ * The header appearance a persisted theme actually renders: the catalogue
21323
+ * recipe unless the theme's own site style has taken that id over (#1318).
21324
+ *
21325
+ * Consumers that hold a theme and a selected style id — the public frontend and
21326
+ * the chrome customiser — go through here rather than reading the style
21327
+ * definition, so a site-style override is visible to every reader rather than
21328
+ * only to the compiler.
21329
+ */
21330
+ function headerStyleRecipeForTheme(theme, styleId) {
21331
+ const siteStyle = theme?.siteStyleId ? getCuratedSiteStyle(theme.siteStyleId) : null;
21332
+ return resolveHeaderStyleRecipe(siteStyle, styleId);
21333
+ }
20998
21334
  function getCuratedSiteStyle(id) {
20999
21335
  return curatedSiteStylesById.get(id) ?? null;
21000
21336
  }
@@ -22696,7 +23032,7 @@ function compileHeaderDirective(input) {
22696
23032
  layoutId: resolvedLayoutId,
22697
23033
  styleId: resolvedStyleId
22698
23034
  });
22699
- const header = compileHeaderLayoutStyleSelection(input.theme, resolution);
23035
+ const header = compileHeaderLayoutStyleSelection(input.theme, resolution, input.siteStyle);
22700
23036
  const brandPresentation = input.directive.brandPresentation.kind === "apply-logo-context" ? resolveHeaderBrandPresentationForLayout({
22701
23037
  layout: resolution.layout,
22702
23038
  logo: input.directive.brandPresentation.logo
@@ -23836,8 +24172,8 @@ function runGeneratedPageDesignPipeline(input) {
23836
24172
 
23837
24173
  //#endregion
23838
24174
  //#region ../theme-core/src/site-styles/headerOpeningForeground.ts
23839
- function headerStyleAvailability(style, context) {
23840
- if (!style.openingForegroundTarget) return { kind: "available" };
24175
+ function headerStyleAvailability(recipe, context) {
24176
+ if (!recipe.openingForeground) return { kind: "available" };
23841
24177
  return context?.openingForeground?.kind === "known" ? { kind: "available" } : {
23842
24178
  kind: "unavailable",
23843
24179
  reason: "requires-known-opening-foreground"
@@ -23849,16 +24185,16 @@ function headerStyleAvailabilityReasonLabel(reason) {
23849
24185
  default: return assertNever$5(reason, "Unhandled header style availability reason");
23850
24186
  }
23851
24187
  }
23852
- function applyOpeningForeground(theme, header, style, context) {
23853
- if (!style.openingForegroundTarget) return header;
24188
+ function applyOpeningForeground(theme, header, recipe, context) {
24189
+ if (!recipe.openingForeground) return header;
23854
24190
  const foreground = context?.openingForeground ?? { kind: "unknown" };
23855
24191
  if (foreground.kind === "unknown") return applyUnknownOpeningForegroundFallback(header);
23856
24192
  const withBrandForeground = {
23857
24193
  ...header,
23858
24194
  textColor: foreground.roles.text
23859
24195
  };
23860
- if (style.openingForegroundTarget === "brand-only") return withBrandForeground;
23861
- const scrollTreatment = compileHeaderScrollTreatment(theme, style, foreground.roles.text);
24196
+ if (recipe.openingForeground === "brand-only") return withBrandForeground;
24197
+ const scrollTreatment = compileHeaderScrollTreatment(theme, recipe, foreground.roles.text);
23862
24198
  return {
23863
24199
  ...withBrandForeground,
23864
24200
  navColor: foreground.roles.text,
@@ -23875,8 +24211,8 @@ function applyOpeningForeground(theme, header, style, context) {
23875
24211
  ...scrollTreatment ? { scrollTreatment } : {}
23876
24212
  };
23877
24213
  }
23878
- function compileHeaderScrollTreatment(theme, style, foregroundToken) {
23879
- if (style.scrollTreatment !== "contrast-glass") return undefined;
24214
+ function compileHeaderScrollTreatment(theme, recipe, foregroundToken) {
24215
+ if (recipe.scrollTreatment !== "contrast-glass") return undefined;
23880
24216
  const tokenParts = parseColorTokenParts(foregroundToken);
23881
24217
  if (tokenParts.kind !== "token") return undefined;
23882
24218
  const foregroundHex = expandPalette(theme.palette)[tokenParts.token];
@@ -23913,11 +24249,11 @@ function applyUnknownOpeningForegroundFallback(header) {
23913
24249
  container: UNKNOWN_OPENING_FOREGROUND_CONTAINER
23914
24250
  };
23915
24251
  }
23916
- function applyPageOpeningForegroundToTheme(theme, style, context) {
23917
- if (!style || !style.openingForegroundTarget) return theme;
24252
+ function applyPageOpeningForegroundToTheme(theme, recipe, context) {
24253
+ if (!recipe?.openingForeground) return theme;
23918
24254
  return {
23919
24255
  ...theme,
23920
- header: applyOpeningForeground(theme, theme.header, style, context)
24256
+ header: applyOpeningForeground(theme, theme.header, recipe, context)
23921
24257
  };
23922
24258
  }
23923
24259
 
@@ -27618,7 +27954,7 @@ const resourceKinds = [
27618
27954
  "customer-pass",
27619
27955
  "customer-membership",
27620
27956
  "appointment",
27621
- "course-enrollment",
27957
+ "event-series-registration",
27622
27958
  "event-registration",
27623
27959
  "pass-redemption",
27624
27960
  "order",
@@ -27767,7 +28103,7 @@ const appointmentBookingStatuses = [
27767
28103
  "cancelled",
27768
28104
  "no_show"
27769
28105
  ];
27770
- const courseEnrollmentStatuses = ["enrolled"];
28106
+ const eventSeriesRegistrationStatuses = ["enrolled"];
27771
28107
  const eventRegistrationStatuses = ["confirmed"];
27772
28108
 
27773
28109
  //#endregion
@@ -27921,7 +28257,6 @@ const classicProfessionalTheme = {
27921
28257
  positioning: "static",
27922
28258
  shrinkOnScroll: false,
27923
28259
  maxWidth: "container",
27924
- logoOverride: null,
27925
28260
  background: {
27926
28261
  type: "color",
27927
28262
  color: "surface"
@@ -28078,7 +28413,6 @@ const vibrantCreativeTheme = {
28078
28413
  positioning: "sticky",
28079
28414
  shrinkOnScroll: false,
28080
28415
  maxWidth: "container",
28081
- logoOverride: null,
28082
28416
  background: {
28083
28417
  type: "color",
28084
28418
  color: "surface"
@@ -31273,7 +31607,7 @@ const appointmentBookingRefSchema = resourceRefSchema("appointment");
31273
31607
  const appointmentResourceRefSchema = resourceRefSchema("appointment-resource");
31274
31608
  const appointmentServiceRefSchema = resourceRefSchema("appointment-service");
31275
31609
  const bookingCustomerRefSchema = resourceRefSchema("customer");
31276
- const courseEnrollmentRefSchema = resourceRefSchema("course-enrollment");
31610
+ const eventSeriesRegistrationRefSchema = resourceRefSchema("event-series-registration");
31277
31611
  const customerMembershipRefSchema = resourceRefSchema("customer-membership");
31278
31612
  const customerPassRefSchema = resourceRefSchema("customer-pass");
31279
31613
  const eventRegistrationRefSchema = resourceRefSchema("event-registration");
@@ -31454,13 +31788,13 @@ const seedAppointmentBookingCommandSchema = z.object({
31454
31788
  });
31455
31789
  })
31456
31790
  }).strict();
31457
- const seedCourseEnrollmentCommandSchema = z.object({
31458
- type: z.literal("seedCourseEnrollment"),
31459
- ref: courseEnrollmentRefSchema,
31791
+ const seedEventSeriesRegistrationCommandSchema = z.object({
31792
+ type: z.literal("seedEventSeriesRegistration"),
31793
+ ref: eventSeriesRegistrationRefSchema,
31460
31794
  input: z.object({
31461
31795
  customerRef: bookingCustomerRefSchema,
31462
31796
  eventRef: eventSeriesRefSchema$1,
31463
- status: z.enum(courseEnrollmentStatuses).default("enrolled"),
31797
+ status: z.enum(eventSeriesRegistrationStatuses).default("enrolled"),
31464
31798
  paymentMethod: z.literal("free").default("free"),
31465
31799
  paymentStatus: z.literal("not_required").default("not_required"),
31466
31800
  formSubmission: unknownRecordSchema.default({}),
@@ -31502,8 +31836,8 @@ const portalOrderSubjectSchema = z.discriminatedUnion("kind", [z.object({
31502
31836
  kind: z.literal("event_registration"),
31503
31837
  eventRegistrationRef: eventRegistrationRefSchema
31504
31838
  }).strict(), z.object({
31505
- kind: z.literal("course_enrollment"),
31506
- courseEnrollmentRef: courseEnrollmentRefSchema
31839
+ kind: z.literal("event_series_registration"),
31840
+ eventSeriesRegistrationRef: eventSeriesRegistrationRefSchema
31507
31841
  }).strict()]);
31508
31842
  const seedPortalOrderCommandSchema = z.object({
31509
31843
  type: z.literal("seedPortalOrder"),
@@ -32163,7 +32497,7 @@ const siteCommandSchema = z.discriminatedUnion("type", [
32163
32497
  grantCustomerPassCommandSchema,
32164
32498
  grantCustomerMembershipCommandSchema,
32165
32499
  seedAppointmentBookingCommandSchema,
32166
- seedCourseEnrollmentCommandSchema,
32500
+ seedEventSeriesRegistrationCommandSchema,
32167
32501
  seedEventRegistrationCommandSchema,
32168
32502
  seedPassRedemptionCommandSchema,
32169
32503
  seedPortalOrderCommandSchema,
@@ -32287,7 +32621,7 @@ const commandScopes = [
32287
32621
  "customer_pass",
32288
32622
  "customer_membership",
32289
32623
  "appointment",
32290
- "course_enrollment",
32624
+ "event_series_registration",
32291
32625
  "event_registration",
32292
32626
  "pass_redemption",
32293
32627
  "order",
@@ -32882,8 +33216,8 @@ const siteCommandMetadata = {
32882
33216
  capability: "bookings.appointments.write",
32883
33217
  support: "supported"
32884
33218
  },
32885
- seedCourseEnrollment: {
32886
- scope: "course_enrollment",
33219
+ seedEventSeriesRegistration: {
33220
+ scope: "event_series_registration",
32887
33221
  risk: "medium",
32888
33222
  writeSemantics: "upsert",
32889
33223
  lifecycleIntent: "seed",
@@ -32892,7 +33226,7 @@ const siteCommandMetadata = {
32892
33226
  previewability: "dry_run_only",
32893
33227
  allowedRuntimes: allRuntimes,
32894
33228
  intendedExposure: recipeExposure,
32895
- capability: "bookings.course_enrollments.write",
33229
+ capability: "bookings.event_series_registrations.write",
32896
33230
  support: "supported"
32897
33231
  },
32898
33232
  seedEventRegistration: {
@@ -33109,7 +33443,7 @@ const bookingRefCommandTypeValues = [
33109
33443
  "grantCustomerPass",
33110
33444
  "grantCustomerMembership",
33111
33445
  "seedAppointmentBooking",
33112
- "seedCourseEnrollment",
33446
+ "seedEventSeriesRegistration",
33113
33447
  "seedEventRegistration",
33114
33448
  "seedPassRedemption",
33115
33449
  "seedPortalOrder",
@@ -33163,7 +33497,7 @@ function bookingCommandRefContributions(command) {
33163
33497
  field: "input.resourceRef"
33164
33498
  }
33165
33499
  ]);
33166
- case "seedCourseEnrollment": return providedWithRequirements(command.ref, [{
33500
+ case "seedEventSeriesRegistration": return providedWithRequirements(command.ref, [{
33167
33501
  ref: command.input.customerRef,
33168
33502
  field: "input.customerRef"
33169
33503
  }, {
@@ -33239,9 +33573,9 @@ function portalOrderSubjectRefContribution(subject) {
33239
33573
  ref: subject.eventRegistrationRef,
33240
33574
  field: "input.subject.eventRegistrationRef"
33241
33575
  };
33242
- case "course_enrollment": return {
33243
- ref: subject.courseEnrollmentRef,
33244
- field: "input.subject.courseEnrollmentRef"
33576
+ case "event_series_registration": return {
33577
+ ref: subject.eventSeriesRegistrationRef,
33578
+ field: "input.subject.eventSeriesRegistrationRef"
33245
33579
  };
33246
33580
  default: return assertNever(subject);
33247
33581
  }
@@ -33675,7 +34009,7 @@ function matchSiteCommand(command, match) {
33675
34009
  case "grantCustomerPass": return match(command);
33676
34010
  case "grantCustomerMembership": return match(command);
33677
34011
  case "seedAppointmentBooking": return match(command);
33678
- case "seedCourseEnrollment": return match(command);
34012
+ case "seedEventSeriesRegistration": return match(command);
33679
34013
  case "seedEventRegistration": return match(command);
33680
34014
  case "seedPassRedemption": return match(command);
33681
34015
  case "seedPortalOrder": return match(command);
@@ -33932,7 +34266,7 @@ function checkPortalOrdersHaveUniqueSubjects(batch) {
33932
34266
  function portalOrderSubjectKey(subject) {
33933
34267
  switch (subject.kind) {
33934
34268
  case "event_registration": return `event_registration:${subject.eventRegistrationRef}`;
33935
- case "course_enrollment": return `course_enrollment:${subject.courseEnrollmentRef}`;
34269
+ case "event_series_registration": return `event_series_registration:${subject.eventSeriesRegistrationRef}`;
33936
34270
  }
33937
34271
  }
33938
34272
  function indexOfferingCommands(batch) {
@@ -33981,7 +34315,7 @@ function indexOfferingCommands(batch) {
33981
34315
  case "grantCustomerPass":
33982
34316
  case "grantCustomerMembership":
33983
34317
  case "seedAppointmentBooking":
33984
- case "seedCourseEnrollment":
34318
+ case "seedEventSeriesRegistration":
33985
34319
  case "seedEventRegistration":
33986
34320
  case "seedPassRedemption":
33987
34321
  case "seedPortalOrder":
@@ -39193,7 +39527,7 @@ function buildTokenMaps(assets) {
39193
39527
  const byStoragePath = new Map();
39194
39528
  for (const asset of assets) {
39195
39529
  byAssetId.set(asset.id, asset.id);
39196
- const identifier = asset.identifier?.trim();
39530
+ const identifier = asset.identifier.trim();
39197
39531
  if (identifier) {
39198
39532
  byIdentifier.set(identifier, asset.id);
39199
39533
  }
@@ -44855,4 +45189,4 @@ Examples:
44855
45189
  }
44856
45190
 
44857
45191
  //#endregion
44858
- export { require_jsx_runtime as $, NAV_LINK_LETTER_SPACING_MAP as $n, surfaceForegroundDeclarations as $r, formatIgnoredDocumentSyncSectionWarning as $t, getImageUrl as A, MQ_SM_DOWN as An, isCssColorLiteral as Ar, parseJsonData as At, createDryRunReport as B, eyebrowTreatmentValues as Bn, resolveSurfaceForeground as Br, planEnvironmentExecution as Bt, rotateNormalizedPoint as C, BREAKPOINT_LG as Cn, RESOLVED_BUTTON_DISABLED_DECLARATIONS as Cr, currentInvocationEnvelope as Ct, resolveMediaTransformForAspect as D, MQ_LG_UP as Dn, contextualButtonSurfaceStyles as Dr, handleCommandError as Dt, parseAspectRatioValue as E, BREAKPOINT_XL as En, contextualButtonSurfaceResetStyles as Er, getOutputOnlyContext as Et, parseRelativeStoragePath as F, assertNever$5 as Fn, borderColorStyle as Fr, withConfirmation as Ft, getSiteCommandMetadata as G, testimonialsCompositionTreatmentValues as Gn, TokenResolver as Gr, CliExit as Gt, mapEventCommandContent as H, headingDecorationColorTokenValues as Hn, generateEffectsCSS as Hr, requireEnvironmentWriteAuthorization as Ht, classifyKnownMimeType as I, defineBlockDesignCapability as In, cssVarValue as Ir, withErrorHandling as It, entryIdentifierForCommand as J, getComponentBorderWidthPx as Jn, parseThemeForPersistence as Jr, getEnvironmentDebugInfo as Jt, blockIdentifierForCommand as K, tileTreatmentValues as Kn, parseThemeButtonVariantId as Kr, getEnvPrefix as Kt, venueManagementFields as L, defineFrameCapability as Ln, mergeStyles as Lr, withOutputOnlyErrorHandling as Lt, deriveVideoSlotPolicy as M, MQ_TABLET_ONLY as Mn, resolveThemeColorReferenceValue as Mr, resolveCommandPath as Mt, resolveVideoSelectionIntentForMediaField as N, headerVariantValues as Nn, resolveTokenOrCssColorValue as Nr, runWithInvocation as Nt, getDirectImageUrlForRelativePath as O, MQ_MD_DOWN as On, deriveButtonSurfaceContext as Or, mapEntryForOutput as Ot, asRecord as P, pageDesignEditorBackgroundOverrideOwner as Pn, backgroundColorStyle as Pr, withCommandContext as Pt, hasConfiguredBookingVertical as Q, NAV_LINK_BORDER_RADIUS_MAP as Qn, DEFAULT_SURFACE_TEXT_COLOR as Qr, createManagementClient as Qt, sortRecord as R, defineNoBlockDesignCapability as Rn, rgbColorValue as Rr, executeEnvironmentPlan as Rt, deleteEnvSpecificKeys as S, renderHeaderPaintTargetRules as Sn, generateButtonCss as Sr, createOutputForCommand as St, isExplicitRectCrop as T, BREAKPOINT_SM as Tn, resolvedButtonFocusDeclarations as Tr, getOutputContext as Tt, evaluateSiteCommandBatchExposure as U, introCompositionTreatmentValues as Un, generateBaseInteractiveCSS as Ur, withRiverbankEnv as Ut, parseAndPlanCommandBatchForTypes as V, featureCardCompositionTreatmentValues as Vn, generateDefaultButtonSystem as Vr, planEnvironmentWriteAuthorization as Vt, evaluateSiteCommandExposure as W, offeringsPreviewCompositionTreatmentValues as Wn, generateInteractiveChildInheritanceCSS as Wr, formatError as Wt, pageIdentifierForCommand as X, parseBlockCustomCssRules as Xn, formatButtonColourContractError as Xr, isRemoteConfigured as Xt, pageIdentifierForBlockCommand as Y, getComponentShadowVar as Yn, compileButtonColourStates as Yr, isLocalConfigured as Yt, pagePathForCommand as Z, parseCustomCssRules as Zn, generateShadowValue$1 as Zr, loadSdkEnvironment as Zt, hasOwnSettingsField as _, linkPayloadSchema as _i, boxBackgroundOverlaySchema as _n, cardRoleSchema as _r, confirmAction as _t, syncLocalMediaForPull as a, getTextColorForBackground as ai, GRADIENT_PRESET_IDS as an, INPUT_SPACING_MAP as ar, createCommandRef as at, attachRenderableMediaAssetFields as b, generateMobileOverlayBackdropFilterFix as bn, PUBLIC_BUTTON_ROLES as br, createGetCommand as bt, sha256 as c, hexToRgb$1 as ci, boundaryRuntimeMetricsForTransition as cn, ACCORDION_SPACING_MAP as cr, createEventSeriesRef as ct, walkLocalContentMedia as d, unsafeAsOpaqueButtonColourToken as di, parseBackgroundAppearanceColorToken as dn, ICON_CONFIG as dr, createNavigationRef as dt, surfaceForegroundStyle as ei, ManagementApiError as en, NAV_LINK_PADDING_MAP as er, require_react as et, buildStorageUrl as f, parseBlockColorToken as fi, defaultThemeTokens as fn, ICON_SIZE_PX as fr, createPageRef as ft, buildSettingsUpdateInput as g, persistableMediaSchema as gi, themeSchema as gn, generateShadowValue as gr, slugPart as gt, SETTINGS_FILE_FIELDS as h, mediaTypeDiscriminants as hi, sdkThemeWireSchema as hn, generateCardCss as hr, refSlug as ht, syncLocalMediaForPush as i, onColorTokenName as ii, gradientToCss as in, INPUT_FONT_SIZE_MAP as ir, createBlocksRef as it, isSiteScopedDirectImageStoragePath as j, MQ_SM_UP as jn, resolveOnColorForThemeToken as jr, parsePaginationOptions as jt, getDirectImageUrlForSiteScopedPath as k, MQ_MD_UP as kn, resolveContextualButtonRole as kr, parseJsonArray as kt, normalizeMediaIdentifierInput as l, VARIANT_ROLES as li, backgroundAppearanceColorTokenNames as ln, ACCORDION_TRIGGER_FONT_SCALE as lr, createFooterRef as lt, extractMediaIdentifiers as m, mediaSchema as mi, sdkSettingsUpdateSchema as mn, getDefaultCardVariants as mr, createVenueRef as mt, createStyleCommand as n, expandPalette as ni, readHeaderNavFontSizePreference as nn, NAV_LINK_TEXT_SIZE_MAP as nr, generateCssVars as nt, applyLocalMediaPush as o, ORDINARY_TEXT_MIN_CONTRAST_RATIO as oi, getGradientPreset as on, LABEL_FONT_SIZE_MAP as or, createContentEntryRef as ot, downloadMedia as p, mediaIdentifierSchema as pi, defineBlockDesignMetadata as pn, generateCardCoreCss as pr, createSiteCommandSiteRef as pt, blockOrderIdentifiersForCommand as q, visibleHeadingDecorationFamilyValues as qn, themeButtonClassName as qr, getEnvVarName as qt, revalidateLocalMediaPushPlan as r, isOnColorBackgroundCandidateToken as ri, getCuratedSiteStyle as rn, FONT_WEIGHT_MAP as rr, createBlockRef as rt, prepareLocalMediaForPush as s, featuresFromHex as si, parseGradientPresetId as sn, ACCORDION_OPEN_ACCENT_THICKNESS as sr, createEventCategoryRef as st, buildStyleSelectionInitializeCommandFromOptions as t, surfaceForegroundValue as ti, mergeHeaderNavTypographyPreference as tn, NAV_LINK_PADDING_X_MAP as tr, pickShadeTowardBackground as tt, normalizeMediaValueToIdentifierOnly as u, buttonVariantIdSchema as ui, backgroundAppearanceQuickColorTokenNames as un, ACCORDION_TRIGGER_LETTER_SPACING as ur, createFormRef as ut, writeMediaManifest as v, sdkConfiguredBookingVerticalConfigSchema as vi, boxBackgroundSchema as vn, cardVariantRoleValues as vr, createClientForEnv as vt, normalizeWidthCandidates as w, BREAKPOINT_MD as wn, resolvedButtonColourDeclarations as wr, formatDateShort as wt, buildRenderableMediaAssetIndex as x, getHeaderPaintTargets as xn, AFFORDANCE_SUPPRESS_CLASS as xr, createListCommand$1 as xt, isMediaValue as y, __toESM as yi, generateHeaderScrollTreatmentStyles as yn, normalizeCardRole as yr, createCommandContext as yt, stableStringify as z, eventListTreatmentValues as zn, textColorStyle as zr, parseEnvironmentSelection as zt };
45192
+ export { pagePathForCommand as $, NAV_LINK_BORDER_RADIUS_MAP as $n, DEFAULT_SURFACE_TEXT_COLOR as $r, loadSdkEnvironment as $t, getDirectImageUrlForRelativePath as A, sdkConfiguredBookingVerticalConfigSchema as Ai, MQ_MD_DOWN as An, resolveContextualButtonRole as Ar, mapEntryForOutput as At, sortRecord as B, eventListTreatmentValues as Bn, textColorStyle as Br, executeEnvironmentPlan as Bt, deleteEnvSpecificKeys as C, internalLinkSchema as Ci, getHeaderPaintTargets as Cn, generateButtonCss as Cr, createListCommand$1 as Ct, isExplicitRectCrop as D, isResolvedInternalLinkEntityType as Di, BREAKPOINT_SM as Dn, contextualButtonSurfaceResetStyles as Dr, getOutputContext as Dt, normalizeWidthCandidates as E, isInternalResolvedLinkValue as Ei, BREAKPOINT_MD as En, resolvedButtonFocusDeclarations as Er, formatDateShort as Et, resolveVideoSelectionIntentForMediaField as F, pageDesignEditorBackgroundOverrideOwner as Fn, backgroundColorStyle as Fr, runWithInvocation as Ft, evaluateSiteCommandBatchExposure as G, offeringsPreviewCompositionTreatmentValues as Gn, generateInteractiveChildInheritanceCSS as Gr, withRiverbankEnv as Gt, createDryRunReport as H, featureCardCompositionTreatmentValues as Hn, generateDefaultButtonSystem as Hr, planEnvironmentExecution as Ht, asRecord as I, assertNever$5 as In, borderColorStyle as Ir, withCommandContext as It, blockIdentifierForCommand as J, visibleHeadingDecorationFamilyValues as Jn, themeButtonClassName as Jr, getEnvPrefix as Jt, evaluateSiteCommandExposure as K, testimonialsCompositionTreatmentValues as Kn, TokenResolver as Kr, formatError as Kt, parseRelativeStoragePath as L, defineBlockDesignCapability as Ln, cssVarValue as Lr, withConfirmation as Lt, getImageUrl as M, MQ_SM_UP as Mn, resolveOnColorForThemeToken as Mr, parseJsonData as Mt, isSiteScopedDirectImageStoragePath as N, MQ_TABLET_ONLY as Nn, resolveThemeColorReferenceValue as Nr, parsePaginationOptions as Nt, parseAspectRatioValue as O, linkSchema as Oi, BREAKPOINT_XL as On, contextualButtonSurfaceStyles as Or, getOutputOnlyContext as Ot, deriveVideoSlotPolicy as P, headerVariantValues as Pn, resolveTokenOrCssColorValue as Pr, resolveCommandPath as Pt, pageIdentifierForCommand as Q, parseCustomCssRules as Qn, generateShadowValue$1 as Qr, isRemoteConfigured as Qt, classifyKnownMimeType as R, defineFrameCapability as Rn, mergeStyles as Rr, withErrorHandling as Rt, walkAndCollectImageAttrs as S, externalLinkSchema$1 as Si, generateMobileOverlayBackdropFilterFix as Sn, AFFORDANCE_SUPPRESS_CLASS as Sr, createGetCommand as St, rotateNormalizedPoint as T, internalRouteOnlyLinkSchema as Ti, BREAKPOINT_LG as Tn, resolvedButtonColourDeclarations as Tr, currentInvocationEnvelope as Tt, parseAndPlanCommandBatchForTypes as U, headingDecorationColorTokenValues as Un, generateEffectsCSS as Ur, planEnvironmentWriteAuthorization as Ut, stableStringify as V, eyebrowTreatmentValues as Vn, resolveSurfaceForeground as Vr, parseEnvironmentSelection as Vt, mapEventCommandContent as W, introCompositionTreatmentValues as Wn, generateBaseInteractiveCSS as Wr, requireEnvironmentWriteAuthorization as Wt, entryIdentifierForCommand as X, getComponentShadowVar as Xn, compileButtonColourStates as Xr, getEnvironmentDebugInfo as Xt, blockOrderIdentifiersForCommand as Y, getComponentBorderWidthPx as Yn, parseThemeForPersistence as Yr, getEnvVarName as Yt, pageIdentifierForBlockCommand as Z, parseBlockCustomCssRules as Zn, formatButtonColourContractError as Zr, isLocalConfigured as Zt, hasOwnSettingsField as _, persistableMediaSchema as _i, sdkThemeWireSchema as _n, generateShadowValue as _r, refSlug as _t, syncLocalMediaForPull as a, onColorTokenName as ai, getCuratedSiteStyle as an, INPUT_FONT_SIZE_MAP as ar, createBlockRef as at, attachRenderableMediaAssetFields as b, customLinkSchema$1 as bi, boxBackgroundSchema as bn, normalizeCardRole as br, createClientForEnv as bt, sha256 as c, featuresFromHex as ci, getGradientPreset as cn, ACCORDION_OPEN_ACCENT_THICKNESS as cr, createContentEntryRef as ct, walkLocalContentMedia as d, buttonVariantIdSchema as di, backgroundAppearanceColorTokenNames as dn, ACCORDION_TRIGGER_LETTER_SPACING as dr, createFooterRef as dt, surfaceForegroundDeclarations as ei, createManagementClient as en, NAV_LINK_LETTER_SPACING_MAP as er, hasConfiguredBookingVertical as et, buildStorageUrl as f, unsafeAsOpaqueButtonColourToken as fi, backgroundAppearanceQuickColorTokenNames as fn, ICON_CONFIG as fr, createFormRef as ft, buildSettingsUpdateInput as g, mediaTypeDiscriminants as gi, sdkSettingsUpdateSchema as gn, generateCardCss as gr, createVenueRef as gt, SETTINGS_FILE_FIELDS as h, mediaSchema as hi, defineBlockDesignMetadata as hn, getDefaultCardVariants as hr, createSiteCommandSiteRef as ht, syncLocalMediaForPush as i, isOnColorBackgroundCandidateToken as ii, readHeaderNavFontSizePreference as in, FONT_WEIGHT_MAP as ir, generateCssVars as it, getDirectImageUrlForSiteScopedPath as j, __toESM as ji, MQ_SM_DOWN as jn, isCssColorLiteral as jr, parseJsonArray as jt, resolveMediaTransformForAspect as k, pageLinkSchema$1 as ki, MQ_LG_UP as kn, deriveButtonSurfaceContext as kr, handleCommandError as kt, normalizeMediaIdentifierInput as l, hexToRgb$1 as li, parseGradientPresetId as ln, ACCORDION_SPACING_MAP as lr, createEventCategoryRef as lt, extractMediaIdentifiers as m, mediaIdentifierSchema as mi, defaultThemeTokens as mn, generateCardCoreCss as mr, createPageRef as mt, createStyleCommand as n, surfaceForegroundValue as ni, ManagementApiError as nn, NAV_LINK_PADDING_X_MAP as nr, require_react as nt, applyLocalMediaPush as o, getTextColorForBackground as oi, gradientToCss as on, INPUT_SPACING_MAP as or, createBlocksRef as ot, downloadMedia as p, parseBlockColorToken as pi, parseBackgroundAppearanceColorToken as pn, ICON_SIZE_PX as pr, createNavigationRef as pt, getSiteCommandMetadata as q, tileTreatmentValues as qn, parseThemeButtonVariantId as qr, CliExit as qt, revalidateLocalMediaPushPlan as r, expandPalette as ri, mergeHeaderNavTypographyPreference as rn, NAV_LINK_TEXT_SIZE_MAP as rr, pickShadeTowardBackground as rt, prepareLocalMediaForPush as s, ORDINARY_TEXT_MIN_CONTRAST_RATIO as si, GRADIENT_PRESET_IDS as sn, LABEL_FONT_SIZE_MAP as sr, createCommandRef as st, buildStyleSelectionInitializeCommandFromOptions as t, surfaceForegroundStyle as ti, formatIgnoredDocumentSyncSectionWarning as tn, NAV_LINK_PADDING_MAP as tr, require_jsx_runtime as tt, normalizeMediaValueToIdentifierOnly as u, VARIANT_ROLES as ui, boundaryRuntimeMetricsForTransition as un, ACCORDION_TRIGGER_FONT_SCALE as ur, createEventSeriesRef as ut, writeMediaManifest as v, linkPayloadSchema as vi, themeSchema as vn, cardRoleSchema as vr, slugPart as vt, looksLikeUuid as w, internalResolvedLinkSchema as wi, renderHeaderPaintTargetRules as wn, RESOLVED_BUTTON_DISABLED_DECLARATIONS as wr, createOutputForCommand as wt, buildRenderableMediaAssetIndex as x, entryLinkSchema$1 as xi, generateHeaderScrollTreatmentStyles as xn, PUBLIC_BUTTON_ROLES as xr, createCommandContext as xt, isMediaValue as y, RESOLVED_INTERNAL_LINK_ENTITY_TYPES as yi, boxBackgroundOverlaySchema as yn, cardVariantRoleValues as yr, confirmAction as yt, venueManagementFields as z, defineNoBlockDesignCapability as zn, rgbColorValue as zr, withOutputOnlyErrorHandling as zt };