@riverbankcms/sdk 0.104.0 → 0.104.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.
Files changed (129) hide show
  1. package/dist/{PreviewEditorSidebar-ywqcYjTB.mjs → PreviewEditorSidebar-CBMhU9p_.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-DApUNF6g.mjs → PreviewEditorUI-C5KEw4M8.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-DmHCcIMO.mjs → SdkPreviewModeRuntime-Iq12HjL7.mjs} +1147 -180
  4. package/dist/{SiteChromeCustomizeContext-BV9GU-3C.mjs → SiteChromeCustomizeContext-Cx0NMdyv.mjs} +1818 -951
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -0
  6. package/dist/_dts/api/src/bookingVerticals.d.ts +64 -1
  7. package/dist/_dts/blocks/src/primitives/layout/Grid.d.ts +12 -8
  8. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +3 -0
  9. package/dist/_dts/blocks/src/system/blocks/events/shared/layout.d.ts +11 -1
  10. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +7 -1
  11. package/dist/_dts/blocks/src/system/constants/events.d.ts +1 -1
  12. package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +12 -0
  13. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +2 -2
  14. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +14 -0
  15. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +33 -0
  16. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +28 -0
  17. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +32 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +1 -0
  19. package/dist/_dts/blocks/src/system/runtime/nodes/svg.d.ts +77 -0
  20. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +2 -0
  21. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +3 -40
  22. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +14 -0
  23. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +11 -0
  24. package/dist/_dts/core/src/branded.d.ts +5 -0
  25. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +18 -0
  26. package/dist/_dts/editor/src/index.d.ts +3 -1
  27. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +14 -6
  28. package/dist/_dts/editor/src/primitives/rich-text/RichTextToolbar.d.ts +23 -4
  29. package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +6 -0
  30. package/dist/_dts/editor/src/primitives/rich-text/extensions/RichTextLink.d.ts +1 -0
  31. package/dist/_dts/editor/src/primitives/rich-text/paste.d.ts +10 -0
  32. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +2 -2
  33. package/dist/_dts/sdk/src/version.d.ts +1 -1
  34. package/dist/_dts/theme-core/src/ThemeScope.d.ts +1 -1
  35. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +29 -0
  36. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +6 -0
  37. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  38. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +20 -0
  39. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  40. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +4 -0
  41. package/dist/_dts/theme-core/src/buttons/types.d.ts +34 -0
  42. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  43. package/dist/_dts/theme-core/src/gradients/types.d.ts +27 -3
  44. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +51 -15
  45. package/dist/_dts/theme-core/src/palette/curated/brand-led.d.ts +13 -0
  46. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +12 -0
  47. package/dist/_dts/theme-core/src/palette/historicalThemePalette.d.ts +44 -0
  48. package/dist/_dts/theme-core/src/palette/index.d.ts +1 -0
  49. package/dist/_dts/theme-core/src/palette/legacyRuntimeProjection.d.ts +23 -6
  50. package/dist/_dts/theme-core/src/palette/legacySelection.d.ts +13 -2
  51. package/dist/_dts/theme-core/src/palette/paletteCompatibilityTransition.d.ts +0 -9
  52. package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +17 -2
  53. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +3 -4
  54. package/dist/_dts/theme-core/src/runtime/themeCssVarNames.d.ts +1 -0
  55. package/dist/_dts/theme-core/src/schema.d.ts +108 -26
  56. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +2 -1
  57. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +50 -1
  58. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  59. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  60. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +56 -1
  61. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  62. package/dist/_dts/theme-core/src/status/index.d.ts +0 -1
  63. package/dist/_dts/theme-core/src/surfaces/foregroundContract.d.ts +19 -0
  64. package/dist/_dts/theme-core/src/surfaces/foregroundRoles.d.ts +9 -0
  65. package/dist/_dts/theme-core/src/surfaces/index.d.ts +2 -0
  66. package/dist/_dts/ui/src/button.d.ts +1 -1
  67. package/dist/cli/index.mjs +1567 -470
  68. package/dist/client/{DiscountCodeDisclosure-Dit2aItR.mjs → DiscountCodeDisclosure-BXM73_E5.mjs} +1 -1
  69. package/dist/client/{EventCombined.client-BnREyCjf.mjs → EventCombined.client-DT5elP7j.mjs} +4 -4
  70. package/dist/client/{EventListing.client-0uHld51x.mjs → EventListing.client-pTYGfV9C.mjs} +2 -2
  71. package/dist/client/{LeafletStaticMap-DJcvSfmj.mjs → LeafletStaticMap-dQrhlUe3.mjs} +1 -1
  72. package/dist/client/{MagicLinkForm-EAsIktfw.mjs → MagicLinkForm-u6Dul4j5.mjs} +2 -2
  73. package/dist/client/{StepIndicator-CRR17tYI.mjs → StepIndicator-nWqineJ2.mjs} +2 -2
  74. package/dist/client/{accordion-B47HIuuH.mjs → accordion-CSJcTUyH.mjs} +1 -1
  75. package/dist/client/{bookingForm-I1E-8F9P.mjs → bookingForm-C73wOuVa.mjs} +6 -6
  76. package/dist/client/bookings.mjs +137 -1
  77. package/dist/client/{buttons-BbPn8OKA.mjs → buttons-DfYyqt8C.mjs} +138 -2
  78. package/dist/client/{carousel-OlM7SyBs.mjs → carousel-fMBb0JSc.mjs} +1 -1
  79. package/dist/client/{cart-BKpG5jz6.mjs → cart-BtaCwT3S.mjs} +3 -3
  80. package/dist/client/{checkout-Dmmr6qoU.mjs → checkout-DkTwZSnh.mjs} +3 -3
  81. package/dist/client/client.mjs +2336 -544
  82. package/dist/client/{colorStyles-DuW4Fjqd.mjs → colorStyles-Wyl6JujD.mjs} +45 -4
  83. package/dist/client/{courseRegistration-CflZiqGk.mjs → courseRegistration-DnLmapJu.mjs} +7 -7
  84. package/dist/client/{eventCalendar-BvoLWcp-.mjs → eventCalendar-BvLOc9KY.mjs} +165 -5
  85. package/dist/client/{eventCombined-DsrO8t_t.mjs → eventCombined-kShgJPQr.mjs} +2 -2
  86. package/dist/client/{eventDetails-C3hxgcJm.mjs → eventDetails-C5NTM0Vo.mjs} +3 -3
  87. package/dist/client/{eventListing-C-hb237X.mjs → eventListing-B82ZdKP6.mjs} +2 -2
  88. package/dist/client/{eventRegistration-B0gyzDGi.mjs → eventRegistration-qJVFqBWo.mjs} +7 -7
  89. package/dist/client/{form-C_RUi6oJ.mjs → form-BvAcKiuu.mjs} +2 -2
  90. package/dist/client/{headerSection-IKQiD2U0.mjs → headerSection-NvAiEHAg.mjs} +3 -3
  91. package/dist/client/hooks.mjs +1023 -337
  92. package/dist/client/{locationMap-8ZBrMzRJ.mjs → locationMap-D0j52xfI.mjs} +3 -3
  93. package/dist/client/{media-CZJKL7fi.mjs → media-BCW_g2cQ.mjs} +1 -1
  94. package/dist/client/{newsletterForm-CYk3ucwj.mjs → newsletterForm-B8_i93qH.mjs} +2 -2
  95. package/dist/client/{pricing-B5GmvfIH.mjs → pricing-DIYnyHOk.mjs} +1 -1
  96. package/dist/client/{productDetail-BjS2Dqzo.mjs → productDetail-w0eAHkuQ.mjs} +3 -3
  97. package/dist/client/{productList-BOHvC8My.mjs → productList-Vsguq5Xt.mjs} +3 -3
  98. package/dist/client/{propsDecoder-WS6UEJwZ.mjs → propsDecoder-CD2pJ1WB.mjs} +37 -2
  99. package/dist/client/rendering/client.mjs +1723 -762
  100. package/dist/client/rendering/islands.mjs +19 -19
  101. package/dist/client/rendering.mjs +2312 -520
  102. package/dist/client/{shop-CON03-wN.mjs → shop-Dgxs-Q8F.mjs} +6 -6
  103. package/dist/client/{shop-commerce-DlqrFgH8.mjs → shop-commerce-DJAhsTaT.mjs} +6 -6
  104. package/dist/client/{shop-commerce-store-l74-Kne6.mjs → shop-commerce-store-CfCXltXW.mjs} +1 -1
  105. package/dist/client/{shopShared-CQheEXSg.mjs → shopShared-CmDcPXUt.mjs} +2 -2
  106. package/dist/client/{useDiscountCodeUi-v6OluyWl.mjs → useDiscountCodeUi-CirrT2bM.mjs} +1 -1
  107. package/dist/client/{useEventFilters-BqSTcNOf.mjs → useEventFilters-CNZxlCcO.mjs} +5 -5
  108. package/dist/client/{usePolling-DMfADjIF.mjs → usePolling-Baks_iBI.mjs} +2 -2
  109. package/dist/preview-next/client/runtime.mjs +3 -3
  110. package/dist/{sdk-runtime-DWb08Xaz.mjs → sdk-runtime-BfNiFeNJ.mjs} +1 -1
  111. package/dist/{separator--6yjc914.mjs → separator-BhAR_Xmf.mjs} +1 -1
  112. package/dist/server/components.mjs +2301 -531
  113. package/dist/server/config-validation.mjs +1028 -337
  114. package/dist/server/config.mjs +1028 -337
  115. package/dist/server/data.mjs +1023 -337
  116. package/dist/server/index.mjs +1 -1
  117. package/dist/server/next.mjs +2304 -534
  118. package/dist/server/page-converter.mjs +1018 -324
  119. package/dist/server/prebuild.mjs +1 -1
  120. package/dist/server/rendering/server.mjs +2286 -521
  121. package/dist/server/rendering.mjs +2301 -531
  122. package/dist/server/routing.mjs +1100 -338
  123. package/dist/server/server.mjs +1024 -338
  124. package/dist/server/theme-bridge.mjs +1240 -77
  125. package/dist/server/theme.mjs +165 -5
  126. package/dist/styles/index.css +617 -34
  127. package/package.json +1 -1
  128. package/dist/_dts/blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.d.ts +0 -2
  129. package/dist/_dts/theme-core/src/status/contextualColors.d.ts +0 -6
