@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
@@ -959,11 +959,11 @@ var init_fileStorage = __esmMin((() => {
959
959
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
960
960
  //#endregion
961
961
  //#region ../media-core/src/typeGuards.ts
962
- function isRecord$33(value) {
962
+ function isRecord$35(value) {
963
963
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
964
964
  }
965
965
  function asRecord$3(value) {
966
- return isRecord$33(value) ? value : void 0;
966
+ return isRecord$35(value) ? value : void 0;
967
967
  }
968
968
  var init_typeGuards$1 = __esmMin((() => {}));
969
969
  function isFileJsonObject(value) {
@@ -973,7 +973,7 @@ function isFileJsonValue(value) {
973
973
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
974
974
  if (typeof value === "number") return Number.isFinite(value);
975
975
  if (Array.isArray(value)) return value.every(isFileJsonValue);
976
- return isRecord$33(value) && isFileJsonObject(value);
976
+ return isRecord$35(value) && isFileJsonObject(value);
977
977
  }
978
978
  var init_filePersistence = __esmMin((() => {
979
979
  init_src$3();
@@ -1383,7 +1383,7 @@ function isCmsMediaObjectType(value) {
1383
1383
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
1384
1384
  }
1385
1385
  function isCmsMediaObject(value) {
1386
- if (!isRecord$33(value)) return false;
1386
+ if (!isRecord$35(value)) return false;
1387
1387
  const type = value.type;
1388
1388
  if (!isCmsMediaObjectType(type)) return false;
1389
1389
  if ("attrs" in value) return false;
@@ -1394,7 +1394,7 @@ function collectMediaObjects(value, out, location = "") {
1394
1394
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
1395
1395
  return;
1396
1396
  }
1397
- if (!isRecord$33(value)) return;
1397
+ if (!isRecord$35(value)) return;
1398
1398
  if (isCmsMediaObject(value)) out.push({
1399
1399
  obj: value,
1400
1400
  location
@@ -1428,8 +1428,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
1428
1428
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
1429
1429
  return;
1430
1430
  }
1431
- if (!isRecord$33(value)) return;
1432
- if (value.type === "image" && isRecord$33(value.attrs)) out.push({
1431
+ if (!isRecord$35(value)) return;
1432
+ if (value.type === "image" && isRecord$35(value.attrs)) out.push({
1433
1433
  attrs: value.attrs,
1434
1434
  location: location ? `${location}.attrs` : "attrs"
1435
1435
  });
@@ -1639,7 +1639,7 @@ var init_media$2 = __esmMin((() => {
1639
1639
  /**
1640
1640
  * Strict record guard: excludes null, primitives, and arrays.
1641
1641
  */
1642
- function isRecord$32(value) {
1642
+ function isRecord$34(value) {
1643
1643
  return typeof value === "object" && value !== null && !Array.isArray(value);
1644
1644
  }
1645
1645
  /**
@@ -1675,10 +1675,10 @@ var init_typeGuards = __esmMin((() => {}));
1675
1675
  * helper inside `@riverbankcms/blocks/bindings`.
1676
1676
  */
1677
1677
  function unwrapRichTextRoot(value) {
1678
- if (!isRecord$32(value)) return value;
1678
+ if (!isRecord$34(value)) return value;
1679
1679
  if (!("doc" in value)) return value;
1680
1680
  const inner = value.doc;
1681
- if (isRecord$32(inner) && inner.type === "doc") return inner;
1681
+ if (isRecord$34(inner) && inner.type === "doc") return inner;
1682
1682
  return value;
1683
1683
  }
1684
1684
  function createHardBreakNode() {
@@ -2979,6 +2979,82 @@ var init_ctaRow$1 = __esmMin((() => {
2979
2979
  init_ctaButton();
2980
2980
  }));
2981
2981
  //#endregion
2982
+ //#region ../theme-core/src/surfaces/foregroundRoles.ts
2983
+ var SURFACE_FOREGROUND_ROLES;
2984
+ var init_foregroundRoles = __esmMin((() => {
2985
+ SURFACE_FOREGROUND_ROLES = [
2986
+ "text",
2987
+ "heading",
2988
+ "link",
2989
+ "supporting"
2990
+ ];
2991
+ }));
2992
+ //#endregion
2993
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
2994
+ function requireSurfaceColorValue(role, value) {
2995
+ const normalized = value.trim();
2996
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
2997
+ return normalized;
2998
+ }
2999
+ function completeSurfaceForegrounds(input) {
3000
+ const text = requireSurfaceColorValue("text", input.text);
3001
+ return {
3002
+ text,
3003
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
3004
+ link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
3005
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
3006
+ };
3007
+ }
3008
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
3009
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
3010
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
3011
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
3012
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
3013
+ }
3014
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
3015
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
3016
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
3017
+ }
3018
+ function surfaceForegroundStyle(input) {
3019
+ const foregrounds = completeSurfaceForegrounds(input);
3020
+ return {
3021
+ color: foregrounds.text,
3022
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
3023
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
3024
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
3025
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
3026
+ };
3027
+ }
3028
+ function surfaceForegroundDeclarations(input) {
3029
+ const foregrounds = completeSurfaceForegrounds(input);
3030
+ return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
3031
+ }
3032
+ var SURFACE_FOREGROUND_CSS_VARS, DEFAULT_SURFACE_TEXT_COLOR, DEFAULT_SURFACE_LINK_COLOR, DEFAULT_SURFACE_SUPPORTING_COLOR, DEFAULT_ROLE_FALLBACKS;
3033
+ var init_foregroundContract = __esmMin((() => {
3034
+ init_foregroundRoles();
3035
+ SURFACE_FOREGROUND_CSS_VARS = {
3036
+ text: "--rb-surface-text-color",
3037
+ heading: "--rb-surface-heading-color",
3038
+ link: "--rb-surface-link-color",
3039
+ supporting: "--rb-surface-supporting-color"
3040
+ };
3041
+ DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
3042
+ DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
3043
+ DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
3044
+ DEFAULT_ROLE_FALLBACKS = {
3045
+ text: DEFAULT_SURFACE_TEXT_COLOR,
3046
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
3047
+ link: DEFAULT_SURFACE_LINK_COLOR,
3048
+ supporting: DEFAULT_SURFACE_SUPPORTING_COLOR
3049
+ };
3050
+ }));
3051
+ //#endregion
3052
+ //#region ../theme-core/src/surfaces/index.ts
3053
+ var init_surfaces = __esmMin((() => {
3054
+ init_foregroundContract();
3055
+ init_foregroundRoles();
3056
+ }));
3057
+ //#endregion
2982
3058
  //#region ../theme-core/src/tokens/colorTokenParts.ts
2983
3059
  function parseOpacityPercent(source) {
2984
3060
  const trimmed = source.trim();
@@ -3028,9 +3104,12 @@ function parseToken(source) {
3028
3104
  if (parts.kind === "invalid") return { token: source };
3029
3105
  return {
3030
3106
  token: parts.token,
3031
- alpha: parts.opacityPercent === null ? void 0 : parts.opacityPercent / 100
3107
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
3032
3108
  };
3033
3109
  }
3110
+ function surfaceRoleForTextToken(token) {
3111
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
3112
+ }
3034
3113
  /**
3035
3114
  * Converts a theme color token to a CSS rgb value.
3036
3115
  * This is the primary function for applying theme colors to CSS properties.
@@ -3044,11 +3123,26 @@ function parseToken(source) {
3044
3123
  * rgbColorValue('raw:transparent') // => 'transparent'
3045
3124
  */
3046
3125
  function rgbColorValue(token) {
3047
- const { token: baseToken, alpha, raw } = parseToken(token);
3126
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
3048
3127
  if (raw) return raw;
3049
3128
  const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
3050
- if (alpha === void 0) return `rgb(var(${cssVar}))`;
3051
- return `rgb(var(${cssVar}) / ${alpha})`;
3129
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
3130
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
3131
+ }
3132
+ /**
3133
+ * Converts a theme color token to a CSS variable reference.
3134
+ * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
3135
+ *
3136
+ * @param token - Theme color token
3137
+ * @returns CSS variable reference
3138
+ *
3139
+ * @example
3140
+ * cssVarValue('primary') // => 'var(--tb-primary)'
3141
+ * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
3142
+ */
3143
+ function cssVarValue(token) {
3144
+ const { token: baseToken } = parseToken(token);
3145
+ return `var(${COLOR_VAR_PREFIX}${baseToken})`;
3052
3146
  }
3053
3147
  /**
3054
3148
  * Creates a backgroundColor style object from a theme token.
@@ -3066,6 +3160,9 @@ function backgroundColorStyle(token) {
3066
3160
  * @returns CSSProperties with color
3067
3161
  */
3068
3162
  function textColorStyle(token) {
3163
+ const parsed = parseToken(token);
3164
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
3165
+ if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
3069
3166
  return { color: rgbColorValue(token) };
3070
3167
  }
3071
3168
  /**
@@ -3101,10 +3198,16 @@ function mergeStyles(...styles) {
3101
3198
  }
3102
3199
  return Object.keys(merged).length ? merged : void 0;
3103
3200
  }
3104
- var COLOR_VAR_PREFIX;
3201
+ var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
3105
3202
  var init_colorStyles = __esmMin((() => {
3203
+ init_surfaces();
3106
3204
  init_colorTokenParts();
3107
3205
  COLOR_VAR_PREFIX = "--tb-";
3206
+ SURFACE_TEXT_ROLE_BY_TOKEN = {
3207
+ text: "text",
3208
+ heading: "heading",
3209
+ mutedText: "supporting"
3210
+ };
3108
3211
  }));
3109
3212
  var init_cardContainer = __esmMin((() => {
3110
3213
  init_builder$2();
@@ -5058,6 +5161,207 @@ var init_all = __esmMin((() => {
5058
5161
  init_vibrant_creative();
5059
5162
  init_PaletteCard();
5060
5163
  }));
5164
+ function isBlockColorToken(value) {
5165
+ if (typeof value !== "string") return false;
5166
+ const parts = parseColorTokenParts(value);
5167
+ return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
5168
+ }
5169
+ function parseBlockColorToken(value) {
5170
+ if (!isBlockColorToken(value)) return null;
5171
+ return value.trim();
5172
+ }
5173
+ var blockColorTokenNames, blockColorTokenNameSet;
5174
+ var init_blockColorTokens = __esmMin((() => {
5175
+ init_colorTokenParts();
5176
+ blockColorTokenNames = [
5177
+ "text",
5178
+ "heading",
5179
+ "mutedText",
5180
+ "surface",
5181
+ "background",
5182
+ "foreground",
5183
+ "border",
5184
+ "primary",
5185
+ "secondary",
5186
+ "accent",
5187
+ "success",
5188
+ "warning",
5189
+ "info",
5190
+ "error",
5191
+ "destructive",
5192
+ "scrim",
5193
+ "shadow",
5194
+ "onPrimary",
5195
+ "onSecondary",
5196
+ "onAccent",
5197
+ "onSuccess",
5198
+ "onWarning",
5199
+ "onInfo",
5200
+ "onError",
5201
+ "onDestructive",
5202
+ "onSurface"
5203
+ ];
5204
+ blockColorTokenNameSet = new Set(blockColorTokenNames);
5205
+ }));
5206
+ //#endregion
5207
+ //#region ../theme-core/src/tokens/themeColorTokens.ts
5208
+ function isKnownBaseToken(value) {
5209
+ return themeColorBaseTokenSet.has(value);
5210
+ }
5211
+ function isKnownShadeToken(value) {
5212
+ const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
5213
+ if (!match) return false;
5214
+ const [, base, shade] = match;
5215
+ return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
5216
+ }
5217
+ function isThemeColorTokenBase(value) {
5218
+ return isKnownBaseToken(value) || isKnownShadeToken(value);
5219
+ }
5220
+ function isThemeColorToken(value) {
5221
+ if (typeof value !== "string") return false;
5222
+ const parts = parseColorTokenParts(value);
5223
+ return parts.kind === "token" && isThemeColorTokenBase(parts.token);
5224
+ }
5225
+ function parseThemeColorToken(value) {
5226
+ if (!isThemeColorToken(value)) return null;
5227
+ return value.trim();
5228
+ }
5229
+ var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
5230
+ var init_themeColorTokens = __esmMin((() => {
5231
+ init_blockColorTokens();
5232
+ init_colorTokenParts();
5233
+ PALETTE_TOKEN_NAMES = [
5234
+ "primary",
5235
+ "primaryForeground",
5236
+ "secondary",
5237
+ "accent",
5238
+ "success",
5239
+ "warning",
5240
+ "destructive",
5241
+ "background",
5242
+ "surface",
5243
+ "surfaceAlt",
5244
+ "muted",
5245
+ "text",
5246
+ "border"
5247
+ ];
5248
+ paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
5249
+ themeColorBaseTokenNames = [
5250
+ ...PALETTE_TOKEN_NAMES,
5251
+ ...blockColorTokenNames,
5252
+ "white",
5253
+ "neutral",
5254
+ "primaryText",
5255
+ "secondaryForeground",
5256
+ "accentForeground"
5257
+ ];
5258
+ themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
5259
+ themeColorShadeSteps = [
5260
+ "50",
5261
+ "100",
5262
+ "200",
5263
+ "300",
5264
+ "400",
5265
+ "500",
5266
+ "600",
5267
+ "700",
5268
+ "800",
5269
+ "900",
5270
+ "950"
5271
+ ];
5272
+ shadeStepSet = new Set(themeColorShadeSteps);
5273
+ themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
5274
+ }));
5275
+ //#endregion
5276
+ //#region ../theme-core/src/palette/colors.ts
5277
+ function normalizePaletteHex(value) {
5278
+ if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
5279
+ const normalized = value.toLowerCase();
5280
+ if (normalized.length === 7) return normalized;
5281
+ const triplet = normalized.slice(1);
5282
+ const red = triplet.charAt(0);
5283
+ const green = triplet.charAt(1);
5284
+ const blue = triplet.charAt(2);
5285
+ return `#${red}${red}${green}${green}${blue}${blue}`;
5286
+ }
5287
+ function paletteColorsFromEntries(entries) {
5288
+ const values = {};
5289
+ for (const entry of entries) {
5290
+ const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
5291
+ if (!parsedRole.success) return {
5292
+ ok: false,
5293
+ error: {
5294
+ kind: "unknown-role",
5295
+ role: entry.name
5296
+ }
5297
+ };
5298
+ const role = parsedRole.data;
5299
+ if (values[role] !== void 0) return {
5300
+ ok: false,
5301
+ error: {
5302
+ kind: "duplicate-role",
5303
+ role
5304
+ }
5305
+ };
5306
+ const hex = normalizePaletteHex(entry.hex);
5307
+ if (!hex) return {
5308
+ ok: false,
5309
+ error: {
5310
+ kind: "invalid-color",
5311
+ role,
5312
+ value: entry.hex
5313
+ }
5314
+ };
5315
+ values[role] = hex;
5316
+ }
5317
+ const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
5318
+ if (missing.length > 0) return {
5319
+ ok: false,
5320
+ error: {
5321
+ kind: "missing-roles",
5322
+ roles: missing
5323
+ }
5324
+ };
5325
+ return {
5326
+ ok: true,
5327
+ colors: paletteColorsSchema.parse(values)
5328
+ };
5329
+ }
5330
+ function requirePaletteColorsFromEntries(entries) {
5331
+ const result = paletteColorsFromEntries(entries);
5332
+ if (result.ok) return result.colors;
5333
+ throw new Error(`Invalid complete palette: ${result.error.kind}`);
5334
+ }
5335
+ var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema, paletteModeSchema, paletteColorsSchema, init_colors = __esmMin((() => {
5336
+ init_themeColorTokens();
5337
+ HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
5338
+ NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
5339
+ hexColorSchema = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
5340
+ paletteModeSchema = z$1.enum(["light", "dark"]);
5341
+ z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
5342
+ paletteColorsSchema = z$1.object({
5343
+ primary: hexColorSchema,
5344
+ primaryForeground: hexColorSchema,
5345
+ secondary: hexColorSchema,
5346
+ accent: hexColorSchema,
5347
+ success: hexColorSchema,
5348
+ warning: hexColorSchema,
5349
+ destructive: hexColorSchema,
5350
+ background: hexColorSchema,
5351
+ surface: hexColorSchema,
5352
+ surfaceAlt: hexColorSchema,
5353
+ muted: hexColorSchema,
5354
+ text: hexColorSchema,
5355
+ border: hexColorSchema
5356
+ }).strict().transform((value) => value);
5357
+ }));
5358
+ var init_historicalThemePalette = __esmMin((() => {
5359
+ init_themeColorTokens();
5360
+ init_colors();
5361
+ init_colorConversion();
5362
+ init_textColor();
5363
+ new Set(PALETTE_TOKEN_NAMES);
5364
+ }));
5061
5365
  //#endregion
5062
5366
  //#region ../theme-core/src/palette/types.ts
5063
5367
  var init_types$15 = __esmMin((() => {}));
@@ -6185,201 +6489,6 @@ var init_browser = __esmMin((() => {
6185
6489
  var init_extractPalette = __esmMin((() => {
6186
6490
  init_browser();
6187
6491
  }));
6188
- function isBlockColorToken(value) {
6189
- if (typeof value !== "string") return false;
6190
- const parts = parseColorTokenParts(value);
6191
- return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
6192
- }
6193
- function parseBlockColorToken(value) {
6194
- if (!isBlockColorToken(value)) return null;
6195
- return value.trim();
6196
- }
6197
- var blockColorTokenNames, blockColorTokenNameSet;
6198
- var init_blockColorTokens = __esmMin((() => {
6199
- init_colorTokenParts();
6200
- blockColorTokenNames = [
6201
- "text",
6202
- "heading",
6203
- "mutedText",
6204
- "surface",
6205
- "background",
6206
- "foreground",
6207
- "border",
6208
- "primary",
6209
- "secondary",
6210
- "accent",
6211
- "success",
6212
- "warning",
6213
- "info",
6214
- "error",
6215
- "destructive",
6216
- "scrim",
6217
- "shadow",
6218
- "onPrimary",
6219
- "onSecondary",
6220
- "onAccent",
6221
- "onSuccess",
6222
- "onWarning",
6223
- "onInfo",
6224
- "onError",
6225
- "onDestructive",
6226
- "onSurface"
6227
- ];
6228
- blockColorTokenNameSet = new Set(blockColorTokenNames);
6229
- }));
6230
- //#endregion
6231
- //#region ../theme-core/src/tokens/themeColorTokens.ts
6232
- function isKnownBaseToken(value) {
6233
- return themeColorBaseTokenSet.has(value);
6234
- }
6235
- function isKnownShadeToken(value) {
6236
- const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
6237
- if (!match) return false;
6238
- const [, base, shade] = match;
6239
- return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
6240
- }
6241
- function isThemeColorTokenBase(value) {
6242
- return isKnownBaseToken(value) || isKnownShadeToken(value);
6243
- }
6244
- function isThemeColorToken(value) {
6245
- if (typeof value !== "string") return false;
6246
- const parts = parseColorTokenParts(value);
6247
- return parts.kind === "token" && isThemeColorTokenBase(parts.token);
6248
- }
6249
- function parseThemeColorToken(value) {
6250
- if (!isThemeColorToken(value)) return null;
6251
- return value.trim();
6252
- }
6253
- var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
6254
- var init_themeColorTokens = __esmMin((() => {
6255
- init_blockColorTokens();
6256
- init_colorTokenParts();
6257
- PALETTE_TOKEN_NAMES = [
6258
- "primary",
6259
- "primaryForeground",
6260
- "secondary",
6261
- "accent",
6262
- "success",
6263
- "warning",
6264
- "destructive",
6265
- "background",
6266
- "surface",
6267
- "surfaceAlt",
6268
- "muted",
6269
- "text",
6270
- "border"
6271
- ];
6272
- paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
6273
- themeColorBaseTokenNames = [
6274
- ...PALETTE_TOKEN_NAMES,
6275
- ...blockColorTokenNames,
6276
- "white",
6277
- "neutral",
6278
- "primaryText",
6279
- "secondaryForeground",
6280
- "accentForeground"
6281
- ];
6282
- themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
6283
- themeColorShadeSteps = [
6284
- "50",
6285
- "100",
6286
- "200",
6287
- "300",
6288
- "400",
6289
- "500",
6290
- "600",
6291
- "700",
6292
- "800",
6293
- "900",
6294
- "950"
6295
- ];
6296
- shadeStepSet = new Set(themeColorShadeSteps);
6297
- themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
6298
- }));
6299
- //#endregion
6300
- //#region ../theme-core/src/palette/colors.ts
6301
- function normalizePaletteHex(value) {
6302
- if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
6303
- const normalized = value.toLowerCase();
6304
- if (normalized.length === 7) return normalized;
6305
- const triplet = normalized.slice(1);
6306
- const red = triplet.charAt(0);
6307
- const green = triplet.charAt(1);
6308
- const blue = triplet.charAt(2);
6309
- return `#${red}${red}${green}${green}${blue}${blue}`;
6310
- }
6311
- function paletteColorsFromEntries(entries) {
6312
- const values = {};
6313
- for (const entry of entries) {
6314
- const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
6315
- if (!parsedRole.success) return {
6316
- ok: false,
6317
- error: {
6318
- kind: "unknown-role",
6319
- role: entry.name
6320
- }
6321
- };
6322
- const role = parsedRole.data;
6323
- if (values[role] !== void 0) return {
6324
- ok: false,
6325
- error: {
6326
- kind: "duplicate-role",
6327
- role
6328
- }
6329
- };
6330
- const hex = normalizePaletteHex(entry.hex);
6331
- if (!hex) return {
6332
- ok: false,
6333
- error: {
6334
- kind: "invalid-color",
6335
- role,
6336
- value: entry.hex
6337
- }
6338
- };
6339
- values[role] = hex;
6340
- }
6341
- const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
6342
- if (missing.length > 0) return {
6343
- ok: false,
6344
- error: {
6345
- kind: "missing-roles",
6346
- roles: missing
6347
- }
6348
- };
6349
- return {
6350
- ok: true,
6351
- colors: paletteColorsSchema.parse(values)
6352
- };
6353
- }
6354
- function requirePaletteColorsFromEntries(entries) {
6355
- const result = paletteColorsFromEntries(entries);
6356
- if (result.ok) return result.colors;
6357
- throw new Error(`Invalid complete palette: ${result.error.kind}`);
6358
- }
6359
- var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema, paletteModeSchema, paletteColorsSchema;
6360
- var init_colors = __esmMin((() => {
6361
- init_themeColorTokens();
6362
- HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
6363
- NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
6364
- hexColorSchema = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
6365
- paletteModeSchema = z$1.enum(["light", "dark"]);
6366
- z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
6367
- paletteColorsSchema = z$1.object({
6368
- primary: hexColorSchema,
6369
- primaryForeground: hexColorSchema,
6370
- secondary: hexColorSchema,
6371
- accent: hexColorSchema,
6372
- success: hexColorSchema,
6373
- warning: hexColorSchema,
6374
- destructive: hexColorSchema,
6375
- background: hexColorSchema,
6376
- surface: hexColorSchema,
6377
- surfaceAlt: hexColorSchema,
6378
- muted: hexColorSchema,
6379
- text: hexColorSchema,
6380
- border: hexColorSchema
6381
- }).strict().transform((value) => value);
6382
- }));
6383
6492
  var init_editorState = __esmMin((() => {}));
6384
6493
  var init_libraryModel = __esmMin((() => {}));
6385
6494
  var init_themePaletteCompatibility = __esmMin((() => {
@@ -6390,6 +6499,7 @@ var init_legacySelection = __esmMin((() => {
6390
6499
  init_themeColorTokens();
6391
6500
  init_colors();
6392
6501
  init_themePaletteCompatibility();
6502
+ init_historicalThemePalette();
6393
6503
  }));
6394
6504
  //#endregion
6395
6505
  //#region ../theme-core/src/site-styles/styleTags.ts
@@ -6470,7 +6580,7 @@ var init_types$14 = __esmMin((() => {
6470
6580
  }));
6471
6581
  //#endregion
6472
6582
  //#region ../theme-core/src/palette/curated/brand-led.ts
6473
- var brandLedCool, brandLedWarm, brandLedJewel, brandLedBurgundyGold;
6583
+ var brandLedCool, brandLedWarm, brandLedJewel, brandLedSpruce, brandLedBurgundyGold;
6474
6584
  var init_brand_led = __esmMin((() => {
6475
6585
  init_types$14();
6476
6586
  brandLedCool = defineCuratedPalette({
@@ -6668,6 +6778,71 @@ var init_brand_led = __esmMin((() => {
6668
6778
  }
6669
6779
  ]
6670
6780
  });
6781
+ brandLedSpruce = defineCuratedPalette({
6782
+ id: "brand-led-spruce",
6783
+ name: "Brand-led — Spruce",
6784
+ description: "Spruce-ink primary and moss secondary with an amber accent over a green-mist ground and hairline sage borders.",
6785
+ tags: {
6786
+ tone: "classic",
6787
+ energy: "calm",
6788
+ era: "editorial"
6789
+ },
6790
+ mode: "light",
6791
+ colors: [
6792
+ {
6793
+ name: "primary",
6794
+ hex: "#14312b"
6795
+ },
6796
+ {
6797
+ name: "secondary",
6798
+ hex: "#356a59"
6799
+ },
6800
+ {
6801
+ name: "accent",
6802
+ hex: "#f08a4b"
6803
+ },
6804
+ {
6805
+ name: "success",
6806
+ hex: "#356a59"
6807
+ },
6808
+ {
6809
+ name: "warning",
6810
+ hex: "#f08a4b"
6811
+ },
6812
+ {
6813
+ name: "destructive",
6814
+ hex: "#b5561f"
6815
+ },
6816
+ {
6817
+ name: "background",
6818
+ hex: "#ecefe9"
6819
+ },
6820
+ {
6821
+ name: "surface",
6822
+ hex: "#ffffff"
6823
+ },
6824
+ {
6825
+ name: "surfaceAlt",
6826
+ hex: "#f4f6f1"
6827
+ },
6828
+ {
6829
+ name: "muted",
6830
+ hex: "#5c6a64"
6831
+ },
6832
+ {
6833
+ name: "text",
6834
+ hex: "#1c2a26"
6835
+ },
6836
+ {
6837
+ name: "primaryForeground",
6838
+ hex: "#f4f7f1"
6839
+ },
6840
+ {
6841
+ name: "border",
6842
+ hex: "#d7ddd2"
6843
+ }
6844
+ ]
6845
+ });
6671
6846
  brandLedBurgundyGold = defineCuratedPalette({
6672
6847
  id: "brand-led-burgundy-gold",
6673
6848
  name: "Brand-led — Burgundy Gold",
@@ -7608,8 +7783,7 @@ var init_warm_dark = __esmMin((() => {
7608
7783
  function findCuratedPalette(id) {
7609
7784
  return curatedPalettesById.get(id);
7610
7785
  }
7611
- var curatedPalettes, curatedPalettesById;
7612
- var init_curated = __esmMin((() => {
7786
+ var curatedPalettes, curatedPalettesById, init_curated = __esmMin((() => {
7613
7787
  init_brand_led();
7614
7788
  init_high_contrast();
7615
7789
  init_soft_natural();
@@ -7621,6 +7795,7 @@ var init_curated = __esmMin((() => {
7621
7795
  brandLedWarm,
7622
7796
  brandLedJewel,
7623
7797
  brandLedBurgundyGold,
7798
+ brandLedSpruce,
7624
7799
  warmNeutralClay,
7625
7800
  warmNeutralCream,
7626
7801
  warmNeutralSoftEarth,
@@ -7737,6 +7912,7 @@ var init_palette$1 = __esmMin((() => {
7737
7912
  init_expandPalette();
7738
7913
  init_generateCssVars();
7739
7914
  init_generateShades();
7915
+ init_historicalThemePalette();
7740
7916
  init_neutralScale();
7741
7917
  init_types$15();
7742
7918
  init_utils$5();
@@ -8206,7 +8382,7 @@ function asSpecialVariantId(value) {
8206
8382
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
8207
8383
  return value;
8208
8384
  }
8209
- 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;
8385
+ 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;
8210
8386
  var init_types$13 = __esmMin((() => {
8211
8387
  init_themeColorTokens();
8212
8388
  VARIANT_ROLES = [
@@ -8366,6 +8542,10 @@ var init_types$13 = __esmMin((() => {
8366
8542
  widthClass: z$1.string(),
8367
8543
  colorToken: themeColorTokenSchema
8368
8544
  });
8545
+ buttonVariantAffordanceSchema = z$1.object({
8546
+ iconId: z$1.string().min(1),
8547
+ colorToken: themeColorTokenSchema.optional()
8548
+ });
8369
8549
  variantShadowSchema = z$1.object({
8370
8550
  elevation: z$1.enum([
8371
8551
  "none",
@@ -8406,7 +8586,8 @@ var init_types$13 = __esmMin((() => {
8406
8586
  border: buttonBorderSchema.optional(),
8407
8587
  hoverBackgroundToken: z$1.string().optional(),
8408
8588
  effects: variantEffectsSchema.optional(),
8409
- sizes: variantSizeOverridesSchema.optional()
8589
+ sizes: variantSizeOverridesSchema.optional(),
8590
+ affordance: buttonVariantAffordanceSchema.optional()
8410
8591
  });
8411
8592
  buttonSystemSchema = z$1.object({
8412
8593
  global: buttonGlobalSettingsSchema,
@@ -8956,6 +9137,132 @@ var init_editorial_link = __esmMin((() => {
8956
9137
  });
8957
9138
  }));
8958
9139
  //#endregion
9140
+ //#region ../theme-core/src/buttons/personalities/flat-ink.ts
9141
+ var flatInk;
9142
+ var init_flat_ink = __esmMin((() => {
9143
+ init_types$12();
9144
+ flatInk = defineButtonPersonality({
9145
+ id: "flat-ink",
9146
+ name: "Flat Ink",
9147
+ description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
9148
+ tags: {
9149
+ tone: "classic",
9150
+ energy: "calm",
9151
+ motion: "subtle",
9152
+ era: "editorial"
9153
+ },
9154
+ buttonSystem: {
9155
+ global: {
9156
+ cornerStyle: "rounded",
9157
+ shadow: "low",
9158
+ textTransform: "none",
9159
+ fontWeight: 600,
9160
+ borderWidth: 1,
9161
+ typography: "body",
9162
+ letterSpacing: "tight",
9163
+ paddingPreset: "default",
9164
+ hoverTransform: "lift",
9165
+ hoverColor: "none"
9166
+ },
9167
+ sizes: {
9168
+ sm: {
9169
+ padding: "0.625rem 1.125rem",
9170
+ fontSize: "text-sm"
9171
+ },
9172
+ md: { padding: "0.8125rem 1.375rem" },
9173
+ lg: {
9174
+ padding: "0.9375rem 1.625rem",
9175
+ fontSize: "text-lg"
9176
+ },
9177
+ xl: {
9178
+ padding: "1.0625rem 2rem",
9179
+ fontSize: "text-xl"
9180
+ }
9181
+ },
9182
+ variants: [
9183
+ {
9184
+ id: "primary",
9185
+ name: "Primary",
9186
+ enabled: true,
9187
+ priority: 1,
9188
+ background: {
9189
+ type: "solid",
9190
+ colorToken: "primary"
9191
+ },
9192
+ textColorToken: "primaryForeground",
9193
+ borderRadius: "rounded-lg",
9194
+ affordance: {
9195
+ iconId: "ArrowRight",
9196
+ colorToken: "accent"
9197
+ },
9198
+ shadow: {
9199
+ elevation: "none",
9200
+ softness: null,
9201
+ position: "bottom"
9202
+ },
9203
+ effects: { hover: [{
9204
+ effectId: "lift",
9205
+ options: { translateY: "-2px" }
9206
+ }, {
9207
+ effectId: "background-on-hover",
9208
+ options: { colorToken: "secondary" }
9209
+ }] }
9210
+ },
9211
+ {
9212
+ id: "secondary",
9213
+ name: "Secondary",
9214
+ enabled: true,
9215
+ priority: 2,
9216
+ background: { type: "transparent" },
9217
+ textColorToken: "primary",
9218
+ borderRadius: "rounded-lg",
9219
+ border: {
9220
+ widthClass: "border",
9221
+ colorToken: "border"
9222
+ },
9223
+ shadow: {
9224
+ elevation: "none",
9225
+ softness: null,
9226
+ position: "bottom"
9227
+ },
9228
+ effects: { hover: [{
9229
+ effectId: "lift",
9230
+ options: { translateY: "-2px" }
9231
+ }, {
9232
+ effectId: "background-on-hover",
9233
+ options: { colorToken: "surfaceAlt" }
9234
+ }] }
9235
+ },
9236
+ {
9237
+ id: "accent",
9238
+ name: "Accent",
9239
+ enabled: true,
9240
+ priority: 3,
9241
+ background: {
9242
+ type: "solid",
9243
+ colorToken: "accent"
9244
+ },
9245
+ textColorToken: "accentForeground",
9246
+ borderRadius: "rounded-lg",
9247
+ shadow: {
9248
+ elevation: "none",
9249
+ softness: null,
9250
+ position: "bottom"
9251
+ },
9252
+ affordance: {
9253
+ iconId: "ArrowRight",
9254
+ colorToken: "accentForeground"
9255
+ },
9256
+ effects: { hover: [{
9257
+ effectId: "lift",
9258
+ options: { translateY: "-2px" }
9259
+ }] }
9260
+ }
9261
+ ]
9262
+ }
9263
+ });
9264
+ }));
9265
+ //#endregion
8959
9266
  //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
8960
9267
  var inkStamp;
8961
9268
  var init_ink_stamp = __esmMin((() => {
@@ -9722,6 +10029,7 @@ var init_personalities = __esmMin((() => {
9722
10029
  init_confident_chip();
9723
10030
  init_earth_pill();
9724
10031
  init_editorial_link();
10032
+ init_flat_ink();
9725
10033
  init_ink_stamp();
9726
10034
  init_joy_stamp();
9727
10035
  init_ornate_ritual();
@@ -9736,6 +10044,7 @@ var init_personalities = __esmMin((() => {
9736
10044
  editorialLink,
9737
10045
  pebble,
9738
10046
  inkStamp,
10047
+ flatInk,
9739
10048
  brushedWash,
9740
10049
  showtimePill,
9741
10050
  joyStamp,
@@ -10205,6 +10514,50 @@ function getCompatibleHeaderStyleIds(layoutId) {
10205
10514
  return isHeaderStyleCompatibleWithLayout(getHeaderStyleOrThrow(styleId), layoutId);
10206
10515
  });
10207
10516
  }
10517
+ function applyNavTypography(style, typography) {
10518
+ switch (typography) {
10519
+ case "plain": return style;
10520
+ case "heading": return {
10521
+ ...style,
10522
+ typography: "heading",
10523
+ fontWeight: "medium",
10524
+ letterSpacing: "wide"
10525
+ };
10526
+ case "quiet-caps": return {
10527
+ ...style,
10528
+ textTransform: "uppercase",
10529
+ textSize: "sm",
10530
+ letterSpacing: "wide"
10531
+ };
10532
+ case "brand-caps": return {
10533
+ ...style,
10534
+ textTransform: "uppercase",
10535
+ textSize: "sm",
10536
+ letterSpacing: "wider"
10537
+ };
10538
+ default: return assertNever$16(typography, "Unhandled header nav typography");
10539
+ }
10540
+ }
10541
+ function underlineNavLinkStyle(colorToken, underlineColorToken, typography = "plain") {
10542
+ return applyNavTypography({
10543
+ name: "Underline grow",
10544
+ typography: "body",
10545
+ fontWeight: "medium",
10546
+ textTransform: "none",
10547
+ italic: false,
10548
+ colorToken,
10549
+ padding: "compact",
10550
+ paddingX: "compact",
10551
+ borderRadius: "none",
10552
+ effects: { hover: [{
10553
+ effectId: "nav-underline",
10554
+ options: {
10555
+ style: "grow",
10556
+ ...underlineColorToken ? { colorToken: underlineColorToken } : {}
10557
+ }
10558
+ }] }
10559
+ }, typography);
10560
+ }
10208
10561
  function themedHeaderShadow(theme) {
10209
10562
  switch (theme.shadow.elevation) {
10210
10563
  case "none": return;
@@ -10304,6 +10657,38 @@ function cleanBaseHeader(theme) {
10304
10657
  ctaGap: "default"
10305
10658
  };
10306
10659
  }
10660
+ function classicCenteredNavHeader(theme) {
10661
+ return {
10662
+ ...baseHeader(theme),
10663
+ variant: "classic",
10664
+ navPlacement: "center",
10665
+ positioning: "sticky",
10666
+ shrinkOnScroll: false,
10667
+ background: {
10668
+ type: "color",
10669
+ color: "surface"
10670
+ },
10671
+ textColor: "text",
10672
+ navColor: "text",
10673
+ navStyle: "underline-grow",
10674
+ navWeight: "medium",
10675
+ navLinkStyle: underlineNavLinkStyle("text", "accent"),
10676
+ border: {
10677
+ style: "solid",
10678
+ width: "thin",
10679
+ position: "bottom",
10680
+ colorToken: "border"
10681
+ },
10682
+ ctaTreatment: "primary",
10683
+ ctaVariant: resolveHeaderCtaVariant(theme, "primary"),
10684
+ ctaGap: "default",
10685
+ logoText: {
10686
+ mobileMaxWidth: "sm",
10687
+ mobileWrapLines: 1,
10688
+ hideOnShrink: false
10689
+ }
10690
+ };
10691
+ }
10307
10692
  function serifLineHeader(theme) {
10308
10693
  return {
10309
10694
  ...baseHeader(theme),
@@ -10882,6 +11267,13 @@ var init_headerLooks = __esmMin((() => {
10882
11267
  styleId: asHeaderStyleId("minimal")
10883
11268
  }
10884
11269
  },
11270
+ {
11271
+ lookId: asHeaderLookId("classic-centered-nav"),
11272
+ selection: {
11273
+ layoutId: asHeaderLayoutId("classic"),
11274
+ styleId: asHeaderStyleId("fine-line")
11275
+ }
11276
+ },
10885
11277
  {
10886
11278
  lookId: asHeaderLookId("brand-solid"),
10887
11279
  selection: {
@@ -10948,6 +11340,21 @@ var init_headerLooks = __esmMin((() => {
10948
11340
  logoAccommodations: inlineClassicLogoAccommodations,
10949
11341
  compile: cleanBaseHeader
10950
11342
  },
11343
+ {
11344
+ id: asHeaderLookId("classic-centered-nav"),
11345
+ label: "Centered nav",
11346
+ visualTreatment: "solid-neutral",
11347
+ layoutBehavior: "sticky",
11348
+ configuration: {
11349
+ structure: "inline-classic",
11350
+ treatment: "solid-neutral",
11351
+ behavior: "sticky"
11352
+ },
11353
+ openingRequirement: "none",
11354
+ maxRecommendedNavItems: 6,
11355
+ logoAccommodations: inlineClassicLogoAccommodations,
11356
+ compile: classicCenteredNavHeader
11357
+ },
10951
11358
  {
10952
11359
  id: asHeaderLookId("brand-solid"),
10953
11360
  label: "Brand solid",
@@ -11508,7 +11915,7 @@ function defineTypographyPreset(preset) {
11508
11915
  id: asTypographyPresetId(preset.id)
11509
11916
  };
11510
11917
  }
11511
- var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, typographyPresets;
11918
+ var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, fulcrumTypography, typographyPresets;
11512
11919
  var init_typographyPresets = __esmMin((() => {
11513
11920
  bodyReadablePolicy = {
11514
11921
  recommendedCategories: ["sans-serif", "serif"],
@@ -11870,6 +12277,49 @@ var init_typographyPresets = __esmMin((() => {
11870
12277
  },
11871
12278
  scale: "balanced"
11872
12279
  };
12280
+ fulcrumTypography = {
12281
+ body: {
12282
+ family: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
12283
+ size: "lg",
12284
+ weight: "regular",
12285
+ lineHeight: "relaxed",
12286
+ letterSpacing: "normal"
12287
+ },
12288
+ headings: {
12289
+ default: {
12290
+ family: "Newsreader, Georgia, \"Times New Roman\", serif",
12291
+ weight: "medium",
12292
+ lineHeight: "normal",
12293
+ letterSpacing: "tight",
12294
+ colorToken: "primary",
12295
+ italic: null,
12296
+ case: null
12297
+ },
12298
+ h1: {
12299
+ size: "2xl",
12300
+ weight: "medium",
12301
+ lineHeight: "normal",
12302
+ letterSpacing: "tight",
12303
+ italic: null
12304
+ },
12305
+ h2: {
12306
+ size: "xl",
12307
+ weight: "medium",
12308
+ lineHeight: "normal",
12309
+ letterSpacing: "tight",
12310
+ italic: null
12311
+ },
12312
+ h3: {
12313
+ size: "md",
12314
+ weight: "semibold",
12315
+ lineHeight: "normal",
12316
+ letterSpacing: "normal",
12317
+ italic: null
12318
+ }
12319
+ },
12320
+ scale: "spacious",
12321
+ eyebrow: { family: "IBM Plex Mono, ui-monospace, \"SF Mono\", monospace" }
12322
+ };
11873
12323
  typographyPresets = [
11874
12324
  defineTypographyPreset({
11875
12325
  id: "typography-preset:modern-sans",
@@ -12129,6 +12579,32 @@ var init_typographyPresets = __esmMin((() => {
12129
12579
  }
12130
12580
  }
12131
12581
  }
12582
+ }),
12583
+ defineTypographyPreset({
12584
+ id: "typography-preset:fulcrum",
12585
+ name: "Fulcrum",
12586
+ description: "Newsreader serif headings over an IBM Plex Sans body, with an IBM Plex Mono eyebrow role for uppercase kickers and mono captions.",
12587
+ defaultFonts: {
12588
+ body: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
12589
+ heading: "Newsreader, Georgia, \"Times New Roman\", serif"
12590
+ },
12591
+ recommendedFonts: {
12592
+ body: [
12593
+ "IBM Plex Sans",
12594
+ "Source Sans 3",
12595
+ "Inter"
12596
+ ],
12597
+ heading: [
12598
+ "Newsreader",
12599
+ "Source Serif 4",
12600
+ "Lora"
12601
+ ]
12602
+ },
12603
+ slotPolicies: {
12604
+ body: bodyReadablePolicy,
12605
+ heading: displayHeadingPolicy
12606
+ },
12607
+ typography: fulcrumTypography
12132
12608
  })
12133
12609
  ];
12134
12610
  new Map(typographyPresets.map((preset) => [preset.id, preset]));
@@ -13847,6 +14323,28 @@ var init_generateDefaultButtonSystem = __esmMin((() => {
13847
14323
  "high"
13848
14324
  ];
13849
14325
  }));
14326
+ /**
14327
+ * Build a `data:image/svg+xml,...` URL for an affordance icon, suitable for use
14328
+ * as a CSS `mask-image`. The stroke is painted solid black so the mask's alpha
14329
+ * traces the icon outline; the visible colour is supplied separately by the
14330
+ * `::after` rule's `background-color`. Returns `null` for unknown ids.
14331
+ */
14332
+ function affordanceIconMaskUrl(iconId) {
14333
+ const paths = AFFORDANCE_ICON_PATHS[iconId];
14334
+ if (!paths || paths.length === 0) return null;
14335
+ return `data:image/svg+xml,${`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>${paths.map((d) => `<path d='${d}'/>`).join("")}</svg>`.replace(/"/g, "'").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ")}`;
14336
+ }
14337
+ var AFFORDANCE_ICON_PATHS;
14338
+ var init_affordanceIcons = __esmMin((() => {
14339
+ AFFORDANCE_ICON_PATHS = {
14340
+ ArrowRight: ["M5 12h14", "m13 6 6 6-6 6"],
14341
+ ArrowLeft: ["M19 12H5", "m11 6-6 6 6 6"],
14342
+ ChevronRight: ["m9 18 6-6-6-6"],
14343
+ ChevronLeft: ["m15 18-6-6 6-6"],
14344
+ ChevronDown: ["m6 9 6 6 6-6"],
14345
+ ArrowUpRight: ["M7 17 17 7", "M7 7h10v10"]
14346
+ };
14347
+ }));
13850
14348
  //#endregion
13851
14349
  //#region ../theme-core/src/buttons/generateButtonCss.ts
13852
14350
  function rule(selector, declarations) {
@@ -13925,10 +14423,40 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
13925
14423
  out.push(variantFocusVisibleRule(variantId, themeId));
13926
14424
  const effects = variantEffectsCss(variant, themeId, tokens, theme);
13927
14425
  if (effects) out.push({ raw: effects });
14426
+ const affordance = variantAffordanceRule(variant, selector, tokens);
14427
+ if (affordance) out.push(affordance);
13928
14428
  out.push(...variantDisabledRules(variantId, themeId));
13929
14429
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
13930
14430
  return out;
13931
14431
  }
14432
+ /**
14433
+ * Emit the optional trailing affordance icon as a masked `::after`.
14434
+ *
14435
+ * Only variants that declare `affordance` with a known icon id produce a rule —
14436
+ * every other variant is byte-identical to before. The `:not(.rb-affordance-off)`
14437
+ * guard lets a `button` node that renders its own trailing icon suppress this
14438
+ * one (node overrides personality). Colour comes from the affordance token, or
14439
+ * `currentColor` (the button text colour) when no token is given.
14440
+ */
14441
+ function variantAffordanceRule(variant, selector, tokens) {
14442
+ const affordance = variant.affordance;
14443
+ if (!affordance) return null;
14444
+ const maskUrl = affordanceIconMaskUrl(affordance.iconId);
14445
+ if (!maskUrl) return null;
14446
+ const color = affordance.colorToken ? tokens.getColor(affordance.colorToken) : "currentColor";
14447
+ const mask = `url("${maskUrl}") no-repeat center / contain`;
14448
+ return rule(`${selector}:not(.${AFFORDANCE_SUPPRESS_CLASS})::after`, [
14449
+ ["content", "\"\""],
14450
+ ["display", "inline-block"],
14451
+ ["width", "1em"],
14452
+ ["height", "1em"],
14453
+ ["margin-inline-start", "0.5em"],
14454
+ ["flex", "0 0 auto"],
14455
+ ["background-color", color],
14456
+ ["-webkit-mask", mask],
14457
+ ["mask", mask]
14458
+ ]);
14459
+ }
13932
14460
  function parseButtonVariantIdForCss(value) {
13933
14461
  const variantId = parseThemeButtonVariantId(value);
13934
14462
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
@@ -14075,7 +14603,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
14075
14603
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
14076
14604
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
14077
14605
  }
14078
- var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
14606
+ var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
14079
14607
  var init_generateButtonCss = __esmMin((() => {
14080
14608
  init_types$13();
14081
14609
  init_classNames();
@@ -14084,6 +14612,8 @@ var init_generateButtonCss = __esmMin((() => {
14084
14612
  init_generateEffectsCSS();
14085
14613
  init_constants$2();
14086
14614
  init_generateDefaultButtonSystem();
14615
+ init_affordanceIcons();
14616
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
14087
14617
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
14088
14618
  LETTER_SPACING_MAP = {
14089
14619
  tight: "-0.025em",
@@ -14110,6 +14640,7 @@ var init_buttons = __esmMin((() => {
14110
14640
  init_types$13();
14111
14641
  init_classNames();
14112
14642
  init_generateButtonCss();
14643
+ init_affordanceIcons();
14113
14644
  init_generateDefaultButtonSystem();
14114
14645
  init_constants$2();
14115
14646
  init_presets$1();
@@ -14350,23 +14881,6 @@ function generateDefaultCardSystem(theme) {
14350
14881
  }
14351
14882
  var init_generateDefaultCardSystem = __esmMin((() => {}));
14352
14883
  //#endregion
14353
- //#region ../theme-core/src/status/contextualColors.ts
14354
- function statusMutedColorValue() {
14355
- return `var(${STATUS_MUTED_COLOR_VAR}, ${DEFAULT_STATUS_MUTED_COLOR})`;
14356
- }
14357
- function statusMutedColorDeclaration() {
14358
- return `color: ${statusMutedColorValue()};`;
14359
- }
14360
- function contextualMutedStatusColorDeclaration(value) {
14361
- return `${STATUS_MUTED_COLOR_VAR}: ${value}`;
14362
- }
14363
- var STATUS_MUTED_COLOR_VAR, DEFAULT_STATUS_MUTED_COLOR, SURFACE_MUTED_STATUS_COLOR;
14364
- var init_contextualColors = __esmMin((() => {
14365
- STATUS_MUTED_COLOR_VAR = "--rb-status-muted-color";
14366
- DEFAULT_STATUS_MUTED_COLOR = "rgb(var(--tb-mutedText))";
14367
- SURFACE_MUTED_STATUS_COLOR = "color-mix(in oklab, currentColor, transparent 18%)";
14368
- }));
14369
- //#endregion
14370
14884
  //#region ../theme-core/src/cards/generateCardCss.ts
14371
14885
  function resolveCornerRadiiCss$1(cornerRadii, fallback) {
14372
14886
  const fallbackValue = CORNER_RADIUS_MAP$2[fallback];
@@ -14411,8 +14925,10 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
14411
14925
  const direction = GRADIENT_DIRECTION_MAP$1[variant.background.direction] || "to right";
14412
14926
  rules.push(`background: linear-gradient(${direction}, ${fromColor}, ${toColor})`);
14413
14927
  } else rules.push(`background: transparent`);
14414
- if (variant.foregroundToken) rules.push(`color: ${tokens.getColor(variant.foregroundToken)}`);
14415
- rules.push(contextualMutedStatusColorDeclaration(SURFACE_MUTED_STATUS_COLOR));
14928
+ if (variant.background.type !== "transparent") {
14929
+ const foreground = tokens.getColor(variant.foregroundToken ?? "text");
14930
+ rules.push(...surfaceForegroundDeclarations({ text: foreground }));
14931
+ }
14416
14932
  if (variant.accentEdge) {
14417
14933
  const side = ACCENT_EDGE_SIDE_MAP$1[variant.accentEdge.edge];
14418
14934
  const width = ACCENT_EDGE_WIDTH_MAP$1[variant.accentEdge.width];
@@ -14450,7 +14966,7 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
14450
14966
  init_resolver$1();
14451
14967
  init_constants$1();
14452
14968
  init_generateDefaultCardSystem();
14453
- init_contextualColors();
14969
+ init_surfaces();
14454
14970
  PER_CORNER_RADIUS_MAP$1 = {
14455
14971
  square: "0",
14456
14972
  soft: "0.5rem",
@@ -14485,7 +15001,9 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
14485
15001
  pill: "1.5rem"
14486
15002
  };
14487
15003
  }));
14488
- var init_core = __esmMin((() => {}));
15004
+ var init_core = __esmMin((() => {
15005
+ init_surfaces();
15006
+ }));
14489
15007
  //#endregion
14490
15008
  //#region ../theme-core/src/cards/index.ts
14491
15009
  var init_cards = __esmMin((() => {
@@ -14778,16 +15296,22 @@ var init_types$8 = __esmMin((() => {
14778
15296
  /**
14779
15297
  * Gradient configuration types and schemas
14780
15298
  */
14781
- var gradientStopSchema, gradientConfigSchema;
15299
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
14782
15300
  var init_types$7 = __esmMin((() => {
14783
15301
  init_themeColorTokens();
14784
15302
  gradientStopSchema = z$1.object({
14785
15303
  color: themeColorTokenSchema,
14786
15304
  position: z$1.number().min(0).max(100)
14787
15305
  });
15306
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
14788
15307
  gradientConfigSchema = z$1.object({
14789
- type: z$1.enum(["linear", "radial"]),
15308
+ type: z$1.enum([
15309
+ "linear",
15310
+ "radial",
15311
+ "conic"
15312
+ ]).default("linear"),
14790
15313
  angle: z$1.number().min(0).max(360).optional(),
15314
+ shape: radialGradientShapeSchema.optional(),
14791
15315
  position: z$1.string().optional(),
14792
15316
  stops: z$1.array(gradientStopSchema).min(2)
14793
15317
  });
@@ -15326,7 +15850,7 @@ var init_tokenOrColor = __esmMin((() => {
15326
15850
  "white",
15327
15851
  "yellow"
15328
15852
  ]);
15329
- })), 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;
15853
+ })), 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;
15330
15854
  var init_schema$1 = __esmMin((() => {
15331
15855
  init_media$1();
15332
15856
  init_buttons();
@@ -15606,6 +16130,7 @@ var init_schema$1 = __esmMin((() => {
15606
16130
  "majorThird",
15607
16131
  "perfectFourth"
15608
16132
  ]);
16133
+ eyebrowTypographyStyleSchema = z$1.object({ family: z$1.string().min(1) });
15609
16134
  typographySchema = z$1.object({
15610
16135
  body: bodyTypographyStyleSchema,
15611
16136
  headings: z$1.object({
@@ -15618,7 +16143,8 @@ var init_schema$1 = __esmMin((() => {
15618
16143
  h6: headingTypographyOverridesSchema.optional()
15619
16144
  }),
15620
16145
  scale: typographyScaleSchema,
15621
- proseLinkStyle: proseLinkStyleSchema.optional()
16146
+ proseLinkStyle: proseLinkStyleSchema.optional(),
16147
+ eyebrow: eyebrowTypographyStyleSchema.optional()
15622
16148
  });
15623
16149
  spaceSchema = z$1.enum([
15624
16150
  "comfortable",
@@ -15643,7 +16169,8 @@ var init_schema$1 = __esmMin((() => {
15643
16169
  "soft",
15644
16170
  "hard"
15645
16171
  ]).nullable(),
15646
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
16172
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
16173
+ colorToken: themeColorTokenSchema.optional()
15647
16174
  });
15648
16175
  border = z$1.object({
15649
16176
  width: z$1.enum([
@@ -15884,6 +16411,7 @@ var init_schema$1 = __esmMin((() => {
15884
16411
  navWeight: navFontWeight.default("medium"),
15885
16412
  navTypography: z$1.enum(["body", "heading"]).optional(),
15886
16413
  navTextSize: navLinkStyleSchema.shape.textSize,
16414
+ navPlacement: z$1.enum(["end", "center"]).optional(),
15887
16415
  container: headerContainerSchema,
15888
16416
  border: headerBorderSchema,
15889
16417
  shadow: componentShadowSchema.optional(),
@@ -16642,7 +17170,8 @@ var init_curatedSiteStyles = __esmMin((() => {
16642
17170
  "site-style:bold-launch",
16643
17171
  "site-style:south-west-twerk-school",
16644
17172
  "site-style:kirtan-ornate",
16645
- "site-style:original-joy"
17173
+ "site-style:original-joy",
17174
+ "site-style:fulcrum"
16646
17175
  ];
16647
17176
  quietBudget = {
16648
17177
  accentDensity: "low",
@@ -17854,6 +18383,104 @@ var init_curatedSiteStyles = __esmMin((() => {
17854
18383
  buttonChoice("showtime-pill")
17855
18384
  ],
17856
18385
  paletteRecommendations: [paletteRecommendation("warm-dark-ember")]
18386
+ }),
18387
+ defineCuratedSiteStyle({
18388
+ id: "site-style:fulcrum",
18389
+ name: "Fulcrum",
18390
+ headingDecoration: {
18391
+ family: "short-center-rule",
18392
+ colorToken: "accent"
18393
+ },
18394
+ 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.",
18395
+ 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.",
18396
+ siteCreatorSelection: {
18397
+ kind: "site_creator_keyword_heuristic",
18398
+ priority: 28
18399
+ },
18400
+ selectionKeywordRules: [
18401
+ {
18402
+ kind: "substring",
18403
+ value: "physiotherap"
18404
+ },
18405
+ {
18406
+ kind: "word",
18407
+ value: "physio"
18408
+ },
18409
+ {
18410
+ kind: "phrase",
18411
+ value: "sports injury"
18412
+ },
18413
+ {
18414
+ kind: "phrase",
18415
+ value: "rehab clinic"
18416
+ },
18417
+ {
18418
+ kind: "substring",
18419
+ value: "musculoskeletal"
18420
+ },
18421
+ {
18422
+ kind: "phrase",
18423
+ value: "sports therapy"
18424
+ }
18425
+ ],
18426
+ tokenRecipes: {
18427
+ palette: "brand-led",
18428
+ contrast: "standard",
18429
+ radius: "rounded",
18430
+ shadow: "subtle",
18431
+ typography: "serif-editorial",
18432
+ spacing: "airy",
18433
+ motion: "subtle"
18434
+ },
18435
+ compositionBudget: quietBudget,
18436
+ typographyPresetChoices: [
18437
+ typographyChoice("typography-preset:fulcrum"),
18438
+ typographyChoice("typography-preset:editorial-serif"),
18439
+ typographyChoice("typography-preset:modern-sans")
18440
+ ],
18441
+ defaultTypographyPresetId: "typography-preset:fulcrum",
18442
+ themeOverrides: {
18443
+ shadow: { colorToken: "primary" },
18444
+ accordions: {
18445
+ background: null,
18446
+ spacing: "comfortable",
18447
+ corners: "square",
18448
+ border: null,
18449
+ shadow: null,
18450
+ icon: {
18451
+ style: "plus-minus",
18452
+ position: "right",
18453
+ size: "md",
18454
+ colorToken: "accent"
18455
+ },
18456
+ trigger: {
18457
+ textColorToken: "primary",
18458
+ fontWeight: "medium",
18459
+ fontFamily: "heading",
18460
+ fontScale: "md"
18461
+ },
18462
+ hover: { textColorToken: "secondary" },
18463
+ content: { textColorToken: "muted" }
18464
+ },
18465
+ testimonialQuote: serifDisplayQuote
18466
+ },
18467
+ recommendedHeaderLookIds: [
18468
+ "classic-centered-nav",
18469
+ "serif-line",
18470
+ "centered-calm",
18471
+ "clean-base"
18472
+ ],
18473
+ recommendedFooterLookIds: ["footer-editorial-columns", "footer-muted-grounding"],
18474
+ buttonPersonalityChoices: [
18475
+ buttonChoice("flat-ink"),
18476
+ buttonChoice("confident-chip"),
18477
+ buttonChoice("editorial-link")
18478
+ ],
18479
+ paletteRecommendations: [
18480
+ paletteRecommendation("brand-led-spruce"),
18481
+ paletteRecommendation("warm-neutral-forest"),
18482
+ paletteRecommendation("soft-natural-sage")
18483
+ ]
17857
18484
  })
17858
18485
  ];
17859
18486
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
@@ -18335,7 +18962,7 @@ var init_themeColorResolution = __esmMin((() => {
18335
18962
  init_tokenOrColor();
18336
18963
  }));
18337
18964
  //#endregion
18338
- //#region ../blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.ts
18965
+ //#region ../blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.ts
18339
18966
  function readColorToken(input, key) {
18340
18967
  const value = input[key];
18341
18968
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
@@ -18344,20 +18971,20 @@ function resolveOptionalForegroundColor(value, context) {
18344
18971
  if (!value) return null;
18345
18972
  return resolveBackgroundColorValue(value, context);
18346
18973
  }
18347
- function resolveSectionForegroundStyles(value, context) {
18974
+ function resolveSurfaceForegroundStyles(value, context) {
18348
18975
  if (!value || typeof value !== "object") return {};
18349
18976
  const input = value;
18350
18977
  const resolvedText = resolveOptionalForegroundColor(readColorToken(input, "textColor"), context);
18351
18978
  if (!resolvedText) return {};
18352
- return {
18353
- color: resolvedText,
18354
- "--section-text-color": resolvedText,
18355
- "--section-heading-color": resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? resolvedText,
18356
- "--section-link-color": resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? resolvedText,
18357
- "--section-supporting-color": resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? resolvedText
18358
- };
18979
+ return { ...surfaceForegroundStyle({
18980
+ text: resolvedText,
18981
+ heading: resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? void 0,
18982
+ link: resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? void 0,
18983
+ supporting: resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? void 0
18984
+ }) };
18359
18985
  }
18360
- var init_sectionForegroundStyles = __esmMin((() => {
18986
+ var init_surfaceForegroundStyles = __esmMin((() => {
18987
+ init_surfaces();
18361
18988
  init_themeColorResolution();
18362
18989
  }));
18363
18990
  //#endregion
@@ -18389,7 +19016,7 @@ function isTileTreatment(value) {
18389
19016
  function isEventListTreatment(value) {
18390
19017
  return typeof value === "string" && eventListTreatmentSet.has(value);
18391
19018
  }
18392
- 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;
19019
+ 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;
18393
19020
  var init_boxStyles$1 = __esmMin((() => {
18394
19021
  init_core$2();
18395
19022
  init_spacing();
@@ -18397,8 +19024,7 @@ var init_boxStyles$1 = __esmMin((() => {
18397
19024
  init_colorStyles();
18398
19025
  init_cards();
18399
19026
  init_blockColorTokens();
18400
- init_themeColorResolution();
18401
- init_sectionForegroundStyles();
19027
+ init_surfaceForegroundStyles();
18402
19028
  spacingTransform = {
18403
19029
  id: "boxStyles.spacing",
18404
19030
  kind: "string",
@@ -18624,45 +19250,11 @@ var init_boxStyles$1 = __esmMin((() => {
18624
19250
  }, context);
18625
19251
  }
18626
19252
  };
18627
- sectionTextColorStyleTransform = {
18628
- id: "sectionStyles.resolveTextColorStyle",
18629
- kind: "formatter",
18630
- summary: "Resolve section text color token into a style object",
18631
- run: (value, options, context) => {
18632
- const fallbackToken = options?.fallbackToken;
18633
- if (typeof value === "string" && value.trim()) {
18634
- const colorValue = resolveBackgroundColorValue(value.trim(), context);
18635
- return {
18636
- color: colorValue,
18637
- "--section-text-color": colorValue
18638
- };
18639
- }
18640
- if (typeof fallbackToken === "string" && fallbackToken.trim()) {
18641
- const colorValue = resolveBackgroundColorValue(fallbackToken.trim(), context);
18642
- return {
18643
- color: colorValue,
18644
- "--section-text-color": colorValue
18645
- };
18646
- }
18647
- return {};
18648
- }
18649
- };
18650
- sectionHeadingColorStyleTransform = {
18651
- id: "sectionStyles.resolveHeadingColorStyle",
18652
- kind: "formatter",
18653
- summary: "Resolve section heading color token into a style object",
18654
- run: (value, options, context) => {
18655
- const fallbackToken = options?.fallbackToken;
18656
- if (typeof value === "string" && value.trim()) return { "--section-heading-color": resolveBackgroundColorValue(value.trim(), context) };
18657
- if (typeof fallbackToken === "string" && fallbackToken.trim()) return { "--section-heading-color": resolveBackgroundColorValue(fallbackToken.trim(), context) };
18658
- return {};
18659
- }
18660
- };
18661
19253
  sectionColorsStyleTransform = {
18662
19254
  id: "sectionStyles.resolveColorsStyle",
18663
19255
  kind: "formatter",
18664
- summary: "Resolve section foreground colors into a style object",
18665
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
19256
+ summary: "Resolve surface foreground colors into a style object",
19257
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
18666
19258
  };
18667
19259
  GAP_CLASS_MAP = {
18668
19260
  none: "rb-gap-semantic-none",
@@ -18710,8 +19302,6 @@ var init_boxStyles$1 = __esmMin((() => {
18710
19302
  sectionClassNameTransform,
18711
19303
  containerStylesResolveClassName,
18712
19304
  containerStylesResolveBoxClassName,
18713
- sectionTextColorStyleTransform,
18714
- sectionHeadingColorStyleTransform,
18715
19305
  sectionColorsStyleTransform,
18716
19306
  semanticGapTransform,
18717
19307
  semanticGapValueTransform
@@ -19340,8 +19930,11 @@ var init_filtering = __esmMin((() => {
19340
19930
  }));
19341
19931
  //#endregion
19342
19932
  //#region ../blocks/src/system/blocks/events/shared/layout.ts
19343
- function eventSectionHeaderLayoutNodes() {
19344
- 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 }))];
19933
+ function eventSectionHeaderLayoutNodes(options = {}) {
19934
+ const headingNode = text({ as: "h2" }, bind("content.heading"), when("content.heading", { authoringPresence: recoverEmptyHeadingWhenActive }));
19935
+ const descriptionNode = richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description", { authoringPresence: recoverEmptyDescriptionWhenActive }));
19936
+ if (options.splitClassName) return [el("div", { className: options.splitClassName }, [headingNode, descriptionNode])];
19937
+ return [headingNode, descriptionNode];
19345
19938
  }
19346
19939
  var recoverEmptyHeadingWhenActive, recoverEmptyDescriptionWhenActive;
19347
19940
  var init_layout = __esmMin((() => {
@@ -19424,6 +20017,9 @@ var init_validation_constants = __esmMin((() => {
19424
20017
  "richText",
19425
20018
  "media",
19426
20019
  "videoEmbed",
20020
+ "icon",
20021
+ "feature-card-icon",
20022
+ "svg",
19427
20023
  "button",
19428
20024
  "link",
19429
20025
  "carousel",
@@ -19453,11 +20049,13 @@ var init_validation_constants = __esmMin((() => {
19453
20049
  "value.jsonArray",
19454
20050
  "value.csv",
19455
20051
  "array.marqueeLoop",
20052
+ "value.mapToken",
19456
20053
  "layout.maxWidthClass",
19457
20054
  "layout.headerRootClass",
19458
20055
  "layout.footerRootClass",
19459
20056
  "layout.headerRootStyle",
19460
20057
  "layout.headerSectionBackground",
20058
+ "layout.classicNavMode",
19461
20059
  "layout.footerRootStyle",
19462
20060
  "ui.headerNavLinkClass",
19463
20061
  "ui.headingClassFromAlignment",
@@ -20634,7 +21232,29 @@ var init_ctaRow = __esmMin((() => {
20634
21232
  fields: [createCtasRepeater({
20635
21233
  label: "Calls to action",
20636
21234
  itemLabel: "CTA",
20637
- maxItems: 3
21235
+ maxItems: 3,
21236
+ button: { variants: [
21237
+ {
21238
+ value: "primary",
21239
+ label: "Primary"
21240
+ },
21241
+ {
21242
+ value: "secondary",
21243
+ label: "Secondary"
21244
+ },
21245
+ {
21246
+ value: "outline",
21247
+ label: "Outline"
21248
+ },
21249
+ {
21250
+ value: "link",
21251
+ label: "Link"
21252
+ },
21253
+ {
21254
+ value: "accent",
21255
+ label: "Accent"
21256
+ }
21257
+ ] }
20638
21258
  })],
20639
21259
  layout: [ctaRow({
20640
21260
  collectionPath: "content.ctas",
@@ -20937,6 +21557,55 @@ function buildHighlightLayout() {
20937
21557
  function buildGridCardsLayout(className) {
20938
21558
  return el("div", { className }, buildResponsiveGridCards());
20939
21559
  }
21560
+ /**
21561
+ * Build a single "featured editorial" testimonial card.
21562
+ *
21563
+ * This card type deliberately renders NO avatar/headshot: an amber quote mark,
21564
+ * the quote body, then the author name and a context line. Colour + surface
21565
+ * treatment is driven entirely by `variantClass` (see testimonials.css):
21566
+ * - `rb-testimonials-fe-card--feature` → spruce-ink card (dark primary bg)
21567
+ * - `rb-testimonials-fe-card--plain` → white surface card
21568
+ *
21569
+ * Extra modifiers (`repeat`, `when`) are forwarded to the card node so the
21570
+ * caller can drive first-vs-rest branching.
21571
+ */
21572
+ function buildFeaturedEditorialCard(variantClass, ...mods) {
21573
+ const quoteMark = text({
21574
+ as: "span",
21575
+ className: "rb-testimonials-fe-qmark",
21576
+ "aria-hidden": "true"
21577
+ }, props({ value: "“" }));
21578
+ const quote = richText({ className: "rb-testimonials-fe-quote rb-max-w-none" }, bind("testimonial.content.body"), when("testimonial.content.body"));
21579
+ const meta = el("div", { className: "rb-testimonials-fe-meta" }, [text({
21580
+ as: "strong",
21581
+ className: "rb-testimonials-fe-name"
21582
+ }, bind("testimonial.content.name", { fallback: "Anonymous" })), text({
21583
+ as: "span",
21584
+ className: "rb-testimonials-fe-context"
21585
+ }, when("testimonial.content.jobTitle"), bind("testimonial.content.jobTitle"))]);
21586
+ return el("div", { className: `rb-testimonials-fe-card ${variantClass}` }, [
21587
+ quoteMark,
21588
+ quote,
21589
+ meta
21590
+ ], ...mods);
21591
+ }
21592
+ /**
21593
+ * Build the "featured editorial" layout: an asymmetric two-column arrangement
21594
+ * where the FIRST testimonial is a large featured (spruce-ink) card and the
21595
+ * remaining testimonials stack as white cards beside it.
21596
+ *
21597
+ * First-vs-rest branching is done without an offset primitive: the featured
21598
+ * card uses `repeat(..., { limit: 1 })` (entry 0 only), and the rest column
21599
+ * repeats over every entry but skips index 0 via `when("tIndex", { equals: 0,
21600
+ * not: true })`. The `$when` guard is re-evaluated per repeated item with the
21601
+ * index scope in context, so entry 0 produces no node in the rest column.
21602
+ */
21603
+ function buildFeaturedEditorialLayout() {
21604
+ 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", {
21605
+ equals: 0,
21606
+ not: true
21607
+ }))])]);
21608
+ }
20940
21609
  var grid$4, testimonialsCarouselFragment;
20941
21610
  var init_testimonialsCarousel = __esmMin((() => {
20942
21611
  init_types$4();
@@ -25085,7 +25754,8 @@ var init_events$1 = __esmMin((() => {
25085
25754
  "combined",
25086
25755
  "calendar",
25087
25756
  "list",
25088
- "timetable"
25757
+ "timetable",
25758
+ "week-board"
25089
25759
  ];
25090
25760
  eventCalendarDefaultViewValues = ["month", "week"];
25091
25761
  eventCalendarListLayoutValues = [
@@ -25873,6 +26543,40 @@ function getEventAvailability(event) {
25873
26543
  isFull: false
25874
26544
  };
25875
26545
  }
26546
+ /**
26547
+ * Derive the three-state availability status (available / filling / waitlist)
26548
+ * plus a short pill label. Builds on {@link getEventAvailability} so the
26549
+ * capacity math (availableSpots with a `capacity - registeredCount` fallback)
26550
+ * stays consistent with the binary helper used elsewhere.
26551
+ */
26552
+ function getEventAvailabilityStatus(event, options) {
26553
+ const threshold = options?.fillingThreshold ?? 2;
26554
+ const { available, isFull } = getEventAvailability(event);
26555
+ if (available == null) return {
26556
+ status: "available",
26557
+ available: null,
26558
+ isFull: false,
26559
+ label: null
26560
+ };
26561
+ if (isFull) return {
26562
+ status: "waitlist",
26563
+ available: 0,
26564
+ isFull: true,
26565
+ label: event.waitlistEnabled ? "Waitlist" : "Full"
26566
+ };
26567
+ if (available <= threshold) return {
26568
+ status: "filling",
26569
+ available,
26570
+ isFull: false,
26571
+ label: `${available} left`
26572
+ };
26573
+ return {
26574
+ status: "available",
26575
+ available,
26576
+ isFull: false,
26577
+ label: `${available} places`
26578
+ };
26579
+ }
25876
26580
  var init_eventCapacity = __esmMin((() => {}));
25877
26581
  //#endregion
25878
26582
  //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
@@ -101179,7 +101883,7 @@ var init_event_registration_client = __esmMin((() => {
101179
101883
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
101180
101884
  */
101181
101885
  function isLeafletApi(value) {
101182
- if (!isRecord$32(value)) return false;
101886
+ if (!isRecord$34(value)) return false;
101183
101887
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
101184
101888
  }
101185
101889
  function loadLeaflet() {
@@ -103754,6 +104458,153 @@ var init_EventCombined_client = __esmMin((() => {
103754
104458
  EventCombinedIslandClient = (props) => /* @__PURE__ */ jsx(EventCombinedClient, { ...toEventCombinedControllerProps(props) });
103755
104459
  }));
103756
104460
  //#endregion
104461
+ //#region ../blocks/src/system/runtime/nodes/events/shared/WeekBoardView.tsx
104462
+ /**
104463
+ * Format an event's start–end as a compact range, merging the shared meridiem.
104464
+ * "6:00 PM" + "7:00 PM" -> "6:00 – 7:00 PM"; "9:30 AM" + "10:15 AM" -> "9:30 – 10:15 AM".
104465
+ */
104466
+ function formatCompactTimeRange(event) {
104467
+ const timeZone = event.timeZone ?? null;
104468
+ const start = formatTime$3(event.startsAt, { timeZone });
104469
+ const end = formatTime$3(event.endsAt, { timeZone });
104470
+ const startMeridiem = start.slice(-2);
104471
+ const endMeridiem = end.slice(-2);
104472
+ if ((startMeridiem === "AM" || startMeridiem === "PM") && startMeridiem === endMeridiem) return `${start.slice(0, -3).trim()} – ${end}`;
104473
+ return `${start} – ${end}`;
104474
+ }
104475
+ var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardView;
104476
+ var init_WeekBoardView = __esmMin((() => {
104477
+ init_clsx();
104478
+ init_buttons();
104479
+ init_eventCapacity();
104480
+ init_utils$3();
104481
+ SHORT_DAY_NAMES = [
104482
+ "Sun",
104483
+ "Mon",
104484
+ "Tue",
104485
+ "Wed",
104486
+ "Thu",
104487
+ "Fri",
104488
+ "Sat"
104489
+ ];
104490
+ LEGEND_ITEMS = [
104491
+ {
104492
+ status: "available",
104493
+ label: "Places available"
104494
+ },
104495
+ {
104496
+ status: "filling",
104497
+ label: "Filling up"
104498
+ },
104499
+ {
104500
+ status: "waitlist",
104501
+ label: "Waitlist"
104502
+ }
104503
+ ];
104504
+ WeekBoardCard = ({ event, showCapacity }) => {
104505
+ const linkProps = resolveEventLinkProps(event);
104506
+ const { status, label } = getEventAvailabilityStatus(event);
104507
+ const pill = showCapacity ? label : null;
104508
+ return /* @__PURE__ */ jsxs("a", {
104509
+ ...linkProps,
104510
+ className: "event-week-board-card",
104511
+ "data-status": status,
104512
+ children: [
104513
+ /* @__PURE__ */ jsx("span", {
104514
+ className: "event-week-board-card-title",
104515
+ children: event.title
104516
+ }),
104517
+ /* @__PURE__ */ jsx("span", {
104518
+ className: "event-week-board-card-time",
104519
+ children: formatCompactTimeRange(event)
104520
+ }),
104521
+ pill ? /* @__PURE__ */ jsx("span", {
104522
+ className: "event-week-board-card-pill",
104523
+ "data-status": status,
104524
+ children: pill
104525
+ }) : null
104526
+ ]
104527
+ });
104528
+ };
104529
+ 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" }) => {
104530
+ const eventsByDate = groupEventsByDate(events);
104531
+ const hasAnyEvents = days.some((date) => (eventsByDate.get(formatDateKey(date)) ?? []).length > 0);
104532
+ const ctaClassName = themeButtonClassName({
104533
+ variant: buttonVariant,
104534
+ size: "sm"
104535
+ });
104536
+ return /* @__PURE__ */ jsx("div", {
104537
+ className: "event-calendar event-calendar--week-board",
104538
+ "data-block": "event-calendar",
104539
+ children: /* @__PURE__ */ jsxs("div", {
104540
+ className: "event-week-board",
104541
+ style: { "--event-week-board-cols": String(days.length) },
104542
+ children: [
104543
+ /* @__PURE__ */ jsxs("div", {
104544
+ className: "event-week-board-top",
104545
+ children: [/* @__PURE__ */ jsx("span", {
104546
+ className: "event-week-board-title",
104547
+ children: title
104548
+ }), /* @__PURE__ */ jsx("div", {
104549
+ className: "event-week-board-legend",
104550
+ "aria-hidden": "true",
104551
+ children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
104552
+ className: "event-week-board-legend-item",
104553
+ children: [/* @__PURE__ */ jsx("i", {
104554
+ className: "event-week-board-legend-dot",
104555
+ "data-status": item.status
104556
+ }), item.label]
104557
+ }, item.status))
104558
+ })]
104559
+ }),
104560
+ /* @__PURE__ */ jsx("div", {
104561
+ className: "event-week-board-grid",
104562
+ children: days.map((date) => {
104563
+ const dateKey = formatDateKey(date);
104564
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
104565
+ const today = isToday(date);
104566
+ return /* @__PURE__ */ jsxs("div", {
104567
+ className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
104568
+ children: [/* @__PURE__ */ jsxs("div", {
104569
+ className: "event-week-board-day-head",
104570
+ children: [/* @__PURE__ */ jsx("span", {
104571
+ className: "event-week-board-day-abbr",
104572
+ children: SHORT_DAY_NAMES[date.getDay()]
104573
+ }), /* @__PURE__ */ jsx("span", {
104574
+ className: "event-week-board-day-num",
104575
+ children: date.getDate()
104576
+ })]
104577
+ }), /* @__PURE__ */ jsx("div", {
104578
+ className: "event-week-board-day-body",
104579
+ children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
104580
+ event,
104581
+ showCapacity
104582
+ }, event.occurrenceId || event.id))
104583
+ })]
104584
+ }, dateKey);
104585
+ })
104586
+ }),
104587
+ /* @__PURE__ */ jsxs("div", {
104588
+ className: "event-week-board-foot",
104589
+ children: [/* @__PURE__ */ jsx("p", {
104590
+ className: "event-week-board-foot-note",
104591
+ children: hasAnyEvents ? footerNote : emptyMessage
104592
+ }), ctaHref ? /* @__PURE__ */ jsx("a", {
104593
+ className: ctaClassName,
104594
+ href: ctaHref,
104595
+ children: ctaLabel
104596
+ }) : /* @__PURE__ */ jsx("button", {
104597
+ type: "button",
104598
+ className: ctaClassName,
104599
+ children: ctaLabel
104600
+ })]
104601
+ })
104602
+ ]
104603
+ })
104604
+ });
104605
+ };
104606
+ }));
104607
+ //#endregion
103757
104608
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
103758
104609
  function buildTimetableModel(input) {
103759
104610
  const generic = buildTimetableModel$1({
@@ -104054,7 +104905,7 @@ function buildDisplayFilterParams(display) {
104054
104905
  filterVenueId: display.filterVenueId
104055
104906
  });
104056
104907
  }
104057
- var EventCalendarClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
104908
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
104058
104909
  var init_EventCalendar_client = __esmMin((() => {
104059
104910
  init_EventCalendar_interactive();
104060
104911
  init_EventListing_client();
@@ -104067,6 +104918,7 @@ var init_EventCalendar_client = __esmMin((() => {
104067
104918
  init_EventModalContext();
104068
104919
  init_EventModals();
104069
104920
  init_WeekAgendaView();
104921
+ init_WeekBoardView();
104070
104922
  init_WeekTimetableView();
104071
104923
  init_buttons();
104072
104924
  init_listOptions();
@@ -104104,8 +104956,20 @@ var init_EventCalendar_client = __esmMin((() => {
104104
104956
  });
104105
104957
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
104106
104958
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
104959
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
104107
104960
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
104108
104961
  };
104962
+ EventCalendarWeekBoardClient = ({ display }) => {
104963
+ const days = useMemo(() => getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek), [display.startOfWeek]);
104964
+ return /* @__PURE__ */ jsx(WeekBoardView, {
104965
+ days,
104966
+ events: [...display.events],
104967
+ showCapacity: display.showCapacity,
104968
+ emptyMessage: display.emptyMessage,
104969
+ ctaLabel: display.buttonText,
104970
+ buttonVariant: display.buttonVariant
104971
+ });
104972
+ };
104109
104973
  EventCalendarTimetableClient = ({ render }) => {
104110
104974
  const { display, hydration } = render;
104111
104975
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
@@ -106816,7 +107680,7 @@ var init_RichText = __esmMin((() => {
106816
107680
  function coerceRichTextDoc(value) {
106817
107681
  const raw = unwrapRichTextRoot(value);
106818
107682
  if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
106819
- if (isRecord$32(raw) && typeof raw.type === "string") return raw;
107683
+ if (isRecord$34(raw) && typeof raw.type === "string") return raw;
106820
107684
  return null;
106821
107685
  }
106822
107686
  var init_richText_coerce = __esmMin((() => {
@@ -112524,7 +113388,7 @@ const defaultLayout = styledSection({
112524
113388
  children: styledContainer({
112525
113389
  baseClassName: "rb-relative rb-isolate",
112526
113390
  children: stack({
112527
- gap: "xl",
113391
+ gap: "lg",
112528
113392
  className: "rb-w-full rb-max-w-4xl rb-mx-auto"
112529
113393
  }, [headingLayout, accordionLayout])
112530
113394
  }),
@@ -112541,7 +113405,7 @@ const questionColumnsLayout = styledSection({
112541
113405
  children: styledContainer({
112542
113406
  baseClassName: "rb-relative rb-isolate",
112543
113407
  children: stack({
112544
- gap: "xl",
113408
+ gap: "lg",
112545
113409
  className: "rb-w-full"
112546
113410
  }, [headingLayout, questionColumnsAccordionLayout])
112547
113411
  }),
@@ -112706,7 +113570,26 @@ const formattingTransforms = [
112706
113570
  arrayLengthTransform,
112707
113571
  jsonArrayTransform,
112708
113572
  csvTransform,
112709
- marqueeLoopTransform
113573
+ marqueeLoopTransform,
113574
+ {
113575
+ id: "value.mapToken",
113576
+ kind: "formatter",
113577
+ summary: "Map a state/enum value to a theme token colour (rgb(var(--tb-<role>)))",
113578
+ schema: z$1.object({
113579
+ /**
113580
+ * Maps an input state/enum value (stringified) to a theme token ROLE name
113581
+ * (e.g. `secondary`, `accent`, `muted`, `border`). The role is wrapped to
113582
+ * `rgb(var(--tb-<role>))` so the result drops straight into a `style` binding.
113583
+ */
113584
+ cases: z$1.record(z$1.string(), z$1.string()),
113585
+ /** Role used when the value matches no case. Omit to yield `undefined`. */
113586
+ fallback: z$1.string().optional()
113587
+ }),
113588
+ run: (value, options) => {
113589
+ const role = options.cases[String(value)] ?? options.fallback;
113590
+ return role ? `rgb(var(--tb-${role}))` : void 0;
113591
+ }
113592
+ }
112710
113593
  ];
112711
113594
  //#endregion
112712
113595
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -113290,6 +114173,7 @@ function splitSiteChromePlacementClasses(className) {
113290
114173
  init_colorConversion();
113291
114174
  init_core$2();
113292
114175
  init_colorStyles();
114176
+ init_surfaces();
113293
114177
  const joinClasses$1 = (parts) => parts.filter((part) => typeof part === "string" && part.trim().length > 0).join(" ").replace(/\s+/g, " ").trim();
113294
114178
  function resolveHeaderBrandDisplay(logo) {
113295
114179
  const display = logo?.brandDisplay ?? "logo-plus-title";
@@ -113359,6 +114243,26 @@ const headerLogoTextVisibleTransform = {
113359
114243
  return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
113360
114244
  }
113361
114245
  };
114246
+ /**
114247
+ * Selects which classic-layout nav row should render.
114248
+ *
114249
+ * - `'inline'` → classic variant with the historical logo-left / nav-right row
114250
+ * - `'centered'`→ classic variant with a centred (flex-1) nav and a right CTA
114251
+ * - `'other'` → not a classic variant (centered/floating/transparent handle it)
114252
+ *
114253
+ * Consumed by the site-header block's `$when` gates so the two classic rows are
114254
+ * mutually exclusive without introducing a new top-level header variant.
114255
+ */
114256
+ const classicNavModeTransform = {
114257
+ id: "layout.classicNavMode",
114258
+ kind: "formatter",
114259
+ summary: "Resolve which classic-layout nav row to render",
114260
+ run: (value) => {
114261
+ const header = asPartialObject(value);
114262
+ if (header?.variant !== "classic") return "other";
114263
+ return header?.navPlacement === "center" ? "centered" : "inline";
114264
+ }
114265
+ };
113362
114266
  const maxWidthClassTransform = {
113363
114267
  id: "layout.maxWidthClass",
113364
114268
  kind: "string",
@@ -113541,8 +114445,9 @@ const footerRootStyleTransform = {
113541
114445
  styleParts.push(backgroundColorStyle(token));
113542
114446
  }
113543
114447
  }
113544
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
113545
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
114448
+ const foreground = visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
114449
+ if (!visuals.isTransparent && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
114450
+ else if (foreground) styleParts.push({ color: foreground });
113546
114451
  styleParts.push(borderColorStyle("border"));
113547
114452
  return mergeStyles(...styleParts);
113548
114453
  }
@@ -113628,18 +114533,16 @@ const footerBottomBarStyleTransform = {
113628
114533
  const styleParts = [];
113629
114534
  const background = bottomBar?.background;
113630
114535
  if (background?.type === "color") styleParts.push(backgroundColorStyle(background.color ?? "surface"));
113631
- if (bottomBar?.textColor) styleParts.push(textColorStyle(bottomBar.textColor));
113632
114536
  const borderColorToken = bottomBar?.borderTop?.colorToken;
113633
114537
  if (borderColorToken) styleParts.push(borderColorStyle(borderColorToken));
113634
114538
  else styleParts.push(borderColorStyle("border"));
113635
114539
  const borderWidth = bottomBar?.borderTop?.width;
113636
114540
  if (borderWidth && borderWidth !== "none") styleParts.push({ borderTopWidth: borderWidth === "thin" ? "1px" : borderWidth === "medium" ? "2px" : "3px" });
113637
114541
  else if (borderWidth === "none") styleParts.push({ borderTopWidth: "0px" });
113638
- if (!bottomBar?.textColor) {
113639
- const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
113640
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
113641
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
113642
- }
114542
+ const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
114543
+ const foreground = bottomBar?.textColor ? rgbColorValue(bottomBar.textColor) : visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
114544
+ if (background?.type === "color" && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
114545
+ else if (foreground && bottomBar?.textColor) styleParts.push({ color: foreground });
113643
114546
  return mergeStyles(...styleParts);
113644
114547
  }
113645
114548
  };
@@ -113774,6 +114677,7 @@ const layoutTransforms = [
113774
114677
  headerLogoClassTransform,
113775
114678
  headerLogoMediaClassTransform,
113776
114679
  headerLogoTextVisibleTransform,
114680
+ classicNavModeTransform,
113777
114681
  footerRootClassTransform,
113778
114682
  headerRootStyleTransform,
113779
114683
  headerSectionBackgroundTransform,
@@ -113853,16 +114757,16 @@ const interpolateRichTextTokensOptionsSchema = z$1.object({ tokens: z$1.array(su
113853
114757
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
113854
114758
  function getSiteName(context) {
113855
114759
  const viewModel = context.viewModel;
113856
- if (!isRecord$32(viewModel)) return null;
114760
+ if (!isRecord$34(viewModel)) return null;
113857
114761
  const site = viewModel.site;
113858
- if (isRecord$32(site) && typeof site.title === "string") {
114762
+ if (isRecord$34(site) && typeof site.title === "string") {
113859
114763
  const title = site.title.trim();
113860
114764
  return title.length > 0 ? title : null;
113861
114765
  }
113862
114766
  const root = viewModel.$root;
113863
- if (isRecord$32(root)) {
114767
+ if (isRecord$34(root)) {
113864
114768
  const rootSite = root.site;
113865
- if (isRecord$32(rootSite) && typeof rootSite.title === "string") {
114769
+ if (isRecord$34(rootSite) && typeof rootSite.title === "string") {
113866
114770
  const title = rootSite.title.trim();
113867
114771
  if (title.length > 0) return title;
113868
114772
  }
@@ -113884,7 +114788,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
113884
114788
  });
113885
114789
  }
113886
114790
  function visitRichTextNode(node, allowedTokens, tokenValues) {
113887
- if (!isRecord$32(node)) return node;
114791
+ if (!isRecord$34(node)) return node;
113888
114792
  let changed = false;
113889
114793
  const nextNode = { ...node };
113890
114794
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -113905,13 +114809,13 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
113905
114809
  return changed ? nextNode : node;
113906
114810
  }
113907
114811
  function interpolateRichTextTokens(value, options, context) {
113908
- if (!isRecord$32(value)) return value;
114812
+ if (!isRecord$34(value)) return value;
113909
114813
  const allowedTokens = new Set(options.tokens);
113910
114814
  const tokenValues = {
113911
114815
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
113912
114816
  site_name: getSiteName(context)
113913
114817
  };
113914
- if (isRecord$32(value.doc)) {
114818
+ if (isRecord$34(value.doc)) {
113915
114819
  const nextDoc = visitRichTextNode(value.doc, allowedTokens, tokenValues);
113916
114820
  if (nextDoc === value.doc) return value;
113917
114821
  return {
@@ -114191,7 +115095,18 @@ const classicLayout = inline({
114191
115095
  logoRow,
114192
115096
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
114193
115097
  headerCta
114194
- ], when("$root.theme.header.variant", { equals: "classic" }));
115098
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "inline"));
115099
+ const classicCenteredNavLayout = inline({
115100
+ className: bindProp("$root.theme.header.maxWidth", {
115101
+ transforms: pipe(tx("layout.maxWidthClass", { base: `rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6` })),
115102
+ fallback: `rb-container rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6`
115103
+ }),
115104
+ align: "center"
115105
+ }, [
115106
+ logoRow,
115107
+ createNavRow(`rb-flex-1 rb-justify-center ${desktopOnlyDisplay("flex")} rb-gap-6`, "center"),
115108
+ headerCta
115109
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "centered"));
114195
115110
  const centeredLayout = stack({
114196
115111
  gap: "md",
114197
115112
  align: "center",
@@ -114266,6 +115181,7 @@ const siteHeaderManifest = createBlockManifest({
114266
115181
  }, [
114267
115182
  mobileHeaderBar,
114268
115183
  classicLayout,
115184
+ classicCenteredNavLayout,
114269
115185
  centeredLayout,
114270
115186
  transparentLayout,
114271
115187
  floatingLayout,
@@ -114314,6 +115230,7 @@ init_builder$2();
114314
115230
  init_fragments();
114315
115231
  init_defineBlock();
114316
115232
  init_colorStyles();
115233
+ init_surfaces();
114317
115234
  const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
114318
115235
  const whenTransformed = (from, transformId, equals = true) => (node) => ({
114319
115236
  ...node,
@@ -114483,7 +115400,7 @@ const footerLayout = section$1({
114483
115400
  style: { $bind: {
114484
115401
  from: "$root.theme.footer",
114485
115402
  transforms: [{ id: "layout.footerRootStyle" }],
114486
- fallback: mergeStyles(backgroundColorStyle("surface"), textColorStyle("text"), borderColorStyle("border"))
115403
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
114487
115404
  } }
114488
115405
  }, [
114489
115406
  simpleFooterLayout,
@@ -114546,7 +115463,7 @@ const backgroundImageClassName = "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full r
114546
115463
  */
114547
115464
  const wrapVariant$2 = (variantLayout) => styledSection({
114548
115465
  children: styledContainer({ children: stack({
114549
- gap: "xl",
115466
+ gap: "lg",
114550
115467
  className: "rb-relative"
114551
115468
  }, [...testimonialsHeadingFragment.layout, variantLayout]) }),
114552
115469
  baseClass: "",
@@ -114572,6 +115489,27 @@ const splitGridLayout = styledSection({
114572
115489
  spacing: "comfortable",
114573
115490
  imageClassName: backgroundImageClassName
114574
115491
  });
115492
+ const featuredEditorialHead = el("div", { className: "rb-testimonials-fe-head" }, [text({
115493
+ as: "h2",
115494
+ className: "rb-text-left",
115495
+ headingDecoration: "off"
115496
+ }, when("content.heading"), bind("content.heading")), el("div", { className: "rb-testimonials-fe-leadin" }, [text({
115497
+ as: "p",
115498
+ className: "rb-prose",
115499
+ style: textColorStyle("mutedText")
115500
+ }, when("content.subheading"), bind("content.subheading"))])]);
115501
+ const featuredEditorialLayout = styledSection({
115502
+ children: styledContainer({
115503
+ baseClassName: "rb-relative rb-isolate",
115504
+ children: stack({
115505
+ gap: "lg",
115506
+ className: "rb-relative"
115507
+ }, [featuredEditorialHead, buildFeaturedEditorialLayout()])
115508
+ }),
115509
+ baseClass: "",
115510
+ spacing: "comfortable",
115511
+ imageClassName: backgroundImageClassName
115512
+ });
114575
115513
  const additionalFields = parseFieldDefinitions([
114576
115514
  ...testimonialsHeadingFragment.fields,
114577
115515
  {
@@ -114659,6 +115597,7 @@ const testimonialsBlockDefinition = {
114659
115597
  carousel: carouselLayout$1,
114660
115598
  grid: gridLayout$1,
114661
115599
  "split-grid": splitGridLayout,
115600
+ "featured-editorial": featuredEditorialLayout,
114662
115601
  highlight: highlightLayout
114663
115602
  },
114664
115603
  defaultVariant: "carousel",
@@ -114678,6 +115617,11 @@ const testimonialsBlockDefinition = {
114678
115617
  description: "Heading on the left with testimonial cards on the right",
114679
115618
  icon: "PanelLeft"
114680
115619
  },
115620
+ "featured-editorial": {
115621
+ label: "Featured editorial",
115622
+ description: "A large featured ink quote beside a column of stacked cards (no avatars)",
115623
+ icon: "Quote"
115624
+ },
114681
115625
  highlight: {
114682
115626
  label: "Highlight",
114683
115627
  description: "A single, centered testimonial with no carousel",
@@ -115221,7 +116165,7 @@ function grid$2(props, children) {
115221
116165
  const cardsLayout = styledSection({
115222
116166
  children: styledContainer({
115223
116167
  rootType: "stack",
115224
- rootProps: { gap: "xl" },
116168
+ rootProps: { gap: "lg" },
115225
116169
  children: [stack({
115226
116170
  gap: "sm",
115227
116171
  className: "rb-feature-cards-heading rb-mx-auto rb-max-w-3xl rb-text-center"
@@ -117575,7 +118519,7 @@ const eventCalendarLayout = [styledSection({
117575
118519
  children: styledContainer({
117576
118520
  rootType: "stack",
117577
118521
  rootProps: { gap: "lg" },
117578
- children: [...eventSectionHeaderLayoutNodes(), el("event-calendar", withApiBindings({
118522
+ children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
117579
118523
  events: { $bind: { from: "data.events" } },
117580
118524
  stage: { $bind: {
117581
118525
  from: "$root.previewStage",
@@ -117686,6 +118630,10 @@ const eventCalendarAdditionalFields = [
117686
118630
  value: "timetable",
117687
118631
  label: "Timetable"
117688
118632
  },
118633
+ {
118634
+ value: "week-board",
118635
+ label: "Week board"
118636
+ },
117689
118637
  {
117690
118638
  value: "list",
117691
118639
  label: "List"
@@ -117868,7 +118816,8 @@ const eventCalendarAdditionalFields = [
117868
118816
  oneOf: [
117869
118817
  "combined",
117870
118818
  "calendar",
117871
- "timetable"
118819
+ "timetable",
118820
+ "week-board"
117872
118821
  ]
117873
118822
  }
117874
118823
  }
@@ -117971,7 +118920,8 @@ const eventCalendarAdditionalFields = [
117971
118920
  "combined",
117972
118921
  "calendar",
117973
118922
  "list",
117974
- "timetable"
118923
+ "timetable",
118924
+ "week-board"
117975
118925
  ]
117976
118926
  }
117977
118927
  }
@@ -118006,7 +118956,8 @@ const eventCalendarAdditionalFields = [
118006
118956
  "combined",
118007
118957
  "calendar",
118008
118958
  "list",
118009
- "timetable"
118959
+ "timetable",
118960
+ "week-board"
118010
118961
  ]
118011
118962
  }, {
118012
118963
  field: "showFilters",
@@ -118029,7 +118980,8 @@ const eventCalendarAdditionalFields = [
118029
118980
  "combined",
118030
118981
  "calendar",
118031
118982
  "list",
118032
- "timetable"
118983
+ "timetable",
118984
+ "week-board"
118033
118985
  ]
118034
118986
  }, {
118035
118987
  field: "showFilters",
@@ -118052,7 +119004,8 @@ const eventCalendarAdditionalFields = [
118052
119004
  "combined",
118053
119005
  "calendar",
118054
119006
  "list",
118055
- "timetable"
119007
+ "timetable",
119008
+ "week-board"
118056
119009
  ]
118057
119010
  }, {
118058
119011
  field: "showFilters",
@@ -118074,7 +119027,8 @@ const eventCalendarAdditionalFields = [
118074
119027
  oneOf: [
118075
119028
  "combined",
118076
119029
  "list",
118077
- "timetable"
119030
+ "timetable",
119031
+ "week-board"
118078
119032
  ]
118079
119033
  }, { allOf: [{
118080
119034
  field: "variant",
@@ -118250,6 +119204,7 @@ const eventCalendarVariants = {
118250
119204
  combined: eventCalendarLayout[0],
118251
119205
  calendar: eventCalendarLayout[0],
118252
119206
  timetable: eventCalendarLayout[0],
119207
+ "week-board": eventCalendarLayout[0],
118253
119208
  list: eventCalendarLayout[0]
118254
119209
  };
118255
119210
  const eventCalendarContentShape = {
@@ -118263,6 +119218,7 @@ const eventCalendarContentShape = {
118263
119218
  { value: "combined" },
118264
119219
  { value: "calendar" },
118265
119220
  { value: "timetable" },
119221
+ { value: "week-board" },
118266
119222
  { value: "list" }
118267
119223
  ]
118268
119224
  },
@@ -118329,6 +119285,7 @@ const eventCalendarBlockDefinition = {
118329
119285
  combined: { label: "Combined" },
118330
119286
  calendar: { label: "Calendar" },
118331
119287
  timetable: { label: "Timetable" },
119288
+ "week-board": { label: "Week board" },
118332
119289
  list: { label: "List" }
118333
119290
  }
118334
119291
  }, eventCalendarContentShape),
@@ -122694,6 +123651,12 @@ const systemBlockDefinitions = [
122694
123651
  family: "centered",
122695
123652
  weight: "featured",
122696
123653
  bias: "soft"
123654
+ }),
123655
+ layoutProfile({
123656
+ variantKey: "featured-editorial",
123657
+ family: "split",
123658
+ weight: "featured",
123659
+ bias: "soft"
122697
123660
  })
122698
123661
  ]
122699
123662
  })),
@@ -122826,6 +123789,11 @@ const systemBlockDefinitions = [
122826
123789
  variantKey: "timetable",
122827
123790
  family: "stack",
122828
123791
  weight: "standard"
123792
+ }),
123793
+ layoutProfile({
123794
+ variantKey: "week-board",
123795
+ family: "stack",
123796
+ weight: "standard"
122829
123797
  })
122830
123798
  ]
122831
123799
  })),
@@ -123186,7 +124154,15 @@ function gradientToCss(config, tokens) {
123186
124154
  const stops = config.stops.map((stop) => {
123187
124155
  return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
123188
124156
  }).join(", ");
123189
- if (config.type === "radial") return `radial-gradient(circle at ${config.position ?? "center"}, ${stops})`;
124157
+ const type = config.type ?? "linear";
124158
+ if (type === "radial") {
124159
+ const position = config.position ?? "center";
124160
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
124161
+ }
124162
+ if (type === "conic") {
124163
+ const position = config.position ?? "center";
124164
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
124165
+ }
123190
124166
  return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
123191
124167
  }
123192
124168
  //#endregion
@@ -123215,7 +124191,7 @@ function backgroundVideoMobileClassNames(input) {
123215
124191
  //#region ../blocks/src/system/transforms/registry/background.ts
123216
124192
  init_background$1();
123217
124193
  init_themeColorResolution();
123218
- init_sectionForegroundStyles();
124194
+ init_surfaceForegroundStyles();
123219
124195
  init_media();
123220
124196
  const isString$1 = (value) => typeof value === "string" && value.trim().length > 0;
123221
124197
  const isNumber$1 = (value) => typeof value === "number" && !isNaN(value);
@@ -123272,8 +124248,8 @@ const backgroundTransforms = [
123272
124248
  {
123273
124249
  id: "background.resolveColorsStyle",
123274
124250
  kind: "formatter",
123275
- summary: "Resolve section foreground colors from a background object into scoped CSS vars",
123276
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
124251
+ summary: "Resolve surface foreground colors from a background object into scoped CSS vars",
124252
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
123277
124253
  },
123278
124254
  {
123279
124255
  id: "background.resolveAllowOverflow",
@@ -123909,21 +124885,53 @@ function Inline({ as: Comp = "div", gap = "md", align = "center", justify = "sta
123909
124885
  //#endregion
123910
124886
  //#region ../blocks/src/primitives/layout/Grid.tsx
123911
124887
  init_clsx();
124888
+ /** Utility class for a numeric column COUNT at a given breakpoint. */
124889
+ const COL_COUNT_CLASS = {
124890
+ base: (n) => `rb-grid-cols-${n}`,
124891
+ sm: (n) => `rb-sm-grid-cols-${n}`,
124892
+ md: (n) => `rb-md-grid-cols-${n}`,
124893
+ lg: (n) => `rb-lg-grid-cols-${n}`,
124894
+ xl: (n) => `rb-xl-grid-cols-${n}`
124895
+ };
124896
+ /** Inline custom property read by the `.rb-grid-tracks` utility per breakpoint. */
124897
+ const TRACK_VAR = {
124898
+ base: "--rb-gtc-base",
124899
+ sm: "--rb-gtc-sm",
124900
+ md: "--rb-gtc-md",
124901
+ lg: "--rb-gtc-lg",
124902
+ xl: "--rb-gtc-xl"
124903
+ };
124904
+ const GRID_BREAKPOINTS = [
124905
+ "base",
124906
+ "sm",
124907
+ "md",
124908
+ "lg",
124909
+ "xl"
124910
+ ];
123912
124911
  function Grid({ as: Comp = "div", cols = {
123913
124912
  base: 1,
123914
124913
  md: 2
123915
- }, gap = "md", className, children, "data-slot": dataSlot, ...rest }) {
123916
- const colsObj = typeof cols === "number" ? { base: cols } : cols;
123917
- const colClasses = [
123918
- colsObj.base && `rb-grid-cols-${colsObj.base}`,
123919
- colsObj.sm && `rb-sm-grid-cols-${colsObj.sm}`,
123920
- colsObj.md && `rb-md-grid-cols-${colsObj.md}`,
123921
- colsObj.lg && `rb-lg-grid-cols-${colsObj.lg}`,
123922
- colsObj.xl && `rb-xl-grid-cols-${colsObj.xl}`
123923
- ];
124914
+ }, gap = "md", className, style, children, "data-slot": dataSlot, ...rest }) {
124915
+ const colsObj = typeof cols === "number" || typeof cols === "string" ? { base: cols } : cols;
124916
+ const colClasses = [];
124917
+ const trackVars = {};
124918
+ let hasTracks = false;
124919
+ for (const bp of GRID_BREAKPOINTS) {
124920
+ const value = colsObj[bp];
124921
+ if (value == null) continue;
124922
+ if (typeof value === "string") {
124923
+ trackVars[TRACK_VAR[bp]] = value;
124924
+ hasTracks = true;
124925
+ } else colClasses.push(COL_COUNT_CLASS[bp](value));
124926
+ }
124927
+ const mergedStyle = hasTracks ? {
124928
+ ...trackVars,
124929
+ ...style
124930
+ } : style;
123924
124931
  return /* @__PURE__ */ jsx(Comp, {
123925
124932
  ...rest,
123926
- className: clsx("rb-grid", colClasses, {
124933
+ style: mergedStyle,
124934
+ className: clsx("rb-grid", hasTracks && "rb-grid-tracks", colClasses, {
123927
124935
  "rb-gap-0": gap === "none",
123928
124936
  "rb-gap-1": gap === "xs",
123929
124937
  "rb-gap-2": gap === "sm",
@@ -124004,6 +125012,138 @@ function Text$2({ as: Comp = "span", children, className = "", path, maxLength:
124004
125012
  });
124005
125013
  }
124006
125014
  //#endregion
125015
+ //#region ../blocks/src/system/icons/cta.ts
125016
+ init_svg();
125017
+ /**
125018
+ * Curated icon set for CTA/button icons.
125019
+ *
125020
+ * Guardrail: keep this list small and action-oriented. This is intentionally not the full Lucide set.
125021
+ * Extend by adding to CTA_ICON_NAMES and the mapping below (explicit imports only).
125022
+ */
125023
+ const CTA_ICON_NAMES = [
125024
+ "ArrowRight",
125025
+ "ArrowLeft",
125026
+ "ChevronRight",
125027
+ "ChevronLeft",
125028
+ "ChevronUp",
125029
+ "ChevronDown",
125030
+ "ExternalLink",
125031
+ "Download",
125032
+ "Upload",
125033
+ "Mail",
125034
+ "Phone",
125035
+ "Play",
125036
+ "ShoppingCart",
125037
+ "Calendar",
125038
+ "MapPin",
125039
+ "Info",
125040
+ "Plus",
125041
+ "Minus",
125042
+ "Check",
125043
+ "X"
125044
+ ];
125045
+ const CTA_ICON_COMPONENTS = {
125046
+ ArrowRight: ArrowRightIcon,
125047
+ ArrowLeft: ArrowLeftIcon,
125048
+ ChevronRight: ChevronRightIcon,
125049
+ ChevronLeft: ChevronLeftIcon,
125050
+ ChevronUp: ChevronUpIcon,
125051
+ ChevronDown: ChevronDownIcon,
125052
+ ExternalLink: ExternalLinkIcon,
125053
+ Download: DownloadIcon,
125054
+ Upload: UploadIcon,
125055
+ Mail: MailIcon,
125056
+ Phone: PhoneIcon,
125057
+ Play: PlayIcon,
125058
+ ShoppingCart: ShoppingCartIcon,
125059
+ Calendar: CalendarIcon,
125060
+ MapPin: MapPinIcon,
125061
+ Info: InfoIcon,
125062
+ Plus: PlusIcon,
125063
+ Minus: MinusIcon,
125064
+ Check: CheckIcon$1,
125065
+ X: XIcon
125066
+ };
125067
+ function isCtaIconName(value) {
125068
+ return typeof value === "string" && CTA_ICON_NAMES.includes(value);
125069
+ }
125070
+ function formatLucideName(name) {
125071
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
125072
+ }
125073
+ const CTA_ICON_OPTIONS = CTA_ICON_NAMES.map((id) => ({
125074
+ id,
125075
+ label: formatLucideName(id)
125076
+ }));
125077
+ function getCtaIconComponent(name) {
125078
+ if (!isCtaIconName(name)) return null;
125079
+ return CTA_ICON_COMPONENTS[name] ?? null;
125080
+ }
125081
+ //#endregion
125082
+ //#region ../blocks/src/system/icons/registry.ts
125083
+ init_presets();
125084
+ function buildSearchText(parts) {
125085
+ return parts.map((part) => part.trim()).filter(Boolean).join(" ");
125086
+ }
125087
+ function semanticDefinitionToOption(definition, preset) {
125088
+ return {
125089
+ id: definition.id,
125090
+ label: definition.label,
125091
+ searchText: buildSearchText([
125092
+ definition.label,
125093
+ definition.id,
125094
+ ...definition.tags,
125095
+ ...definition.domains,
125096
+ ...definition.tone
125097
+ ]),
125098
+ preset
125099
+ };
125100
+ }
125101
+ CTA_ICON_OPTIONS.map((option) => ({
125102
+ id: option.id,
125103
+ label: option.label,
125104
+ searchText: buildSearchText([option.label, option.id]),
125105
+ preset: "cta"
125106
+ }));
125107
+ function semanticOptionsForPreset(preset) {
125108
+ return SEMANTIC_ICON_DEFINITIONS.filter((definition) => definition.presets.includes(preset)).map((definition) => semanticDefinitionToOption(definition, preset));
125109
+ }
125110
+ semanticOptionsForPreset("feature");
125111
+ function getIconComponent(name) {
125112
+ return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
125113
+ }
125114
+ //#endregion
125115
+ //#region ../blocks/src/system/runtime/nodes/buttonAffordance.ts
125116
+ function normalize(value) {
125117
+ const trimmed = typeof value === "string" ? value.trim() : "";
125118
+ return trimmed.length > 0 ? trimmed : null;
125119
+ }
125120
+ /**
125121
+ * Resolve the trailing affordance a button should render. Node overrides
125122
+ * personality; returns `null` when nothing is configured.
125123
+ */
125124
+ function resolveButtonAffordance(input) {
125125
+ const nodeIcon = normalize(input.trailingIcon);
125126
+ if (nodeIcon) {
125127
+ const colorToken = normalize(input.trailingIconColorToken);
125128
+ return {
125129
+ iconId: nodeIcon,
125130
+ source: "node",
125131
+ ...colorToken ? { colorToken } : {}
125132
+ };
125133
+ }
125134
+ const personality = input.personalityAffordance;
125135
+ const personalityIcon = normalize(personality?.iconId);
125136
+ if (personality && personalityIcon) {
125137
+ const colorToken = normalize(personality.colorToken);
125138
+ return {
125139
+ iconId: personalityIcon,
125140
+ source: "personality",
125141
+ ...colorToken ? { colorToken } : {}
125142
+ };
125143
+ }
125144
+ return null;
125145
+ }
125146
+ //#endregion
124007
125147
  //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
124008
125148
  function renderInlineText(value) {
124009
125149
  return value.map((run, index) => renderRun(run, index));
@@ -124057,37 +125197,57 @@ const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockCo
124057
125197
  ...rest
124058
125198
  });
124059
125199
  };
124060
- 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 }) => {
125200
+ /**
125201
+ * Render the resolved trailing affordance icon. Colour is applied via a theme
125202
+ * CSS var so it recolours with the palette; the icon stroke uses `currentColor`.
125203
+ */
125204
+ function renderTrailingAffordanceIcon(affordance) {
125205
+ if (!affordance) return null;
125206
+ const Icon = getIconComponent(affordance.iconId);
125207
+ if (!Icon) return null;
125208
+ return /* @__PURE__ */ jsx(Icon, {
125209
+ "aria-hidden": true,
125210
+ className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block",
125211
+ style: affordance.colorToken ? { color: `rgb(var(--tb-${affordance.colorToken}))` } : void 0
125212
+ });
125213
+ }
125214
+ 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 }) => {
124061
125215
  const content = value ?? children;
124062
125216
  if (!content) {
124063
125217
  console.warn("[ButtonNode] No content to render - value and children are both empty");
124064
125218
  return null;
124065
125219
  }
125220
+ const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({
125221
+ trailingIcon,
125222
+ trailingIconColorToken,
125223
+ personalityAffordance
125224
+ }));
124066
125225
  const resolvedHref = typeof href === "string" ? href.trim() : "";
124067
125226
  if (linkRequired && resolvedHref.length === 0) {
124068
125227
  console.warn("[ButtonNode] Missing href for link-required button");
124069
125228
  return null;
124070
125229
  }
125230
+ const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
124071
125231
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
124072
125232
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
124073
125233
  variant: resolvedVariantId,
124074
125234
  size,
124075
- extraClassName: className
124076
- }) : className;
124077
- if (resolvedHref) return /* @__PURE__ */ jsx("a", {
125235
+ extraClassName
125236
+ }) : extraClassName;
125237
+ if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
124078
125238
  href: resolvedHref,
124079
125239
  target,
124080
125240
  rel,
124081
125241
  className: combinedClassName,
124082
125242
  ...rest,
124083
- children: content
125243
+ children: [content, affordanceIcon]
124084
125244
  });
124085
- return /* @__PURE__ */ jsx("button", {
125245
+ return /* @__PURE__ */ jsxs("button", {
124086
125246
  type,
124087
125247
  disabled,
124088
125248
  className: combinedClassName,
124089
125249
  ...rest,
124090
- children: content
125250
+ children: [content, affordanceIcon]
124091
125251
  });
124092
125252
  };
124093
125253
  const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
@@ -124112,106 +125272,6 @@ const LinkNode = ({ href, children, className, target, rel, linkRequired = false
124112
125272
  });
124113
125273
  };
124114
125274
  //#endregion
124115
- //#region ../blocks/src/system/icons/cta.ts
124116
- init_svg();
124117
- /**
124118
- * Curated icon set for CTA/button icons.
124119
- *
124120
- * Guardrail: keep this list small and action-oriented. This is intentionally not the full Lucide set.
124121
- * Extend by adding to CTA_ICON_NAMES and the mapping below (explicit imports only).
124122
- */
124123
- const CTA_ICON_NAMES = [
124124
- "ArrowRight",
124125
- "ArrowLeft",
124126
- "ChevronRight",
124127
- "ChevronLeft",
124128
- "ChevronUp",
124129
- "ChevronDown",
124130
- "ExternalLink",
124131
- "Download",
124132
- "Upload",
124133
- "Mail",
124134
- "Phone",
124135
- "Play",
124136
- "ShoppingCart",
124137
- "Calendar",
124138
- "MapPin",
124139
- "Info",
124140
- "Plus",
124141
- "Minus",
124142
- "Check",
124143
- "X"
124144
- ];
124145
- const CTA_ICON_COMPONENTS = {
124146
- ArrowRight: ArrowRightIcon,
124147
- ArrowLeft: ArrowLeftIcon,
124148
- ChevronRight: ChevronRightIcon,
124149
- ChevronLeft: ChevronLeftIcon,
124150
- ChevronUp: ChevronUpIcon,
124151
- ChevronDown: ChevronDownIcon,
124152
- ExternalLink: ExternalLinkIcon,
124153
- Download: DownloadIcon,
124154
- Upload: UploadIcon,
124155
- Mail: MailIcon,
124156
- Phone: PhoneIcon,
124157
- Play: PlayIcon,
124158
- ShoppingCart: ShoppingCartIcon,
124159
- Calendar: CalendarIcon,
124160
- MapPin: MapPinIcon,
124161
- Info: InfoIcon,
124162
- Plus: PlusIcon,
124163
- Minus: MinusIcon,
124164
- Check: CheckIcon$1,
124165
- X: XIcon
124166
- };
124167
- function isCtaIconName(value) {
124168
- return typeof value === "string" && CTA_ICON_NAMES.includes(value);
124169
- }
124170
- function formatLucideName(name) {
124171
- return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
124172
- }
124173
- const CTA_ICON_OPTIONS = CTA_ICON_NAMES.map((id) => ({
124174
- id,
124175
- label: formatLucideName(id)
124176
- }));
124177
- function getCtaIconComponent(name) {
124178
- if (!isCtaIconName(name)) return null;
124179
- return CTA_ICON_COMPONENTS[name] ?? null;
124180
- }
124181
- //#endregion
124182
- //#region ../blocks/src/system/icons/registry.ts
124183
- init_presets();
124184
- function buildSearchText(parts) {
124185
- return parts.map((part) => part.trim()).filter(Boolean).join(" ");
124186
- }
124187
- function semanticDefinitionToOption(definition, preset) {
124188
- return {
124189
- id: definition.id,
124190
- label: definition.label,
124191
- searchText: buildSearchText([
124192
- definition.label,
124193
- definition.id,
124194
- ...definition.tags,
124195
- ...definition.domains,
124196
- ...definition.tone
124197
- ]),
124198
- preset
124199
- };
124200
- }
124201
- CTA_ICON_OPTIONS.map((option) => ({
124202
- id: option.id,
124203
- label: option.label,
124204
- searchText: buildSearchText([option.label, option.id]),
124205
- preset: "cta"
124206
- }));
124207
- function semanticOptionsForPreset(preset) {
124208
- return SEMANTIC_ICON_DEFINITIONS.filter((definition) => definition.presets.includes(preset)).map((definition) => semanticDefinitionToOption(definition, preset));
124209
- }
124210
- semanticOptionsForPreset("feature");
124211
- function getIconComponent(name) {
124212
- return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
124213
- }
124214
- //#endregion
124215
125275
  //#region ../blocks/src/system/runtime/nodes/icon.tsx
124216
125276
  const IconNode = ({ value, title, className, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
124217
125277
  const parsedValue = parseBlockIconValue(value);
@@ -124838,6 +125898,77 @@ const HeaderSectionNode = ({ blockId, children, className, "data-preview-site-ch
124838
125898
  };
124839
125899
  var header_section_server_default = markEditableSurfaceForwarding(HeaderSectionNode);
124840
125900
  //#endregion
125901
+ //#region ../blocks/src/system/runtime/nodes/svg.tsx
125902
+ /**
125903
+ * Turn paint props into a CSS style object. Colour values pass through as-is so
125904
+ * they may reference theme tokens via `var()`, which only resolves in a CSS
125905
+ * property context (not in a bare presentation attribute).
125906
+ */
125907
+ function paintStyle(shape) {
125908
+ const style = {};
125909
+ if (shape.fill !== void 0) style.fill = shape.fill;
125910
+ if (shape.stroke !== void 0) style.stroke = shape.stroke;
125911
+ if (shape.strokeWidth !== void 0) style.strokeWidth = shape.strokeWidth;
125912
+ if (shape.fillOpacity !== void 0) style.fillOpacity = shape.fillOpacity;
125913
+ if (shape.strokeOpacity !== void 0) style.strokeOpacity = shape.strokeOpacity;
125914
+ if (shape.strokeLinecap !== void 0) style.strokeLinecap = shape.strokeLinecap;
125915
+ if (shape.strokeLinejoin !== void 0) style.strokeLinejoin = shape.strokeLinejoin;
125916
+ if (shape.strokeDasharray !== void 0) style.strokeDasharray = shape.strokeDasharray;
125917
+ return style;
125918
+ }
125919
+ function renderShape(shape, key) {
125920
+ const style = paintStyle(shape);
125921
+ switch (shape.kind) {
125922
+ case "path": return /* @__PURE__ */ jsx("path", {
125923
+ d: shape.d,
125924
+ style
125925
+ }, key);
125926
+ case "ellipse": return /* @__PURE__ */ jsx("ellipse", {
125927
+ cx: shape.cx,
125928
+ cy: shape.cy,
125929
+ rx: shape.rx,
125930
+ ry: shape.ry,
125931
+ style
125932
+ }, key);
125933
+ case "circle": return /* @__PURE__ */ jsx("circle", {
125934
+ cx: shape.cx,
125935
+ cy: shape.cy,
125936
+ r: shape.r,
125937
+ style
125938
+ }, key);
125939
+ case "rect": return /* @__PURE__ */ jsx("rect", {
125940
+ x: shape.x,
125941
+ y: shape.y,
125942
+ width: shape.width,
125943
+ height: shape.height,
125944
+ rx: shape.rx,
125945
+ ry: shape.ry,
125946
+ style
125947
+ }, key);
125948
+ case "line": return /* @__PURE__ */ jsx("line", {
125949
+ x1: shape.x1,
125950
+ y1: shape.y1,
125951
+ x2: shape.x2,
125952
+ y2: shape.y2,
125953
+ style
125954
+ }, key);
125955
+ default: return null;
125956
+ }
125957
+ }
125958
+ const SvgNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, viewBox, width, height, className, style, ariaHidden = true, shapes }) => {
125959
+ return /* @__PURE__ */ jsx("svg", {
125960
+ viewBox,
125961
+ width,
125962
+ height,
125963
+ className,
125964
+ style,
125965
+ "aria-hidden": ariaHidden,
125966
+ xmlns: "http://www.w3.org/2000/svg",
125967
+ fill: "none",
125968
+ children: (Array.isArray(shapes) ? shapes : []).map((shape, index) => renderShape(shape, index))
125969
+ });
125970
+ };
125971
+ //#endregion
124841
125972
  //#region ../blocks/src/system/runtime/nodes/booking-form.server.tsx
124842
125973
  init_booking_form_interactive();
124843
125974
  /**
@@ -126289,6 +127420,7 @@ init_clsx();
126289
127420
  init_EventListing_view();
126290
127421
  init_EventCalendar_interactive();
126291
127422
  init_WeekAgendaView();
127423
+ init_WeekBoardView();
126292
127424
  init_utils$3();
126293
127425
  init_timetableModel();
126294
127426
  init_buttons();
@@ -126633,6 +127765,17 @@ function renderTimetableSsr(display) {
126633
127765
  })]
126634
127766
  });
126635
127767
  }
127768
+ function renderWeekBoardSsr(display) {
127769
+ const days = getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek);
127770
+ return /* @__PURE__ */ jsx(WeekBoardView, {
127771
+ days,
127772
+ events: [...display.events],
127773
+ showCapacity: display.showCapacity,
127774
+ emptyMessage: display.emptyMessage,
127775
+ ctaLabel: display.buttonText,
127776
+ buttonVariant: display.buttonVariant
127777
+ });
127778
+ }
126636
127779
  function formatHourLabel(hour) {
126637
127780
  if (hour === 0) return "12 AM";
126638
127781
  if (hour === 12) return "12 PM";
@@ -126659,6 +127802,9 @@ const EventCalendarSSR = (props) => {
126659
127802
  case "timetable":
126660
127803
  content = renderTimetableSsr(display);
126661
127804
  break;
127805
+ case "week-board":
127806
+ content = renderWeekBoardSsr(display);
127807
+ break;
126662
127808
  case "calendar":
126663
127809
  content = renderCalendarSsr(display);
126664
127810
  break;
@@ -127222,6 +128368,7 @@ init_spinner();
127222
128368
  const serverComponentRegistry = {
127223
128369
  div: DivNode,
127224
128370
  figure: FigureNode,
128371
+ svg: SvgNode,
127225
128372
  section: SectionNode,
127226
128373
  headerSection: header_section_server_default,
127227
128374
  stack: StackNode,
@@ -128734,9 +129881,12 @@ function formatFontFamily(family, fallback = "sans-serif") {
128734
129881
  }
128735
129882
  //#endregion
128736
129883
  //#region ../theme-core/src/styles/shadow.ts
129884
+ init_colorStyles();
128737
129885
  function generateShadowCssVars(theme) {
128738
129886
  const level = theme.shadow.elevation;
128739
129887
  const soft = theme.shadow.softness !== "crisp";
129888
+ const tintVar = theme.shadow.colorToken ? cssVarValue(theme.shadow.colorToken) : null;
129889
+ const shadowColor = (a) => tintVar ? `rgb(${tintVar} / ${a})` : `rgba(0, 0, 0, ${a})`;
128740
129890
  const base = {
128741
129891
  sm: [{
128742
129892
  y: 1,
@@ -128796,7 +129946,7 @@ function generateShadowCssVars(theme) {
128796
129946
  const blurMul = soft ? 1.2 : 1;
128797
129947
  const alphaMul = soft ? .9 : 1.05;
128798
129948
  const fmt = (layers) => layers.map((l) => {
128799
- return `0 ${Math.round(l.y * scale)}px ${Math.round(l.blur * scale * blurMul)}px ${Math.round(l.spread * scale)}px rgba(0, 0, 0, ${Math.max(0, Math.min(1, +(l.a * alphaMul).toFixed(3)))})`;
129949
+ return `0 ${Math.round(l.y * scale)}px ${Math.round(l.blur * scale * blurMul)}px ${Math.round(l.spread * scale)}px ${shadowColor(Math.max(0, Math.min(1, +(l.a * alphaMul).toFixed(3))))}`;
128800
129950
  }).join(", ");
128801
129951
  return {
128802
129952
  "--shadow-sm": fmt(base.sm),
@@ -128832,6 +129982,7 @@ function parseBorderWidth(widthClass) {
128832
129982
  init_types$9();
128833
129983
  init_constants$1();
128834
129984
  init_colorStyles();
129985
+ init_surfaces();
128835
129986
  /**
128836
129987
  * Corner radius map for accordion surfaces. Pill is capped here because FAQ
128837
129988
  * rows contain long text and expanded content; full capsules clip awkwardly.
@@ -128865,7 +130016,13 @@ function generateAccordionCss({ themeId, theme, accordionSystem }) {
128865
130016
  const questionColumnsLastItemSelector = `${questionColumnsItemSelector}:last-child`;
128866
130017
  const questionColumnsTriggerSelector = `${questionColumnsItemSelector} .accordion-trigger`;
128867
130018
  const rootRules = [];
128868
- if (accordionSystem.background) rootRules.push(`background-color: ${rgbColorValue(accordionSystem.background.colorToken)}`);
130019
+ if (accordionSystem.background) {
130020
+ rootRules.push(`background-color: ${rgbColorValue(accordionSystem.background.colorToken)}`);
130021
+ rootRules.push(...surfaceForegroundDeclarations({
130022
+ text: rgbColorValue(accordionSystem.content.textColorToken),
130023
+ heading: rgbColorValue(accordionSystem.trigger.textColorToken)
130024
+ }));
130025
+ }
128869
130026
  const borderRadius = CORNER_MAP$2[accordionSystem.corners ?? theme.corners];
128870
130027
  rootRules.push(`border-radius: ${borderRadius}`);
128871
130028
  if (accordionSystem.border) {
@@ -130430,7 +131587,7 @@ function toHeroLineHeight(lineHeight) {
130430
131587
  }
130431
131588
  //#endregion
130432
131589
  //#region ../theme-core/src/status/generateStatusCss.ts
130433
- init_contextualColors();
131590
+ init_surfaces();
130434
131591
  /**
130435
131592
  * Corner radius map - derives alert border-radius from theme.corners
130436
131593
  */
@@ -130460,7 +131617,7 @@ ${root} .status-error { color: rgb(var(--tb-destructive)); }
130460
131617
  ${root} .status-success { color: rgb(var(--tb-success)); }
130461
131618
  ${root} .status-warning { color: rgb(var(--tb-warning)); }
130462
131619
  ${root} .status-info { color: rgb(var(--tb-info)); }
130463
- ${root} .status-muted { ${statusMutedColorDeclaration()} }`);
131620
+ ${root} .status-muted { color: ${surfaceForegroundValue("supporting")}; }`);
130464
131621
  cssBlocks.push(`/* Alert containers */
130465
131622
  ${root} .alert {
130466
131623
  padding: 1rem;
@@ -130514,9 +131671,6 @@ ${root} .button-link:hover {
130514
131671
  return cssBlocks.join("\n\n");
130515
131672
  }
130516
131673
  //#endregion
130517
- //#region ../theme-core/src/status/index.ts
130518
- init_contextualColors();
130519
- //#endregion
130520
131674
  //#region ../theme-core/src/progress/generateProgressCss.ts
130521
131675
  /**
130522
131676
  * Generate progress indicator CSS from theme settings.
@@ -130601,6 +131755,10 @@ ${root} .step-connector {
130601
131755
  }
130602
131756
  //#endregion
130603
131757
  //#region ../theme-core/src/typography/generateTypographyCss.ts
131758
+ init_surfaces();
131759
+ function globalHeadingColorFallback(level) {
131760
+ return `var(--hc-h${level}, var(--hc-heading, ${DEFAULT_SURFACE_TEXT_COLOR}))`;
131761
+ }
130604
131762
  /**
130605
131763
  * Generate typography CSS for heading elements.
130606
131764
  *
@@ -130629,7 +131787,7 @@ ${root} :where(h1) {
130629
131787
  font-style: var(--fi-h1, var(--fi-heading, normal));
130630
131788
  letter-spacing: var(--ls-h1, var(--ls-heading));
130631
131789
  line-height: var(--lh-h1, var(--lh-heading));
130632
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h1, var(--hc-heading, inherit))));
131790
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(1))};
130633
131791
  }
130634
131792
 
130635
131793
  ${root} :where(h2) {
@@ -130638,7 +131796,7 @@ ${root} :where(h2) {
130638
131796
  font-style: var(--fi-h2, var(--fi-heading, normal));
130639
131797
  letter-spacing: var(--ls-h2, var(--ls-heading));
130640
131798
  line-height: var(--lh-h2, var(--lh-heading));
130641
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h2, var(--hc-heading, inherit))));
131799
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(2))};
130642
131800
  }
130643
131801
 
130644
131802
  ${root} :where(h3) {
@@ -130647,7 +131805,7 @@ ${root} :where(h3) {
130647
131805
  font-style: var(--fi-h3, var(--fi-heading, normal));
130648
131806
  letter-spacing: var(--ls-h3, var(--ls-heading));
130649
131807
  line-height: var(--lh-h3, var(--lh-heading));
130650
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h3, var(--hc-heading, inherit))));
131808
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(3))};
130651
131809
  }
130652
131810
 
130653
131811
  ${root} :where(h4) {
@@ -130656,7 +131814,7 @@ ${root} :where(h4) {
130656
131814
  font-style: var(--fi-h4, var(--fi-heading, normal));
130657
131815
  letter-spacing: var(--ls-h4, var(--ls-heading));
130658
131816
  line-height: var(--lh-h4, var(--lh-heading));
130659
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h4, var(--hc-heading, inherit))));
131817
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(4))};
130660
131818
  }
130661
131819
 
130662
131820
  ${root} :where(h5) {
@@ -130665,7 +131823,7 @@ ${root} :where(h5) {
130665
131823
  font-style: var(--fi-h5, var(--fi-heading, normal));
130666
131824
  letter-spacing: var(--ls-h5, var(--ls-heading));
130667
131825
  line-height: var(--lh-h5, var(--lh-heading));
130668
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h5, var(--hc-heading, inherit))));
131826
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(5))};
130669
131827
  }
130670
131828
 
130671
131829
  ${root} :where(h6) {
@@ -130674,7 +131832,7 @@ ${root} :where(h6) {
130674
131832
  font-style: var(--fi-h6, var(--fi-heading, normal));
130675
131833
  letter-spacing: var(--ls-h6, var(--ls-heading));
130676
131834
  line-height: var(--lh-h6, var(--lh-heading));
130677
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h6, var(--hc-heading, inherit))));
131835
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(6))};
130678
131836
  }`);
130679
131837
  cssBlocks.push(`/* Display variant for hero/splash headings */
130680
131838
  ${root} :where(.heading-display) {
@@ -131073,6 +132231,7 @@ const THEME_RADIUS_CSS_VARS = {
131073
132231
  block: "--rb-block-radius",
131074
132232
  button: "--rb-button-radius",
131075
132233
  input: "--rb-input-radius",
132234
+ panel: "--rb-panel-radius",
131076
132235
  legacyCard: "--radius-card",
131077
132236
  legacyControl: "--radius-control"
131078
132237
  };
@@ -131154,6 +132313,10 @@ ${`:where([data-theme-scope="${themeId}"]) :where([data-block="customer-portal"]
131154
132313
  /* Modal (shared rb-modal classes) */
131155
132314
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.35);
131156
132315
  --rb-modal-bg: var(--cp-card-bg);
132316
+ --rb-modal-text: var(--cp-text);
132317
+ --rb-modal-heading: var(--cp-text);
132318
+ --rb-modal-link: var(--cp-primary);
132319
+ --rb-modal-supporting: var(--cp-muted);
131157
132320
  --rb-modal-border: var(--cp-card-border);
131158
132321
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
131159
132322
  --rb-modal-radius: var(--cp-card-radius);
@@ -131879,6 +133042,7 @@ function buildThemeCssVars(theme) {
131879
133042
  const inputSystem = resolveThemeInputSystem(theme);
131880
133043
  const blockRadius = mapBlockRadius(theme.corners);
131881
133044
  const buttonRadius = mapButtonRadius(theme.corners);
133045
+ const panelRadius = mapPanelRadius(theme.corners);
131882
133046
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
131883
133047
  return {
131884
133048
  ...generateCssVars(theme.palette),
@@ -131887,6 +133051,7 @@ function buildThemeCssVars(theme) {
131887
133051
  ...generateShadowCssVars(theme),
131888
133052
  ["--font-heading"]: formatFontFamily(typography.headings.default.family),
131889
133053
  ["--font-body"]: formatFontFamily(typography.body.family),
133054
+ ["--font-eyebrow"]: typography.eyebrow?.family ? formatFontFamily(typography.eyebrow.family) : "var(--font-body)",
131890
133055
  ["--font-weight-heading"]: mapWeight(typography.headings.default.weight),
131891
133056
  ["--font-weight-body"]: mapWeight(typography.body.weight),
131892
133057
  ...typography.headings.h1.weight ? { ["--fw-h1"]: mapWeight(typography.headings.h1.weight) } : {},
@@ -131937,12 +133102,13 @@ function buildThemeCssVars(theme) {
131937
133102
  ["--fs-h3-fluid"]: sized.h3Fluid,
131938
133103
  ["--fs-h1-display"]: sized.h1Display,
131939
133104
  ["--fs-h1-display-fluid"]: sized.h1DisplayFluid,
131940
- ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom"),
133105
+ ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom", shadow.colorToken),
131941
133106
  ["--space-mult"]: mapSpaceMult(space),
131942
133107
  ["--motion-duration"]: mapMotionDuration(motion.level),
131943
133108
  ["--motion-ease"]: mapMotionEasing(motion.easing ?? "standard"),
131944
133109
  ["--rt-space-y"]: mapRhythm(space),
131945
133110
  [THEME_RADIUS_CSS_VARS.block]: blockRadius,
133111
+ [THEME_RADIUS_CSS_VARS.panel]: panelRadius,
131946
133112
  ["--rb-block-transition"]: mapBlockTransition(motion.level),
131947
133113
  [THEME_RADIUS_CSS_VARS.button]: buttonRadius,
131948
133114
  ["--rb-border-width"]: mapBorderWidth(border.width),
@@ -131996,20 +133162,22 @@ function mapWeight(w) {
131996
133162
  bold: 700
131997
133163
  }[w];
131998
133164
  }
131999
- function mapShadow(level, softness, position = "bottom") {
133165
+ function mapShadow(level, softness, position = "bottom", colorToken) {
132000
133166
  if (level === "none") return "none";
133167
+ const tintVar = colorToken ? cssVarValue(colorToken) : null;
133168
+ const shadowColor = (a) => tintVar ? `rgb(${tintVar} / ${a})` : `rgba(0,0,0,${a})`;
132001
133169
  const offset = {
132002
133170
  low: 2,
132003
133171
  medium: 4,
132004
133172
  high: 6
132005
133173
  }[level];
132006
133174
  const xOffset = position === "bottom-right" ? offset : 0;
132007
- if (softness === "hard") return `${xOffset}px ${offset}px 0 0 rgba(0,0,0,1)`;
133175
+ if (softness === "hard") return `${xOffset}px ${offset}px 0 0 ${shadowColor("1")}`;
132008
133176
  const soft = softness !== "crisp";
132009
133177
  switch (level) {
132010
- case "low": return soft ? `${xOffset}px 1px 2px rgba(0,0,0,.06)` : `${xOffset}px 1px 1px rgba(0,0,0,.12)`;
132011
- case "medium": return soft ? `${xOffset}px 10px 20px rgba(0,0,0,.08)` : `${xOffset}px 6px 12px rgba(0,0,0,.16)`;
132012
- case "high": return soft ? `${xOffset}px 25px 50px rgba(0,0,0,.18)` : `${xOffset}px 20px 30px rgba(0,0,0,.28)`;
133178
+ case "low": return soft ? `${xOffset}px 1px 2px ${shadowColor(".06")}` : `${xOffset}px 1px 1px ${shadowColor(".12")}`;
133179
+ case "medium": return soft ? `${xOffset}px 10px 20px ${shadowColor(".08")}` : `${xOffset}px 6px 12px ${shadowColor(".16")}`;
133180
+ case "high": return soft ? `${xOffset}px 25px 50px ${shadowColor(".18")}` : `${xOffset}px 20px 30px ${shadowColor(".28")}`;
132013
133181
  }
132014
133182
  }
132015
133183
  function mapSpaceMult(space) {
@@ -132056,6 +133224,21 @@ function mapBlockRadius(corners) {
132056
133224
  }[corners];
132057
133225
  }
132058
133226
  /**
133227
+ * Map corner style to large-panel radius CSS value (Tier 2 `--rb-panel-radius`).
133228
+ * Derived from the same `corners` enum, one step more generous than the
133229
+ * block/card radius so large surfaces can carry a softer corner without a new
133230
+ * schema field. `rounded` lands on 20px (1.25rem), matching the physio mockup's
133231
+ * large-panel radius.
133232
+ */
133233
+ function mapPanelRadius(corners) {
133234
+ return {
133235
+ square: "0",
133236
+ soft: "0.75rem",
133237
+ rounded: "1.25rem",
133238
+ pill: "2rem"
133239
+ }[corners];
133240
+ }
133241
+ /**
132059
133242
  * Map motion level to block transition duration.
132060
133243
  * These are Tier 2 vars used consistently across blocks.
132061
133244
  */
@@ -132292,7 +133475,7 @@ function hydrateValue(value, context) {
132292
133475
  const resolvedItems = value.map((item) => hydrateValue(item, context));
132293
133476
  return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
132294
133477
  }
132295
- if (isRecord$32(value)) {
133478
+ if (isRecord$34(value)) {
132296
133479
  if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
132297
133480
  if (isPageLink$1(value)) return hydratePageLink(value, context);
132298
133481
  if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
@@ -133049,8 +134232,12 @@ const containerResponsiveThemeCss = `/*
133049
134232
  text-transform: uppercase;
133050
134233
  }
133051
134234
 
133052
- /* Eyebrow text - small uppercase labels for section introductions */
134235
+ /* Eyebrow text - small uppercase labels for section introductions.
134236
+ font-family resolves to the optional eyebrow/mono font role, falling back
134237
+ to the body font when the theme sets none (so existing themes are
134238
+ unchanged). */
133053
134239
  .rb-eyebrow {
134240
+ font-family: var(--font-eyebrow, var(--font-body));
133054
134241
  font-size: 0.875rem;
133055
134242
  font-weight: 600;
133056
134243
  letter-spacing: 0.025em;
@@ -133065,11 +134252,11 @@ const containerResponsiveThemeCss = `/*
133065
134252
  width: fit-content;
133066
134253
  align-items: center;
133067
134254
  justify-content: center;
133068
- border: 1px solid color-mix(in srgb, var(--section-text-color, rgb(var(--tb-text))) 46%, transparent);
134255
+ border: 1px solid color-mix(in srgb, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 46%, transparent);
133069
134256
  border-radius: 9999px;
133070
- background: color-mix(in srgb, var(--section-text-color, rgb(var(--tb-text))) 14%, transparent);
134257
+ background: color-mix(in srgb, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 14%, transparent);
133071
134258
  padding: 0.5rem 1rem;
133072
- color: var(--section-text-color, rgb(var(--tb-text)));
134259
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
133073
134260
  line-height: 1;
133074
134261
  }
133075
134262
  .rb-eyebrow-treatment-pill.rb-eyebrow-treatment-accent {
@@ -133571,6 +134758,58 @@ const containerResponsiveThemeCss = `/*
133571
134758
  }
133572
134759
  }
133573
134760
 
134761
+ }
134762
+
134763
+ /*
134764
+ * Responsive fractional grid tracks (rb-grid-tracks).
134765
+ *
134766
+ * Asymmetric AND responsive grid-template-columns, driven by inline custom
134767
+ * properties the Grid primitive sets per breakpoint from string track
134768
+ * templates:
134769
+ * --rb-gtc-base / --rb-gtc-sm / --rb-gtc-md / --rb-gtc-lg / --rb-gtc-xl
134770
+ * Each breakpoint falls back to the next smaller one, so only the breakpoints
134771
+ * an author actually sets take effect (e.g. base '1fr' + lg '1fr 0.9fr'
134772
+ * collapses to a single column below lg). Authored here (not per node) so the
134773
+ * @media -> @container conversion (container responsive mode) applies too.
134774
+ */
134775
+ .rb-grid-tracks {
134776
+ grid-template-columns: var(--rb-gtc-base, 1fr);
134777
+ }
134778
+ @container rb-site (min-width: 640px) {
134779
+
134780
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
134781
+ .rb-grid-tracks {
134782
+ grid-template-columns: var(--rb-gtc-sm, var(--rb-gtc-base, 1fr));
134783
+ }
134784
+ }
134785
+
134786
+ }
134787
+ @container rb-site (min-width: 768px) {
134788
+
134789
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
134790
+ .rb-grid-tracks {
134791
+ grid-template-columns: var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr)));
134792
+ }
134793
+ }
134794
+
134795
+ }
134796
+ @container rb-site (min-width: 1024px) {
134797
+
134798
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
134799
+ .rb-grid-tracks {
134800
+ grid-template-columns: var(--rb-gtc-lg, var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr))));
134801
+ }
134802
+ }
134803
+
134804
+ }
134805
+ @container rb-site (min-width: 1280px) {
134806
+
134807
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
134808
+ .rb-grid-tracks {
134809
+ grid-template-columns: var(--rb-gtc-xl, var(--rb-gtc-lg, var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr)))));
134810
+ }
134811
+ }
134812
+
133574
134813
  }
133575
134814
 
133576
134815
  /* Alignment */
@@ -134775,6 +136014,11 @@ const containerResponsiveThemeCss = `/*
134775
136014
  :where(.theme-scope) .rb-modal {
134776
136015
  width: min(var(--rb-modal-max-width, 560px), 100%);
134777
136016
  background: var(--rb-modal-bg, rgb(var(--tb-surface)));
136017
+ color: var(--rb-modal-text, rgb(var(--tb-text, 17 24 39)));
136018
+ --rb-surface-text-color: var(--rb-modal-text, rgb(var(--tb-text, 17 24 39)));
136019
+ --rb-surface-heading-color: var(--rb-modal-heading, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
136020
+ --rb-surface-link-color: var(--rb-modal-link, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
136021
+ --rb-surface-supporting-color: var(--rb-modal-supporting, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
134778
136022
  border: 1px solid var(--rb-modal-border, rgb(var(--tb-border)));
134779
136023
  border-radius: var(--rb-modal-radius, var(--radius-card));
134780
136024
  box-shadow: var(--rb-modal-shadow, var(--shadow-lg, var(--shadow-elev)));
@@ -134794,7 +136038,7 @@ const containerResponsiveThemeCss = `/*
134794
136038
  font-family: var(--font-heading);
134795
136039
  font-size: 1.0625rem;
134796
136040
  font-weight: 600;
134797
- color: rgb(var(--tb-text));
136041
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
134798
136042
  }
134799
136043
 
134800
136044
  :where(.theme-scope) .rb-modal__close {
@@ -134804,7 +136048,7 @@ const containerResponsiveThemeCss = `/*
134804
136048
  height: 2.25rem;
134805
136049
  padding: 0;
134806
136050
  line-height: 1;
134807
- color: rgb(var(--tb-mutedText));
136051
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
134808
136052
  cursor: pointer;
134809
136053
  display: grid;
134810
136054
  place-items: center;
@@ -134812,7 +136056,7 @@ const containerResponsiveThemeCss = `/*
134812
136056
  }
134813
136057
 
134814
136058
  :where(.theme-scope) .rb-modal__close:hover {
134815
- color: rgb(var(--tb-text));
136059
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
134816
136060
  background: rgba(var(--tb-border), 0.2);
134817
136061
  }
134818
136062
 
@@ -134823,7 +136067,7 @@ const containerResponsiveThemeCss = `/*
134823
136067
 
134824
136068
  :where(.theme-scope) .rb-modal__body {
134825
136069
  padding: 0.875rem 1rem 1rem;
134826
- color: rgb(var(--tb-text));
136070
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
134827
136071
  font-size: 0.9375rem;
134828
136072
  line-height: 1.45;
134829
136073
  }
@@ -134983,7 +136227,7 @@ const containerResponsiveThemeCss = `/*
134983
136227
  & h6 {
134984
136228
  font-family: var(--font-heading);
134985
136229
  /* Color is set by generateTypographyCss.ts with full cascade:
134986
- --section-heading-color -> --section-text-color -> --hc-hN -> --hc-heading -> inherit */
136230
+ --rb-surface-heading-color -> --rb-surface-text-color -> --hc-hN -> --hc-heading -> global text */
134987
136231
  font-weight: var(--font-weight-heading);
134988
136232
  text-transform: var(--tt-heading);
134989
136233
  font-variant-caps: var(--fv-heading);
@@ -135131,7 +136375,7 @@ const containerResponsiveThemeCss = `/*
135131
136375
 
135132
136376
  /* Neutral prose uses theme text color by default */
135133
136377
  :where(.theme-scope) .rb-prose-neutral {
135134
- color: var(--section-text-color, rgb(var(--tb-text)));
136378
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
135135
136379
  }
135136
136380
 
135137
136381
  :where(.theme-scope) .rb-prose p,
@@ -135165,8 +136409,14 @@ const containerResponsiveThemeCss = `/*
135165
136409
 
135166
136410
  :where(.theme-scope) .rb-prose a {
135167
136411
  --rb-prose-effective-link-color: var(
135168
- --section-link-color,
135169
- var(--rb-prose-link-color, rgb(var(--tb-primary)))
136412
+ --rb-surface-link-color,
136413
+ var(
136414
+ --rb-surface-text-color,
136415
+ var(
136416
+ --rb-prose-link-color,
136417
+ rgb(var(--tb-primary, var(--tb-text, 17 24 39)))
136418
+ )
136419
+ )
135170
136420
  );
135171
136421
  color: var(--rb-prose-effective-link-color);
135172
136422
  text-decoration-line: var(--rb-prose-link-decoration-line, underline);
@@ -135177,14 +136427,11 @@ const containerResponsiveThemeCss = `/*
135177
136427
  );
135178
136428
  text-underline-offset: var(--rb-prose-link-underline-offset, 0.14em);
135179
136429
  text-decoration-color: var(
135180
- --section-link-decoration-color,
135181
- var(
135182
- --rb-prose-link-decoration-color,
135183
- color-mix(
135184
- in srgb,
135185
- var(--rb-prose-effective-link-color) 35%,
135186
- transparent
135187
- )
136430
+ --rb-prose-link-decoration-color,
136431
+ color-mix(
136432
+ in srgb,
136433
+ var(--rb-prose-effective-link-color) 35%,
136434
+ transparent
135188
136435
  )
135189
136436
  );
135190
136437
  transition:
@@ -135208,7 +136455,7 @@ const containerResponsiveThemeCss = `/*
135208
136455
 
135209
136456
  :where(.theme-scope) .rb-prose blockquote {
135210
136457
  /* Blockquotes use muted text color */
135211
- color: var(--section-supporting-color, rgb(var(--tb-mutedText)));
136458
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
135212
136459
  border-left-color: rgb(var(--tb-border));
135213
136460
  }
135214
136461
 
@@ -136242,6 +137489,10 @@ const containerResponsiveThemeCss = `/*
136242
137489
  :where(.theme-scope) .card-surface {
136243
137490
  background: rgb(var(--tb-surface));
136244
137491
  color: rgb(var(--tb-onSurface, var(--tb-text)));
137492
+ --rb-surface-text-color: rgb(var(--tb-onSurface, var(--tb-text)));
137493
+ --rb-surface-heading-color: rgb(var(--tb-onSurface, var(--tb-text)));
137494
+ --rb-surface-link-color: rgb(var(--tb-onSurface, var(--tb-text)));
137495
+ --rb-surface-supporting-color: rgb(var(--tb-onSurface, var(--tb-text)));
136245
137496
  border: 1px solid rgb(var(--tb-border));
136246
137497
  border-radius: var(--radius-card);
136247
137498
  box-shadow: var(--shadow-elev);
@@ -136385,6 +137636,10 @@ const containerResponsiveThemeCss = `/*
136385
137636
  padding: clamp(1rem, 2vw, 1.5rem);
136386
137637
  background: var(--rb-reg-surface-bg, rgb(var(--tb-surface, 248 250 252)));
136387
137638
  color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
137639
+ --rb-surface-text-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
137640
+ --rb-surface-heading-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
137641
+ --rb-surface-link-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
137642
+ --rb-surface-supporting-color: var(--rb-reg-on-surface-muted, var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42)))));
136388
137643
  transition: border-color var(--rb-block-transition, 150ms) ease;
136389
137644
  width: 100%;
136390
137645
  max-width: 800px;
@@ -139472,6 +140727,350 @@ const containerResponsiveThemeCss = `/*
139472
140727
  }
139473
140728
  }
139474
140729
 
140730
+ /* -----------------------------------------------------------------------------
140731
+ * Week Board View
140732
+ * Compact "class day-board": day columns side by side, one card per class,
140733
+ * three-state availability (available / filling / waitlist), and a footer CTA.
140734
+ * ----------------------------------------------------------------------------- */
140735
+
140736
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board {
140737
+ /* Status accent tokens — map the three availability states onto theme colours.
140738
+ * available -> secondary, filling -> accent, waitlist -> muted text. */
140739
+ --ec-status-available: rgb(var(--tb-secondary));
140740
+ --ec-status-filling: rgb(var(--tb-accent));
140741
+ --ec-status-waitlist: rgba(var(--tb-text), 0.4);
140742
+ --event-week-board-cols: 7;
140743
+
140744
+ border: 1px solid var(--ec-border);
140745
+ border-radius: var(--rb-block-radius);
140746
+ background-color: var(--ec-surface);
140747
+ color: var(--ec-text);
140748
+ overflow: hidden;
140749
+ box-shadow: 0 14px 34px -24px rgba(var(--tb-text), 0.35);
140750
+ }
140751
+
140752
+ /* Top bar: title + legend */
140753
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-top {
140754
+ display: flex;
140755
+ align-items: center;
140756
+ justify-content: space-between;
140757
+ gap: 1rem;
140758
+ flex-wrap: wrap;
140759
+ padding: 1.1rem 1.5rem;
140760
+ background-color: var(--ec-header-bg);
140761
+ border-bottom: 1px solid var(--ec-border-subtle);
140762
+ }
140763
+
140764
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-title {
140765
+ font-size: 0.8125rem;
140766
+ font-weight: 600;
140767
+ letter-spacing: 0.12em;
140768
+ text-transform: uppercase;
140769
+ color: rgb(var(--tb-primary));
140770
+ }
140771
+
140772
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend {
140773
+ display: flex;
140774
+ align-items: center;
140775
+ gap: 1.1rem;
140776
+ flex-wrap: wrap;
140777
+ font-size: 0.6875rem;
140778
+ letter-spacing: 0.03em;
140779
+ opacity: 0.75;
140780
+ }
140781
+
140782
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-item {
140783
+ display: inline-flex;
140784
+ align-items: center;
140785
+ gap: 0.4rem;
140786
+ }
140787
+
140788
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot {
140789
+ width: 0.55rem;
140790
+ height: 0.55rem;
140791
+ border-radius: 50%;
140792
+ display: inline-block;
140793
+ }
140794
+
140795
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="available"] {
140796
+ background-color: var(--ec-status-available);
140797
+ }
140798
+
140799
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="filling"] {
140800
+ background-color: var(--ec-status-filling);
140801
+ }
140802
+
140803
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="waitlist"] {
140804
+ background-color: var(--ec-status-waitlist);
140805
+ }
140806
+
140807
+ /* Day columns grid */
140808
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-grid {
140809
+ display: grid;
140810
+ grid-template-columns: repeat(var(--event-week-board-cols), minmax(0, 1fr));
140811
+ }
140812
+
140813
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day {
140814
+ display: flex;
140815
+ flex-direction: column;
140816
+ min-height: 15rem;
140817
+ /* Tabular column rule. Driven by the theme border tokens so borderless site
140818
+ * styles (border.width: 'none' -> --rb-border-width: 0) render no grid at all,
140819
+ * while hairline/thin/thick themes get a crisp full-strength divider. */
140820
+ border-right: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
140821
+ }
140822
+
140823
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day:last-child {
140824
+ border-right: none;
140825
+ }
140826
+
140827
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-head {
140828
+ display: flex;
140829
+ align-items: baseline;
140830
+ gap: 0.4rem;
140831
+ padding: 0.9rem 0.9rem 0.65rem;
140832
+ /* Header-row underline — same border-token gating as the column rules. */
140833
+ border-bottom: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
140834
+ }
140835
+
140836
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--today .event-week-board-day-head {
140837
+ background-color: var(--ec-today-bg);
140838
+ }
140839
+
140840
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-abbr {
140841
+ font-size: 0.6875rem;
140842
+ font-weight: 600;
140843
+ letter-spacing: 0.1em;
140844
+ text-transform: uppercase;
140845
+ opacity: 0.65;
140846
+ }
140847
+
140848
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--today .event-week-board-day-abbr {
140849
+ opacity: 1;
140850
+ color: var(--ec-today-text);
140851
+ }
140852
+
140853
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-num {
140854
+ font-size: 0.8125rem;
140855
+ font-weight: 600;
140856
+ opacity: 0.5;
140857
+ }
140858
+
140859
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-body {
140860
+ display: flex;
140861
+ flex-direction: column;
140862
+ gap: 0.65rem;
140863
+ padding: 0.9rem;
140864
+ flex: 1;
140865
+ }
140866
+
140867
+ /* Class card */
140868
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
140869
+ display: flex;
140870
+ flex-direction: column;
140871
+ gap: 0.45rem;
140872
+ padding: 0.8rem 0.85rem;
140873
+ border: 1px solid var(--ec-border-subtle);
140874
+ border-left: 3px solid var(--ec-status-available);
140875
+ border-radius: calc(var(--rb-block-radius) / 1.5);
140876
+ background-color: var(--ec-surface);
140877
+ color: inherit;
140878
+ text-decoration: none;
140879
+ transition:
140880
+ transform var(--rb-block-transition) ease,
140881
+ box-shadow var(--rb-block-transition) ease,
140882
+ border-color var(--rb-block-transition) ease;
140883
+ }
140884
+
140885
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card[data-status="filling"] {
140886
+ border-left-color: var(--ec-status-filling);
140887
+ }
140888
+
140889
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card[data-status="waitlist"] {
140890
+ border-left-color: var(--ec-status-waitlist);
140891
+ }
140892
+
140893
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card:hover {
140894
+ transform: translateY(-2px);
140895
+ box-shadow: 0 6px 16px -8px rgba(var(--tb-text), 0.28);
140896
+ border-color: rgba(var(--tb-primary), 0.4);
140897
+ }
140898
+
140899
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card:focus-visible {
140900
+ outline: 2px solid rgb(var(--tb-primary));
140901
+ outline-offset: 2px;
140902
+ }
140903
+
140904
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-title {
140905
+ font-family: var(--font-heading, inherit);
140906
+ font-size: 0.9375rem;
140907
+ font-weight: 600;
140908
+ line-height: 1.2;
140909
+ }
140910
+
140911
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-time {
140912
+ font-size: 0.75rem;
140913
+ letter-spacing: 0.01em;
140914
+ opacity: 0.7;
140915
+ }
140916
+
140917
+ /* Capacity pill */
140918
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill {
140919
+ align-self: flex-start;
140920
+ display: inline-flex;
140921
+ align-items: center;
140922
+ padding: 0.15rem 0.6rem;
140923
+ border-radius: 999px;
140924
+ font-size: 0.6875rem;
140925
+ font-weight: 600;
140926
+ letter-spacing: 0.02em;
140927
+ /* Available (default): a calm neutral/muted pill — not a coloured outline.
140928
+ * Filling -> amber and waitlist -> muted outline are handled by the
140929
+ * data-status overrides below. */
140930
+ border: 1px solid var(--ec-border);
140931
+ background-color: rgba(var(--tb-text), 0.06);
140932
+ color: rgba(var(--tb-text), 0.62);
140933
+ border-color: var(--ec-border);
140934
+ }
140935
+
140936
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill[data-status="filling"] {
140937
+ background-color: rgba(var(--tb-accent), 0.14);
140938
+ color: var(--ec-status-filling);
140939
+ border-color: rgba(var(--tb-accent), 0.32);
140940
+ }
140941
+
140942
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill[data-status="waitlist"] {
140943
+ background-color: transparent;
140944
+ color: rgba(var(--tb-text), 0.6);
140945
+ border-color: var(--ec-border);
140946
+ }
140947
+
140948
+ /* Footer */
140949
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-foot {
140950
+ display: flex;
140951
+ align-items: center;
140952
+ justify-content: space-between;
140953
+ gap: 1rem;
140954
+ flex-wrap: wrap;
140955
+ padding: 1.1rem 1.5rem;
140956
+ background-color: var(--ec-header-bg);
140957
+ border-top: 1px solid var(--ec-border-subtle);
140958
+ }
140959
+
140960
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-foot-note {
140961
+ margin: 0;
140962
+ font-size: 0.875rem;
140963
+ opacity: 0.75;
140964
+ }
140965
+
140966
+ /* Responsive: collapse day columns to a stacked list on narrow viewports */
140967
+ @container rb-site (max-width: 1023px) {
140968
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
140969
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-grid {
140970
+ grid-template-columns: 1fr;
140971
+ }
140972
+
140973
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day {
140974
+ min-height: 0;
140975
+ border-right: none;
140976
+ border-bottom: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
140977
+ }
140978
+
140979
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day:last-child {
140980
+ border-bottom: none;
140981
+ }
140982
+
140983
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--empty {
140984
+ display: none;
140985
+ }
140986
+
140987
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-head {
140988
+ border-bottom: none;
140989
+ padding-bottom: 0.25rem;
140990
+ }
140991
+
140992
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-body {
140993
+ flex-direction: row;
140994
+ flex-wrap: wrap;
140995
+ padding-top: 0.35rem;
140996
+ }
140997
+
140998
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
140999
+ flex: 1 1 14rem;
141000
+ }
141001
+ }
141002
+ }
141003
+
141004
+ @container rb-site (max-width: 639px) {
141005
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
141006
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend {
141007
+ display: none;
141008
+ }
141009
+
141010
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
141011
+ flex: 1 1 100%;
141012
+ }
141013
+ }
141014
+ }
141015
+
141016
+ /* -----------------------------------------------------------------------------
141017
+ * Week-board section band
141018
+ * Give the whole week-board section (head + panel) a subtle surface band so it
141019
+ * reads as a distinct zone from the page — the "testimonials band" pattern.
141020
+ * Painted as a pseudo-element above the section's fallback background layer
141021
+ * (z-index -10) but behind the content, so no block-content wiring is needed.
141022
+ * Surface + hairline rules are token-referenced: on a borderless site style
141023
+ * (--rb-border-width: 0) the band keeps its surface tint but drops the rules.
141024
+ * ----------------------------------------------------------------------------- */
141025
+ :where(.theme-scope) [data-slot="section"]:has(.event-calendar--week-board)::before {
141026
+ content: "";
141027
+ position: absolute;
141028
+ inset: 0;
141029
+ z-index: -9;
141030
+ background-color: rgb(var(--tb-surfaceAlt));
141031
+ border-block: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
141032
+ pointer-events: none;
141033
+ }
141034
+
141035
+ /* -----------------------------------------------------------------------------
141036
+ * Event section head — split (heading left, intro right)
141037
+ * Rendered by the block frame (outside [data-block="event-calendar"]) via
141038
+ * eventSectionHeaderLayoutNodes({ splitClassName }). Lays the heading and its
141039
+ * supporting intro out as a two-column head on wide viewports, stacking on
141040
+ * narrow ones. The section band above provides the distinct background.
141041
+ * ----------------------------------------------------------------------------- */
141042
+ :where(.theme-scope) .event-section-head--split {
141043
+ display: flex;
141044
+ align-items: flex-end;
141045
+ justify-content: space-between;
141046
+ gap: clamp(1.5rem, 4vw, 3.5rem);
141047
+ flex-wrap: wrap;
141048
+ }
141049
+
141050
+ :where(.theme-scope) .event-section-head--split > :where(h1, h2, h3) {
141051
+ margin: 0;
141052
+ }
141053
+
141054
+ :where(.theme-scope) .event-section-head--split > .rb-prose {
141055
+ flex: 1 1 22rem;
141056
+ max-width: 34rem;
141057
+ margin: 0;
141058
+ }
141059
+
141060
+ @container rb-site (max-width: 767px) {
141061
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
141062
+ :where(.theme-scope) .event-section-head--split {
141063
+ flex-direction: column;
141064
+ align-items: flex-start;
141065
+ gap: 0.75rem;
141066
+ }
141067
+
141068
+ :where(.theme-scope) .event-section-head--split > .rb-prose {
141069
+ flex-basis: auto;
141070
+ }
141071
+ }
141072
+ }
141073
+
139475
141074
  /* -----------------------------------------------------------------------------
139476
141075
  * Event Calendar Modals
139477
141076
  * Modal overlays for event details and day events list
@@ -139899,7 +141498,7 @@ const containerResponsiveThemeCss = `/*
139899
141498
  }
139900
141499
 
139901
141500
  :where(.theme-scope) .rb-inline-text-accent-contrast {
139902
- color: var(--section-text-color, rgb(var(--tb-text)));
141501
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
139903
141502
  }
139904
141503
 
139905
141504
  :where(.theme-scope) .rb-inline-text-highlight {
@@ -139910,7 +141509,7 @@ const containerResponsiveThemeCss = `/*
139910
141509
  }
139911
141510
 
139912
141511
  :where(.theme-scope) .rb-inline-text-highlight-soft {
139913
- background: color-mix(in oklab, var(--section-text-color, rgb(var(--tb-text))) 14%, transparent);
141512
+ background: color-mix(in oklab, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 14%, transparent);
139914
141513
  }
139915
141514
 
139916
141515
  :where(.theme-scope) .rb-inline-text-highlight-accent {
@@ -139929,7 +141528,7 @@ const containerResponsiveThemeCss = `/*
139929
141528
 
139930
141529
  /* Eyebrow - color only (typography via .rb-eyebrow) */
139931
141530
  :where(.theme-scope) :where([data-block="hero"]) .hero-eyebrow:not(.rb-eyebrow-treatment-accent) {
139932
- color: var(--section-text-color, rgb(var(--tb-text)));
141531
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
139933
141532
  }
139934
141533
 
139935
141534
  /* Subheadline - supporting text below headline */
@@ -139939,7 +141538,7 @@ const containerResponsiveThemeCss = `/*
139939
141538
 
139940
141539
  :where(.theme-scope) :where([data-block="hero"]) .hero-subheadline {
139941
141540
  font-size: 1.125rem;
139942
- color: var(--section-supporting-color, var(--section-text-color, rgb(var(--tb-text))));
141541
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
139943
141542
  }
139944
141543
 
139945
141544
  @container rb-site (min-width: 640px) {
@@ -140030,7 +141629,7 @@ const containerResponsiveThemeCss = `/*
140030
141629
 
140031
141630
  /* CTA content/body text */
140032
141631
  :where(.theme-scope) :where([data-block="cta-full"]) .cta-content {
140033
- color: var(--section-supporting-color, rgb(var(--tb-mutedText)));
141632
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
140034
141633
  }
140035
141634
 
140036
141635
  /* CTA button row container */
@@ -140130,7 +141729,7 @@ const containerResponsiveThemeCss = `/*
140130
141729
  /* Form intro text */
140131
141730
  :where(.theme-scope) :where([data-block="form"]) .form-copy-intro {
140132
141731
  font-size: 1rem;
140133
- color: var(--section-text-color, rgb(var(--tb-text)));
141732
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
140134
141733
  }
140135
141734
 
140136
141735
  /* =============================================================================
@@ -140489,6 +142088,10 @@ const containerResponsiveThemeCss = `/*
140489
142088
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.6);
140490
142089
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
140491
142090
  --rb-modal-z-index: 20000;
142091
+ --rb-modal-text: rgb(var(--tb-text, 17 24 39));
142092
+ --rb-modal-heading: rgb(var(--tb-text, 17 24 39));
142093
+ --rb-modal-link: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
142094
+ --rb-modal-supporting: rgb(var(--tb-mutedText, 100 116 139));
140492
142095
  --shop-card-radius: var(--rb-block-radius, var(--radius-card, 0.75rem));
140493
142096
  --shop-control-radius: var(--rb-input-radius, var(--radius-control, 0.375rem));
140494
142097
  }
@@ -140546,6 +142149,11 @@ const containerResponsiveThemeCss = `/*
140546
142149
  /* Product card */
140547
142150
  :where(.theme-scope) .shop__card {
140548
142151
  background: rgb(var(--tb-surface));
142152
+ color: rgb(var(--tb-text, 17 24 39));
142153
+ --rb-surface-text-color: rgb(var(--tb-text, 17 24 39));
142154
+ --rb-surface-heading-color: rgb(var(--tb-text, 17 24 39));
142155
+ --rb-surface-link-color: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
142156
+ --rb-surface-supporting-color: rgb(var(--tb-mutedText, 100 116 139));
140549
142157
  border: 1px solid rgb(var(--tb-border));
140550
142158
  border-radius: var(--shop-card-radius);
140551
142159
  padding: 1.5rem;
@@ -140700,6 +142308,11 @@ const containerResponsiveThemeCss = `/*
140700
142308
  border: 1px solid rgb(var(--tb-border));
140701
142309
  border-radius: var(--shop-card-radius);
140702
142310
  background: rgb(var(--tb-surface));
142311
+ color: rgb(var(--tb-text, 17 24 39));
142312
+ --rb-surface-text-color: rgb(var(--tb-text, 17 24 39));
142313
+ --rb-surface-heading-color: rgb(var(--tb-text, 17 24 39));
142314
+ --rb-surface-link-color: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
142315
+ --rb-surface-supporting-color: rgb(var(--tb-mutedText, 100 116 139));
140703
142316
  }
140704
142317
 
140705
142318
  :where(.theme-scope) :where([data-block="shop"]) .rb-state-icon--success {
@@ -140772,6 +142385,11 @@ const containerResponsiveThemeCss = `/*
140772
142385
  margin: 0 auto;
140773
142386
  padding: 2rem;
140774
142387
  background: var(--cp-card-bg);
142388
+ color: var(--cp-text);
142389
+ --rb-surface-text-color: var(--cp-text);
142390
+ --rb-surface-heading-color: var(--cp-text);
142391
+ --rb-surface-link-color: var(--cp-primary);
142392
+ --rb-surface-supporting-color: var(--cp-muted);
140775
142393
  border: 1px solid var(--cp-card-border);
140776
142394
  border-radius: var(--cp-card-radius);
140777
142395
  }
@@ -140900,6 +142518,11 @@ const containerResponsiveThemeCss = `/*
140900
142518
  padding: 3rem 2rem;
140901
142519
  text-align: center;
140902
142520
  background: var(--cp-card-bg);
142521
+ color: var(--cp-text);
142522
+ --rb-surface-text-color: var(--cp-text);
142523
+ --rb-surface-heading-color: var(--cp-text);
142524
+ --rb-surface-link-color: var(--cp-primary);
142525
+ --rb-surface-supporting-color: var(--cp-muted);
140903
142526
  border: 1px dashed var(--cp-card-border);
140904
142527
  border-radius: var(--cp-card-radius);
140905
142528
  }
@@ -140912,6 +142535,11 @@ const containerResponsiveThemeCss = `/*
140912
142535
  /* Card */
140913
142536
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card {
140914
142537
  background: var(--cp-card-bg);
142538
+ color: var(--cp-text);
142539
+ --rb-surface-text-color: var(--cp-text);
142540
+ --rb-surface-heading-color: var(--cp-text);
142541
+ --rb-surface-link-color: var(--cp-primary);
142542
+ --rb-surface-supporting-color: var(--cp-muted);
140915
142543
  border: 1px solid var(--cp-card-border);
140916
142544
  border-radius: var(--cp-card-radius);
140917
142545
  padding: 1.25rem;
@@ -141076,6 +142704,11 @@ const containerResponsiveThemeCss = `/*
141076
142704
  /* Table */
141077
142705
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table-wrap {
141078
142706
  background: var(--cp-card-bg);
142707
+ color: var(--cp-text);
142708
+ --rb-surface-text-color: var(--cp-text);
142709
+ --rb-surface-heading-color: var(--cp-text);
142710
+ --rb-surface-link-color: var(--cp-primary);
142711
+ --rb-surface-supporting-color: var(--cp-muted);
141079
142712
  border: 1px solid var(--cp-card-border);
141080
142713
  border-radius: var(--cp-card-radius);
141081
142714
  }
@@ -141637,6 +143270,143 @@ const containerResponsiveThemeCss = `/*
141637
143270
  }
141638
143271
 
141639
143272
 
143273
+ /* =============================================================================
143274
+ * Variant: featured-editorial
143275
+ *
143276
+ * An asymmetric layout: a large featured (spruce-ink) quote card beside a
143277
+ * column of stacked white cards. Renders NO avatars. Colours are palette
143278
+ * tokens only. Node structure is built in testimonialsCarousel.ts.
143279
+ * ============================================================================= */
143280
+
143281
+ /* Section head: heading left, lead-in line to the right; stacks on mobile. */
143282
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-head {
143283
+ display: flex;
143284
+ flex-direction: column;
143285
+ align-items: flex-start;
143286
+ gap: 0.875rem;
143287
+ }
143288
+
143289
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-leadin {
143290
+ max-width: 30rem;
143291
+ }
143292
+
143293
+ @container rb-site (min-width: 768px) {
143294
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
143295
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-head {
143296
+ flex-direction: row;
143297
+ align-items: flex-end;
143298
+ justify-content: space-between;
143299
+ gap: 1.5rem;
143300
+ }
143301
+ }
143302
+ }
143303
+
143304
+ /* Card grid: featured (wider) beside the stacked column. Single column on
143305
+ * small screens. */
143306
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-grid {
143307
+ display: grid;
143308
+ grid-template-columns: minmax(0, 1fr);
143309
+ gap: 1.25rem;
143310
+ align-items: stretch;
143311
+ }
143312
+
143313
+ @container rb-site (min-width: 1024px) {
143314
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
143315
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-grid {
143316
+ grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
143317
+ }
143318
+ }
143319
+ }
143320
+
143321
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-col {
143322
+ display: grid;
143323
+ gap: 1.25rem;
143324
+ align-content: start;
143325
+ }
143326
+
143327
+ /* Base card (white surface) */
143328
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card {
143329
+ display: flex;
143330
+ flex-direction: column;
143331
+ height: 100%;
143332
+ border-radius: var(--rb-block-radius);
143333
+ padding: 1.875rem 1.875rem 1.625rem;
143334
+ background: rgb(var(--tb-surface));
143335
+ border: 1px solid rgba(var(--tb-border), 0.9);
143336
+ box-shadow: 0 1px 2px rgba(var(--tb-shadow, 0 0 0), 0.05);
143337
+ }
143338
+
143339
+ /* Featured (spruce-ink) card */
143340
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature {
143341
+ padding: 2.5rem;
143342
+ background: rgb(var(--tb-primary));
143343
+ border-color: transparent;
143344
+ color: rgb(var(--tb-onPrimary));
143345
+ }
143346
+
143347
+ /* Amber quote mark, oversized serif */
143348
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-qmark {
143349
+ display: block;
143350
+ height: 1.6rem;
143351
+ font-family: var(--font-heading, Georgia, serif);
143352
+ font-style: italic;
143353
+ font-size: 3.375rem;
143354
+ line-height: 0.6;
143355
+ color: rgb(var(--tb-secondary));
143356
+ }
143357
+
143358
+ /* Quote body. The inner <p> is targeted directly (not via :where) so the
143359
+ * serif display font and sizing win over the theme's base paragraph rule. */
143360
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-quote {
143361
+ flex: 1 1 auto;
143362
+ margin-top: 1.25rem;
143363
+ }
143364
+
143365
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-quote p {
143366
+ margin: 0;
143367
+ font-family: var(--font-heading, Georgia, serif);
143368
+ font-size: 1.15rem;
143369
+ line-height: 1.5;
143370
+ color: rgb(var(--tb-text));
143371
+ }
143372
+
143373
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-quote p {
143374
+ color: rgb(var(--tb-onPrimary));
143375
+ font-size: clamp(1.375rem, 2.4vw, 1.6875rem);
143376
+ line-height: 1.42;
143377
+ letter-spacing: -0.01em;
143378
+ }
143379
+
143380
+ /* Attribution: name (bold) + context line, no avatar */
143381
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-meta {
143382
+ display: flex;
143383
+ flex-direction: column;
143384
+ gap: 0.25rem;
143385
+ margin-top: 1.625rem;
143386
+ }
143387
+
143388
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-name {
143389
+ font-weight: 600;
143390
+ font-size: 0.97rem;
143391
+ color: rgb(var(--tb-text));
143392
+ }
143393
+
143394
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-context {
143395
+ font-size: 0.78rem;
143396
+ letter-spacing: 0.02em;
143397
+ color: rgb(var(--tb-mutedText));
143398
+ }
143399
+
143400
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-name {
143401
+ color: rgb(var(--tb-onPrimary));
143402
+ }
143403
+
143404
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-context {
143405
+ color: rgb(var(--tb-onPrimary));
143406
+ opacity: 0.7;
143407
+ }
143408
+
143409
+
141640
143410
  /* Testimonials carousel tweaks: arrow styling + gutters + equal-height cards */
141641
143411
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-carousel.carousel-root .carousel-nav-btn {
141642
143412
  height: var(--rb-testimonial-carousel-arrow-size);
@@ -142783,7 +144553,7 @@ const containerResponsiveThemeCss = `/*
142783
144553
 
142784
144554
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
142785
144555
  font-size: 1rem;
142786
- color: var(--section-text-color, rgb(var(--tb-text)));
144556
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142787
144557
  opacity: 0.85;
142788
144558
  }
142789
144559
 
@@ -142832,7 +144602,7 @@ const containerResponsiveThemeCss = `/*
142832
144602
  margin-top: 0.75rem;
142833
144603
  font-size: 1rem;
142834
144604
  line-height: 1.6;
142835
- color: var(--section-text-color, rgb(var(--tb-text)));
144605
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142836
144606
  text-align: center;
142837
144607
  }
142838
144608
 
@@ -142914,7 +144684,7 @@ const containerResponsiveThemeCss = `/*
142914
144684
 
142915
144685
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .form-copy-intro,
142916
144686
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .newsletter-copy-subtitle {
142917
- color: var(--section-text-color, rgb(var(--tb-text)));
144687
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142918
144688
  }
142919
144689
 
142920
144690
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .contact-newsletter-info {
@@ -143312,7 +145082,7 @@ const containerResponsiveThemeCss = `/*
143312
145082
 
143313
145083
  :where(.theme-scope) .event-compact-row-title {
143314
145084
  margin: 0;
143315
- color: var(--section-heading-color, rgb(var(--tb-primary, 0 0 0)));
145085
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-primary, var(--tb-text, 17 24 39)))));
143316
145086
  font-family: var(--font-heading, var(--font-body, inherit));
143317
145087
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.3rem);
143318
145088
  font-weight: 400;
@@ -143974,27 +145744,41 @@ const containerResponsiveThemeCss = `/*
143974
145744
  background: rgb(var(--tb-surface));
143975
145745
  }
143976
145746
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 1) {
145747
+ background: rgb(var(--tb-surface));
143977
145748
  color: rgb(var(--tb-onSurface));
145749
+ --rb-surface-text-color: rgb(var(--tb-onSurface));
145750
+ --rb-surface-heading-color: rgb(var(--tb-onSurface));
145751
+ --rb-surface-link-color: rgb(var(--tb-onSurface));
145752
+ --rb-surface-supporting-color: rgb(var(--tb-onSurface));
143978
145753
  }
143979
145754
 
143980
145755
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) > .rb-bg-surface {
143981
145756
  background: rgb(var(--tb-secondary));
143982
145757
  }
143983
145758
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) {
145759
+ background: rgb(var(--tb-secondary));
143984
145760
  color: rgb(var(--tb-onSecondary));
145761
+ --rb-surface-text-color: rgb(var(--tb-onSecondary));
145762
+ --rb-surface-heading-color: rgb(var(--tb-onSecondary));
145763
+ --rb-surface-link-color: rgb(var(--tb-onSecondary));
145764
+ --rb-surface-supporting-color: rgb(var(--tb-onSecondary));
143985
145765
  }
143986
145766
 
143987
145767
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) > .rb-bg-surface {
143988
145768
  background: rgb(var(--tb-primary));
143989
145769
  }
143990
145770
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) {
145771
+ background: rgb(var(--tb-primary));
143991
145772
  color: rgb(var(--tb-onPrimary));
145773
+ --rb-surface-text-color: rgb(var(--tb-onPrimary));
145774
+ --rb-surface-heading-color: rgb(var(--tb-onPrimary));
145775
+ --rb-surface-link-color: rgb(var(--tb-onPrimary));
145776
+ --rb-surface-supporting-color: rgb(var(--tb-onPrimary));
143992
145777
  }
143993
145778
 
143994
- /* Body copy carries an inline muted colour from the block; force it to the
143995
- * card's on-colour so it reads on every block (inline style needs !important). */
145779
+ /* Keep the intended visual hierarchy; the body color itself now resolves via
145780
+ * the nearest surface provider instead of requiring an inline override. */
143996
145781
  :where(.theme-scope) .rb-card-treatment-color-blocked .rb-feature-card-body {
143997
- color: inherit !important;
143998
145782
  opacity: 0.9;
143999
145783
  }
144000
145784
 
@@ -146319,6 +148103,8 @@ const VERTICAL_IDS = [
146319
148103
  "yoga_wellness",
146320
148104
  "fitness_pt",
146321
148105
  "dance_school",
148106
+ "physiotherapy_physical_health",
148107
+ "massage_bodywork",
146322
148108
  "therapist_practitioner",
146323
148109
  "beauty_spa",
146324
148110
  "consultant_coach",
@@ -146354,6 +148140,12 @@ const VERTICAL_BOOKING_PRESETS = [
146354
148140
  preset("dance_school.workshops", "dance_school", "workshop", "Workshop", "Workshops", "One-off workshops, masterclasses, or intensives."),
146355
148141
  preset("dance_school.private_lessons", "dance_school", "appointment", "Private lesson", "Private lessons", "One-to-one lessons or coaching sessions."),
146356
148142
  preset("dance_school.shows", "dance_school", "performance", "Show", "Shows", "Ticketed performances, showcases, and recitals."),
148143
+ preset("physiotherapy_physical_health.appointments", "physiotherapy_physical_health", "appointment", "Appointment", "Appointments", "Assessments, treatments, follow-ups, and rehabilitation sessions."),
148144
+ preset("physiotherapy_physical_health.rehab_classes", "physiotherapy_physical_health", "class", "Rehab class", "Rehab classes", "Regular rehabilitation, mobility, strength, or recovery classes."),
148145
+ preset("physiotherapy_physical_health.workshops", "physiotherapy_physical_health", "workshop", "Workshop", "Workshops", "One-off workshops, talks, or practical group sessions."),
148146
+ preset("massage_bodywork.treatments", "massage_bodywork", "appointment", "Treatment", "Treatments", "Massage treatments, bodywork sessions, and one-to-one appointments."),
148147
+ preset("massage_bodywork.group_sessions", "massage_bodywork", "class", "Group session", "Group sessions", "Regular bodywork, somatic movement, or self-massage sessions."),
148148
+ preset("massage_bodywork.workshops", "massage_bodywork", "workshop", "Workshop", "Workshops", "One-off bodywork, self-massage, or somatic practice workshops."),
146357
148149
  preset("therapist_practitioner.appointments", "therapist_practitioner", "appointment", "Appointment", "Appointments", "Sessions, consultations, treatments, or assessments."),
146358
148150
  preset("therapist_practitioner.workshops", "therapist_practitioner", "workshop", "Workshop", "Workshops", "One-off group workshops, talks, or wellbeing sessions."),
146359
148151
  preset("therapist_practitioner.retreats", "therapist_practitioner", "retreat", "Retreat", "Retreats", "Multi-day retreats or immersive group experiences."),
@@ -147848,7 +149640,7 @@ function applyBindings$1(bindings, context) {
147848
149640
  if (value !== void 0 && value !== null) setBindingValue(result, key, value);
147849
149641
  continue;
147850
149642
  }
147851
- if (isRecord$32(bindingSpec)) {
149643
+ if (isRecord$34(bindingSpec)) {
147852
149644
  const nested = applyBindings$1(bindingSpec, context);
147853
149645
  if (Object.keys(nested).length > 0) setBindingValue(result, key, nested);
147854
149646
  }
@@ -147909,7 +149701,7 @@ function setBindingValue(target, path, value) {
147909
149701
  current[Number(segment)] = value;
147910
149702
  return;
147911
149703
  }
147912
- if (isRecord$32(current)) current[segment] = value;
149704
+ if (isRecord$34(current)) current[segment] = value;
147913
149705
  return;
147914
149706
  }
147915
149707
  const nextWantsArray = typeof nextSegment === "string" && isIndex(nextSegment);
@@ -147918,15 +149710,15 @@ function setBindingValue(target, path, value) {
147918
149710
  const existing = current[index];
147919
149711
  if (nextWantsArray) {
147920
149712
  if (!Array.isArray(existing)) current[index] = [];
147921
- } else if (!isRecord$32(existing)) current[index] = {};
149713
+ } else if (!isRecord$34(existing)) current[index] = {};
147922
149714
  current = current[index];
147923
149715
  continue;
147924
149716
  }
147925
- if (isRecord$32(current)) {
149717
+ if (isRecord$34(current)) {
147926
149718
  const existing = current[segment];
147927
149719
  if (nextWantsArray) {
147928
149720
  if (!Array.isArray(existing)) current[segment] = [];
147929
- } else if (!isRecord$32(existing)) current[segment] = {};
149721
+ } else if (!isRecord$34(existing)) current[segment] = {};
147930
149722
  current = current[segment];
147931
149723
  continue;
147932
149724
  }
@@ -147964,7 +149756,7 @@ function getPath$1(source, path) {
147964
149756
  const segments = path.split(".").map((segment) => segment.trim()).filter(Boolean);
147965
149757
  let current = source;
147966
149758
  for (const segment of segments) {
147967
- if (!isRecord$32(current)) return void 0;
149759
+ if (!isRecord$34(current)) return void 0;
147968
149760
  current = current[segment];
147969
149761
  }
147970
149762
  return current;
@@ -147999,13 +149791,13 @@ function textToInlineText(value) {
147999
149791
  */
148000
149792
  function extractFirstParagraph$1(value) {
148001
149793
  const unwrapped = unwrapRichTextRoot(value);
148002
- if (!isRecord$32(unwrapped)) return null;
149794
+ if (!isRecord$34(unwrapped)) return null;
148003
149795
  const doc = unwrapped;
148004
149796
  if (!Array.isArray(doc.content)) return null;
148005
149797
  for (const node of doc.content) {
148006
- if (!isRecord$32(node)) continue;
149798
+ if (!isRecord$34(node)) continue;
148007
149799
  if (node.type !== "paragraph" || !Array.isArray(node.content)) continue;
148008
- const text = node.content.filter((item) => isRecord$32(item) && item.type === "text").map((item) => typeof item.text === "string" ? item.text : "").join("").trim();
149800
+ const text = node.content.filter((item) => isRecord$34(item) && item.type === "text").map((item) => typeof item.text === "string" ? item.text : "").join("").trim();
148009
149801
  if (text.length > 0) return text;
148010
149802
  }
148011
149803
  return null;
@@ -148023,7 +149815,7 @@ function formatDate$1(value, options) {
148023
149815
  * Type guard to check if a value is a valid binding descriptor.
148024
149816
  */
148025
149817
  function isBindingDescriptor$2(value) {
148026
- if (!isRecord$32(value) || typeof value.source !== "string") return false;
149818
+ if (!isRecord$34(value) || typeof value.source !== "string") return false;
148027
149819
  if (!BINDING_SOURCES$1.includes(value.source)) return false;
148028
149820
  switch (value.source) {
148029
149821
  case "field":
@@ -148038,7 +149830,7 @@ function isBindingDescriptor$2(value) {
148038
149830
  * Type guard to check if a value is binding-descriptor-like (can be normalized).
148039
149831
  */
148040
149832
  function isBindingDescriptorLike$1(value) {
148041
- return isBindingDescriptor$2(value) || typeof value === "string" || isRecord$32(value) && typeof value.source === "string" && typeof value.path === "string";
149833
+ return isBindingDescriptor$2(value) || typeof value === "string" || isRecord$34(value) && typeof value.source === "string" && typeof value.path === "string";
148042
149834
  }
148043
149835
  /**
148044
149836
  * Normalizes a binding input to a binding descriptor.
@@ -148064,7 +149856,7 @@ function normalizeBindingOutput$1(value) {
148064
149856
  }
148065
149857
  function normalizeValue(value) {
148066
149858
  if (Array.isArray(value)) return value.map((item) => normalizeValue(item));
148067
- if (!isRecord$32(value)) return value;
149859
+ if (!isRecord$34(value)) return value;
148068
149860
  if (isDocWrapper(value)) return normalizeValue(value.doc);
148069
149861
  const entries = Object.entries(value).map(([key, val]) => [key, normalizeValue(val)]);
148070
149862
  return Object.fromEntries(entries);
@@ -148086,7 +149878,7 @@ function isDocWrapper(value) {
148086
149878
  if (!("doc" in value)) return false;
148087
149879
  if (Object.keys(value).length !== 1) return false;
148088
149880
  const doc = value.doc;
148089
- return isRecord$32(doc) && typeof doc.type === "string" && doc.type === "doc";
149881
+ return isRecord$34(doc) && typeof doc.type === "string" && doc.type === "doc";
148090
149882
  }
148091
149883
  BINDING_TRANSFORM_VALUES$1.join(", ");
148092
149884
  //#endregion
@@ -148113,7 +149905,7 @@ const ImagePresets = {
148113
149905
  resize: "contain"
148114
149906
  }
148115
149907
  };
148116
- const isRecord$3 = isRecord$32;
149908
+ const isRecord$3 = isRecord$34;
148117
149909
  const normalizeBindingOutput = normalizeBindingOutput$1;
148118
149910
  const applyBindingsToContent = applyBindingsToContent$1;
148119
149911
  const builtInReferenceKindSet = /* @__PURE__ */ new Set([