@@ -8005,11 +8005,11 @@ var init_fileStorage = __esmMin((() => {
8005
8005
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
8006
8006
  //#endregion
8007
8007
  //#region ../media-core/src/typeGuards.ts
8008
- function isRecord$49(value) {
8008
+ function isRecord$51(value) {
8009
8009
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8010
8010
  }
8011
8011
  function asRecord$4(value) {
8012
- return isRecord$49(value) ? value : void 0;
8012
+ return isRecord$51(value) ? value : void 0;
8013
8013
  }
8014
8014
  var init_typeGuards$1 = __esmMin((() => {}));
8015
8015
  function isFileJsonObject(value) {
@@ -8019,7 +8019,7 @@ function isFileJsonValue(value) {
8019
8019
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
8020
8020
  if (typeof value === "number") return Number.isFinite(value);
8021
8021
  if (Array.isArray(value)) return value.every(isFileJsonValue);
8022
- return isRecord$49(value) && isFileJsonObject(value);
8022
+ return isRecord$51(value) && isFileJsonObject(value);
8023
8023
  }
8024
8024
  var init_filePersistence = __esmMin((() => {
8025
8025
  init_src$4();
@@ -8453,7 +8453,7 @@ function isCmsMediaObjectType(value) {
8453
8453
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
8454
8454
  }
8455
8455
  function isCmsMediaObject(value) {
8456
- if (!isRecord$49(value)) return false;
8456
+ if (!isRecord$51(value)) return false;
8457
8457
  const type = value.type;
8458
8458
  if (!isCmsMediaObjectType(type)) return false;
8459
8459
  if ("attrs" in value) return false;
@@ -8464,7 +8464,7 @@ function collectMediaObjects(value, out, location = "") {
8464
8464
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
8465
8465
  return;
8466
8466
  }
8467
- if (!isRecord$49(value)) return;
8467
+ if (!isRecord$51(value)) return;
8468
8468
  if (isCmsMediaObject(value)) out.push({
8469
8469
  obj: value,
8470
8470
  location
@@ -8498,8 +8498,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
8498
8498
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
8499
8499
  return;
8500
8500
  }
8501
- if (!isRecord$49(value)) return;
8502
- if (value.type === "image" && isRecord$49(value.attrs)) out.push({
8501
+ if (!isRecord$51(value)) return;
8502
+ if (value.type === "image" && isRecord$51(value.attrs)) out.push({
8503
8503
  attrs: value.attrs,
8504
8504
  location: location ? `${location}.attrs` : "attrs"
8505
8505
  });
@@ -8788,6 +8788,9 @@ var init_validation_constants = __esmMin((() => {
8788
8788
  "richText",
8789
8789
  "media",
8790
8790
  "videoEmbed",
8791
+ "icon",
8792
+ "feature-card-icon",
8793
+ "svg",
8791
8794
  "button",
8792
8795
  "link",
8793
8796
  "carousel",
@@ -8817,11 +8820,13 @@ var init_validation_constants = __esmMin((() => {
8817
8820
  "value.jsonArray",
8818
8821
  "value.csv",
8819
8822
  "array.marqueeLoop",
8823
+ "value.mapToken",
8820
8824
  "layout.maxWidthClass",
8821
8825
  "layout.headerRootClass",
8822
8826
  "layout.footerRootClass",
8823
8827
  "layout.headerRootStyle",
8824
8828
  "layout.headerSectionBackground",
8829
+ "layout.classicNavMode",
8825
8830
  "layout.footerRootStyle",
8826
8831
  "ui.headerNavLinkClass",
8827
8832
  "ui.headingClassFromAlignment",
@@ -10697,7 +10702,7 @@ function getSemanticIconComponent(name) {
10697
10702
  //#endregion
10698
10703
  //#region ../blocks/src/system/icons/value.ts
10699
10704
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
10700
- function isRecord$48(value) {
10705
+ function isRecord$50(value) {
10701
10706
  return typeof value === "object" && value !== null && !Array.isArray(value);
10702
10707
  }
10703
10708
  function parseBlockIconValue(value) {
@@ -10705,7 +10710,7 @@ function parseBlockIconValue(value) {
10705
10710
  kind: "semantic",
10706
10711
  iconId: value
10707
10712
  };
10708
- if (!isRecord$48(value)) return NO_BLOCK_ICON_VALUE;
10713
+ if (!isRecord$50(value)) return NO_BLOCK_ICON_VALUE;
10709
10714
  switch (value.kind) {
10710
10715
  case "none": return NO_BLOCK_ICON_VALUE;
10711
10716
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -10778,7 +10783,7 @@ function buildGeneratedBlockIconRenderAssetLookupFromUnknown(value) {
10778
10783
  if (!Array.isArray(value)) return { kind: "invalid_asset_list" };
10779
10784
  const inputs = [];
10780
10785
  for (const [index, item] of value.entries()) {
10781
- if (!isRecord$48(item)) return {
10786
+ if (!isRecord$50(item)) return {
10782
10787
  kind: "invalid_asset_entry",
10783
10788
  index,
10784
10789
  reason: "not_object"
@@ -13195,6 +13200,246 @@ var init_all = __esmMin((() => {
13195
13200
  init_PaletteCard();
13196
13201
  }));
13197
13202
  //#endregion
13203
+ //#region ../theme-core/src/tokens/colorTokenParts.ts
13204
+ function parseOpacityPercent(source) {
13205
+ const trimmed = source.trim();
13206
+ if (!trimmed) return null;
13207
+ if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
13208
+ const value = Number(trimmed);
13209
+ if (!Number.isFinite(value)) return null;
13210
+ if (value < 0 || value > 100) return null;
13211
+ return value;
13212
+ }
13213
+ function parseColorTokenParts(source) {
13214
+ const trimmed = source.trim();
13215
+ if (trimmed.startsWith("raw:")) return {
13216
+ kind: "raw",
13217
+ value: trimmed.slice(4)
13218
+ };
13219
+ const [token, opacityRaw, extra] = trimmed.split("/");
13220
+ if (!token || extra !== void 0) return {
13221
+ kind: "invalid",
13222
+ token: trimmed
13223
+ };
13224
+ if (opacityRaw === void 0) return {
13225
+ kind: "token",
13226
+ token,
13227
+ opacityPercent: null
13228
+ };
13229
+ const opacityPercent = parseOpacityPercent(opacityRaw);
13230
+ if (opacityPercent === null) return {
13231
+ kind: "invalid",
13232
+ token: trimmed
13233
+ };
13234
+ return {
13235
+ kind: "token",
13236
+ token,
13237
+ opacityPercent
13238
+ };
13239
+ }
13240
+ var init_colorTokenParts = __esmMin((() => {}));
13241
+ function isBlockColorToken(value) {
13242
+ if (typeof value !== "string") return false;
13243
+ const parts = parseColorTokenParts(value);
13244
+ return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
13245
+ }
13246
+ function parseBlockColorToken(value) {
13247
+ if (!isBlockColorToken(value)) return null;
13248
+ return value.trim();
13249
+ }
13250
+ var blockColorTokenNames, blockColorTokenNameSet;
13251
+ var init_blockColorTokens = __esmMin((() => {
13252
+ init_colorTokenParts();
13253
+ blockColorTokenNames = [
13254
+ "text",
13255
+ "heading",
13256
+ "mutedText",
13257
+ "surface",
13258
+ "background",
13259
+ "foreground",
13260
+ "border",
13261
+ "primary",
13262
+ "secondary",
13263
+ "accent",
13264
+ "success",
13265
+ "warning",
13266
+ "info",
13267
+ "error",
13268
+ "destructive",
13269
+ "scrim",
13270
+ "shadow",
13271
+ "onPrimary",
13272
+ "onSecondary",
13273
+ "onAccent",
13274
+ "onSuccess",
13275
+ "onWarning",
13276
+ "onInfo",
13277
+ "onError",
13278
+ "onDestructive",
13279
+ "onSurface"
13280
+ ];
13281
+ blockColorTokenNameSet = new Set(blockColorTokenNames);
13282
+ }));
13283
+ //#endregion
13284
+ //#region ../theme-core/src/tokens/themeColorTokens.ts
13285
+ function isKnownBaseToken(value) {
13286
+ return themeColorBaseTokenSet.has(value);
13287
+ }
13288
+ function isKnownShadeToken(value) {
13289
+ const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
13290
+ if (!match) return false;
13291
+ const [, base, shade] = match;
13292
+ return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
13293
+ }
13294
+ function isThemeColorTokenBase(value) {
13295
+ return isKnownBaseToken(value) || isKnownShadeToken(value);
13296
+ }
13297
+ function isThemeColorToken(value) {
13298
+ if (typeof value !== "string") return false;
13299
+ const parts = parseColorTokenParts(value);
13300
+ return parts.kind === "token" && isThemeColorTokenBase(parts.token);
13301
+ }
13302
+ function parseThemeColorToken(value) {
13303
+ if (!isThemeColorToken(value)) return null;
13304
+ return value.trim();
13305
+ }
13306
+ var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
13307
+ var init_themeColorTokens = __esmMin((() => {
13308
+ init_blockColorTokens();
13309
+ init_colorTokenParts();
13310
+ PALETTE_TOKEN_NAMES = [
13311
+ "primary",
13312
+ "primaryForeground",
13313
+ "secondary",
13314
+ "accent",
13315
+ "success",
13316
+ "warning",
13317
+ "destructive",
13318
+ "background",
13319
+ "surface",
13320
+ "surfaceAlt",
13321
+ "muted",
13322
+ "text",
13323
+ "border"
13324
+ ];
13325
+ paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
13326
+ themeColorBaseTokenNames = [
13327
+ ...PALETTE_TOKEN_NAMES,
13328
+ ...blockColorTokenNames,
13329
+ "white",
13330
+ "neutral",
13331
+ "primaryText",
13332
+ "secondaryForeground",
13333
+ "accentForeground"
13334
+ ];
13335
+ themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
13336
+ themeColorShadeSteps = [
13337
+ "50",
13338
+ "100",
13339
+ "200",
13340
+ "300",
13341
+ "400",
13342
+ "500",
13343
+ "600",
13344
+ "700",
13345
+ "800",
13346
+ "900",
13347
+ "950"
13348
+ ];
13349
+ shadeStepSet = new Set(themeColorShadeSteps);
13350
+ themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
13351
+ }));
13352
+ //#endregion
13353
+ //#region ../theme-core/src/palette/colors.ts
13354
+ function normalizePaletteHex(value) {
13355
+ if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
13356
+ const normalized = value.toLowerCase();
13357
+ if (normalized.length === 7) return normalized;
13358
+ const triplet = normalized.slice(1);
13359
+ const red = triplet.charAt(0);
13360
+ const green = triplet.charAt(1);
13361
+ const blue = triplet.charAt(2);
13362
+ return `#${red}${red}${green}${green}${blue}${blue}`;
13363
+ }
13364
+ function paletteColorsFromEntries(entries) {
13365
+ const values = {};
13366
+ for (const entry of entries) {
13367
+ const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
13368
+ if (!parsedRole.success) return {
13369
+ ok: false,
13370
+ error: {
13371
+ kind: "unknown-role",
13372
+ role: entry.name
13373
+ }
13374
+ };
13375
+ const role = parsedRole.data;
13376
+ if (values[role] !== void 0) return {
13377
+ ok: false,
13378
+ error: {
13379
+ kind: "duplicate-role",
13380
+ role
13381
+ }
13382
+ };
13383
+ const hex = normalizePaletteHex(entry.hex);
13384
+ if (!hex) return {
13385
+ ok: false,
13386
+ error: {
13387
+ kind: "invalid-color",
13388
+ role,
13389
+ value: entry.hex
13390
+ }
13391
+ };
13392
+ values[role] = hex;
13393
+ }
13394
+ const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
13395
+ if (missing.length > 0) return {
13396
+ ok: false,
13397
+ error: {
13398
+ kind: "missing-roles",
13399
+ roles: missing
13400
+ }
13401
+ };
13402
+ return {
13403
+ ok: true,
13404
+ colors: paletteColorsSchema.parse(values)
13405
+ };
13406
+ }
13407
+ function requirePaletteColorsFromEntries(entries) {
13408
+ const result = paletteColorsFromEntries(entries);
13409
+ if (result.ok) return result.colors;
13410
+ throw new Error(`Invalid complete palette: ${result.error.kind}`);
13411
+ }
13412
+ var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema$1, paletteModeSchema, paletteColorsSchema, init_colors = __esmMin((() => {
13413
+ init_themeColorTokens();
13414
+ HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
13415
+ NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
13416
+ hexColorSchema$1 = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
13417
+ paletteModeSchema = z$1.enum(["light", "dark"]);
13418
+ z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
13419
+ paletteColorsSchema = z$1.object({
13420
+ primary: hexColorSchema$1,
13421
+ primaryForeground: hexColorSchema$1,
13422
+ secondary: hexColorSchema$1,
13423
+ accent: hexColorSchema$1,
13424
+ success: hexColorSchema$1,
13425
+ warning: hexColorSchema$1,
13426
+ destructive: hexColorSchema$1,
13427
+ background: hexColorSchema$1,
13428
+ surface: hexColorSchema$1,
13429
+ surfaceAlt: hexColorSchema$1,
13430
+ muted: hexColorSchema$1,
13431
+ text: hexColorSchema$1,
13432
+ border: hexColorSchema$1
13433
+ }).strict().transform((value) => value);
13434
+ }));
13435
+ var init_historicalThemePalette = __esmMin((() => {
13436
+ init_themeColorTokens();
13437
+ init_colors();
13438
+ init_colorConversion();
13439
+ init_textColor();
13440
+ new Set(PALETTE_TOKEN_NAMES);
13441
+ }));
13442
+ //#endregion
13198
13443
  //#region ../theme-core/src/palette/types.ts
13199
13444
  var init_types$16 = __esmMin((() => {}));
13200
13445
  //#endregion
@@ -14321,240 +14566,6 @@ var init_browser = __esmMin((() => {
14321
14566
  var init_extractPalette = __esmMin((() => {
14322
14567
  init_browser();
14323
14568
  }));
14324
- //#endregion
14325
- //#region ../theme-core/src/tokens/colorTokenParts.ts
14326
- function parseOpacityPercent(source) {
14327
- const trimmed = source.trim();
14328
- if (!trimmed) return null;
14329
- if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
14330
- const value = Number(trimmed);
14331
- if (!Number.isFinite(value)) return null;
14332
- if (value < 0 || value > 100) return null;
14333
- return value;
14334
- }
14335
- function parseColorTokenParts(source) {
14336
- const trimmed = source.trim();
14337
- if (trimmed.startsWith("raw:")) return {
14338
- kind: "raw",
14339
- value: trimmed.slice(4)
14340
- };
14341
- const [token, opacityRaw, extra] = trimmed.split("/");
14342
- if (!token || extra !== void 0) return {
14343
- kind: "invalid",
14344
- token: trimmed
14345
- };
14346
- if (opacityRaw === void 0) return {
14347
- kind: "token",
14348
- token,
14349
- opacityPercent: null
14350
- };
14351
- const opacityPercent = parseOpacityPercent(opacityRaw);
14352
- if (opacityPercent === null) return {
14353
- kind: "invalid",
14354
- token: trimmed
14355
- };
14356
- return {
14357
- kind: "token",
14358
- token,
14359
- opacityPercent
14360
- };
14361
- }
14362
- var init_colorTokenParts = __esmMin((() => {}));
14363
- function isBlockColorToken(value) {
14364
- if (typeof value !== "string") return false;
14365
- const parts = parseColorTokenParts(value);
14366
- return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
14367
- }
14368
- function parseBlockColorToken(value) {
14369
- if (!isBlockColorToken(value)) return null;
14370
- return value.trim();
14371
- }
14372
- var blockColorTokenNames, blockColorTokenNameSet;
14373
- var init_blockColorTokens = __esmMin((() => {
14374
- init_colorTokenParts();
14375
- blockColorTokenNames = [
14376
- "text",
14377
- "heading",
14378
- "mutedText",
14379
- "surface",
14380
- "background",
14381
- "foreground",
14382
- "border",
14383
- "primary",
14384
- "secondary",
14385
- "accent",
14386
- "success",
14387
- "warning",
14388
- "info",
14389
- "error",
14390
- "destructive",
14391
- "scrim",
14392
- "shadow",
14393
- "onPrimary",
14394
- "onSecondary",
14395
- "onAccent",
14396
- "onSuccess",
14397
- "onWarning",
14398
- "onInfo",
14399
- "onError",
14400
- "onDestructive",
14401
- "onSurface"
14402
- ];
14403
- blockColorTokenNameSet = new Set(blockColorTokenNames);
14404
- }));
14405
- //#endregion
14406
- //#region ../theme-core/src/tokens/themeColorTokens.ts
14407
- function isKnownBaseToken(value) {
14408
- return themeColorBaseTokenSet.has(value);
14409
- }
14410
- function isKnownShadeToken(value) {
14411
- const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
14412
- if (!match) return false;
14413
- const [, base, shade] = match;
14414
- return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
14415
- }
14416
- function isThemeColorTokenBase(value) {
14417
- return isKnownBaseToken(value) || isKnownShadeToken(value);
14418
- }
14419
- function isThemeColorToken(value) {
14420
- if (typeof value !== "string") return false;
14421
- const parts = parseColorTokenParts(value);
14422
- return parts.kind === "token" && isThemeColorTokenBase(parts.token);
14423
- }
14424
- function parseThemeColorToken(value) {
14425
- if (!isThemeColorToken(value)) return null;
14426
- return value.trim();
14427
- }
14428
- var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
14429
- var init_themeColorTokens = __esmMin((() => {
14430
- init_blockColorTokens();
14431
- init_colorTokenParts();
14432
- PALETTE_TOKEN_NAMES = [
14433
- "primary",
14434
- "primaryForeground",
14435
- "secondary",
14436
- "accent",
14437
- "success",
14438
- "warning",
14439
- "destructive",
14440
- "background",
14441
- "surface",
14442
- "surfaceAlt",
14443
- "muted",
14444
- "text",
14445
- "border"
14446
- ];
14447
- paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
14448
- themeColorBaseTokenNames = [
14449
- ...PALETTE_TOKEN_NAMES,
14450
- ...blockColorTokenNames,
14451
- "white",
14452
- "neutral",
14453
- "primaryText",
14454
- "secondaryForeground",
14455
- "accentForeground"
14456
- ];
14457
- themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
14458
- themeColorShadeSteps = [
14459
- "50",
14460
- "100",
14461
- "200",
14462
- "300",
14463
- "400",
14464
- "500",
14465
- "600",
14466
- "700",
14467
- "800",
14468
- "900",
14469
- "950"
14470
- ];
14471
- shadeStepSet = new Set(themeColorShadeSteps);
14472
- themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
14473
- }));
14474
- //#endregion
14475
- //#region ../theme-core/src/palette/colors.ts
14476
- function normalizePaletteHex(value) {
14477
- if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
14478
- const normalized = value.toLowerCase();
14479
- if (normalized.length === 7) return normalized;
14480
- const triplet = normalized.slice(1);
14481
- const red = triplet.charAt(0);
14482
- const green = triplet.charAt(1);
14483
- const blue = triplet.charAt(2);
14484
- return `#${red}${red}${green}${green}${blue}${blue}`;
14485
- }
14486
- function paletteColorsFromEntries(entries) {
14487
- const values = {};
14488
- for (const entry of entries) {
14489
- const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
14490
- if (!parsedRole.success) return {
14491
- ok: false,
14492
- error: {
14493
- kind: "unknown-role",
14494
- role: entry.name
14495
- }
14496
- };
14497
- const role = parsedRole.data;
14498
- if (values[role] !== void 0) return {
14499
- ok: false,
14500
- error: {
14501
- kind: "duplicate-role",
14502
- role
14503
- }
14504
- };
14505
- const hex = normalizePaletteHex(entry.hex);
14506
- if (!hex) return {
14507
- ok: false,
14508
- error: {
14509
- kind: "invalid-color",
14510
- role,
14511
- value: entry.hex
14512
- }
14513
- };
14514
- values[role] = hex;
14515
- }
14516
- const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
14517
- if (missing.length > 0) return {
14518
- ok: false,
14519
- error: {
14520
- kind: "missing-roles",
14521
- roles: missing
14522
- }
14523
- };
14524
- return {
14525
- ok: true,
14526
- colors: paletteColorsSchema.parse(values)
14527
- };
14528
- }
14529
- function requirePaletteColorsFromEntries(entries) {
14530
- const result = paletteColorsFromEntries(entries);
14531
- if (result.ok) return result.colors;
14532
- throw new Error(`Invalid complete palette: ${result.error.kind}`);
14533
- }
14534
- var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema$1, paletteModeSchema, paletteColorsSchema;
14535
- var init_colors = __esmMin((() => {
14536
- init_themeColorTokens();
14537
- HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
14538
- NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
14539
- hexColorSchema$1 = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
14540
- paletteModeSchema = z$1.enum(["light", "dark"]);
14541
- z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
14542
- paletteColorsSchema = z$1.object({
14543
- primary: hexColorSchema$1,
14544
- primaryForeground: hexColorSchema$1,
14545
- secondary: hexColorSchema$1,
14546
- accent: hexColorSchema$1,
14547
- success: hexColorSchema$1,
14548
- warning: hexColorSchema$1,
14549
- destructive: hexColorSchema$1,
14550
- background: hexColorSchema$1,
14551
- surface: hexColorSchema$1,
14552
- surfaceAlt: hexColorSchema$1,
14553
- muted: hexColorSchema$1,
14554
- text: hexColorSchema$1,
14555
- border: hexColorSchema$1
14556
- }).strict().transform((value) => value);
14557
- }));
14558
14569
  var init_editorState = __esmMin((() => {}));
14559
14570
  var init_libraryModel = __esmMin((() => {}));
14560
14571
  var init_themePaletteCompatibility = __esmMin((() => {
@@ -14565,6 +14576,7 @@ var init_legacySelection = __esmMin((() => {
14565
14576
  init_themeColorTokens();
14566
14577
  init_colors();
14567
14578
  init_themePaletteCompatibility();
14579
+ init_historicalThemePalette();
14568
14580
  }));
14569
14581
  //#endregion
14570
14582
  //#region ../theme-core/src/site-styles/styleTags.ts
@@ -14645,7 +14657,7 @@ var init_types$15 = __esmMin((() => {
14645
14657
  }));
14646
14658
  //#endregion
14647
14659
  //#region ../theme-core/src/palette/curated/brand-led.ts
14648
- var brandLedCool, brandLedWarm, brandLedJewel, brandLedBurgundyGold;
14660
+ var brandLedCool, brandLedWarm, brandLedJewel, brandLedSpruce, brandLedBurgundyGold;
14649
14661
  var init_brand_led = __esmMin((() => {
14650
14662
  init_types$15();
14651
14663
  brandLedCool = defineCuratedPalette({
@@ -14843,6 +14855,71 @@ var init_brand_led = __esmMin((() => {
14843
14855
  }
14844
14856
  ]
14845
14857
  });
14858
+ brandLedSpruce = defineCuratedPalette({
14859
+ id: "brand-led-spruce",
14860
+ name: "Brand-led — Spruce",
14861
+ description: "Spruce-ink primary and moss secondary with an amber accent over a green-mist ground and hairline sage borders.",
14862
+ tags: {
14863
+ tone: "classic",
14864
+ energy: "calm",
14865
+ era: "editorial"
14866
+ },
14867
+ mode: "light",
14868
+ colors: [
14869
+ {
14870
+ name: "primary",
14871
+ hex: "#14312b"
14872
+ },
14873
+ {
14874
+ name: "secondary",
14875
+ hex: "#356a59"
14876
+ },
14877
+ {
14878
+ name: "accent",
14879
+ hex: "#f08a4b"
14880
+ },
14881
+ {
14882
+ name: "success",
14883
+ hex: "#356a59"
14884
+ },
14885
+ {
14886
+ name: "warning",
14887
+ hex: "#f08a4b"
14888
+ },
14889
+ {
14890
+ name: "destructive",
14891
+ hex: "#b5561f"
14892
+ },
14893
+ {
14894
+ name: "background",
14895
+ hex: "#ecefe9"
14896
+ },
14897
+ {
14898
+ name: "surface",
14899
+ hex: "#ffffff"
14900
+ },
14901
+ {
14902
+ name: "surfaceAlt",
14903
+ hex: "#f4f6f1"
14904
+ },
14905
+ {
14906
+ name: "muted",
14907
+ hex: "#5c6a64"
14908
+ },
14909
+ {
14910
+ name: "text",
14911
+ hex: "#1c2a26"
14912
+ },
14913
+ {
14914
+ name: "primaryForeground",
14915
+ hex: "#f4f7f1"
14916
+ },
14917
+ {
14918
+ name: "border",
14919
+ hex: "#d7ddd2"
14920
+ }
14921
+ ]
14922
+ });
14846
14923
  brandLedBurgundyGold = defineCuratedPalette({
14847
14924
  id: "brand-led-burgundy-gold",
14848
14925
  name: "Brand-led — Burgundy Gold",
@@ -15783,8 +15860,7 @@ var init_warm_dark = __esmMin((() => {
15783
15860
  function findCuratedPalette(id) {
15784
15861
  return curatedPalettesById.get(id);
15785
15862
  }
15786
- var curatedPalettes, curatedPalettesById;
15787
- var init_curated = __esmMin((() => {
15863
+ var curatedPalettes, curatedPalettesById, init_curated = __esmMin((() => {
15788
15864
  init_brand_led();
15789
15865
  init_high_contrast();
15790
15866
  init_soft_natural();
@@ -15796,6 +15872,7 @@ var init_curated = __esmMin((() => {
15796
15872
  brandLedWarm,
15797
15873
  brandLedJewel,
15798
15874
  brandLedBurgundyGold,
15875
+ brandLedSpruce,
15799
15876
  warmNeutralClay,
15800
15877
  warmNeutralCream,
15801
15878
  warmNeutralSoftEarth,
@@ -15912,6 +15989,7 @@ var init_palette = __esmMin((() => {
15912
15989
  init_expandPalette();
15913
15990
  init_generateCssVars();
15914
15991
  init_generateShades();
15992
+ init_historicalThemePalette();
15915
15993
  init_neutralScale();
15916
15994
  init_types$16();
15917
15995
  init_utils$5();
@@ -16297,7 +16375,7 @@ function asSpecialVariantId(value) {
16297
16375
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
16298
16376
  return value;
16299
16377
  }
16300
- var VARIANT_ROLES, DEFAULT_VARIANT_ALIAS_ID, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonBackgroundSchema, effectApplicationSchema$1, buttonBorderSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, buttonVariantSchema, buttonSystemSchema;
16378
+ var VARIANT_ROLES, DEFAULT_VARIANT_ALIAS_ID, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonBackgroundSchema, effectApplicationSchema$1, buttonBorderSchema, buttonVariantAffordanceSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, buttonVariantSchema, buttonSystemSchema;
16301
16379
  var init_types$14 = __esmMin((() => {
16302
16380
  init_themeColorTokens();
16303
16381
  VARIANT_ROLES = [
@@ -16457,6 +16535,10 @@ var init_types$14 = __esmMin((() => {
16457
16535
  widthClass: z$1.string(),
16458
16536
  colorToken: themeColorTokenSchema
16459
16537
  });
16538
+ buttonVariantAffordanceSchema = z$1.object({
16539
+ iconId: z$1.string().min(1),
16540
+ colorToken: themeColorTokenSchema.optional()
16541
+ });
16460
16542
  variantShadowSchema = z$1.object({
16461
16543
  elevation: z$1.enum([
16462
16544
  "none",
@@ -16497,7 +16579,8 @@ var init_types$14 = __esmMin((() => {
16497
16579
  border: buttonBorderSchema.optional(),
16498
16580
  hoverBackgroundToken: z$1.string().optional(),
16499
16581
  effects: variantEffectsSchema.optional(),
16500
- sizes: variantSizeOverridesSchema.optional()
16582
+ sizes: variantSizeOverridesSchema.optional(),
16583
+ affordance: buttonVariantAffordanceSchema.optional()
16501
16584
  });
16502
16585
  buttonSystemSchema = z$1.object({
16503
16586
  global: buttonGlobalSettingsSchema,
@@ -17047,6 +17130,132 @@ var init_editorial_link = __esmMin((() => {
17047
17130
  });
17048
17131
  }));
17049
17132
  //#endregion
17133
+ //#region ../theme-core/src/buttons/personalities/flat-ink.ts
17134
+ var flatInk;
17135
+ var init_flat_ink = __esmMin((() => {
17136
+ init_types$13();
17137
+ flatInk = defineButtonPersonality({
17138
+ id: "flat-ink",
17139
+ name: "Flat Ink",
17140
+ description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
17141
+ tags: {
17142
+ tone: "classic",
17143
+ energy: "calm",
17144
+ motion: "subtle",
17145
+ era: "editorial"
17146
+ },
17147
+ buttonSystem: {
17148
+ global: {
17149
+ cornerStyle: "rounded",
17150
+ shadow: "low",
17151
+ textTransform: "none",
17152
+ fontWeight: 600,
17153
+ borderWidth: 1,
17154
+ typography: "body",
17155
+ letterSpacing: "tight",
17156
+ paddingPreset: "default",
17157
+ hoverTransform: "lift",
17158
+ hoverColor: "none"
17159
+ },
17160
+ sizes: {
17161
+ sm: {
17162
+ padding: "0.625rem 1.125rem",
17163
+ fontSize: "text-sm"
17164
+ },
17165
+ md: { padding: "0.8125rem 1.375rem" },
17166
+ lg: {
17167
+ padding: "0.9375rem 1.625rem",
17168
+ fontSize: "text-lg"
17169
+ },
17170
+ xl: {
17171
+ padding: "1.0625rem 2rem",
17172
+ fontSize: "text-xl"
17173
+ }
17174
+ },
17175
+ variants: [
17176
+ {
17177
+ id: "primary",
17178
+ name: "Primary",
17179
+ enabled: true,
17180
+ priority: 1,
17181
+ background: {
17182
+ type: "solid",
17183
+ colorToken: "primary"
17184
+ },
17185
+ textColorToken: "primaryForeground",
17186
+ borderRadius: "rounded-lg",
17187
+ affordance: {
17188
+ iconId: "ArrowRight",
17189
+ colorToken: "accent"
17190
+ },
17191
+ shadow: {
17192
+ elevation: "none",
17193
+ softness: null,
17194
+ position: "bottom"
17195
+ },
17196
+ effects: { hover: [{
17197
+ effectId: "lift",
17198
+ options: { translateY: "-2px" }
17199
+ }, {
17200
+ effectId: "background-on-hover",
17201
+ options: { colorToken: "secondary" }
17202
+ }] }
17203
+ },
17204
+ {
17205
+ id: "secondary",
17206
+ name: "Secondary",
17207
+ enabled: true,
17208
+ priority: 2,
17209
+ background: { type: "transparent" },
17210
+ textColorToken: "primary",
17211
+ borderRadius: "rounded-lg",
17212
+ border: {
17213
+ widthClass: "border",
17214
+ colorToken: "border"
17215
+ },
17216
+ shadow: {
17217
+ elevation: "none",
17218
+ softness: null,
17219
+ position: "bottom"
17220
+ },
17221
+ effects: { hover: [{
17222
+ effectId: "lift",
17223
+ options: { translateY: "-2px" }
17224
+ }, {
17225
+ effectId: "background-on-hover",
17226
+ options: { colorToken: "surfaceAlt" }
17227
+ }] }
17228
+ },
17229
+ {
17230
+ id: "accent",
17231
+ name: "Accent",
17232
+ enabled: true,
17233
+ priority: 3,
17234
+ background: {
17235
+ type: "solid",
17236
+ colorToken: "accent"
17237
+ },
17238
+ textColorToken: "accentForeground",
17239
+ borderRadius: "rounded-lg",
17240
+ shadow: {
17241
+ elevation: "none",
17242
+ softness: null,
17243
+ position: "bottom"
17244
+ },
17245
+ affordance: {
17246
+ iconId: "ArrowRight",
17247
+ colorToken: "accentForeground"
17248
+ },
17249
+ effects: { hover: [{
17250
+ effectId: "lift",
17251
+ options: { translateY: "-2px" }
17252
+ }] }
17253
+ }
17254
+ ]
17255
+ }
17256
+ });
17257
+ }));
17258
+ //#endregion
17050
17259
  //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
17051
17260
  var inkStamp;
17052
17261
  var init_ink_stamp = __esmMin((() => {
@@ -17819,6 +18028,7 @@ var init_personalities = __esmMin((() => {
17819
18028
  init_confident_chip();
17820
18029
  init_earth_pill();
17821
18030
  init_editorial_link();
18031
+ init_flat_ink();
17822
18032
  init_ink_stamp();
17823
18033
  init_joy_stamp();
17824
18034
  init_ornate_ritual();
@@ -17833,6 +18043,7 @@ var init_personalities = __esmMin((() => {
17833
18043
  editorialLink,
17834
18044
  pebble,
17835
18045
  inkStamp,
18046
+ flatInk,
17836
18047
  brushedWash,
17837
18048
  showtimePill,
17838
18049
  joyStamp,
@@ -18305,6 +18516,50 @@ function getCompatibleHeaderStyleIds(layoutId) {
18305
18516
  return isHeaderStyleCompatibleWithLayout(getHeaderStyleOrThrow(styleId), layoutId);
18306
18517
  });
18307
18518
  }
18519
+ function applyNavTypography(style, typography) {
18520
+ switch (typography) {
18521
+ case "plain": return style;
18522
+ case "heading": return {
18523
+ ...style,
18524
+ typography: "heading",
18525
+ fontWeight: "medium",
18526
+ letterSpacing: "wide"
18527
+ };
18528
+ case "quiet-caps": return {
18529
+ ...style,
18530
+ textTransform: "uppercase",
18531
+ textSize: "sm",
18532
+ letterSpacing: "wide"
18533
+ };
18534
+ case "brand-caps": return {
18535
+ ...style,
18536
+ textTransform: "uppercase",
18537
+ textSize: "sm",
18538
+ letterSpacing: "wider"
18539
+ };
18540
+ default: return assertNever$19(typography, "Unhandled header nav typography");
18541
+ }
18542
+ }
18543
+ function underlineNavLinkStyle(colorToken, underlineColorToken, typography = "plain") {
18544
+ return applyNavTypography({
18545
+ name: "Underline grow",
18546
+ typography: "body",
18547
+ fontWeight: "medium",
18548
+ textTransform: "none",
18549
+ italic: false,
18550
+ colorToken,
18551
+ padding: "compact",
18552
+ paddingX: "compact",
18553
+ borderRadius: "none",
18554
+ effects: { hover: [{
18555
+ effectId: "nav-underline",
18556
+ options: {
18557
+ style: "grow",
18558
+ ...underlineColorToken ? { colorToken: underlineColorToken } : {}
18559
+ }
18560
+ }] }
18561
+ }, typography);
18562
+ }
18308
18563
  function themedHeaderShadow(theme) {
18309
18564
  switch (theme.shadow.elevation) {
18310
18565
  case "none": return;
@@ -18404,6 +18659,38 @@ function cleanBaseHeader(theme) {
18404
18659
  ctaGap: "default"
18405
18660
  };
18406
18661
  }
18662
+ function classicCenteredNavHeader(theme) {
18663
+ return {
18664
+ ...baseHeader(theme),
18665
+ variant: "classic",
18666
+ navPlacement: "center",
18667
+ positioning: "sticky",
18668
+ shrinkOnScroll: false,
18669
+ background: {
18670
+ type: "color",
18671
+ color: "surface"
18672
+ },
18673
+ textColor: "text",
18674
+ navColor: "text",
18675
+ navStyle: "underline-grow",
18676
+ navWeight: "medium",
18677
+ navLinkStyle: underlineNavLinkStyle("text", "accent"),
18678
+ border: {
18679
+ style: "solid",
18680
+ width: "thin",
18681
+ position: "bottom",
18682
+ colorToken: "border"
18683
+ },
18684
+ ctaTreatment: "primary",
18685
+ ctaVariant: resolveHeaderCtaVariant(theme, "primary"),
18686
+ ctaGap: "default",
18687
+ logoText: {
18688
+ mobileMaxWidth: "sm",
18689
+ mobileWrapLines: 1,
18690
+ hideOnShrink: false
18691
+ }
18692
+ };
18693
+ }
18407
18694
  function serifLineHeader(theme) {
18408
18695
  return {
18409
18696
  ...baseHeader(theme),
@@ -18985,6 +19272,13 @@ var init_headerLooks = __esmMin((() => {
18985
19272
  styleId: asHeaderStyleId("minimal")
18986
19273
  }
18987
19274
  },
19275
+ {
19276
+ lookId: asHeaderLookId("classic-centered-nav"),
19277
+ selection: {
19278
+ layoutId: asHeaderLayoutId("classic"),
19279
+ styleId: asHeaderStyleId("fine-line")
19280
+ }
19281
+ },
18988
19282
  {
18989
19283
  lookId: asHeaderLookId("brand-solid"),
18990
19284
  selection: {
@@ -19051,6 +19345,21 @@ var init_headerLooks = __esmMin((() => {
19051
19345
  logoAccommodations: inlineClassicLogoAccommodations,
19052
19346
  compile: cleanBaseHeader
19053
19347
  },
19348
+ {
19349
+ id: asHeaderLookId("classic-centered-nav"),
19350
+ label: "Centered nav",
19351
+ visualTreatment: "solid-neutral",
19352
+ layoutBehavior: "sticky",
19353
+ configuration: {
19354
+ structure: "inline-classic",
19355
+ treatment: "solid-neutral",
19356
+ behavior: "sticky"
19357
+ },
19358
+ openingRequirement: "none",
19359
+ maxRecommendedNavItems: 6,
19360
+ logoAccommodations: inlineClassicLogoAccommodations,
19361
+ compile: classicCenteredNavHeader
19362
+ },
19054
19363
  {
19055
19364
  id: asHeaderLookId("brand-solid"),
19056
19365
  label: "Brand solid",
@@ -19619,7 +19928,7 @@ function defineTypographyPreset(preset) {
19619
19928
  function findTypographyPreset(id) {
19620
19929
  return typographyPresetsById.get(id);
19621
19930
  }
19622
- var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, typographyPresets, typographyPresetsById;
19931
+ var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, fulcrumTypography, typographyPresets, typographyPresetsById;
19623
19932
  var init_typographyPresets = __esmMin((() => {
19624
19933
  bodyReadablePolicy = {
19625
19934
  recommendedCategories: ["sans-serif", "serif"],
@@ -19981,6 +20290,49 @@ var init_typographyPresets = __esmMin((() => {
19981
20290
  },
19982
20291
  scale: "balanced"
19983
20292
  };
20293
+ fulcrumTypography = {
20294
+ body: {
20295
+ family: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
20296
+ size: "lg",
20297
+ weight: "regular",
20298
+ lineHeight: "relaxed",
20299
+ letterSpacing: "normal"
20300
+ },
20301
+ headings: {
20302
+ default: {
20303
+ family: "Newsreader, Georgia, \"Times New Roman\", serif",
20304
+ weight: "medium",
20305
+ lineHeight: "normal",
20306
+ letterSpacing: "tight",
20307
+ colorToken: "primary",
20308
+ italic: null,
20309
+ case: null
20310
+ },
20311
+ h1: {
20312
+ size: "2xl",
20313
+ weight: "medium",
20314
+ lineHeight: "normal",
20315
+ letterSpacing: "tight",
20316
+ italic: null
20317
+ },
20318
+ h2: {
20319
+ size: "xl",
20320
+ weight: "medium",
20321
+ lineHeight: "normal",
20322
+ letterSpacing: "tight",
20323
+ italic: null
20324
+ },
20325
+ h3: {
20326
+ size: "md",
20327
+ weight: "semibold",
20328
+ lineHeight: "normal",
20329
+ letterSpacing: "normal",
20330
+ italic: null
20331
+ }
20332
+ },
20333
+ scale: "spacious",
20334
+ eyebrow: { family: "IBM Plex Mono, ui-monospace, \"SF Mono\", monospace" }
20335
+ };
19984
20336
  typographyPresets = [
19985
20337
  defineTypographyPreset({
19986
20338
  id: "typography-preset:modern-sans",
@@ -20240,6 +20592,32 @@ var init_typographyPresets = __esmMin((() => {
20240
20592
  }
20241
20593
  }
20242
20594
  }
20595
+ }),
20596
+ defineTypographyPreset({
20597
+ id: "typography-preset:fulcrum",
20598
+ name: "Fulcrum",
20599
+ description: "Newsreader serif headings over an IBM Plex Sans body, with an IBM Plex Mono eyebrow role for uppercase kickers and mono captions.",
20600
+ defaultFonts: {
20601
+ body: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
20602
+ heading: "Newsreader, Georgia, \"Times New Roman\", serif"
20603
+ },
20604
+ recommendedFonts: {
20605
+ body: [
20606
+ "IBM Plex Sans",
20607
+ "Source Sans 3",
20608
+ "Inter"
20609
+ ],
20610
+ heading: [
20611
+ "Newsreader",
20612
+ "Source Serif 4",
20613
+ "Lora"
20614
+ ]
20615
+ },
20616
+ slotPolicies: {
20617
+ body: bodyReadablePolicy,
20618
+ heading: displayHeadingPolicy
20619
+ },
20620
+ typography: fulcrumTypography
20243
20621
  })
20244
20622
  ];
20245
20623
  typographyPresetsById = new Map(typographyPresets.map((preset) => [preset.id, preset]));
@@ -21577,9 +21955,10 @@ var init_registry$1 = __esmMin((() => {
21577
21955
  }));
21578
21956
  var init_generateEffectsCSS = __esmMin((() => {
21579
21957
  init_registry$1();
21580
- })), init_contrast = __esmMin((() => {})), init_generateDefaultButtonSystem = __esmMin((() => {
21958
+ })), init_contrast = __esmMin((() => {}));
21959
+ var init_generateDefaultButtonSystem = __esmMin((() => {
21581
21960
  init_contrast();
21582
- }));
21961
+ })), init_affordanceIcons = __esmMin((() => {})), AFFORDANCE_SUPPRESS_CLASS;
21583
21962
  var init_generateButtonCss = __esmMin((() => {
21584
21963
  init_types$14();
21585
21964
  init_classNames();
@@ -21588,6 +21967,8 @@ var init_generateButtonCss = __esmMin((() => {
21588
21967
  init_generateEffectsCSS();
21589
21968
  init_constants$2();
21590
21969
  init_generateDefaultButtonSystem();
21970
+ init_affordanceIcons();
21971
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
21591
21972
  buttonSizeNameSchema.options;
21592
21973
  }));
21593
21974
  var init_presets = __esmMin((() => {}));
@@ -21601,6 +21982,7 @@ var init_buttons = __esmMin((() => {
21601
21982
  init_types$14();
21602
21983
  init_classNames();
21603
21984
  init_generateButtonCss();
21985
+ init_affordanceIcons();
21604
21986
  init_generateDefaultButtonSystem();
21605
21987
  init_constants$2();
21606
21988
  init_presets();
@@ -21735,13 +22117,75 @@ var cardVariantRoleValues, boxlessCardVariantValue, legacyCardVariantRoleAliases
21735
22117
  });
21736
22118
  cardSystemSchema = z$1.object({ variants: z$1.array(cardVariantSchema).min(1).max(3) });
21737
22119
  }));
21738
- var init_constants$1 = __esmMin((() => {})), init_generateDefaultCardSystem = __esmMin((() => {})), init_contextualColors = __esmMin((() => {})), init_generateCardCss = __esmMin((() => {
22120
+ var init_constants$1 = __esmMin((() => {}));
22121
+ var init_generateDefaultCardSystem = __esmMin((() => {}));
22122
+ var init_foregroundRoles = __esmMin((() => {}));
22123
+ //#endregion
22124
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
22125
+ function requireSurfaceColorValue(role, value) {
22126
+ const normalized = value.trim();
22127
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
22128
+ return normalized;
22129
+ }
22130
+ function completeSurfaceForegrounds(input) {
22131
+ const text = requireSurfaceColorValue("text", input.text);
22132
+ return {
22133
+ text,
22134
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
22135
+ link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
22136
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
22137
+ };
22138
+ }
22139
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
22140
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
22141
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
22142
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
22143
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
22144
+ }
22145
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
22146
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
22147
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
22148
+ }
22149
+ function surfaceForegroundStyle(input) {
22150
+ const foregrounds = completeSurfaceForegrounds(input);
22151
+ return {
22152
+ color: foregrounds.text,
22153
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
22154
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
22155
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
22156
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
22157
+ };
22158
+ }
22159
+ var SURFACE_FOREGROUND_CSS_VARS, DEFAULT_SURFACE_TEXT_COLOR, DEFAULT_SURFACE_LINK_COLOR, DEFAULT_SURFACE_SUPPORTING_COLOR, DEFAULT_ROLE_FALLBACKS;
22160
+ var init_foregroundContract = __esmMin((() => {
22161
+ init_foregroundRoles();
22162
+ SURFACE_FOREGROUND_CSS_VARS = {
22163
+ text: "--rb-surface-text-color",
22164
+ heading: "--rb-surface-heading-color",
22165
+ link: "--rb-surface-link-color",
22166
+ supporting: "--rb-surface-supporting-color"
22167
+ };
22168
+ DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
22169
+ DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
22170
+ DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
22171
+ DEFAULT_ROLE_FALLBACKS = {
22172
+ text: DEFAULT_SURFACE_TEXT_COLOR,
22173
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
22174
+ link: DEFAULT_SURFACE_LINK_COLOR,
22175
+ supporting: DEFAULT_SURFACE_SUPPORTING_COLOR
22176
+ };
22177
+ })), init_surfaces = __esmMin((() => {
22178
+ init_foregroundContract();
22179
+ init_foregroundRoles();
22180
+ })), init_generateCardCss = __esmMin((() => {
21739
22181
  init_resolver$1();
21740
22182
  init_constants$1();
21741
22183
  init_generateDefaultCardSystem();
21742
- init_contextualColors();
22184
+ init_surfaces();
22185
+ }));
22186
+ var init_core$1 = __esmMin((() => {
22187
+ init_surfaces();
21743
22188
  }));
21744
- var init_core$1 = __esmMin((() => {}));
21745
22189
  //#endregion
21746
22190
  //#region ../theme-core/src/cards/index.ts
21747
22191
  var init_cards = __esmMin((() => {
@@ -21976,16 +22420,22 @@ var init_types$9 = __esmMin((() => {
21976
22420
  /**
21977
22421
  * Gradient configuration types and schemas
21978
22422
  */
21979
- var gradientStopSchema, gradientConfigSchema;
22423
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
21980
22424
  var init_types$8 = __esmMin((() => {
21981
22425
  init_themeColorTokens();
21982
22426
  gradientStopSchema = z$1.object({
21983
22427
  color: themeColorTokenSchema,
21984
22428
  position: z$1.number().min(0).max(100)
21985
22429
  });
22430
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
21986
22431
  gradientConfigSchema = z$1.object({
21987
- type: z$1.enum(["linear", "radial"]),
22432
+ type: z$1.enum([
22433
+ "linear",
22434
+ "radial",
22435
+ "conic"
22436
+ ]).default("linear"),
21988
22437
  angle: z$1.number().min(0).max(360).optional(),
22438
+ shape: radialGradientShapeSchema.optional(),
21989
22439
  position: z$1.string().optional(),
21990
22440
  stops: z$1.array(gradientStopSchema).min(2)
21991
22441
  });
@@ -22322,9 +22772,12 @@ function parseToken(source) {
22322
22772
  if (parts.kind === "invalid") return { token: source };
22323
22773
  return {
22324
22774
  token: parts.token,
22325
- alpha: parts.opacityPercent === null ? void 0 : parts.opacityPercent / 100
22775
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
22326
22776
  };
22327
22777
  }
22778
+ function surfaceRoleForTextToken(token) {
22779
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
22780
+ }
22328
22781
  /**
22329
22782
  * Converts a theme color token to a CSS rgb value.
22330
22783
  * This is the primary function for applying theme colors to CSS properties.
@@ -22338,11 +22791,11 @@ function parseToken(source) {
22338
22791
  * rgbColorValue('raw:transparent') // => 'transparent'
22339
22792
  */
22340
22793
  function rgbColorValue(token) {
22341
- const { token: baseToken, alpha, raw } = parseToken(token);
22794
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
22342
22795
  if (raw) return raw;
22343
22796
  const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
22344
- if (alpha === void 0) return `rgb(var(${cssVar}))`;
22345
- return `rgb(var(${cssVar}) / ${alpha})`;
22797
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
22798
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
22346
22799
  }
22347
22800
  /**
22348
22801
  * Creates a backgroundColor style object from a theme token.
@@ -22360,6 +22813,9 @@ function backgroundColorStyle(token) {
22360
22813
  * @returns CSSProperties with color
22361
22814
  */
22362
22815
  function textColorStyle(token) {
22816
+ const parsed = parseToken(token);
22817
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
22818
+ if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
22363
22819
  return { color: rgbColorValue(token) };
22364
22820
  }
22365
22821
  /**
@@ -22395,10 +22851,16 @@ function mergeStyles(...styles) {
22395
22851
  }
22396
22852
  return Object.keys(merged).length ? merged : void 0;
22397
22853
  }
22398
- var COLOR_VAR_PREFIX;
22854
+ var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
22399
22855
  var init_colorStyles = __esmMin((() => {
22856
+ init_surfaces();
22400
22857
  init_colorTokenParts();
22401
22858
  COLOR_VAR_PREFIX = "--tb-";
22859
+ SURFACE_TEXT_ROLE_BY_TOKEN = {
22860
+ text: "text",
22861
+ heading: "heading",
22862
+ mutedText: "supporting"
22863
+ };
22402
22864
  }));
22403
22865
  //#endregion
22404
22866
  //#region ../theme-core/src/utils/tokenOrColor.ts
@@ -22506,7 +22968,7 @@ var init_tokenOrColor = __esmMin((() => {
22506
22968
  "white",
22507
22969
  "yellow"
22508
22970
  ]);
22509
- })), axesSchema, colourHexString, paletteColorSchema, paletteMetaSchema, paletteSchema, typographyStyleSchema, bodyTypographyStyleSchema, headingSizeSchema, headingTypographyOverridesSchema, headingTypographyStyleSchema, proseLinkUnderlineStyleSchema, proseLinkUnderlineThicknessSchema, proseLinkUnderlineOffsetSchema, proseLinkStyleSchema, semanticSpacingSchema, boxRoundedSchema, boxBackgroundOverlaySchema, boxBackgroundSchema, noHeadingDecorationSchema, visibleHeadingDecorationSchema, headingDecorationSchema, headingDecorationOverrideSchema, accordionIconTreatmentSchema, sectionStylesOverrideSchema, containerStylesOverrideSchema, cardBorderOverrideSchema, cardStylesOverrideSchema, blockStyleOverridesSchema, blockThemeOverrideSchema, typographyScaleSchema, typographySchema, spaceSchema, corners, shadow, border, motion, inputStyle, headerVariant, headerPositioning, headerNavStyle, navFontWeight, headerMaxWidth, headerContainerSchema, headerBorderSchema, logoStyleSchema, headerLogoTextSchema, navEffectsSchema, dropdownStyleSchema, headerCtaGapSchema, headerCtaTreatmentSchema, navContainerSchema, headerBackgroundSchema, headerSchema, footerVariant, footerMaxWidth, footerMode, footerNavLayoutMode, footerNavLayoutAlign, footerSpacing, footerLogoPlacement, footerLogoSize, footerLogoMaxHeight, footerBottomTextLinkStyleSchema, footerBottomBarSchema, footerNavLayoutSchema, footerLogoSchema, footerSchema, containerPaddingPresetSchema, layoutSchema, heroTypographySizeSchema, heroTypographyLineHeightSchema, heroResponsiveTypographySchema, heroTypographySchema, heroSchema, bodyTextIntroTypographySizeSchema, bodyTextSchema, gradientsSchema, testimonialQuoteTreatmentSchema, themeSchema;
22971
+ })), axesSchema, colourHexString, paletteColorSchema, paletteMetaSchema, paletteSchema, typographyStyleSchema, bodyTypographyStyleSchema, headingSizeSchema, headingTypographyOverridesSchema, headingTypographyStyleSchema, proseLinkUnderlineStyleSchema, proseLinkUnderlineThicknessSchema, proseLinkUnderlineOffsetSchema, proseLinkStyleSchema, semanticSpacingSchema, boxRoundedSchema, boxBackgroundOverlaySchema, boxBackgroundSchema, noHeadingDecorationSchema, visibleHeadingDecorationSchema, headingDecorationSchema, headingDecorationOverrideSchema, accordionIconTreatmentSchema, sectionStylesOverrideSchema, containerStylesOverrideSchema, cardBorderOverrideSchema, cardStylesOverrideSchema, blockStyleOverridesSchema, blockThemeOverrideSchema, typographyScaleSchema, eyebrowTypographyStyleSchema, typographySchema, spaceSchema, corners, shadow, border, motion, inputStyle, headerVariant, headerPositioning, headerNavStyle, navFontWeight, headerMaxWidth, headerContainerSchema, headerBorderSchema, logoStyleSchema, headerLogoTextSchema, navEffectsSchema, dropdownStyleSchema, headerCtaGapSchema, headerCtaTreatmentSchema, navContainerSchema, headerBackgroundSchema, headerSchema, footerVariant, footerMaxWidth, footerMode, footerNavLayoutMode, footerNavLayoutAlign, footerSpacing, footerLogoPlacement, footerLogoSize, footerLogoMaxHeight, footerBottomTextLinkStyleSchema, footerBottomBarSchema, footerNavLayoutSchema, footerLogoSchema, footerSchema, containerPaddingPresetSchema, layoutSchema, heroTypographySizeSchema, heroTypographyLineHeightSchema, heroResponsiveTypographySchema, heroTypographySchema, heroSchema, bodyTextIntroTypographySizeSchema, bodyTextSchema, gradientsSchema, testimonialQuoteTreatmentSchema, themeSchema;
22510
22972
  var init_schema = __esmMin((() => {
22511
22973
  init_media$2();
22512
22974
  init_buttons();
@@ -22786,6 +23248,7 @@ var init_schema = __esmMin((() => {
22786
23248
  "majorThird",
22787
23249
  "perfectFourth"
22788
23250
  ]);
23251
+ eyebrowTypographyStyleSchema = z$1.object({ family: z$1.string().min(1) });
22789
23252
  typographySchema = z$1.object({
22790
23253
  body: bodyTypographyStyleSchema,
22791
23254
  headings: z$1.object({
@@ -22798,7 +23261,8 @@ var init_schema = __esmMin((() => {
22798
23261
  h6: headingTypographyOverridesSchema.optional()
22799
23262
  }),
22800
23263
  scale: typographyScaleSchema,
22801
- proseLinkStyle: proseLinkStyleSchema.optional()
23264
+ proseLinkStyle: proseLinkStyleSchema.optional(),
23265
+ eyebrow: eyebrowTypographyStyleSchema.optional()
22802
23266
  });
22803
23267
  spaceSchema = z$1.enum([
22804
23268
  "comfortable",
@@ -22823,7 +23287,8 @@ var init_schema = __esmMin((() => {
22823
23287
  "soft",
22824
23288
  "hard"
22825
23289
  ]).nullable(),
22826
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
23290
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
23291
+ colorToken: themeColorTokenSchema.optional()
22827
23292
  });
22828
23293
  border = z$1.object({
22829
23294
  width: z$1.enum([
@@ -23064,6 +23529,7 @@ var init_schema = __esmMin((() => {
23064
23529
  navWeight: navFontWeight.default("medium"),
23065
23530
  navTypography: z$1.enum(["body", "heading"]).optional(),
23066
23531
  navTextSize: navLinkStyleSchema.shape.textSize,
23532
+ navPlacement: z$1.enum(["end", "center"]).optional(),
23067
23533
  container: headerContainerSchema,
23068
23534
  border: headerBorderSchema,
23069
23535
  shadow: componentShadowSchema.optional(),
@@ -23822,7 +24288,8 @@ var init_curatedSiteStyles = __esmMin((() => {
23822
24288
  "site-style:bold-launch",
23823
24289
  "site-style:south-west-twerk-school",
23824
24290
  "site-style:kirtan-ornate",
23825
- "site-style:original-joy"
24291
+ "site-style:original-joy",
24292
+ "site-style:fulcrum"
23826
24293
  ];
23827
24294
  quietBudget = {
23828
24295
  accentDensity: "low",
@@ -25034,6 +25501,104 @@ var init_curatedSiteStyles = __esmMin((() => {
25034
25501
  buttonChoice("showtime-pill")
25035
25502
  ],
25036
25503
  paletteRecommendations: [paletteRecommendation("warm-dark-ember")]
25504
+ }),
25505
+ defineCuratedSiteStyle({
25506
+ id: "site-style:fulcrum",
25507
+ name: "Fulcrum",
25508
+ headingDecoration: {
25509
+ family: "short-center-rule",
25510
+ colorToken: "accent"
25511
+ },
25512
+ description: "Spruce-ink and moss with an amber climax, Newsreader serif over IBM Plex Sans, hairline sage borders and flat buttons — a grounded, editorial physiotherapy skin.",
25513
+ generationBrief: "Use a calm, clinician-led voice: precise, reassuring and specific rather than clinical-cold. Lead with the assessment-treatment-rehab journey, mono uppercase eyebrows for practical labels (hours, registrations, appointment windows), Newsreader serif headings over IBM Plex Sans body, and a single amber call to action as the page climax. Keep proof concrete (registrations, same-week appointments, return-to-activity outcomes) and avoid spa or hard-sell wellness language or medical claims.",
25514
+ siteCreatorSelection: {
25515
+ kind: "site_creator_keyword_heuristic",
25516
+ priority: 28
25517
+ },
25518
+ selectionKeywordRules: [
25519
+ {
25520
+ kind: "substring",
25521
+ value: "physiotherap"
25522
+ },
25523
+ {
25524
+ kind: "word",
25525
+ value: "physio"
25526
+ },
25527
+ {
25528
+ kind: "phrase",
25529
+ value: "sports injury"
25530
+ },
25531
+ {
25532
+ kind: "phrase",
25533
+ value: "rehab clinic"
25534
+ },
25535
+ {
25536
+ kind: "substring",
25537
+ value: "musculoskeletal"
25538
+ },
25539
+ {
25540
+ kind: "phrase",
25541
+ value: "sports therapy"
25542
+ }
25543
+ ],
25544
+ tokenRecipes: {
25545
+ palette: "brand-led",
25546
+ contrast: "standard",
25547
+ radius: "rounded",
25548
+ shadow: "subtle",
25549
+ typography: "serif-editorial",
25550
+ spacing: "airy",
25551
+ motion: "subtle"
25552
+ },
25553
+ compositionBudget: quietBudget,
25554
+ typographyPresetChoices: [
25555
+ typographyChoice("typography-preset:fulcrum"),
25556
+ typographyChoice("typography-preset:editorial-serif"),
25557
+ typographyChoice("typography-preset:modern-sans")
25558
+ ],
25559
+ defaultTypographyPresetId: "typography-preset:fulcrum",
25560
+ themeOverrides: {
25561
+ shadow: { colorToken: "primary" },
25562
+ accordions: {
25563
+ background: null,
25564
+ spacing: "comfortable",
25565
+ corners: "square",
25566
+ border: null,
25567
+ shadow: null,
25568
+ icon: {
25569
+ style: "plus-minus",
25570
+ position: "right",
25571
+ size: "md",
25572
+ colorToken: "accent"
25573
+ },
25574
+ trigger: {
25575
+ textColorToken: "primary",
25576
+ fontWeight: "medium",
25577
+ fontFamily: "heading",
25578
+ fontScale: "md"
25579
+ },
25580
+ hover: { textColorToken: "secondary" },
25581
+ content: { textColorToken: "muted" }
25582
+ },
25583
+ testimonialQuote: serifDisplayQuote
25584
+ },
25585
+ recommendedHeaderLookIds: [
25586
+ "classic-centered-nav",
25587
+ "serif-line",
25588
+ "centered-calm",
25589
+ "clean-base"
25590
+ ],
25591
+ recommendedFooterLookIds: ["footer-editorial-columns", "footer-muted-grounding"],
25592
+ buttonPersonalityChoices: [
25593
+ buttonChoice("flat-ink"),
25594
+ buttonChoice("confident-chip"),
25595
+ buttonChoice("editorial-link")
25596
+ ],
25597
+ paletteRecommendations: [
25598
+ paletteRecommendation("brand-led-spruce"),
25599
+ paletteRecommendation("warm-neutral-forest"),
25600
+ paletteRecommendation("soft-natural-sage")
25601
+ ]
25037
25602
  })
25038
25603
  ];
25039
25604
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
@@ -27302,7 +27867,7 @@ var init_themeColorResolution = __esmMin((() => {
27302
27867
  init_tokenOrColor();
27303
27868
  }));
27304
27869
  //#endregion
27305
- //#region ../blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.ts
27870
+ //#region ../blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.ts
27306
27871
  function readColorToken(input, key) {
27307
27872
  const value = input[key];
27308
27873
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
@@ -27311,20 +27876,20 @@ function resolveOptionalForegroundColor(value, context) {
27311
27876
  if (!value) return null;
27312
27877
  return resolveBackgroundColorValue(value, context);
27313
27878
  }
27314
- function resolveSectionForegroundStyles(value, context) {
27879
+ function resolveSurfaceForegroundStyles(value, context) {
27315
27880
  if (!value || typeof value !== "object") return {};
27316
27881
  const input = value;
27317
27882
  const resolvedText = resolveOptionalForegroundColor(readColorToken(input, "textColor"), context);
27318
27883
  if (!resolvedText) return {};
27319
- return {
27320
- color: resolvedText,
27321
- "--section-text-color": resolvedText,
27322
- "--section-heading-color": resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? resolvedText,
27323
- "--section-link-color": resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? resolvedText,
27324
- "--section-supporting-color": resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? resolvedText
27325
- };
27884
+ return { ...surfaceForegroundStyle({
27885
+ text: resolvedText,
27886
+ heading: resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? void 0,
27887
+ link: resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? void 0,
27888
+ supporting: resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? void 0
27889
+ }) };
27326
27890
  }
27327
- var init_sectionForegroundStyles = __esmMin((() => {
27891
+ var init_surfaceForegroundStyles = __esmMin((() => {
27892
+ init_surfaces();
27328
27893
  init_themeColorResolution();
27329
27894
  }));
27330
27895
  //#endregion
@@ -27356,7 +27921,7 @@ function isTileTreatment(value) {
27356
27921
  function isEventListTreatment(value) {
27357
27922
  return typeof value === "string" && eventListTreatmentSet.has(value);
27358
27923
  }
27359
- var spacingTransform, raisedTransform, roundedTransform, boxStylesCompositeTransform, cardVariantClassTransform, boxStylesBorderColorTransform, fixedFrameScopeClass, tileTreatmentClassMap, tileTreatmentSet, eventListTreatmentClassMap, eventListTreatmentSet, sectionClassNameTransform, containerStylesResolveClassName, containerStylesResolveBoxClassName, sectionTextColorStyleTransform, sectionHeadingColorStyleTransform, sectionColorsStyleTransform, GAP_CLASS_MAP, GAP_VALUE_MAP, semanticGapTransform, semanticGapValueTransform, boxStylesTransforms;
27924
+ var spacingTransform, raisedTransform, roundedTransform, boxStylesCompositeTransform, cardVariantClassTransform, boxStylesBorderColorTransform, fixedFrameScopeClass, tileTreatmentClassMap, tileTreatmentSet, eventListTreatmentClassMap, eventListTreatmentSet, sectionClassNameTransform, containerStylesResolveClassName, containerStylesResolveBoxClassName, sectionColorsStyleTransform, GAP_CLASS_MAP, GAP_VALUE_MAP, semanticGapTransform, semanticGapValueTransform, boxStylesTransforms;
27360
27925
  var init_boxStyles = __esmMin((() => {
27361
27926
  init_core();
27362
27927
  init_spacing();
@@ -27364,8 +27929,7 @@ var init_boxStyles = __esmMin((() => {
27364
27929
  init_colorStyles();
27365
27930
  init_cards();
27366
27931
  init_blockColorTokens();
27367
- init_themeColorResolution();
27368
- init_sectionForegroundStyles();
27932
+ init_surfaceForegroundStyles();
27369
27933
  spacingTransform = {
27370
27934
  id: "boxStyles.spacing",
27371
27935
  kind: "string",
@@ -27595,45 +28159,11 @@ var init_boxStyles = __esmMin((() => {
27595
28159
  }, context);
27596
28160
  }
27597
28161
  };
27598
- sectionTextColorStyleTransform = {
27599
- id: "sectionStyles.resolveTextColorStyle",
27600
- kind: "formatter",
27601
- summary: "Resolve section text color token into a style object",
27602
- run: (value, options, context) => {
27603
- const fallbackToken = options?.fallbackToken;
27604
- if (typeof value === "string" && value.trim()) {
27605
- const colorValue = resolveBackgroundColorValue(value.trim(), context);
27606
- return {
27607
- color: colorValue,
27608
- "--section-text-color": colorValue
27609
- };
27610
- }
27611
- if (typeof fallbackToken === "string" && fallbackToken.trim()) {
27612
- const colorValue = resolveBackgroundColorValue(fallbackToken.trim(), context);
27613
- return {
27614
- color: colorValue,
27615
- "--section-text-color": colorValue
27616
- };
27617
- }
27618
- return {};
27619
- }
27620
- };
27621
- sectionHeadingColorStyleTransform = {
27622
- id: "sectionStyles.resolveHeadingColorStyle",
27623
- kind: "formatter",
27624
- summary: "Resolve section heading color token into a style object",
27625
- run: (value, options, context) => {
27626
- const fallbackToken = options?.fallbackToken;
27627
- if (typeof value === "string" && value.trim()) return { "--section-heading-color": resolveBackgroundColorValue(value.trim(), context) };
27628
- if (typeof fallbackToken === "string" && fallbackToken.trim()) return { "--section-heading-color": resolveBackgroundColorValue(fallbackToken.trim(), context) };
27629
- return {};
27630
- }
27631
- };
27632
28162
  sectionColorsStyleTransform = {
27633
28163
  id: "sectionStyles.resolveColorsStyle",
27634
28164
  kind: "formatter",
27635
- summary: "Resolve section foreground colors into a style object",
27636
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
28165
+ summary: "Resolve surface foreground colors into a style object",
28166
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
27637
28167
  };
27638
28168
  GAP_CLASS_MAP = {
27639
28169
  none: "rb-gap-semantic-none",
@@ -27681,8 +28211,6 @@ var init_boxStyles = __esmMin((() => {
27681
28211
  sectionClassNameTransform,
27682
28212
  containerStylesResolveClassName,
27683
28213
  containerStylesResolveBoxClassName,
27684
- sectionTextColorStyleTransform,
27685
- sectionHeadingColorStyleTransform,
27686
28214
  sectionColorsStyleTransform,
27687
28215
  semanticGapTransform,
27688
28216
  semanticGapValueTransform
@@ -28518,7 +29046,29 @@ var init_ctaRow = __esmMin((() => {
28518
29046
  fields: [createCtasRepeater({
28519
29047
  label: "Calls to action",
28520
29048
  itemLabel: "CTA",
28521
- maxItems: 3
29049
+ maxItems: 3,
29050
+ button: { variants: [
29051
+ {
29052
+ value: "primary",
29053
+ label: "Primary"
29054
+ },
29055
+ {
29056
+ value: "secondary",
29057
+ label: "Secondary"
29058
+ },
29059
+ {
29060
+ value: "outline",
29061
+ label: "Outline"
29062
+ },
29063
+ {
29064
+ value: "link",
29065
+ label: "Link"
29066
+ },
29067
+ {
29068
+ value: "accent",
29069
+ label: "Accent"
29070
+ }
29071
+ ] }
28522
29072
  })],
28523
29073
  layout: [ctaRow({
28524
29074
  collectionPath: "content.ctas",
@@ -28821,6 +29371,55 @@ function buildHighlightLayout() {
28821
29371
  function buildGridCardsLayout(className) {
28822
29372
  return el("div", { className }, buildResponsiveGridCards());
28823
29373
  }
29374
+ /**
29375
+ * Build a single "featured editorial" testimonial card.
29376
+ *
29377
+ * This card type deliberately renders NO avatar/headshot: an amber quote mark,
29378
+ * the quote body, then the author name and a context line. Colour + surface
29379
+ * treatment is driven entirely by `variantClass` (see testimonials.css):
29380
+ * - `rb-testimonials-fe-card--feature` → spruce-ink card (dark primary bg)
29381
+ * - `rb-testimonials-fe-card--plain` → white surface card
29382
+ *
29383
+ * Extra modifiers (`repeat`, `when`) are forwarded to the card node so the
29384
+ * caller can drive first-vs-rest branching.
29385
+ */
29386
+ function buildFeaturedEditorialCard(variantClass, ...mods) {
29387
+ const quoteMark = text({
29388
+ as: "span",
29389
+ className: "rb-testimonials-fe-qmark",
29390
+ "aria-hidden": "true"
29391
+ }, props({ value: "“" }));
29392
+ const quote = richText({ className: "rb-testimonials-fe-quote rb-max-w-none" }, bind("testimonial.content.body"), when("testimonial.content.body"));
29393
+ const meta = el("div", { className: "rb-testimonials-fe-meta" }, [text({
29394
+ as: "strong",
29395
+ className: "rb-testimonials-fe-name"
29396
+ }, bind("testimonial.content.name", { fallback: "Anonymous" })), text({
29397
+ as: "span",
29398
+ className: "rb-testimonials-fe-context"
29399
+ }, when("testimonial.content.jobTitle"), bind("testimonial.content.jobTitle"))]);
29400
+ return el("div", { className: `rb-testimonials-fe-card ${variantClass}` }, [
29401
+ quoteMark,
29402
+ quote,
29403
+ meta
29404
+ ], ...mods);
29405
+ }
29406
+ /**
29407
+ * Build the "featured editorial" layout: an asymmetric two-column arrangement
29408
+ * where the FIRST testimonial is a large featured (spruce-ink) card and the
29409
+ * remaining testimonials stack as white cards beside it.
29410
+ *
29411
+ * First-vs-rest branching is done without an offset primitive: the featured
29412
+ * card uses `repeat(..., { limit: 1 })` (entry 0 only), and the rest column
29413
+ * repeats over every entry but skips index 0 via `when("tIndex", { equals: 0,
29414
+ * not: true })`. The `$when` guard is re-evaluated per repeated item with the
29415
+ * index scope in context, so entry 0 produces no node in the rest column.
29416
+ */
29417
+ function buildFeaturedEditorialLayout() {
29418
+ return el("div", { className: "rb-testimonials-fe-grid" }, [buildFeaturedEditorialCard("rb-testimonials-fe-card--feature", repeat("data.entries", "testimonial", { limit: 1 })), el("div", { className: "rb-testimonials-fe-col" }, [buildFeaturedEditorialCard("rb-testimonials-fe-card--plain", repeat("data.entries", "testimonial", { indexName: "tIndex" }), when("tIndex", {
29419
+ equals: 0,
29420
+ not: true
29421
+ }))])]);
29422
+ }
28824
29423
  var grid$4, testimonialsCarouselFragment;
28825
29424
  var init_testimonialsCarousel = __esmMin((() => {
28826
29425
  init_types$5();
@@ -32645,7 +33244,7 @@ const defaultLayout = styledSection({
32645
33244
  children: styledContainer({
32646
33245
  baseClassName: "rb-relative rb-isolate",
32647
33246
  children: stack({
32648
- gap: "xl",
33247
+ gap: "lg",
32649
33248
  className: "rb-w-full rb-max-w-4xl rb-mx-auto"
32650
33249
  }, [headingLayout, accordionLayout])
32651
33250
  }),
@@ -32662,7 +33261,7 @@ const questionColumnsLayout = styledSection({
32662
33261
  children: styledContainer({
32663
33262
  baseClassName: "rb-relative rb-isolate",
32664
33263
  children: stack({
32665
- gap: "xl",
33264
+ gap: "lg",
32666
33265
  className: "rb-w-full"
32667
33266
  }, [headingLayout, questionColumnsAccordionLayout])
32668
33267
  }),
@@ -32827,7 +33426,26 @@ const formattingTransforms = [
32827
33426
  arrayLengthTransform,
32828
33427
  jsonArrayTransform,
32829
33428
  csvTransform,
32830
- marqueeLoopTransform
33429
+ marqueeLoopTransform,
33430
+ {
33431
+ id: "value.mapToken",
33432
+ kind: "formatter",
33433
+ summary: "Map a state/enum value to a theme token colour (rgb(var(--tb-<role>)))",
33434
+ schema: z$1.object({
33435
+ /**
33436
+ * Maps an input state/enum value (stringified) to a theme token ROLE name
33437
+ * (e.g. `secondary`, `accent`, `muted`, `border`). The role is wrapped to
33438
+ * `rgb(var(--tb-<role>))` so the result drops straight into a `style` binding.
33439
+ */
33440
+ cases: z$1.record(z$1.string(), z$1.string()),
33441
+ /** Role used when the value matches no case. Omit to yield `undefined`. */
33442
+ fallback: z$1.string().optional()
33443
+ }),
33444
+ run: (value, options) => {
33445
+ const role = options.cases[String(value)] ?? options.fallback;
33446
+ return role ? `rgb(var(--tb-${role}))` : void 0;
33447
+ }
33448
+ }
32831
33449
  ];
32832
33450
  //#endregion
32833
33451
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -33411,6 +34029,7 @@ function splitSiteChromePlacementClasses(className) {
33411
34029
  init_colorConversion();
33412
34030
  init_core();
33413
34031
  init_colorStyles();
34032
+ init_surfaces();
33414
34033
  const joinClasses$4 = (parts) => parts.filter((part) => typeof part === "string" && part.trim().length > 0).join(" ").replace(/\s+/g, " ").trim();
33415
34034
  function resolveHeaderBrandDisplay(logo) {
33416
34035
  const display = logo?.brandDisplay ?? "logo-plus-title";
@@ -33480,6 +34099,26 @@ const headerLogoTextVisibleTransform = {
33480
34099
  return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
33481
34100
  }
33482
34101
  };
34102
+ /**
34103
+ * Selects which classic-layout nav row should render.
34104
+ *
34105
+ * - `'inline'` → classic variant with the historical logo-left / nav-right row
34106
+ * - `'centered'`→ classic variant with a centred (flex-1) nav and a right CTA
34107
+ * - `'other'` → not a classic variant (centered/floating/transparent handle it)
34108
+ *
34109
+ * Consumed by the site-header block's `$when` gates so the two classic rows are
34110
+ * mutually exclusive without introducing a new top-level header variant.
34111
+ */
34112
+ const classicNavModeTransform = {
34113
+ id: "layout.classicNavMode",
34114
+ kind: "formatter",
34115
+ summary: "Resolve which classic-layout nav row to render",
34116
+ run: (value) => {
34117
+ const header = asPartialObject(value);
34118
+ if (header?.variant !== "classic") return "other";
34119
+ return header?.navPlacement === "center" ? "centered" : "inline";
34120
+ }
34121
+ };
33483
34122
  const maxWidthClassTransform = {
33484
34123
  id: "layout.maxWidthClass",
33485
34124
  kind: "string",
@@ -33662,8 +34301,9 @@ const footerRootStyleTransform = {
33662
34301
  styleParts.push(backgroundColorStyle(token));
33663
34302
  }
33664
34303
  }
33665
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
33666
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
34304
+ const foreground = visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
34305
+ if (!visuals.isTransparent && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
34306
+ else if (foreground) styleParts.push({ color: foreground });
33667
34307
  styleParts.push(borderColorStyle("border"));
33668
34308
  return mergeStyles(...styleParts);
33669
34309
  }
@@ -33749,18 +34389,16 @@ const footerBottomBarStyleTransform = {
33749
34389
  const styleParts = [];
33750
34390
  const background = bottomBar?.background;
33751
34391
  if (background?.type === "color") styleParts.push(backgroundColorStyle(background.color ?? "surface"));
33752
- if (bottomBar?.textColor) styleParts.push(textColorStyle(bottomBar.textColor));
33753
34392
  const borderColorToken = bottomBar?.borderTop?.colorToken;
33754
34393
  if (borderColorToken) styleParts.push(borderColorStyle(borderColorToken));
33755
34394
  else styleParts.push(borderColorStyle("border"));
33756
34395
  const borderWidth = bottomBar?.borderTop?.width;
33757
34396
  if (borderWidth && borderWidth !== "none") styleParts.push({ borderTopWidth: borderWidth === "thin" ? "1px" : borderWidth === "medium" ? "2px" : "3px" });
33758
34397
  else if (borderWidth === "none") styleParts.push({ borderTopWidth: "0px" });
33759
- if (!bottomBar?.textColor) {
33760
- const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
33761
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
33762
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
33763
- }
34398
+ const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
34399
+ const foreground = bottomBar?.textColor ? rgbColorValue(bottomBar.textColor) : visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
34400
+ if (background?.type === "color" && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
34401
+ else if (foreground && bottomBar?.textColor) styleParts.push({ color: foreground });
33764
34402
  return mergeStyles(...styleParts);
33765
34403
  }
33766
34404
  };
@@ -33895,6 +34533,7 @@ const layoutTransforms = [
33895
34533
  headerLogoClassTransform,
33896
34534
  headerLogoMediaClassTransform,
33897
34535
  headerLogoTextVisibleTransform,
34536
+ classicNavModeTransform,
33898
34537
  footerRootClassTransform,
33899
34538
  headerRootStyleTransform,
33900
34539
  headerSectionBackgroundTransform,
@@ -34331,7 +34970,18 @@ const classicLayout = inline({
34331
34970
  logoRow,
34332
34971
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
34333
34972
  headerCta
34334
- ], when("$root.theme.header.variant", { equals: "classic" }));
34973
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "inline"));
34974
+ const classicCenteredNavLayout = inline({
34975
+ className: bindProp("$root.theme.header.maxWidth", {
34976
+ transforms: pipe(tx("layout.maxWidthClass", { base: `rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6` })),
34977
+ fallback: `rb-container rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6`
34978
+ }),
34979
+ align: "center"
34980
+ }, [
34981
+ logoRow,
34982
+ createNavRow(`rb-flex-1 rb-justify-center ${desktopOnlyDisplay("flex")} rb-gap-6`, "center"),
34983
+ headerCta
34984
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "centered"));
34335
34985
  const centeredLayout = stack({
34336
34986
  gap: "md",
34337
34987
  align: "center",
@@ -34406,6 +35056,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
34406
35056
  }, [
34407
35057
  mobileHeaderBar,
34408
35058
  classicLayout,
35059
+ classicCenteredNavLayout,
34409
35060
  centeredLayout,
34410
35061
  transparentLayout,
34411
35062
  floatingLayout,
@@ -34453,6 +35104,7 @@ init_builder$1();
34453
35104
  init_fragments();
34454
35105
  init_defineBlock();
34455
35106
  init_colorStyles();
35107
+ init_surfaces();
34456
35108
  const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
34457
35109
  const whenTransformed = (from, transformId, equals = true) => (node) => ({
34458
35110
  ...node,
@@ -34622,7 +35274,7 @@ const footerLayout = section$1({
34622
35274
  style: { $bind: {
34623
35275
  from: "$root.theme.footer",
34624
35276
  transforms: [{ id: "layout.footerRootStyle" }],
34625
- fallback: mergeStyles(backgroundColorStyle("surface"), textColorStyle("text"), borderColorStyle("border"))
35277
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
34626
35278
  } }
34627
35279
  }, [
34628
35280
  simpleFooterLayout,
@@ -34684,7 +35336,7 @@ const backgroundImageClassName = "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full r
34684
35336
  */
34685
35337
  const wrapVariant$2 = (variantLayout) => styledSection({
34686
35338
  children: styledContainer({ children: stack({
34687
- gap: "xl",
35339
+ gap: "lg",
34688
35340
  className: "rb-relative"
34689
35341
  }, [...testimonialsHeadingFragment.layout, variantLayout]) }),
34690
35342
  baseClass: "",
@@ -34710,6 +35362,27 @@ const splitGridLayout = styledSection({
34710
35362
  spacing: "comfortable",
34711
35363
  imageClassName: backgroundImageClassName
34712
35364
  });
35365
+ const featuredEditorialHead = el("div", { className: "rb-testimonials-fe-head" }, [text({
35366
+ as: "h2",
35367
+ className: "rb-text-left",
35368
+ headingDecoration: "off"
35369
+ }, when("content.heading"), bind("content.heading")), el("div", { className: "rb-testimonials-fe-leadin" }, [text({
35370
+ as: "p",
35371
+ className: "rb-prose",
35372
+ style: textColorStyle("mutedText")
35373
+ }, when("content.subheading"), bind("content.subheading"))])]);
35374
+ const featuredEditorialLayout = styledSection({
35375
+ children: styledContainer({
35376
+ baseClassName: "rb-relative rb-isolate",
35377
+ children: stack({
35378
+ gap: "lg",
35379
+ className: "rb-relative"
35380
+ }, [featuredEditorialHead, buildFeaturedEditorialLayout()])
35381
+ }),
35382
+ baseClass: "",
35383
+ spacing: "comfortable",
35384
+ imageClassName: backgroundImageClassName
35385
+ });
34713
35386
  const additionalFields = parseFieldDefinitions([
34714
35387
  ...testimonialsHeadingFragment.fields,
34715
35388
  {
@@ -34797,6 +35470,7 @@ const testimonialsBlockDefinition = {
34797
35470
  carousel: carouselLayout$1,
34798
35471
  grid: gridLayout$1,
34799
35472
  "split-grid": splitGridLayout,
35473
+ "featured-editorial": featuredEditorialLayout,
34800
35474
  highlight: highlightLayout
34801
35475
  },
34802
35476
  defaultVariant: "carousel",
@@ -34816,6 +35490,11 @@ const testimonialsBlockDefinition = {
34816
35490
  description: "Heading on the left with testimonial cards on the right",
34817
35491
  icon: "PanelLeft"
34818
35492
  },
35493
+ "featured-editorial": {
35494
+ label: "Featured editorial",
35495
+ description: "A large featured ink quote beside a column of stacked cards (no avatars)",
35496
+ icon: "Quote"
35497
+ },
34819
35498
  highlight: {
34820
35499
  label: "Highlight",
34821
35500
  description: "A single, centered testimonial with no carousel",
@@ -35359,7 +36038,7 @@ function grid$2(props, children) {
35359
36038
  const cardsLayout = styledSection({
35360
36039
  children: styledContainer({
35361
36040
  rootType: "stack",
35362
- rootProps: { gap: "xl" },
36041
+ rootProps: { gap: "lg" },
35363
36042
  children: [stack({
35364
36043
  gap: "sm",
35365
36044
  className: "rb-feature-cards-heading rb-mx-auto rb-max-w-3xl rb-text-center"
@@ -37311,8 +37990,11 @@ var init_filtering = __esmMin((() => {
37311
37990
  }));
37312
37991
  //#endregion
37313
37992
  //#region ../blocks/src/system/blocks/events/shared/layout.ts
37314
- function eventSectionHeaderLayoutNodes() {
37315
- return [text({ as: "h2" }, bind("content.heading"), when("content.heading", { authoringPresence: recoverEmptyHeadingWhenActive })), richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description", { authoringPresence: recoverEmptyDescriptionWhenActive }))];
37993
+ function eventSectionHeaderLayoutNodes(options = {}) {
37994
+ const headingNode = text({ as: "h2" }, bind("content.heading"), when("content.heading", { authoringPresence: recoverEmptyHeadingWhenActive }));
37995
+ const descriptionNode = richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description", { authoringPresence: recoverEmptyDescriptionWhenActive }));
37996
+ if (options.splitClassName) return [el("div", { className: options.splitClassName }, [headingNode, descriptionNode])];
37997
+ return [headingNode, descriptionNode];
37316
37998
  }
37317
37999
  var recoverEmptyHeadingWhenActive, recoverEmptyDescriptionWhenActive;
37318
38000
  var init_layout = __esmMin((() => {
@@ -37404,7 +38086,8 @@ var init_events$1 = __esmMin((() => {
37404
38086
  "combined",
37405
38087
  "calendar",
37406
38088
  "list",
37407
- "timetable"
38089
+ "timetable",
38090
+ "week-board"
37408
38091
  ];
37409
38092
  eventCalendarDefaultViewValues = ["month", "week"];
37410
38093
  eventCalendarListLayoutValues = [
@@ -40018,6 +40701,40 @@ function getEventAvailability(event) {
40018
40701
  isFull: false
40019
40702
  };
40020
40703
  }
40704
+ /**
40705
+ * Derive the three-state availability status (available / filling / waitlist)
40706
+ * plus a short pill label. Builds on {@link getEventAvailability} so the
40707
+ * capacity math (availableSpots with a `capacity - registeredCount` fallback)
40708
+ * stays consistent with the binary helper used elsewhere.
40709
+ */
40710
+ function getEventAvailabilityStatus(event, options) {
40711
+ const threshold = options?.fillingThreshold ?? 2;
40712
+ const { available, isFull } = getEventAvailability(event);
40713
+ if (available == null) return {
40714
+ status: "available",
40715
+ available: null,
40716
+ isFull: false,
40717
+ label: null
40718
+ };
40719
+ if (isFull) return {
40720
+ status: "waitlist",
40721
+ available: 0,
40722
+ isFull: true,
40723
+ label: event.waitlistEnabled ? "Waitlist" : "Full"
40724
+ };
40725
+ if (available <= threshold) return {
40726
+ status: "filling",
40727
+ available,
40728
+ isFull: false,
40729
+ label: `${available} left`
40730
+ };
40731
+ return {
40732
+ status: "available",
40733
+ available,
40734
+ isFull: false,
40735
+ label: `${available} places`
40736
+ };
40737
+ }
40021
40738
  var init_eventCapacity = __esmMin((() => {}));
40022
40739
  //#endregion
40023
40740
  //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
@@ -42663,7 +43380,7 @@ const eventCalendarLayout = [styledSection({
42663
43380
  children: styledContainer({
42664
43381
  rootType: "stack",
42665
43382
  rootProps: { gap: "lg" },
42666
- children: [...eventSectionHeaderLayoutNodes(), el("event-calendar", withApiBindings({
43383
+ children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
42667
43384
  events: { $bind: { from: "data.events" } },
42668
43385
  stage: { $bind: {
42669
43386
  from: "$root.previewStage",
@@ -42774,6 +43491,10 @@ const eventCalendarAdditionalFields = [
42774
43491
  value: "timetable",
42775
43492
  label: "Timetable"
42776
43493
  },
43494
+ {
43495
+ value: "week-board",
43496
+ label: "Week board"
43497
+ },
42777
43498
  {
42778
43499
  value: "list",
42779
43500
  label: "List"
@@ -42956,7 +43677,8 @@ const eventCalendarAdditionalFields = [
42956
43677
  oneOf: [
42957
43678
  "combined",
42958
43679
  "calendar",
42959
- "timetable"
43680
+ "timetable",
43681
+ "week-board"
42960
43682
  ]
42961
43683
  }
42962
43684
  }
@@ -43059,7 +43781,8 @@ const eventCalendarAdditionalFields = [
43059
43781
  "combined",
43060
43782
  "calendar",
43061
43783
  "list",
43062
- "timetable"
43784
+ "timetable",
43785
+ "week-board"
43063
43786
  ]
43064
43787
  }
43065
43788
  }
@@ -43094,7 +43817,8 @@ const eventCalendarAdditionalFields = [
43094
43817
  "combined",
43095
43818
  "calendar",
43096
43819
  "list",
43097
- "timetable"
43820
+ "timetable",
43821
+ "week-board"
43098
43822
  ]
43099
43823
  }, {
43100
43824
  field: "showFilters",
@@ -43117,7 +43841,8 @@ const eventCalendarAdditionalFields = [
43117
43841
  "combined",
43118
43842
  "calendar",
43119
43843
  "list",
43120
- "timetable"
43844
+ "timetable",
43845
+ "week-board"
43121
43846
  ]
43122
43847
  }, {
43123
43848
  field: "showFilters",
@@ -43140,7 +43865,8 @@ const eventCalendarAdditionalFields = [
43140
43865
  "combined",
43141
43866
  "calendar",
43142
43867
  "list",
43143
- "timetable"
43868
+ "timetable",
43869
+ "week-board"
43144
43870
  ]
43145
43871
  }, {
43146
43872
  field: "showFilters",
@@ -43162,7 +43888,8 @@ const eventCalendarAdditionalFields = [
43162
43888
  oneOf: [
43163
43889
  "combined",
43164
43890
  "list",
43165
- "timetable"
43891
+ "timetable",
43892
+ "week-board"
43166
43893
  ]
43167
43894
  }, { allOf: [{
43168
43895
  field: "variant",
@@ -43338,6 +44065,7 @@ const eventCalendarVariants = {
43338
44065
  combined: eventCalendarLayout[0],
43339
44066
  calendar: eventCalendarLayout[0],
43340
44067
  timetable: eventCalendarLayout[0],
44068
+ "week-board": eventCalendarLayout[0],
43341
44069
  list: eventCalendarLayout[0]
43342
44070
  };
43343
44071
  const eventCalendarContentShape = {
@@ -43351,6 +44079,7 @@ const eventCalendarContentShape = {
43351
44079
  { value: "combined" },
43352
44080
  { value: "calendar" },
43353
44081
  { value: "timetable" },
44082
+ { value: "week-board" },
43354
44083
  { value: "list" }
43355
44084
  ]
43356
44085
  },
@@ -43417,6 +44146,7 @@ const eventCalendarBlockDefinition = {
43417
44146
  combined: { label: "Combined" },
43418
44147
  calendar: { label: "Calendar" },
43419
44148
  timetable: { label: "Timetable" },
44149
+ "week-board": { label: "Week board" },
43420
44150
  list: { label: "List" }
43421
44151
  }
43422
44152
  }, eventCalendarContentShape),
@@ -49266,6 +49996,12 @@ const systemBlockDefinitions = [
49266
49996
  family: "centered",
49267
49997
  weight: "featured",
49268
49998
  bias: "soft"
49999
+ }),
50000
+ layoutProfile({
50001
+ variantKey: "featured-editorial",
50002
+ family: "split",
50003
+ weight: "featured",
50004
+ bias: "soft"
49269
50005
  })
49270
50006
  ]
49271
50007
  })),
@@ -49398,6 +50134,11 @@ const systemBlockDefinitions = [
49398
50134
  variantKey: "timetable",
49399
50135
  family: "stack",
49400
50136
  weight: "standard"
50137
+ }),
50138
+ layoutProfile({
50139
+ variantKey: "week-board",
50140
+ family: "stack",
50141
+ weight: "standard"
49401
50142
  })
49402
50143
  ]
49403
50144
  })),
@@ -49762,7 +50503,15 @@ function gradientToCss(config, tokens) {
49762
50503
  const stops = config.stops.map((stop) => {
49763
50504
  return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
49764
50505
  }).join(", ");
49765
- if (config.type === "radial") return `radial-gradient(circle at ${config.position ?? "center"}, ${stops})`;
50506
+ const type = config.type ?? "linear";
50507
+ if (type === "radial") {
50508
+ const position = config.position ?? "center";
50509
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
50510
+ }
50511
+ if (type === "conic") {
50512
+ const position = config.position ?? "center";
50513
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
50514
+ }
49766
50515
  return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
49767
50516
  }
49768
50517
  //#endregion
@@ -49791,7 +50540,7 @@ function backgroundVideoMobileClassNames(input) {
49791
50540
  //#region ../blocks/src/system/transforms/registry/background.ts
49792
50541
  init_background$1();
49793
50542
  init_themeColorResolution();
49794
- init_sectionForegroundStyles();
50543
+ init_surfaceForegroundStyles();
49795
50544
  init_media();
49796
50545
  const isString$2 = (value) => typeof value === "string" && value.trim().length > 0;
49797
50546
  const isNumber$2 = (value) => typeof value === "number" && !isNaN(value);
@@ -49848,8 +50597,8 @@ const backgroundTransforms = [
49848
50597
  {
49849
50598
  id: "background.resolveColorsStyle",
49850
50599
  kind: "formatter",
49851
- summary: "Resolve section foreground colors from a background object into scoped CSS vars",
49852
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
50600
+ summary: "Resolve surface foreground colors from a background object into scoped CSS vars",
50601
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
49853
50602
  },
49854
50603
  {
49855
50604
  id: "background.resolveAllowOverflow",
@@ -50346,21 +51095,53 @@ function Inline({ as: Comp = "div", gap = "md", align = "center", justify = "sta
50346
51095
  //#endregion
50347
51096
  //#region ../blocks/src/primitives/layout/Grid.tsx
50348
51097
  init_clsx();
51098
+ /** Utility class for a numeric column COUNT at a given breakpoint. */
51099
+ const COL_COUNT_CLASS = {
51100
+ base: (n) => `rb-grid-cols-${n}`,
51101
+ sm: (n) => `rb-sm-grid-cols-${n}`,
51102
+ md: (n) => `rb-md-grid-cols-${n}`,
51103
+ lg: (n) => `rb-lg-grid-cols-${n}`,
51104
+ xl: (n) => `rb-xl-grid-cols-${n}`
51105
+ };
51106
+ /** Inline custom property read by the `.rb-grid-tracks` utility per breakpoint. */
51107
+ const TRACK_VAR = {
51108
+ base: "--rb-gtc-base",
51109
+ sm: "--rb-gtc-sm",
51110
+ md: "--rb-gtc-md",
51111
+ lg: "--rb-gtc-lg",
51112
+ xl: "--rb-gtc-xl"
51113
+ };
51114
+ const GRID_BREAKPOINTS = [
51115
+ "base",
51116
+ "sm",
51117
+ "md",
51118
+ "lg",
51119
+ "xl"
51120
+ ];
50349
51121
  function Grid({ as: Comp = "div", cols = {
50350
51122
  base: 1,
50351
51123
  md: 2
50352
- }, gap = "md", className, children, "data-slot": dataSlot, ...rest }) {
50353
- const colsObj = typeof cols === "number" ? { base: cols } : cols;
50354
- const colClasses = [
50355
- colsObj.base && `rb-grid-cols-${colsObj.base}`,
50356
- colsObj.sm && `rb-sm-grid-cols-${colsObj.sm}`,
50357
- colsObj.md && `rb-md-grid-cols-${colsObj.md}`,
50358
- colsObj.lg && `rb-lg-grid-cols-${colsObj.lg}`,
50359
- colsObj.xl && `rb-xl-grid-cols-${colsObj.xl}`
50360
- ];
51124
+ }, gap = "md", className, style, children, "data-slot": dataSlot, ...rest }) {
51125
+ const colsObj = typeof cols === "number" || typeof cols === "string" ? { base: cols } : cols;
51126
+ const colClasses = [];
51127
+ const trackVars = {};
51128
+ let hasTracks = false;
51129
+ for (const bp of GRID_BREAKPOINTS) {
51130
+ const value = colsObj[bp];
51131
+ if (value == null) continue;
51132
+ if (typeof value === "string") {
51133
+ trackVars[TRACK_VAR[bp]] = value;
51134
+ hasTracks = true;
51135
+ } else colClasses.push(COL_COUNT_CLASS[bp](value));
51136
+ }
51137
+ const mergedStyle = hasTracks ? {
51138
+ ...trackVars,
51139
+ ...style
51140
+ } : style;
50361
51141
  return /* @__PURE__ */ jsx(Comp, {
50362
51142
  ...rest,
50363
- className: clsx("rb-grid", colClasses, {
51143
+ style: mergedStyle,
51144
+ className: clsx("rb-grid", hasTracks && "rb-grid-tracks", colClasses, {
50364
51145
  "rb-gap-0": gap === "none",
50365
51146
  "rb-gap-1": gap === "xs",
50366
51147
  "rb-gap-2": gap === "sm",
@@ -50606,6 +51387,138 @@ function Text$2({ as: Comp = "span", children, className = "", path, maxLength:
50606
51387
  });
50607
51388
  }
50608
51389
  //#endregion
51390
+ //#region ../blocks/src/system/icons/cta.ts
51391
+ init_svg();
51392
+ /**
51393
+ * Curated icon set for CTA/button icons.
51394
+ *
51395
+ * Guardrail: keep this list small and action-oriented. This is intentionally not the full Lucide set.
51396
+ * Extend by adding to CTA_ICON_NAMES and the mapping below (explicit imports only).
51397
+ */
51398
+ const CTA_ICON_NAMES = [
51399
+ "ArrowRight",
51400
+ "ArrowLeft",
51401
+ "ChevronRight",
51402
+ "ChevronLeft",
51403
+ "ChevronUp",
51404
+ "ChevronDown",
51405
+ "ExternalLink",
51406
+ "Download",
51407
+ "Upload",
51408
+ "Mail",
51409
+ "Phone",
51410
+ "Play",
51411
+ "ShoppingCart",
51412
+ "Calendar",
51413
+ "MapPin",
51414
+ "Info",
51415
+ "Plus",
51416
+ "Minus",
51417
+ "Check",
51418
+ "X"
51419
+ ];
51420
+ const CTA_ICON_COMPONENTS = {
51421
+ ArrowRight: ArrowRightIcon,
51422
+ ArrowLeft: ArrowLeftIcon,
51423
+ ChevronRight: ChevronRightIcon,
51424
+ ChevronLeft: ChevronLeftIcon,
51425
+ ChevronUp: ChevronUpIcon,
51426
+ ChevronDown: ChevronDownIcon,
51427
+ ExternalLink: ExternalLinkIcon,
51428
+ Download: DownloadIcon,
51429
+ Upload: UploadIcon,
51430
+ Mail: MailIcon,
51431
+ Phone: PhoneIcon,
51432
+ Play: PlayIcon,
51433
+ ShoppingCart: ShoppingCartIcon,
51434
+ Calendar: CalendarIcon$1,
51435
+ MapPin: MapPinIcon$1,
51436
+ Info: InfoIcon,
51437
+ Plus: PlusIcon,
51438
+ Minus: MinusIcon,
51439
+ Check: CheckIcon$1,
51440
+ X: XIcon
51441
+ };
51442
+ function isCtaIconName(value) {
51443
+ return typeof value === "string" && CTA_ICON_NAMES.includes(value);
51444
+ }
51445
+ function formatLucideName(name) {
51446
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
51447
+ }
51448
+ const CTA_ICON_OPTIONS = CTA_ICON_NAMES.map((id) => ({
51449
+ id,
51450
+ label: formatLucideName(id)
51451
+ }));
51452
+ function getCtaIconComponent(name) {
51453
+ if (!isCtaIconName(name)) return null;
51454
+ return CTA_ICON_COMPONENTS[name] ?? null;
51455
+ }
51456
+ //#endregion
51457
+ //#region ../blocks/src/system/icons/registry.ts
51458
+ init_presets$1();
51459
+ function buildSearchText(parts) {
51460
+ return parts.map((part) => part.trim()).filter(Boolean).join(" ");
51461
+ }
51462
+ function semanticDefinitionToOption(definition, preset) {
51463
+ return {
51464
+ id: definition.id,
51465
+ label: definition.label,
51466
+ searchText: buildSearchText([
51467
+ definition.label,
51468
+ definition.id,
51469
+ ...definition.tags,
51470
+ ...definition.domains,
51471
+ ...definition.tone
51472
+ ]),
51473
+ preset
51474
+ };
51475
+ }
51476
+ CTA_ICON_OPTIONS.map((option) => ({
51477
+ id: option.id,
51478
+ label: option.label,
51479
+ searchText: buildSearchText([option.label, option.id]),
51480
+ preset: "cta"
51481
+ }));
51482
+ function semanticOptionsForPreset(preset) {
51483
+ return SEMANTIC_ICON_DEFINITIONS.filter((definition) => definition.presets.includes(preset)).map((definition) => semanticDefinitionToOption(definition, preset));
51484
+ }
51485
+ semanticOptionsForPreset("feature");
51486
+ function getIconComponent(name) {
51487
+ return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
51488
+ }
51489
+ //#endregion
51490
+ //#region ../blocks/src/system/runtime/nodes/buttonAffordance.ts
51491
+ function normalize(value) {
51492
+ const trimmed = typeof value === "string" ? value.trim() : "";
51493
+ return trimmed.length > 0 ? trimmed : null;
51494
+ }
51495
+ /**
51496
+ * Resolve the trailing affordance a button should render. Node overrides
51497
+ * personality; returns `null` when nothing is configured.
51498
+ */
51499
+ function resolveButtonAffordance(input) {
51500
+ const nodeIcon = normalize(input.trailingIcon);
51501
+ if (nodeIcon) {
51502
+ const colorToken = normalize(input.trailingIconColorToken);
51503
+ return {
51504
+ iconId: nodeIcon,
51505
+ source: "node",
51506
+ ...colorToken ? { colorToken } : {}
51507
+ };
51508
+ }
51509
+ const personality = input.personalityAffordance;
51510
+ const personalityIcon = normalize(personality?.iconId);
51511
+ if (personality && personalityIcon) {
51512
+ const colorToken = normalize(personality.colorToken);
51513
+ return {
51514
+ iconId: personalityIcon,
51515
+ source: "personality",
51516
+ ...colorToken ? { colorToken } : {}
51517
+ };
51518
+ }
51519
+ return null;
51520
+ }
51521
+ //#endregion
50609
51522
  //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
50610
51523
  function coerceRichTextDoc(value) {
50611
51524
  const raw = unwrapRichTextRoot(value);
@@ -50670,37 +51583,57 @@ const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockCo
50670
51583
  ...rest
50671
51584
  });
50672
51585
  };
50673
- const ButtonNode = ({ value, children, href, variantId = "primary", size = "md", disabled, type = "button", target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, className, ...rest }) => {
51586
+ /**
51587
+ * Render the resolved trailing affordance icon. Colour is applied via a theme
51588
+ * CSS var so it recolours with the palette; the icon stroke uses `currentColor`.
51589
+ */
51590
+ function renderTrailingAffordanceIcon(affordance) {
51591
+ if (!affordance) return null;
51592
+ const Icon = getIconComponent(affordance.iconId);
51593
+ if (!Icon) return null;
51594
+ return /* @__PURE__ */ jsx(Icon, {
51595
+ "aria-hidden": true,
51596
+ className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block",
51597
+ style: affordance.colorToken ? { color: `rgb(var(--tb-${affordance.colorToken}))` } : void 0
51598
+ });
51599
+ }
51600
+ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md", disabled, type = "button", target, rel, linkRequired = false, trailingIcon, trailingIconColorToken, personalityAffordance, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, className, ...rest }) => {
50674
51601
  const content = value ?? children;
50675
51602
  if (!content) {
50676
51603
  console.warn("[ButtonNode] No content to render - value and children are both empty");
50677
51604
  return null;
50678
51605
  }
51606
+ const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({
51607
+ trailingIcon,
51608
+ trailingIconColorToken,
51609
+ personalityAffordance
51610
+ }));
50679
51611
  const resolvedHref = typeof href === "string" ? href.trim() : "";
50680
51612
  if (linkRequired && resolvedHref.length === 0) {
50681
51613
  if (process.env.NODE_ENV === "development") console.warn("[ButtonNode] Missing href for link-required button");
50682
51614
  return null;
50683
51615
  }
51616
+ const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
50684
51617
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
50685
51618
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
50686
51619
  variant: resolvedVariantId,
50687
51620
  size,
50688
- extraClassName: className
50689
- }) : className;
50690
- if (resolvedHref) return /* @__PURE__ */ jsx("a", {
51621
+ extraClassName
51622
+ }) : extraClassName;
51623
+ if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
50691
51624
  href: resolvedHref,
50692
51625
  target,
50693
51626
  rel,
50694
51627
  className: combinedClassName,
50695
51628
  ...rest,
50696
- children: content
51629
+ children: [content, affordanceIcon]
50697
51630
  });
50698
- return /* @__PURE__ */ jsx("button", {
51631
+ return /* @__PURE__ */ jsxs("button", {
50699
51632
  type,
50700
51633
  disabled,
50701
51634
  className: combinedClassName,
50702
51635
  ...rest,
50703
- children: content
51636
+ children: [content, affordanceIcon]
50704
51637
  });
50705
51638
  };
50706
51639
  const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
@@ -50725,106 +51658,6 @@ const LinkNode = ({ href, children, className, target, rel, linkRequired = false
50725
51658
  });
50726
51659
  };
50727
51660
  //#endregion
50728
- //#region ../blocks/src/system/icons/cta.ts
50729
- init_svg();
50730
- /**
50731
- * Curated icon set for CTA/button icons.
50732
- *
50733
- * Guardrail: keep this list small and action-oriented. This is intentionally not the full Lucide set.
50734
- * Extend by adding to CTA_ICON_NAMES and the mapping below (explicit imports only).
50735
- */
50736
- const CTA_ICON_NAMES = [
50737
- "ArrowRight",
50738
- "ArrowLeft",
50739
- "ChevronRight",
50740
- "ChevronLeft",
50741
- "ChevronUp",
50742
- "ChevronDown",
50743
- "ExternalLink",
50744
- "Download",
50745
- "Upload",
50746
- "Mail",
50747
- "Phone",
50748
- "Play",
50749
- "ShoppingCart",
50750
- "Calendar",
50751
- "MapPin",
50752
- "Info",
50753
- "Plus",
50754
- "Minus",
50755
- "Check",
50756
- "X"
50757
- ];
50758
- const CTA_ICON_COMPONENTS = {
50759
- ArrowRight: ArrowRightIcon,
50760
- ArrowLeft: ArrowLeftIcon,
50761
- ChevronRight: ChevronRightIcon,
50762
- ChevronLeft: ChevronLeftIcon,
50763
- ChevronUp: ChevronUpIcon,
50764
- ChevronDown: ChevronDownIcon,
50765
- ExternalLink: ExternalLinkIcon,
50766
- Download: DownloadIcon,
50767
- Upload: UploadIcon,
50768
- Mail: MailIcon,
50769
- Phone: PhoneIcon,
50770
- Play: PlayIcon,
50771
- ShoppingCart: ShoppingCartIcon,
50772
- Calendar: CalendarIcon$1,
50773
- MapPin: MapPinIcon$1,
50774
- Info: InfoIcon,
50775
- Plus: PlusIcon,
50776
- Minus: MinusIcon,
50777
- Check: CheckIcon$1,
50778
- X: XIcon
50779
- };
50780
- function isCtaIconName(value) {
50781
- return typeof value === "string" && CTA_ICON_NAMES.includes(value);
50782
- }
50783
- function formatLucideName(name) {
50784
- return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
50785
- }
50786
- const CTA_ICON_OPTIONS = CTA_ICON_NAMES.map((id) => ({
50787
- id,
50788
- label: formatLucideName(id)
50789
- }));
50790
- function getCtaIconComponent(name) {
50791
- if (!isCtaIconName(name)) return null;
50792
- return CTA_ICON_COMPONENTS[name] ?? null;
50793
- }
50794
- //#endregion
50795
- //#region ../blocks/src/system/icons/registry.ts
50796
- init_presets$1();
50797
- function buildSearchText(parts) {
50798
- return parts.map((part) => part.trim()).filter(Boolean).join(" ");
50799
- }
50800
- function semanticDefinitionToOption(definition, preset) {
50801
- return {
50802
- id: definition.id,
50803
- label: definition.label,
50804
- searchText: buildSearchText([
50805
- definition.label,
50806
- definition.id,
50807
- ...definition.tags,
50808
- ...definition.domains,
50809
- ...definition.tone
50810
- ]),
50811
- preset
50812
- };
50813
- }
50814
- CTA_ICON_OPTIONS.map((option) => ({
50815
- id: option.id,
50816
- label: option.label,
50817
- searchText: buildSearchText([option.label, option.id]),
50818
- preset: "cta"
50819
- }));
50820
- function semanticOptionsForPreset(preset) {
50821
- return SEMANTIC_ICON_DEFINITIONS.filter((definition) => definition.presets.includes(preset)).map((definition) => semanticDefinitionToOption(definition, preset));
50822
- }
50823
- semanticOptionsForPreset("feature");
50824
- function getIconComponent(name) {
50825
- return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
50826
- }
50827
- //#endregion
50828
51661
  //#region ../blocks/src/system/runtime/nodes/icon.tsx
50829
51662
  const IconNode = ({ value, title, className, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
50830
51663
  const parsedValue = parseBlockIconValue(value);
@@ -51546,6 +52379,78 @@ function SpinnerNode({ className, size = "md", color, strokeWidth = 3, srLabel,
51546
52379
  var init_spinner = __esmMin((() => {
51547
52380
  init_clsx();
51548
52381
  }));
52382
+ //#endregion
52383
+ //#region ../blocks/src/system/runtime/nodes/svg.tsx
52384
+ init_spinner();
52385
+ /**
52386
+ * Turn paint props into a CSS style object. Colour values pass through as-is so
52387
+ * they may reference theme tokens via `var()`, which only resolves in a CSS
52388
+ * property context (not in a bare presentation attribute).
52389
+ */
52390
+ function paintStyle(shape) {
52391
+ const style = {};
52392
+ if (shape.fill !== void 0) style.fill = shape.fill;
52393
+ if (shape.stroke !== void 0) style.stroke = shape.stroke;
52394
+ if (shape.strokeWidth !== void 0) style.strokeWidth = shape.strokeWidth;
52395
+ if (shape.fillOpacity !== void 0) style.fillOpacity = shape.fillOpacity;
52396
+ if (shape.strokeOpacity !== void 0) style.strokeOpacity = shape.strokeOpacity;
52397
+ if (shape.strokeLinecap !== void 0) style.strokeLinecap = shape.strokeLinecap;
52398
+ if (shape.strokeLinejoin !== void 0) style.strokeLinejoin = shape.strokeLinejoin;
52399
+ if (shape.strokeDasharray !== void 0) style.strokeDasharray = shape.strokeDasharray;
52400
+ return style;
52401
+ }
52402
+ function renderShape(shape, key) {
52403
+ const style = paintStyle(shape);
52404
+ switch (shape.kind) {
52405
+ case "path": return /* @__PURE__ */ jsx("path", {
52406
+ d: shape.d,
52407
+ style
52408
+ }, key);
52409
+ case "ellipse": return /* @__PURE__ */ jsx("ellipse", {
52410
+ cx: shape.cx,
52411
+ cy: shape.cy,
52412
+ rx: shape.rx,
52413
+ ry: shape.ry,
52414
+ style
52415
+ }, key);
52416
+ case "circle": return /* @__PURE__ */ jsx("circle", {
52417
+ cx: shape.cx,
52418
+ cy: shape.cy,
52419
+ r: shape.r,
52420
+ style
52421
+ }, key);
52422
+ case "rect": return /* @__PURE__ */ jsx("rect", {
52423
+ x: shape.x,
52424
+ y: shape.y,
52425
+ width: shape.width,
52426
+ height: shape.height,
52427
+ rx: shape.rx,
52428
+ ry: shape.ry,
52429
+ style
52430
+ }, key);
52431
+ case "line": return /* @__PURE__ */ jsx("line", {
52432
+ x1: shape.x1,
52433
+ y1: shape.y1,
52434
+ x2: shape.x2,
52435
+ y2: shape.y2,
52436
+ style
52437
+ }, key);
52438
+ default: return null;
52439
+ }
52440
+ }
52441
+ const SvgNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, viewBox, width, height, className, style, ariaHidden = true, shapes }) => {
52442
+ return /* @__PURE__ */ jsx("svg", {
52443
+ viewBox,
52444
+ width,
52445
+ height,
52446
+ className,
52447
+ style,
52448
+ "aria-hidden": ariaHidden,
52449
+ xmlns: "http://www.w3.org/2000/svg",
52450
+ fill: "none",
52451
+ children: (Array.isArray(shapes) ? shapes : []).map((shape, index) => renderShape(shape, index))
52452
+ });
52453
+ };
51549
52454
  function clearWorkflowFeedback(state) {
51550
52455
  return {
51551
52456
  ...state,
@@ -54843,7 +55748,6 @@ var init_booking_form_interactive = __esmMin((() => {
54843
55748
  }));
54844
55749
  //#endregion
54845
55750
  //#region ../blocks/src/system/runtime/nodes/booking-form.server.tsx
54846
- init_spinner();
54847
55751
  init_booking_form_interactive();
54848
55752
  /**
54849
55753
  * Server-safe placeholder for booking form.
@@ -57333,6 +58237,153 @@ var init_WeekAgendaView = __esmMin((() => {
57333
58237
  };
57334
58238
  }));
57335
58239
  //#endregion
58240
+ //#region ../blocks/src/system/runtime/nodes/events/shared/WeekBoardView.tsx
58241
+ /**
58242
+ * Format an event's start–end as a compact range, merging the shared meridiem.
58243
+ * "6:00 PM" + "7:00 PM" -> "6:00 – 7:00 PM"; "9:30 AM" + "10:15 AM" -> "9:30 – 10:15 AM".
58244
+ */
58245
+ function formatCompactTimeRange(event) {
58246
+ const timeZone = event.timeZone ?? null;
58247
+ const start = formatTime$3(event.startsAt, { timeZone });
58248
+ const end = formatTime$3(event.endsAt, { timeZone });
58249
+ const startMeridiem = start.slice(-2);
58250
+ const endMeridiem = end.slice(-2);
58251
+ if ((startMeridiem === "AM" || startMeridiem === "PM") && startMeridiem === endMeridiem) return `${start.slice(0, -3).trim()} – ${end}`;
58252
+ return `${start} – ${end}`;
58253
+ }
58254
+ var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardView;
58255
+ var init_WeekBoardView = __esmMin((() => {
58256
+ init_clsx();
58257
+ init_buttons();
58258
+ init_eventCapacity();
58259
+ init_utils$3();
58260
+ SHORT_DAY_NAMES = [
58261
+ "Sun",
58262
+ "Mon",
58263
+ "Tue",
58264
+ "Wed",
58265
+ "Thu",
58266
+ "Fri",
58267
+ "Sat"
58268
+ ];
58269
+ LEGEND_ITEMS = [
58270
+ {
58271
+ status: "available",
58272
+ label: "Places available"
58273
+ },
58274
+ {
58275
+ status: "filling",
58276
+ label: "Filling up"
58277
+ },
58278
+ {
58279
+ status: "waitlist",
58280
+ label: "Waitlist"
58281
+ }
58282
+ ];
58283
+ WeekBoardCard = ({ event, showCapacity }) => {
58284
+ const linkProps = resolveEventLinkProps(event);
58285
+ const { status, label } = getEventAvailabilityStatus(event);
58286
+ const pill = showCapacity ? label : null;
58287
+ return /* @__PURE__ */ jsxs("a", {
58288
+ ...linkProps,
58289
+ className: "event-week-board-card",
58290
+ "data-status": status,
58291
+ children: [
58292
+ /* @__PURE__ */ jsx("span", {
58293
+ className: "event-week-board-card-title",
58294
+ children: event.title
58295
+ }),
58296
+ /* @__PURE__ */ jsx("span", {
58297
+ className: "event-week-board-card-time",
58298
+ children: formatCompactTimeRange(event)
58299
+ }),
58300
+ pill ? /* @__PURE__ */ jsx("span", {
58301
+ className: "event-week-board-card-pill",
58302
+ "data-status": status,
58303
+ children: pill
58304
+ }) : null
58305
+ ]
58306
+ });
58307
+ };
58308
+ WeekBoardView = ({ days, events, showCapacity, emptyMessage = "No classes scheduled this week", title = "The week ahead", footerNote = "New to a class? We'll check it's right for you first.", ctaLabel = "Reserve a place", ctaHref = null, buttonVariant = "outline" }) => {
58309
+ const eventsByDate = groupEventsByDate(events);
58310
+ const hasAnyEvents = days.some((date) => (eventsByDate.get(formatDateKey(date)) ?? []).length > 0);
58311
+ const ctaClassName = themeButtonClassName({
58312
+ variant: buttonVariant,
58313
+ size: "sm"
58314
+ });
58315
+ return /* @__PURE__ */ jsx("div", {
58316
+ className: "event-calendar event-calendar--week-board",
58317
+ "data-block": "event-calendar",
58318
+ children: /* @__PURE__ */ jsxs("div", {
58319
+ className: "event-week-board",
58320
+ style: { "--event-week-board-cols": String(days.length) },
58321
+ children: [
58322
+ /* @__PURE__ */ jsxs("div", {
58323
+ className: "event-week-board-top",
58324
+ children: [/* @__PURE__ */ jsx("span", {
58325
+ className: "event-week-board-title",
58326
+ children: title
58327
+ }), /* @__PURE__ */ jsx("div", {
58328
+ className: "event-week-board-legend",
58329
+ "aria-hidden": "true",
58330
+ children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
58331
+ className: "event-week-board-legend-item",
58332
+ children: [/* @__PURE__ */ jsx("i", {
58333
+ className: "event-week-board-legend-dot",
58334
+ "data-status": item.status
58335
+ }), item.label]
58336
+ }, item.status))
58337
+ })]
58338
+ }),
58339
+ /* @__PURE__ */ jsx("div", {
58340
+ className: "event-week-board-grid",
58341
+ children: days.map((date) => {
58342
+ const dateKey = formatDateKey(date);
58343
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
58344
+ const today = isToday(date);
58345
+ return /* @__PURE__ */ jsxs("div", {
58346
+ className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
58347
+ children: [/* @__PURE__ */ jsxs("div", {
58348
+ className: "event-week-board-day-head",
58349
+ children: [/* @__PURE__ */ jsx("span", {
58350
+ className: "event-week-board-day-abbr",
58351
+ children: SHORT_DAY_NAMES[date.getDay()]
58352
+ }), /* @__PURE__ */ jsx("span", {
58353
+ className: "event-week-board-day-num",
58354
+ children: date.getDate()
58355
+ })]
58356
+ }), /* @__PURE__ */ jsx("div", {
58357
+ className: "event-week-board-day-body",
58358
+ children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
58359
+ event,
58360
+ showCapacity
58361
+ }, event.occurrenceId || event.id))
58362
+ })]
58363
+ }, dateKey);
58364
+ })
58365
+ }),
58366
+ /* @__PURE__ */ jsxs("div", {
58367
+ className: "event-week-board-foot",
58368
+ children: [/* @__PURE__ */ jsx("p", {
58369
+ className: "event-week-board-foot-note",
58370
+ children: hasAnyEvents ? footerNote : emptyMessage
58371
+ }), ctaHref ? /* @__PURE__ */ jsx("a", {
58372
+ className: ctaClassName,
58373
+ href: ctaHref,
58374
+ children: ctaLabel
58375
+ }) : /* @__PURE__ */ jsx("button", {
58376
+ type: "button",
58377
+ className: ctaClassName,
58378
+ children: ctaLabel
58379
+ })]
58380
+ })
58381
+ ]
58382
+ })
58383
+ });
58384
+ };
58385
+ }));
58386
+ //#endregion
57336
58387
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
57337
58388
  function buildTimetableModel(input) {
57338
58389
  const generic = buildTimetableModel$1({
@@ -57427,6 +58478,7 @@ init_clsx();
57427
58478
  init_EventListing_view();
57428
58479
  init_EventCalendar_interactive();
57429
58480
  init_WeekAgendaView();
58481
+ init_WeekBoardView();
57430
58482
  init_utils$3();
57431
58483
  init_timetableModel();
57432
58484
  init_buttons();
@@ -57771,6 +58823,17 @@ function renderTimetableSsr(display) {
57771
58823
  })]
57772
58824
  });
57773
58825
  }
58826
+ function renderWeekBoardSsr(display) {
58827
+ const days = getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek);
58828
+ return /* @__PURE__ */ jsx(WeekBoardView, {
58829
+ days,
58830
+ events: [...display.events],
58831
+ showCapacity: display.showCapacity,
58832
+ emptyMessage: display.emptyMessage,
58833
+ ctaLabel: display.buttonText,
58834
+ buttonVariant: display.buttonVariant
58835
+ });
58836
+ }
57774
58837
  function formatHourLabel$1(hour) {
57775
58838
  if (hour === 0) return "12 AM";
57776
58839
  if (hour === 12) return "12 PM";
@@ -57797,6 +58860,9 @@ const EventCalendarSSR = (props) => {
57797
58860
  case "timetable":
57798
58861
  content = renderTimetableSsr(display);
57799
58862
  break;
58863
+ case "week-board":
58864
+ content = renderWeekBoardSsr(display);
58865
+ break;
57800
58866
  case "calendar":
57801
58867
  content = renderCalendarSsr(display);
57802
58868
  break;
@@ -58391,6 +59457,7 @@ init_media_server();
58391
59457
  const serverComponentRegistry = {
58392
59458
  div: DivNode,
58393
59459
  figure: FigureNode,
59460
+ svg: SvgNode,
58394
59461
  section: SectionNode,
58395
59462
  headerSection: header_section_server_default,
58396
59463
  stack: StackNode,
@@ -59802,10 +60869,14 @@ init_node();
59802
60869
  init_fragments();
59803
60870
  init_defineBlock();
59804
60871
  //#endregion
60872
+ //#region ../theme-core/src/styles/shadow.ts
60873
+ init_colorStyles();
60874
+ //#endregion
59805
60875
  //#region ../theme-core/src/accordions/generateAccordionCss.ts
59806
60876
  init_types$10();
59807
60877
  init_constants$1();
59808
60878
  init_colorStyles();
60879
+ init_surfaces();
59809
60880
  //#endregion
59810
60881
  //#region ../theme-core/src/inputs/generateInputCss.ts
59811
60882
  init_types$9();
@@ -59850,10 +60921,10 @@ function svgDataUrl(svg) {
59850
60921
  }
59851
60922
  //#endregion
59852
60923
  //#region ../theme-core/src/status/generateStatusCss.ts
59853
- init_contextualColors();
60924
+ init_surfaces();
59854
60925
  //#endregion
59855
- //#region ../theme-core/src/status/index.ts
59856
- init_contextualColors();
60926
+ //#region ../theme-core/src/typography/generateTypographyCss.ts
60927
+ init_surfaces();
59857
60928
  //#endregion
59858
60929
  //#region ../theme-core/src/blocks/vars/event-registration.ts
59859
60930
  /**
@@ -60191,6 +61262,7 @@ const THEME_RADIUS_CSS_VARS = {
60191
61262
  block: "--rb-block-radius",
60192
61263
  button: "--rb-button-radius",
60193
61264
  input: "--rb-input-radius",
61265
+ panel: "--rb-panel-radius",
60194
61266
  legacyCard: "--radius-card",
60195
61267
  legacyControl: "--radius-control"
60196
61268
  };
@@ -60272,6 +61344,10 @@ ${`:where([data-theme-scope="${themeId}"]) :where([data-block="customer-portal"]
60272
61344
  /* Modal (shared rb-modal classes) */
60273
61345
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.35);
60274
61346
  --rb-modal-bg: var(--cp-card-bg);
61347
+ --rb-modal-text: var(--cp-text);
61348
+ --rb-modal-heading: var(--cp-text);
61349
+ --rb-modal-link: var(--cp-primary);
61350
+ --rb-modal-supporting: var(--cp-muted);
60275
61351
  --rb-modal-border: var(--cp-card-border);
60276
61352
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
60277
61353
  --rb-modal-radius: var(--cp-card-radius);
@@ -62273,6 +63349,8 @@ const VERTICAL_IDS = [
62273
63349
  "yoga_wellness",
62274
63350
  "fitness_pt",
62275
63351
  "dance_school",
63352
+ "physiotherapy_physical_health",
63353
+ "massage_bodywork",
62276
63354
  "therapist_practitioner",
62277
63355
  "beauty_spa",
62278
63356
  "consultant_coach",
@@ -62308,6 +63386,12 @@ const VERTICAL_BOOKING_PRESETS = [
62308
63386
  preset("dance_school.workshops", "dance_school", "workshop", "Workshop", "Workshops", "One-off workshops, masterclasses, or intensives."),
62309
63387
  preset("dance_school.private_lessons", "dance_school", "appointment", "Private lesson", "Private lessons", "One-to-one lessons or coaching sessions."),
62310
63388
  preset("dance_school.shows", "dance_school", "performance", "Show", "Shows", "Ticketed performances, showcases, and recitals."),
63389
+ preset("physiotherapy_physical_health.appointments", "physiotherapy_physical_health", "appointment", "Appointment", "Appointments", "Assessments, treatments, follow-ups, and rehabilitation sessions."),
63390
+ preset("physiotherapy_physical_health.rehab_classes", "physiotherapy_physical_health", "class", "Rehab class", "Rehab classes", "Regular rehabilitation, mobility, strength, or recovery classes."),
63391
+ preset("physiotherapy_physical_health.workshops", "physiotherapy_physical_health", "workshop", "Workshop", "Workshops", "One-off workshops, talks, or practical group sessions."),
63392
+ preset("massage_bodywork.treatments", "massage_bodywork", "appointment", "Treatment", "Treatments", "Massage treatments, bodywork sessions, and one-to-one appointments."),
63393
+ preset("massage_bodywork.group_sessions", "massage_bodywork", "class", "Group session", "Group sessions", "Regular bodywork, somatic movement, or self-massage sessions."),
63394
+ preset("massage_bodywork.workshops", "massage_bodywork", "workshop", "Workshop", "Workshops", "One-off bodywork, self-massage, or somatic practice workshops."),
62311
63395
  preset("therapist_practitioner.appointments", "therapist_practitioner", "appointment", "Appointment", "Appointments", "Sessions, consultations, treatments, or assessments."),
62312
63396
  preset("therapist_practitioner.workshops", "therapist_practitioner", "workshop", "Workshop", "Workshops", "One-off group workshops, talks, or wellbeing sessions."),
62313
63397
  preset("therapist_practitioner.retreats", "therapist_practitioner", "retreat", "Retreat", "Retreats", "Multi-day retreats or immersive group experiences."),
@@ -147332,7 +148416,7 @@ function buildDisplayFilterParams(display) {
147332
148416
  filterVenueId: display.filterVenueId
147333
148417
  });
147334
148418
  }
147335
- var EventCalendarClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
148419
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
147336
148420
  var init_EventCalendar_client = __esmMin((() => {
147337
148421
  init_EventCalendar_interactive();
147338
148422
  init_EventListing_client();
@@ -147345,6 +148429,7 @@ var init_EventCalendar_client = __esmMin((() => {
147345
148429
  init_EventModalContext();
147346
148430
  init_EventModals();
147347
148431
  init_WeekAgendaView();
148432
+ init_WeekBoardView();
147348
148433
  init_WeekTimetableView();
147349
148434
  init_buttons();
147350
148435
  init_listOptions();
@@ -147382,8 +148467,20 @@ var init_EventCalendar_client = __esmMin((() => {
147382
148467
  });
147383
148468
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
147384
148469
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
148470
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
147385
148471
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
147386
148472
  };
148473
+ EventCalendarWeekBoardClient = ({ display }) => {
148474
+ const days = useMemo(() => getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek), [display.startOfWeek]);
148475
+ return /* @__PURE__ */ jsx(WeekBoardView, {
148476
+ days,
148477
+ events: [...display.events],
148478
+ showCapacity: display.showCapacity,
148479
+ emptyMessage: display.emptyMessage,
148480
+ ctaLabel: display.buttonText,
148481
+ buttonVariant: display.buttonVariant
148482
+ });
148483
+ };
147387
148484
  EventCalendarTimetableClient = ({ render }) => {
147388
148485
  const { display, hydration } = render;
147389
148486
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
@@ -151828,7 +152925,7 @@ var SimpleCache = class {
151828
152925
  * 1. This constant
151829
152926
  * 2. The "version" field in package.json
151830
152927
  */
151831
- const SDK_VERSION = "0.104.0";
152928
+ const SDK_VERSION = "0.104.3";
151832
152929
  //#endregion
151833
152930
  //#region src/client/error.ts
151834
152931
  /**