@riverbankcms/sdk 0.104.1 → 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 (120) hide show
  1. package/dist/{PreviewEditorSidebar-CmaPXdKu.mjs → PreviewEditorSidebar-CBMhU9p_.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-C5xRTh2b.mjs → PreviewEditorUI-C5KEw4M8.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-Eks51NcN.mjs → SdkPreviewModeRuntime-Iq12HjL7.mjs} +1142 -177
  4. package/dist/{SiteChromeCustomizeContext-Bt8zb3qu.mjs → SiteChromeCustomizeContext-Cx0NMdyv.mjs} +1640 -877
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -0
  6. package/dist/_dts/blocks/src/primitives/layout/Grid.d.ts +12 -8
  7. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +3 -0
  8. package/dist/_dts/blocks/src/system/blocks/events/shared/layout.d.ts +11 -1
  9. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +7 -1
  10. package/dist/_dts/blocks/src/system/constants/events.d.ts +1 -1
  11. package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +12 -0
  12. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +2 -2
  13. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +14 -0
  14. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +33 -0
  15. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +28 -0
  16. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +32 -0
  17. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +1 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/svg.d.ts +77 -0
  19. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +2 -0
  20. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +3 -40
  21. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +14 -0
  22. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +11 -0
  23. package/dist/_dts/core/src/branded.d.ts +5 -0
  24. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +18 -0
  25. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +2 -2
  26. package/dist/_dts/sdk/src/version.d.ts +1 -1
  27. package/dist/_dts/theme-core/src/ThemeScope.d.ts +1 -1
  28. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +29 -0
  29. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +6 -0
  30. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  31. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +20 -0
  32. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  33. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +4 -0
  34. package/dist/_dts/theme-core/src/buttons/types.d.ts +34 -0
  35. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  36. package/dist/_dts/theme-core/src/gradients/types.d.ts +27 -3
  37. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +51 -15
  38. package/dist/_dts/theme-core/src/palette/curated/brand-led.d.ts +13 -0
  39. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +12 -0
  40. package/dist/_dts/theme-core/src/palette/historicalThemePalette.d.ts +44 -0
  41. package/dist/_dts/theme-core/src/palette/index.d.ts +1 -0
  42. package/dist/_dts/theme-core/src/palette/legacySelection.d.ts +13 -2
  43. package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +17 -2
  44. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +3 -4
  45. package/dist/_dts/theme-core/src/runtime/themeCssVarNames.d.ts +1 -0
  46. package/dist/_dts/theme-core/src/schema.d.ts +108 -26
  47. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +2 -1
  48. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +50 -1
  49. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  50. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  51. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +56 -1
  52. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  53. package/dist/_dts/theme-core/src/status/index.d.ts +0 -1
  54. package/dist/_dts/theme-core/src/surfaces/foregroundContract.d.ts +19 -0
  55. package/dist/_dts/theme-core/src/surfaces/foregroundRoles.d.ts +9 -0
  56. package/dist/_dts/theme-core/src/surfaces/index.d.ts +2 -0
  57. package/dist/_dts/ui/src/button.d.ts +1 -1
  58. package/dist/cli/index.mjs +1558 -468
  59. package/dist/client/{DiscountCodeDisclosure-Dit2aItR.mjs → DiscountCodeDisclosure-BXM73_E5.mjs} +1 -1
  60. package/dist/client/{EventCombined.client-BnREyCjf.mjs → EventCombined.client-DT5elP7j.mjs} +4 -4
  61. package/dist/client/{EventListing.client-0uHld51x.mjs → EventListing.client-pTYGfV9C.mjs} +2 -2
  62. package/dist/client/{LeafletStaticMap-DJcvSfmj.mjs → LeafletStaticMap-dQrhlUe3.mjs} +1 -1
  63. package/dist/client/{MagicLinkForm-EAsIktfw.mjs → MagicLinkForm-u6Dul4j5.mjs} +2 -2
  64. package/dist/client/{StepIndicator-CRR17tYI.mjs → StepIndicator-nWqineJ2.mjs} +2 -2
  65. package/dist/client/{accordion-B47HIuuH.mjs → accordion-CSJcTUyH.mjs} +1 -1
  66. package/dist/client/{bookingForm-I1E-8F9P.mjs → bookingForm-C73wOuVa.mjs} +6 -6
  67. package/dist/client/bookings.mjs +137 -1
  68. package/dist/client/{buttons-BbPn8OKA.mjs → buttons-DfYyqt8C.mjs} +138 -2
  69. package/dist/client/{carousel-OlM7SyBs.mjs → carousel-fMBb0JSc.mjs} +1 -1
  70. package/dist/client/{cart-BKpG5jz6.mjs → cart-BtaCwT3S.mjs} +3 -3
  71. package/dist/client/{checkout-Dmmr6qoU.mjs → checkout-DkTwZSnh.mjs} +3 -3
  72. package/dist/client/client.mjs +2327 -542
  73. package/dist/client/{colorStyles-DuW4Fjqd.mjs → colorStyles-Wyl6JujD.mjs} +45 -4
  74. package/dist/client/{courseRegistration-CflZiqGk.mjs → courseRegistration-DnLmapJu.mjs} +7 -7
  75. package/dist/client/{eventCalendar-BvoLWcp-.mjs → eventCalendar-BvLOc9KY.mjs} +165 -5
  76. package/dist/client/{eventCombined-DsrO8t_t.mjs → eventCombined-kShgJPQr.mjs} +2 -2
  77. package/dist/client/{eventDetails-C3hxgcJm.mjs → eventDetails-C5NTM0Vo.mjs} +3 -3
  78. package/dist/client/{eventListing-C-hb237X.mjs → eventListing-B82ZdKP6.mjs} +2 -2
  79. package/dist/client/{eventRegistration-B0gyzDGi.mjs → eventRegistration-qJVFqBWo.mjs} +7 -7
  80. package/dist/client/{form-C_RUi6oJ.mjs → form-BvAcKiuu.mjs} +2 -2
  81. package/dist/client/{headerSection-IKQiD2U0.mjs → headerSection-NvAiEHAg.mjs} +3 -3
  82. package/dist/client/hooks.mjs +1034 -356
  83. package/dist/client/{locationMap-8ZBrMzRJ.mjs → locationMap-D0j52xfI.mjs} +3 -3
  84. package/dist/client/{media-CZJKL7fi.mjs → media-BCW_g2cQ.mjs} +1 -1
  85. package/dist/client/{newsletterForm-CYk3ucwj.mjs → newsletterForm-B8_i93qH.mjs} +2 -2
  86. package/dist/client/{pricing-B5GmvfIH.mjs → pricing-DIYnyHOk.mjs} +1 -1
  87. package/dist/client/{productDetail-BjS2Dqzo.mjs → productDetail-w0eAHkuQ.mjs} +3 -3
  88. package/dist/client/{productList-BOHvC8My.mjs → productList-Vsguq5Xt.mjs} +3 -3
  89. package/dist/client/{propsDecoder-WS6UEJwZ.mjs → propsDecoder-CD2pJ1WB.mjs} +37 -2
  90. package/dist/client/rendering/client.mjs +1722 -760
  91. package/dist/client/rendering/islands.mjs +19 -19
  92. package/dist/client/rendering.mjs +2303 -518
  93. package/dist/client/{shop-CON03-wN.mjs → shop-Dgxs-Q8F.mjs} +6 -6
  94. package/dist/client/{shop-commerce-DlqrFgH8.mjs → shop-commerce-DJAhsTaT.mjs} +6 -6
  95. package/dist/client/{shop-commerce-store-l74-Kne6.mjs → shop-commerce-store-CfCXltXW.mjs} +1 -1
  96. package/dist/client/{shopShared-CQheEXSg.mjs → shopShared-CmDcPXUt.mjs} +2 -2
  97. package/dist/client/{useDiscountCodeUi-v6OluyWl.mjs → useDiscountCodeUi-CirrT2bM.mjs} +1 -1
  98. package/dist/client/{useEventFilters-BqSTcNOf.mjs → useEventFilters-CNZxlCcO.mjs} +5 -5
  99. package/dist/client/{usePolling-DMfADjIF.mjs → usePolling-Baks_iBI.mjs} +2 -2
  100. package/dist/preview-next/client/runtime.mjs +3 -3
  101. package/dist/{sdk-runtime-BUmJ0DaT.mjs → sdk-runtime-BfNiFeNJ.mjs} +1 -1
  102. package/dist/{separator-Dd-JYok7.mjs → separator-BhAR_Xmf.mjs} +1 -1
  103. package/dist/server/components.mjs +2293 -531
  104. package/dist/server/config-validation.mjs +1040 -357
  105. package/dist/server/config.mjs +1040 -357
  106. package/dist/server/data.mjs +1034 -356
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/server/next.mjs +2296 -534
  109. package/dist/server/page-converter.mjs +1018 -324
  110. package/dist/server/prebuild.mjs +1 -1
  111. package/dist/server/rendering/server.mjs +2278 -521
  112. package/dist/server/rendering.mjs +2293 -531
  113. package/dist/server/routing.mjs +1092 -338
  114. package/dist/server/server.mjs +1016 -338
  115. package/dist/server/theme-bridge.mjs +1240 -77
  116. package/dist/server/theme.mjs +165 -5
  117. package/dist/styles/index.css +617 -34
  118. package/package.json +1 -1
  119. package/dist/_dts/blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.d.ts +0 -2
  120. 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",
@@ -7620,6 +7795,7 @@ var curatedPalettes, curatedPalettesById, init_curated = __esmMin((() => {
7620
7795
  brandLedWarm,
7621
7796
  brandLedJewel,
7622
7797
  brandLedBurgundyGold,
7798
+ brandLedSpruce,
7623
7799
  warmNeutralClay,
7624
7800
  warmNeutralCream,
7625
7801
  warmNeutralSoftEarth,
@@ -7736,6 +7912,7 @@ var init_palette$1 = __esmMin((() => {
7736
7912
  init_expandPalette();
7737
7913
  init_generateCssVars();
7738
7914
  init_generateShades();
7915
+ init_historicalThemePalette();
7739
7916
  init_neutralScale();
7740
7917
  init_types$15();
7741
7918
  init_utils$5();
@@ -8205,7 +8382,7 @@ function asSpecialVariantId(value) {
8205
8382
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
8206
8383
  return value;
8207
8384
  }
8208
- 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;
8209
8386
  var init_types$13 = __esmMin((() => {
8210
8387
  init_themeColorTokens();
8211
8388
  VARIANT_ROLES = [
@@ -8365,6 +8542,10 @@ var init_types$13 = __esmMin((() => {
8365
8542
  widthClass: z$1.string(),
8366
8543
  colorToken: themeColorTokenSchema
8367
8544
  });
8545
+ buttonVariantAffordanceSchema = z$1.object({
8546
+ iconId: z$1.string().min(1),
8547
+ colorToken: themeColorTokenSchema.optional()
8548
+ });
8368
8549
  variantShadowSchema = z$1.object({
8369
8550
  elevation: z$1.enum([
8370
8551
  "none",
@@ -8405,7 +8586,8 @@ var init_types$13 = __esmMin((() => {
8405
8586
  border: buttonBorderSchema.optional(),
8406
8587
  hoverBackgroundToken: z$1.string().optional(),
8407
8588
  effects: variantEffectsSchema.optional(),
8408
- sizes: variantSizeOverridesSchema.optional()
8589
+ sizes: variantSizeOverridesSchema.optional(),
8590
+ affordance: buttonVariantAffordanceSchema.optional()
8409
8591
  });
8410
8592
  buttonSystemSchema = z$1.object({
8411
8593
  global: buttonGlobalSettingsSchema,
@@ -8955,6 +9137,132 @@ var init_editorial_link = __esmMin((() => {
8955
9137
  });
8956
9138
  }));
8957
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
8958
9266
  //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
8959
9267
  var inkStamp;
8960
9268
  var init_ink_stamp = __esmMin((() => {
@@ -9721,6 +10029,7 @@ var init_personalities = __esmMin((() => {
9721
10029
  init_confident_chip();
9722
10030
  init_earth_pill();
9723
10031
  init_editorial_link();
10032
+ init_flat_ink();
9724
10033
  init_ink_stamp();
9725
10034
  init_joy_stamp();
9726
10035
  init_ornate_ritual();
@@ -9735,6 +10044,7 @@ var init_personalities = __esmMin((() => {
9735
10044
  editorialLink,
9736
10045
  pebble,
9737
10046
  inkStamp,
10047
+ flatInk,
9738
10048
  brushedWash,
9739
10049
  showtimePill,
9740
10050
  joyStamp,
@@ -10204,6 +10514,50 @@ function getCompatibleHeaderStyleIds(layoutId) {
10204
10514
  return isHeaderStyleCompatibleWithLayout(getHeaderStyleOrThrow(styleId), layoutId);
10205
10515
  });
10206
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
+ }
10207
10561
  function themedHeaderShadow(theme) {
10208
10562
  switch (theme.shadow.elevation) {
10209
10563
  case "none": return;
@@ -10303,6 +10657,38 @@ function cleanBaseHeader(theme) {
10303
10657
  ctaGap: "default"
10304
10658
  };
10305
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
+ }
10306
10692
  function serifLineHeader(theme) {
10307
10693
  return {
10308
10694
  ...baseHeader(theme),
@@ -10881,6 +11267,13 @@ var init_headerLooks = __esmMin((() => {
10881
11267
  styleId: asHeaderStyleId("minimal")
10882
11268
  }
10883
11269
  },
11270
+ {
11271
+ lookId: asHeaderLookId("classic-centered-nav"),
11272
+ selection: {
11273
+ layoutId: asHeaderLayoutId("classic"),
11274
+ styleId: asHeaderStyleId("fine-line")
11275
+ }
11276
+ },
10884
11277
  {
10885
11278
  lookId: asHeaderLookId("brand-solid"),
10886
11279
  selection: {
@@ -10947,6 +11340,21 @@ var init_headerLooks = __esmMin((() => {
10947
11340
  logoAccommodations: inlineClassicLogoAccommodations,
10948
11341
  compile: cleanBaseHeader
10949
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
+ },
10950
11358
  {
10951
11359
  id: asHeaderLookId("brand-solid"),
10952
11360
  label: "Brand solid",
@@ -11507,7 +11915,7 @@ function defineTypographyPreset(preset) {
11507
11915
  id: asTypographyPresetId(preset.id)
11508
11916
  };
11509
11917
  }
11510
- 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;
11511
11919
  var init_typographyPresets = __esmMin((() => {
11512
11920
  bodyReadablePolicy = {
11513
11921
  recommendedCategories: ["sans-serif", "serif"],
@@ -11869,6 +12277,49 @@ var init_typographyPresets = __esmMin((() => {
11869
12277
  },
11870
12278
  scale: "balanced"
11871
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
+ };
11872
12323
  typographyPresets = [
11873
12324
  defineTypographyPreset({
11874
12325
  id: "typography-preset:modern-sans",
@@ -12128,6 +12579,32 @@ var init_typographyPresets = __esmMin((() => {
12128
12579
  }
12129
12580
  }
12130
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
12131
12608
  })
12132
12609
  ];
12133
12610
  new Map(typographyPresets.map((preset) => [preset.id, preset]));
@@ -13846,6 +14323,28 @@ var init_generateDefaultButtonSystem = __esmMin((() => {
13846
14323
  "high"
13847
14324
  ];
13848
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
+ }));
13849
14348
  //#endregion
13850
14349
  //#region ../theme-core/src/buttons/generateButtonCss.ts
13851
14350
  function rule(selector, declarations) {
@@ -13924,10 +14423,40 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
13924
14423
  out.push(variantFocusVisibleRule(variantId, themeId));
13925
14424
  const effects = variantEffectsCss(variant, themeId, tokens, theme);
13926
14425
  if (effects) out.push({ raw: effects });
14426
+ const affordance = variantAffordanceRule(variant, selector, tokens);
14427
+ if (affordance) out.push(affordance);
13927
14428
  out.push(...variantDisabledRules(variantId, themeId));
13928
14429
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
13929
14430
  return out;
13930
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
+ }
13931
14460
  function parseButtonVariantIdForCss(value) {
13932
14461
  const variantId = parseThemeButtonVariantId(value);
13933
14462
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
@@ -14074,7 +14603,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
14074
14603
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
14075
14604
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
14076
14605
  }
14077
- var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
14606
+ var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
14078
14607
  var init_generateButtonCss = __esmMin((() => {
14079
14608
  init_types$13();
14080
14609
  init_classNames();
@@ -14083,6 +14612,8 @@ var init_generateButtonCss = __esmMin((() => {
14083
14612
  init_generateEffectsCSS();
14084
14613
  init_constants$2();
14085
14614
  init_generateDefaultButtonSystem();
14615
+ init_affordanceIcons();
14616
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
14086
14617
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
14087
14618
  LETTER_SPACING_MAP = {
14088
14619
  tight: "-0.025em",
@@ -14109,6 +14640,7 @@ var init_buttons = __esmMin((() => {
14109
14640
  init_types$13();
14110
14641
  init_classNames();
14111
14642
  init_generateButtonCss();
14643
+ init_affordanceIcons();
14112
14644
  init_generateDefaultButtonSystem();
14113
14645
  init_constants$2();
14114
14646
  init_presets$1();
@@ -14349,23 +14881,6 @@ function generateDefaultCardSystem(theme) {
14349
14881
  }
14350
14882
  var init_generateDefaultCardSystem = __esmMin((() => {}));
14351
14883
  //#endregion
14352
- //#region ../theme-core/src/status/contextualColors.ts
14353
- function statusMutedColorValue() {
14354
- return `var(${STATUS_MUTED_COLOR_VAR}, ${DEFAULT_STATUS_MUTED_COLOR})`;
14355
- }
14356
- function statusMutedColorDeclaration() {
14357
- return `color: ${statusMutedColorValue()};`;
14358
- }
14359
- function contextualMutedStatusColorDeclaration(value) {
14360
- return `${STATUS_MUTED_COLOR_VAR}: ${value}`;
14361
- }
14362
- var STATUS_MUTED_COLOR_VAR, DEFAULT_STATUS_MUTED_COLOR, SURFACE_MUTED_STATUS_COLOR;
14363
- var init_contextualColors = __esmMin((() => {
14364
- STATUS_MUTED_COLOR_VAR = "--rb-status-muted-color";
14365
- DEFAULT_STATUS_MUTED_COLOR = "rgb(var(--tb-mutedText))";
14366
- SURFACE_MUTED_STATUS_COLOR = "color-mix(in oklab, currentColor, transparent 18%)";
14367
- }));
14368
- //#endregion
14369
14884
  //#region ../theme-core/src/cards/generateCardCss.ts
14370
14885
  function resolveCornerRadiiCss$1(cornerRadii, fallback) {
14371
14886
  const fallbackValue = CORNER_RADIUS_MAP$2[fallback];
@@ -14410,8 +14925,10 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
14410
14925
  const direction = GRADIENT_DIRECTION_MAP$1[variant.background.direction] || "to right";
14411
14926
  rules.push(`background: linear-gradient(${direction}, ${fromColor}, ${toColor})`);
14412
14927
  } else rules.push(`background: transparent`);
14413
- if (variant.foregroundToken) rules.push(`color: ${tokens.getColor(variant.foregroundToken)}`);
14414
- 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
+ }
14415
14932
  if (variant.accentEdge) {
14416
14933
  const side = ACCENT_EDGE_SIDE_MAP$1[variant.accentEdge.edge];
14417
14934
  const width = ACCENT_EDGE_WIDTH_MAP$1[variant.accentEdge.width];
@@ -14449,7 +14966,7 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
14449
14966
  init_resolver$1();
14450
14967
  init_constants$1();
14451
14968
  init_generateDefaultCardSystem();
14452
- init_contextualColors();
14969
+ init_surfaces();
14453
14970
  PER_CORNER_RADIUS_MAP$1 = {
14454
14971
  square: "0",
14455
14972
  soft: "0.5rem",
@@ -14484,7 +15001,9 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
14484
15001
  pill: "1.5rem"
14485
15002
  };
14486
15003
  }));
14487
- var init_core = __esmMin((() => {}));
15004
+ var init_core = __esmMin((() => {
15005
+ init_surfaces();
15006
+ }));
14488
15007
  //#endregion
14489
15008
  //#region ../theme-core/src/cards/index.ts
14490
15009
  var init_cards = __esmMin((() => {
@@ -14777,16 +15296,22 @@ var init_types$8 = __esmMin((() => {
14777
15296
  /**
14778
15297
  * Gradient configuration types and schemas
14779
15298
  */
14780
- var gradientStopSchema, gradientConfigSchema;
15299
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
14781
15300
  var init_types$7 = __esmMin((() => {
14782
15301
  init_themeColorTokens();
14783
15302
  gradientStopSchema = z$1.object({
14784
15303
  color: themeColorTokenSchema,
14785
15304
  position: z$1.number().min(0).max(100)
14786
15305
  });
15306
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
14787
15307
  gradientConfigSchema = z$1.object({
14788
- type: z$1.enum(["linear", "radial"]),
15308
+ type: z$1.enum([
15309
+ "linear",
15310
+ "radial",
15311
+ "conic"
15312
+ ]).default("linear"),
14789
15313
  angle: z$1.number().min(0).max(360).optional(),
15314
+ shape: radialGradientShapeSchema.optional(),
14790
15315
  position: z$1.string().optional(),
14791
15316
  stops: z$1.array(gradientStopSchema).min(2)
14792
15317
  });
@@ -15325,7 +15850,7 @@ var init_tokenOrColor = __esmMin((() => {
15325
15850
  "white",
15326
15851
  "yellow"
15327
15852
  ]);
15328
- })), 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;
15329
15854
  var init_schema$1 = __esmMin((() => {
15330
15855
  init_media$1();
15331
15856
  init_buttons();
@@ -15605,6 +16130,7 @@ var init_schema$1 = __esmMin((() => {
15605
16130
  "majorThird",
15606
16131
  "perfectFourth"
15607
16132
  ]);
16133
+ eyebrowTypographyStyleSchema = z$1.object({ family: z$1.string().min(1) });
15608
16134
  typographySchema = z$1.object({
15609
16135
  body: bodyTypographyStyleSchema,
15610
16136
  headings: z$1.object({
@@ -15617,7 +16143,8 @@ var init_schema$1 = __esmMin((() => {
15617
16143
  h6: headingTypographyOverridesSchema.optional()
15618
16144
  }),
15619
16145
  scale: typographyScaleSchema,
15620
- proseLinkStyle: proseLinkStyleSchema.optional()
16146
+ proseLinkStyle: proseLinkStyleSchema.optional(),
16147
+ eyebrow: eyebrowTypographyStyleSchema.optional()
15621
16148
  });
15622
16149
  spaceSchema = z$1.enum([
15623
16150
  "comfortable",
@@ -15642,7 +16169,8 @@ var init_schema$1 = __esmMin((() => {
15642
16169
  "soft",
15643
16170
  "hard"
15644
16171
  ]).nullable(),
15645
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
16172
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
16173
+ colorToken: themeColorTokenSchema.optional()
15646
16174
  });
15647
16175
  border = z$1.object({
15648
16176
  width: z$1.enum([
@@ -15883,6 +16411,7 @@ var init_schema$1 = __esmMin((() => {
15883
16411
  navWeight: navFontWeight.default("medium"),
15884
16412
  navTypography: z$1.enum(["body", "heading"]).optional(),
15885
16413
  navTextSize: navLinkStyleSchema.shape.textSize,
16414
+ navPlacement: z$1.enum(["end", "center"]).optional(),
15886
16415
  container: headerContainerSchema,
15887
16416
  border: headerBorderSchema,
15888
16417
  shadow: componentShadowSchema.optional(),
@@ -16641,7 +17170,8 @@ var init_curatedSiteStyles = __esmMin((() => {
16641
17170
  "site-style:bold-launch",
16642
17171
  "site-style:south-west-twerk-school",
16643
17172
  "site-style:kirtan-ornate",
16644
- "site-style:original-joy"
17173
+ "site-style:original-joy",
17174
+ "site-style:fulcrum"
16645
17175
  ];
16646
17176
  quietBudget = {
16647
17177
  accentDensity: "low",
@@ -17853,6 +18383,104 @@ var init_curatedSiteStyles = __esmMin((() => {
17853
18383
  buttonChoice("showtime-pill")
17854
18384
  ],
17855
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
+ ]
17856
18484
  })
17857
18485
  ];
17858
18486
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
@@ -18334,7 +18962,7 @@ var init_themeColorResolution = __esmMin((() => {
18334
18962
  init_tokenOrColor();
18335
18963
  }));
18336
18964
  //#endregion
18337
- //#region ../blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.ts
18965
+ //#region ../blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.ts
18338
18966
  function readColorToken(input, key) {
18339
18967
  const value = input[key];
18340
18968
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
@@ -18343,20 +18971,20 @@ function resolveOptionalForegroundColor(value, context) {
18343
18971
  if (!value) return null;
18344
18972
  return resolveBackgroundColorValue(value, context);
18345
18973
  }
18346
- function resolveSectionForegroundStyles(value, context) {
18974
+ function resolveSurfaceForegroundStyles(value, context) {
18347
18975
  if (!value || typeof value !== "object") return {};
18348
18976
  const input = value;
18349
18977
  const resolvedText = resolveOptionalForegroundColor(readColorToken(input, "textColor"), context);
18350
18978
  if (!resolvedText) return {};
18351
- return {
18352
- color: resolvedText,
18353
- "--section-text-color": resolvedText,
18354
- "--section-heading-color": resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? resolvedText,
18355
- "--section-link-color": resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? resolvedText,
18356
- "--section-supporting-color": resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? resolvedText
18357
- };
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
+ }) };
18358
18985
  }
18359
- var init_sectionForegroundStyles = __esmMin((() => {
18986
+ var init_surfaceForegroundStyles = __esmMin((() => {
18987
+ init_surfaces();
18360
18988
  init_themeColorResolution();
18361
18989
  }));
18362
18990
  //#endregion
@@ -18388,7 +19016,7 @@ function isTileTreatment(value) {
18388
19016
  function isEventListTreatment(value) {
18389
19017
  return typeof value === "string" && eventListTreatmentSet.has(value);
18390
19018
  }
18391
- 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;
18392
19020
  var init_boxStyles$1 = __esmMin((() => {
18393
19021
  init_core$2();
18394
19022
  init_spacing();
@@ -18396,8 +19024,7 @@ var init_boxStyles$1 = __esmMin((() => {
18396
19024
  init_colorStyles();
18397
19025
  init_cards();
18398
19026
  init_blockColorTokens();
18399
- init_themeColorResolution();
18400
- init_sectionForegroundStyles();
19027
+ init_surfaceForegroundStyles();
18401
19028
  spacingTransform = {
18402
19029
  id: "boxStyles.spacing",
18403
19030
  kind: "string",
@@ -18623,45 +19250,11 @@ var init_boxStyles$1 = __esmMin((() => {
18623
19250
  }, context);
18624
19251
  }
18625
19252
  };
18626
- sectionTextColorStyleTransform = {
18627
- id: "sectionStyles.resolveTextColorStyle",
18628
- kind: "formatter",
18629
- summary: "Resolve section text color token into a style object",
18630
- run: (value, options, context) => {
18631
- const fallbackToken = options?.fallbackToken;
18632
- if (typeof value === "string" && value.trim()) {
18633
- const colorValue = resolveBackgroundColorValue(value.trim(), context);
18634
- return {
18635
- color: colorValue,
18636
- "--section-text-color": colorValue
18637
- };
18638
- }
18639
- if (typeof fallbackToken === "string" && fallbackToken.trim()) {
18640
- const colorValue = resolveBackgroundColorValue(fallbackToken.trim(), context);
18641
- return {
18642
- color: colorValue,
18643
- "--section-text-color": colorValue
18644
- };
18645
- }
18646
- return {};
18647
- }
18648
- };
18649
- sectionHeadingColorStyleTransform = {
18650
- id: "sectionStyles.resolveHeadingColorStyle",
18651
- kind: "formatter",
18652
- summary: "Resolve section heading color token into a style object",
18653
- run: (value, options, context) => {
18654
- const fallbackToken = options?.fallbackToken;
18655
- if (typeof value === "string" && value.trim()) return { "--section-heading-color": resolveBackgroundColorValue(value.trim(), context) };
18656
- if (typeof fallbackToken === "string" && fallbackToken.trim()) return { "--section-heading-color": resolveBackgroundColorValue(fallbackToken.trim(), context) };
18657
- return {};
18658
- }
18659
- };
18660
19253
  sectionColorsStyleTransform = {
18661
19254
  id: "sectionStyles.resolveColorsStyle",
18662
19255
  kind: "formatter",
18663
- summary: "Resolve section foreground colors into a style object",
18664
- 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)
18665
19258
  };
18666
19259
  GAP_CLASS_MAP = {
18667
19260
  none: "rb-gap-semantic-none",
@@ -18709,8 +19302,6 @@ var init_boxStyles$1 = __esmMin((() => {
18709
19302
  sectionClassNameTransform,
18710
19303
  containerStylesResolveClassName,
18711
19304
  containerStylesResolveBoxClassName,
18712
- sectionTextColorStyleTransform,
18713
- sectionHeadingColorStyleTransform,
18714
19305
  sectionColorsStyleTransform,
18715
19306
  semanticGapTransform,
18716
19307
  semanticGapValueTransform
@@ -19339,8 +19930,11 @@ var init_filtering = __esmMin((() => {
19339
19930
  }));
19340
19931
  //#endregion
19341
19932
  //#region ../blocks/src/system/blocks/events/shared/layout.ts
19342
- function eventSectionHeaderLayoutNodes() {
19343
- 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];
19344
19938
  }
19345
19939
  var recoverEmptyHeadingWhenActive, recoverEmptyDescriptionWhenActive;
19346
19940
  var init_layout = __esmMin((() => {
@@ -19423,6 +20017,9 @@ var init_validation_constants = __esmMin((() => {
19423
20017
  "richText",
19424
20018
  "media",
19425
20019
  "videoEmbed",
20020
+ "icon",
20021
+ "feature-card-icon",
20022
+ "svg",
19426
20023
  "button",
19427
20024
  "link",
19428
20025
  "carousel",
@@ -19452,11 +20049,13 @@ var init_validation_constants = __esmMin((() => {
19452
20049
  "value.jsonArray",
19453
20050
  "value.csv",
19454
20051
  "array.marqueeLoop",
20052
+ "value.mapToken",
19455
20053
  "layout.maxWidthClass",
19456
20054
  "layout.headerRootClass",
19457
20055
  "layout.footerRootClass",
19458
20056
  "layout.headerRootStyle",
19459
20057
  "layout.headerSectionBackground",
20058
+ "layout.classicNavMode",
19460
20059
  "layout.footerRootStyle",
19461
20060
  "ui.headerNavLinkClass",
19462
20061
  "ui.headingClassFromAlignment",
@@ -20633,7 +21232,29 @@ var init_ctaRow = __esmMin((() => {
20633
21232
  fields: [createCtasRepeater({
20634
21233
  label: "Calls to action",
20635
21234
  itemLabel: "CTA",
20636
- 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
+ ] }
20637
21258
  })],
20638
21259
  layout: [ctaRow({
20639
21260
  collectionPath: "content.ctas",
@@ -20936,6 +21557,55 @@ function buildHighlightLayout() {
20936
21557
  function buildGridCardsLayout(className) {
20937
21558
  return el("div", { className }, buildResponsiveGridCards());
20938
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
+ }
20939
21609
  var grid$4, testimonialsCarouselFragment;
20940
21610
  var init_testimonialsCarousel = __esmMin((() => {
20941
21611
  init_types$4();
@@ -25084,7 +25754,8 @@ var init_events$1 = __esmMin((() => {
25084
25754
  "combined",
25085
25755
  "calendar",
25086
25756
  "list",
25087
- "timetable"
25757
+ "timetable",
25758
+ "week-board"
25088
25759
  ];
25089
25760
  eventCalendarDefaultViewValues = ["month", "week"];
25090
25761
  eventCalendarListLayoutValues = [
@@ -25872,6 +26543,40 @@ function getEventAvailability(event) {
25872
26543
  isFull: false
25873
26544
  };
25874
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
+ }
25875
26580
  var init_eventCapacity = __esmMin((() => {}));
25876
26581
  //#endregion
25877
26582
  //#region ../blocks/src/system/runtime/nodes/events/shared/destination.ts
@@ -101178,7 +101883,7 @@ var init_event_registration_client = __esmMin((() => {
101178
101883
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
101179
101884
  */
101180
101885
  function isLeafletApi(value) {
101181
- if (!isRecord$32(value)) return false;
101886
+ if (!isRecord$34(value)) return false;
101182
101887
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
101183
101888
  }
101184
101889
  function loadLeaflet() {
@@ -103753,6 +104458,153 @@ var init_EventCombined_client = __esmMin((() => {
103753
104458
  EventCombinedIslandClient = (props) => /* @__PURE__ */ jsx(EventCombinedClient, { ...toEventCombinedControllerProps(props) });
103754
104459
  }));
103755
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
103756
104608
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
103757
104609
  function buildTimetableModel(input) {
103758
104610
  const generic = buildTimetableModel$1({
@@ -104053,7 +104905,7 @@ function buildDisplayFilterParams(display) {
104053
104905
  filterVenueId: display.filterVenueId
104054
104906
  });
104055
104907
  }
104056
- var EventCalendarClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
104908
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
104057
104909
  var init_EventCalendar_client = __esmMin((() => {
104058
104910
  init_EventCalendar_interactive();
104059
104911
  init_EventListing_client();
@@ -104066,6 +104918,7 @@ var init_EventCalendar_client = __esmMin((() => {
104066
104918
  init_EventModalContext();
104067
104919
  init_EventModals();
104068
104920
  init_WeekAgendaView();
104921
+ init_WeekBoardView();
104069
104922
  init_WeekTimetableView();
104070
104923
  init_buttons();
104071
104924
  init_listOptions();
@@ -104103,8 +104956,20 @@ var init_EventCalendar_client = __esmMin((() => {
104103
104956
  });
104104
104957
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
104105
104958
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
104959
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
104106
104960
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
104107
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
+ };
104108
104973
  EventCalendarTimetableClient = ({ render }) => {
104109
104974
  const { display, hydration } = render;
104110
104975
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
@@ -106815,7 +107680,7 @@ var init_RichText = __esmMin((() => {
106815
107680
  function coerceRichTextDoc(value) {
106816
107681
  const raw = unwrapRichTextRoot(value);
106817
107682
  if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
106818
- if (isRecord$32(raw) && typeof raw.type === "string") return raw;
107683
+ if (isRecord$34(raw) && typeof raw.type === "string") return raw;
106819
107684
  return null;
106820
107685
  }
106821
107686
  var init_richText_coerce = __esmMin((() => {
@@ -112523,7 +113388,7 @@ const defaultLayout = styledSection({
112523
113388
  children: styledContainer({
112524
113389
  baseClassName: "rb-relative rb-isolate",
112525
113390
  children: stack({
112526
- gap: "xl",
113391
+ gap: "lg",
112527
113392
  className: "rb-w-full rb-max-w-4xl rb-mx-auto"
112528
113393
  }, [headingLayout, accordionLayout])
112529
113394
  }),
@@ -112540,7 +113405,7 @@ const questionColumnsLayout = styledSection({
112540
113405
  children: styledContainer({
112541
113406
  baseClassName: "rb-relative rb-isolate",
112542
113407
  children: stack({
112543
- gap: "xl",
113408
+ gap: "lg",
112544
113409
  className: "rb-w-full"
112545
113410
  }, [headingLayout, questionColumnsAccordionLayout])
112546
113411
  }),
@@ -112705,7 +113570,26 @@ const formattingTransforms = [
112705
113570
  arrayLengthTransform,
112706
113571
  jsonArrayTransform,
112707
113572
  csvTransform,
112708
- 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
+ }
112709
113593
  ];
112710
113594
  //#endregion
112711
113595
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -113289,6 +114173,7 @@ function splitSiteChromePlacementClasses(className) {
113289
114173
  init_colorConversion();
113290
114174
  init_core$2();
113291
114175
  init_colorStyles();
114176
+ init_surfaces();
113292
114177
  const joinClasses$1 = (parts) => parts.filter((part) => typeof part === "string" && part.trim().length > 0).join(" ").replace(/\s+/g, " ").trim();
113293
114178
  function resolveHeaderBrandDisplay(logo) {
113294
114179
  const display = logo?.brandDisplay ?? "logo-plus-title";
@@ -113358,6 +114243,26 @@ const headerLogoTextVisibleTransform = {
113358
114243
  return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
113359
114244
  }
113360
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
+ };
113361
114266
  const maxWidthClassTransform = {
113362
114267
  id: "layout.maxWidthClass",
113363
114268
  kind: "string",
@@ -113540,8 +114445,9 @@ const footerRootStyleTransform = {
113540
114445
  styleParts.push(backgroundColorStyle(token));
113541
114446
  }
113542
114447
  }
113543
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
113544
- 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 });
113545
114451
  styleParts.push(borderColorStyle("border"));
113546
114452
  return mergeStyles(...styleParts);
113547
114453
  }
@@ -113627,18 +114533,16 @@ const footerBottomBarStyleTransform = {
113627
114533
  const styleParts = [];
113628
114534
  const background = bottomBar?.background;
113629
114535
  if (background?.type === "color") styleParts.push(backgroundColorStyle(background.color ?? "surface"));
113630
- if (bottomBar?.textColor) styleParts.push(textColorStyle(bottomBar.textColor));
113631
114536
  const borderColorToken = bottomBar?.borderTop?.colorToken;
113632
114537
  if (borderColorToken) styleParts.push(borderColorStyle(borderColorToken));
113633
114538
  else styleParts.push(borderColorStyle("border"));
113634
114539
  const borderWidth = bottomBar?.borderTop?.width;
113635
114540
  if (borderWidth && borderWidth !== "none") styleParts.push({ borderTopWidth: borderWidth === "thin" ? "1px" : borderWidth === "medium" ? "2px" : "3px" });
113636
114541
  else if (borderWidth === "none") styleParts.push({ borderTopWidth: "0px" });
113637
- if (!bottomBar?.textColor) {
113638
- const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
113639
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
113640
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
113641
- }
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 });
113642
114546
  return mergeStyles(...styleParts);
113643
114547
  }
113644
114548
  };
@@ -113773,6 +114677,7 @@ const layoutTransforms = [
113773
114677
  headerLogoClassTransform,
113774
114678
  headerLogoMediaClassTransform,
113775
114679
  headerLogoTextVisibleTransform,
114680
+ classicNavModeTransform,
113776
114681
  footerRootClassTransform,
113777
114682
  headerRootStyleTransform,
113778
114683
  headerSectionBackgroundTransform,
@@ -113852,16 +114757,16 @@ const interpolateRichTextTokensOptionsSchema = z$1.object({ tokens: z$1.array(su
113852
114757
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
113853
114758
  function getSiteName(context) {
113854
114759
  const viewModel = context.viewModel;
113855
- if (!isRecord$32(viewModel)) return null;
114760
+ if (!isRecord$34(viewModel)) return null;
113856
114761
  const site = viewModel.site;
113857
- if (isRecord$32(site) && typeof site.title === "string") {
114762
+ if (isRecord$34(site) && typeof site.title === "string") {
113858
114763
  const title = site.title.trim();
113859
114764
  return title.length > 0 ? title : null;
113860
114765
  }
113861
114766
  const root = viewModel.$root;
113862
- if (isRecord$32(root)) {
114767
+ if (isRecord$34(root)) {
113863
114768
  const rootSite = root.site;
113864
- if (isRecord$32(rootSite) && typeof rootSite.title === "string") {
114769
+ if (isRecord$34(rootSite) && typeof rootSite.title === "string") {
113865
114770
  const title = rootSite.title.trim();
113866
114771
  if (title.length > 0) return title;
113867
114772
  }
@@ -113883,7 +114788,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
113883
114788
  });
113884
114789
  }
113885
114790
  function visitRichTextNode(node, allowedTokens, tokenValues) {
113886
- if (!isRecord$32(node)) return node;
114791
+ if (!isRecord$34(node)) return node;
113887
114792
  let changed = false;
113888
114793
  const nextNode = { ...node };
113889
114794
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -113904,13 +114809,13 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
113904
114809
  return changed ? nextNode : node;
113905
114810
  }
113906
114811
  function interpolateRichTextTokens(value, options, context) {
113907
- if (!isRecord$32(value)) return value;
114812
+ if (!isRecord$34(value)) return value;
113908
114813
  const allowedTokens = new Set(options.tokens);
113909
114814
  const tokenValues = {
113910
114815
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
113911
114816
  site_name: getSiteName(context)
113912
114817
  };
113913
- if (isRecord$32(value.doc)) {
114818
+ if (isRecord$34(value.doc)) {
113914
114819
  const nextDoc = visitRichTextNode(value.doc, allowedTokens, tokenValues);
113915
114820
  if (nextDoc === value.doc) return value;
113916
114821
  return {
@@ -114190,7 +115095,18 @@ const classicLayout = inline({
114190
115095
  logoRow,
114191
115096
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
114192
115097
  headerCta
114193
- ], 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"));
114194
115110
  const centeredLayout = stack({
114195
115111
  gap: "md",
114196
115112
  align: "center",
@@ -114265,6 +115181,7 @@ const siteHeaderManifest = createBlockManifest({
114265
115181
  }, [
114266
115182
  mobileHeaderBar,
114267
115183
  classicLayout,
115184
+ classicCenteredNavLayout,
114268
115185
  centeredLayout,
114269
115186
  transparentLayout,
114270
115187
  floatingLayout,
@@ -114313,6 +115230,7 @@ init_builder$2();
114313
115230
  init_fragments();
114314
115231
  init_defineBlock();
114315
115232
  init_colorStyles();
115233
+ init_surfaces();
114316
115234
  const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
114317
115235
  const whenTransformed = (from, transformId, equals = true) => (node) => ({
114318
115236
  ...node,
@@ -114482,7 +115400,7 @@ const footerLayout = section$1({
114482
115400
  style: { $bind: {
114483
115401
  from: "$root.theme.footer",
114484
115402
  transforms: [{ id: "layout.footerRootStyle" }],
114485
- fallback: mergeStyles(backgroundColorStyle("surface"), textColorStyle("text"), borderColorStyle("border"))
115403
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
114486
115404
  } }
114487
115405
  }, [
114488
115406
  simpleFooterLayout,
@@ -114545,7 +115463,7 @@ const backgroundImageClassName = "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full r
114545
115463
  */
114546
115464
  const wrapVariant$2 = (variantLayout) => styledSection({
114547
115465
  children: styledContainer({ children: stack({
114548
- gap: "xl",
115466
+ gap: "lg",
114549
115467
  className: "rb-relative"
114550
115468
  }, [...testimonialsHeadingFragment.layout, variantLayout]) }),
114551
115469
  baseClass: "",
@@ -114571,6 +115489,27 @@ const splitGridLayout = styledSection({
114571
115489
  spacing: "comfortable",
114572
115490
  imageClassName: backgroundImageClassName
114573
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
+ });
114574
115513
  const additionalFields = parseFieldDefinitions([
114575
115514
  ...testimonialsHeadingFragment.fields,
114576
115515
  {
@@ -114658,6 +115597,7 @@ const testimonialsBlockDefinition = {
114658
115597
  carousel: carouselLayout$1,
114659
115598
  grid: gridLayout$1,
114660
115599
  "split-grid": splitGridLayout,
115600
+ "featured-editorial": featuredEditorialLayout,
114661
115601
  highlight: highlightLayout
114662
115602
  },
114663
115603
  defaultVariant: "carousel",
@@ -114677,6 +115617,11 @@ const testimonialsBlockDefinition = {
114677
115617
  description: "Heading on the left with testimonial cards on the right",
114678
115618
  icon: "PanelLeft"
114679
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
+ },
114680
115625
  highlight: {
114681
115626
  label: "Highlight",
114682
115627
  description: "A single, centered testimonial with no carousel",
@@ -115220,7 +116165,7 @@ function grid$2(props, children) {
115220
116165
  const cardsLayout = styledSection({
115221
116166
  children: styledContainer({
115222
116167
  rootType: "stack",
115223
- rootProps: { gap: "xl" },
116168
+ rootProps: { gap: "lg" },
115224
116169
  children: [stack({
115225
116170
  gap: "sm",
115226
116171
  className: "rb-feature-cards-heading rb-mx-auto rb-max-w-3xl rb-text-center"
@@ -117574,7 +118519,7 @@ const eventCalendarLayout = [styledSection({
117574
118519
  children: styledContainer({
117575
118520
  rootType: "stack",
117576
118521
  rootProps: { gap: "lg" },
117577
- children: [...eventSectionHeaderLayoutNodes(), el("event-calendar", withApiBindings({
118522
+ children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
117578
118523
  events: { $bind: { from: "data.events" } },
117579
118524
  stage: { $bind: {
117580
118525
  from: "$root.previewStage",
@@ -117685,6 +118630,10 @@ const eventCalendarAdditionalFields = [
117685
118630
  value: "timetable",
117686
118631
  label: "Timetable"
117687
118632
  },
118633
+ {
118634
+ value: "week-board",
118635
+ label: "Week board"
118636
+ },
117688
118637
  {
117689
118638
  value: "list",
117690
118639
  label: "List"
@@ -117867,7 +118816,8 @@ const eventCalendarAdditionalFields = [
117867
118816
  oneOf: [
117868
118817
  "combined",
117869
118818
  "calendar",
117870
- "timetable"
118819
+ "timetable",
118820
+ "week-board"
117871
118821
  ]
117872
118822
  }
117873
118823
  }
@@ -117970,7 +118920,8 @@ const eventCalendarAdditionalFields = [
117970
118920
  "combined",
117971
118921
  "calendar",
117972
118922
  "list",
117973
- "timetable"
118923
+ "timetable",
118924
+ "week-board"
117974
118925
  ]
117975
118926
  }
117976
118927
  }
@@ -118005,7 +118956,8 @@ const eventCalendarAdditionalFields = [
118005
118956
  "combined",
118006
118957
  "calendar",
118007
118958
  "list",
118008
- "timetable"
118959
+ "timetable",
118960
+ "week-board"
118009
118961
  ]
118010
118962
  }, {
118011
118963
  field: "showFilters",
@@ -118028,7 +118980,8 @@ const eventCalendarAdditionalFields = [
118028
118980
  "combined",
118029
118981
  "calendar",
118030
118982
  "list",
118031
- "timetable"
118983
+ "timetable",
118984
+ "week-board"
118032
118985
  ]
118033
118986
  }, {
118034
118987
  field: "showFilters",
@@ -118051,7 +119004,8 @@ const eventCalendarAdditionalFields = [
118051
119004
  "combined",
118052
119005
  "calendar",
118053
119006
  "list",
118054
- "timetable"
119007
+ "timetable",
119008
+ "week-board"
118055
119009
  ]
118056
119010
  }, {
118057
119011
  field: "showFilters",
@@ -118073,7 +119027,8 @@ const eventCalendarAdditionalFields = [
118073
119027
  oneOf: [
118074
119028
  "combined",
118075
119029
  "list",
118076
- "timetable"
119030
+ "timetable",
119031
+ "week-board"
118077
119032
  ]
118078
119033
  }, { allOf: [{
118079
119034
  field: "variant",
@@ -118249,6 +119204,7 @@ const eventCalendarVariants = {
118249
119204
  combined: eventCalendarLayout[0],
118250
119205
  calendar: eventCalendarLayout[0],
118251
119206
  timetable: eventCalendarLayout[0],
119207
+ "week-board": eventCalendarLayout[0],
118252
119208
  list: eventCalendarLayout[0]
118253
119209
  };
118254
119210
  const eventCalendarContentShape = {
@@ -118262,6 +119218,7 @@ const eventCalendarContentShape = {
118262
119218
  { value: "combined" },
118263
119219
  { value: "calendar" },
118264
119220
  { value: "timetable" },
119221
+ { value: "week-board" },
118265
119222
  { value: "list" }
118266
119223
  ]
118267
119224
  },
@@ -118328,6 +119285,7 @@ const eventCalendarBlockDefinition = {
118328
119285
  combined: { label: "Combined" },
118329
119286
  calendar: { label: "Calendar" },
118330
119287
  timetable: { label: "Timetable" },
119288
+ "week-board": { label: "Week board" },
118331
119289
  list: { label: "List" }
118332
119290
  }
118333
119291
  }, eventCalendarContentShape),
@@ -122693,6 +123651,12 @@ const systemBlockDefinitions = [
122693
123651
  family: "centered",
122694
123652
  weight: "featured",
122695
123653
  bias: "soft"
123654
+ }),
123655
+ layoutProfile({
123656
+ variantKey: "featured-editorial",
123657
+ family: "split",
123658
+ weight: "featured",
123659
+ bias: "soft"
122696
123660
  })
122697
123661
  ]
122698
123662
  })),
@@ -122825,6 +123789,11 @@ const systemBlockDefinitions = [
122825
123789
  variantKey: "timetable",
122826
123790
  family: "stack",
122827
123791
  weight: "standard"
123792
+ }),
123793
+ layoutProfile({
123794
+ variantKey: "week-board",
123795
+ family: "stack",
123796
+ weight: "standard"
122828
123797
  })
122829
123798
  ]
122830
123799
  })),
@@ -123185,7 +124154,15 @@ function gradientToCss(config, tokens) {
123185
124154
  const stops = config.stops.map((stop) => {
123186
124155
  return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
123187
124156
  }).join(", ");
123188
- 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
+ }
123189
124166
  return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
123190
124167
  }
123191
124168
  //#endregion
@@ -123214,7 +124191,7 @@ function backgroundVideoMobileClassNames(input) {
123214
124191
  //#region ../blocks/src/system/transforms/registry/background.ts
123215
124192
  init_background$1();
123216
124193
  init_themeColorResolution();
123217
- init_sectionForegroundStyles();
124194
+ init_surfaceForegroundStyles();
123218
124195
  init_media();
123219
124196
  const isString$1 = (value) => typeof value === "string" && value.trim().length > 0;
123220
124197
  const isNumber$1 = (value) => typeof value === "number" && !isNaN(value);
@@ -123271,8 +124248,8 @@ const backgroundTransforms = [
123271
124248
  {
123272
124249
  id: "background.resolveColorsStyle",
123273
124250
  kind: "formatter",
123274
- summary: "Resolve section foreground colors from a background object into scoped CSS vars",
123275
- 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)
123276
124253
  },
123277
124254
  {
123278
124255
  id: "background.resolveAllowOverflow",
@@ -123908,21 +124885,53 @@ function Inline({ as: Comp = "div", gap = "md", align = "center", justify = "sta
123908
124885
  //#endregion
123909
124886
  //#region ../blocks/src/primitives/layout/Grid.tsx
123910
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
+ ];
123911
124911
  function Grid({ as: Comp = "div", cols = {
123912
124912
  base: 1,
123913
124913
  md: 2
123914
- }, gap = "md", className, children, "data-slot": dataSlot, ...rest }) {
123915
- const colsObj = typeof cols === "number" ? { base: cols } : cols;
123916
- const colClasses = [
123917
- colsObj.base && `rb-grid-cols-${colsObj.base}`,
123918
- colsObj.sm && `rb-sm-grid-cols-${colsObj.sm}`,
123919
- colsObj.md && `rb-md-grid-cols-${colsObj.md}`,
123920
- colsObj.lg && `rb-lg-grid-cols-${colsObj.lg}`,
123921
- colsObj.xl && `rb-xl-grid-cols-${colsObj.xl}`
123922
- ];
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;
123923
124931
  return /* @__PURE__ */ jsx(Comp, {
123924
124932
  ...rest,
123925
- className: clsx("rb-grid", colClasses, {
124933
+ style: mergedStyle,
124934
+ className: clsx("rb-grid", hasTracks && "rb-grid-tracks", colClasses, {
123926
124935
  "rb-gap-0": gap === "none",
123927
124936
  "rb-gap-1": gap === "xs",
123928
124937
  "rb-gap-2": gap === "sm",
@@ -124003,6 +125012,138 @@ function Text$2({ as: Comp = "span", children, className = "", path, maxLength:
124003
125012
  });
124004
125013
  }
124005
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
124006
125147
  //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
124007
125148
  function renderInlineText(value) {
124008
125149
  return value.map((run, index) => renderRun(run, index));
@@ -124056,37 +125197,57 @@ const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockCo
124056
125197
  ...rest
124057
125198
  });
124058
125199
  };
124059
- 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 }) => {
124060
125215
  const content = value ?? children;
124061
125216
  if (!content) {
124062
125217
  console.warn("[ButtonNode] No content to render - value and children are both empty");
124063
125218
  return null;
124064
125219
  }
125220
+ const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({
125221
+ trailingIcon,
125222
+ trailingIconColorToken,
125223
+ personalityAffordance
125224
+ }));
124065
125225
  const resolvedHref = typeof href === "string" ? href.trim() : "";
124066
125226
  if (linkRequired && resolvedHref.length === 0) {
124067
125227
  console.warn("[ButtonNode] Missing href for link-required button");
124068
125228
  return null;
124069
125229
  }
125230
+ const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
124070
125231
  const resolvedVariantId = parseThemeButtonVariantId(variantId);
124071
125232
  const combinedClassName = resolvedVariantId ? themeButtonClassName({
124072
125233
  variant: resolvedVariantId,
124073
125234
  size,
124074
- extraClassName: className
124075
- }) : className;
124076
- if (resolvedHref) return /* @__PURE__ */ jsx("a", {
125235
+ extraClassName
125236
+ }) : extraClassName;
125237
+ if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
124077
125238
  href: resolvedHref,
124078
125239
  target,
124079
125240
  rel,
124080
125241
  className: combinedClassName,
124081
125242
  ...rest,
124082
- children: content
125243
+ children: [content, affordanceIcon]
124083
125244
  });
124084
- return /* @__PURE__ */ jsx("button", {
125245
+ return /* @__PURE__ */ jsxs("button", {
124085
125246
  type,
124086
125247
  disabled,
124087
125248
  className: combinedClassName,
124088
125249
  ...rest,
124089
- children: content
125250
+ children: [content, affordanceIcon]
124090
125251
  });
124091
125252
  };
124092
125253
  const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
@@ -124111,106 +125272,6 @@ const LinkNode = ({ href, children, className, target, rel, linkRequired = false
124111
125272
  });
124112
125273
  };
124113
125274
  //#endregion
124114
- //#region ../blocks/src/system/icons/cta.ts
124115
- init_svg();
124116
- /**
124117
- * Curated icon set for CTA/button icons.
124118
- *
124119
- * Guardrail: keep this list small and action-oriented. This is intentionally not the full Lucide set.
124120
- * Extend by adding to CTA_ICON_NAMES and the mapping below (explicit imports only).
124121
- */
124122
- const CTA_ICON_NAMES = [
124123
- "ArrowRight",
124124
- "ArrowLeft",
124125
- "ChevronRight",
124126
- "ChevronLeft",
124127
- "ChevronUp",
124128
- "ChevronDown",
124129
- "ExternalLink",
124130
- "Download",
124131
- "Upload",
124132
- "Mail",
124133
- "Phone",
124134
- "Play",
124135
- "ShoppingCart",
124136
- "Calendar",
124137
- "MapPin",
124138
- "Info",
124139
- "Plus",
124140
- "Minus",
124141
- "Check",
124142
- "X"
124143
- ];
124144
- const CTA_ICON_COMPONENTS = {
124145
- ArrowRight: ArrowRightIcon,
124146
- ArrowLeft: ArrowLeftIcon,
124147
- ChevronRight: ChevronRightIcon,
124148
- ChevronLeft: ChevronLeftIcon,
124149
- ChevronUp: ChevronUpIcon,
124150
- ChevronDown: ChevronDownIcon,
124151
- ExternalLink: ExternalLinkIcon,
124152
- Download: DownloadIcon,
124153
- Upload: UploadIcon,
124154
- Mail: MailIcon,
124155
- Phone: PhoneIcon,
124156
- Play: PlayIcon,
124157
- ShoppingCart: ShoppingCartIcon,
124158
- Calendar: CalendarIcon,
124159
- MapPin: MapPinIcon,
124160
- Info: InfoIcon,
124161
- Plus: PlusIcon,
124162
- Minus: MinusIcon,
124163
- Check: CheckIcon$1,
124164
- X: XIcon
124165
- };
124166
- function isCtaIconName(value) {
124167
- return typeof value === "string" && CTA_ICON_NAMES.includes(value);
124168
- }
124169
- function formatLucideName(name) {
124170
- return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
124171
- }
124172
- const CTA_ICON_OPTIONS = CTA_ICON_NAMES.map((id) => ({
124173
- id,
124174
- label: formatLucideName(id)
124175
- }));
124176
- function getCtaIconComponent(name) {
124177
- if (!isCtaIconName(name)) return null;
124178
- return CTA_ICON_COMPONENTS[name] ?? null;
124179
- }
124180
- //#endregion
124181
- //#region ../blocks/src/system/icons/registry.ts
124182
- init_presets();
124183
- function buildSearchText(parts) {
124184
- return parts.map((part) => part.trim()).filter(Boolean).join(" ");
124185
- }
124186
- function semanticDefinitionToOption(definition, preset) {
124187
- return {
124188
- id: definition.id,
124189
- label: definition.label,
124190
- searchText: buildSearchText([
124191
- definition.label,
124192
- definition.id,
124193
- ...definition.tags,
124194
- ...definition.domains,
124195
- ...definition.tone
124196
- ]),
124197
- preset
124198
- };
124199
- }
124200
- CTA_ICON_OPTIONS.map((option) => ({
124201
- id: option.id,
124202
- label: option.label,
124203
- searchText: buildSearchText([option.label, option.id]),
124204
- preset: "cta"
124205
- }));
124206
- function semanticOptionsForPreset(preset) {
124207
- return SEMANTIC_ICON_DEFINITIONS.filter((definition) => definition.presets.includes(preset)).map((definition) => semanticDefinitionToOption(definition, preset));
124208
- }
124209
- semanticOptionsForPreset("feature");
124210
- function getIconComponent(name) {
124211
- return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
124212
- }
124213
- //#endregion
124214
125275
  //#region ../blocks/src/system/runtime/nodes/icon.tsx
124215
125276
  const IconNode = ({ value, title, className, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
124216
125277
  const parsedValue = parseBlockIconValue(value);
@@ -124837,6 +125898,77 @@ const HeaderSectionNode = ({ blockId, children, className, "data-preview-site-ch
124837
125898
  };
124838
125899
  var header_section_server_default = markEditableSurfaceForwarding(HeaderSectionNode);
124839
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
124840
125972
  //#region ../blocks/src/system/runtime/nodes/booking-form.server.tsx
124841
125973
  init_booking_form_interactive();
124842
125974
  /**
@@ -126288,6 +127420,7 @@ init_clsx();
126288
127420
  init_EventListing_view();
126289
127421
  init_EventCalendar_interactive();
126290
127422
  init_WeekAgendaView();
127423
+ init_WeekBoardView();
126291
127424
  init_utils$3();
126292
127425
  init_timetableModel();
126293
127426
  init_buttons();
@@ -126632,6 +127765,17 @@ function renderTimetableSsr(display) {
126632
127765
  })]
126633
127766
  });
126634
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
+ }
126635
127779
  function formatHourLabel(hour) {
126636
127780
  if (hour === 0) return "12 AM";
126637
127781
  if (hour === 12) return "12 PM";
@@ -126658,6 +127802,9 @@ const EventCalendarSSR = (props) => {
126658
127802
  case "timetable":
126659
127803
  content = renderTimetableSsr(display);
126660
127804
  break;
127805
+ case "week-board":
127806
+ content = renderWeekBoardSsr(display);
127807
+ break;
126661
127808
  case "calendar":
126662
127809
  content = renderCalendarSsr(display);
126663
127810
  break;
@@ -127221,6 +128368,7 @@ init_spinner();
127221
128368
  const serverComponentRegistry = {
127222
128369
  div: DivNode,
127223
128370
  figure: FigureNode,
128371
+ svg: SvgNode,
127224
128372
  section: SectionNode,
127225
128373
  headerSection: header_section_server_default,
127226
128374
  stack: StackNode,
@@ -128733,9 +129881,12 @@ function formatFontFamily(family, fallback = "sans-serif") {
128733
129881
  }
128734
129882
  //#endregion
128735
129883
  //#region ../theme-core/src/styles/shadow.ts
129884
+ init_colorStyles();
128736
129885
  function generateShadowCssVars(theme) {
128737
129886
  const level = theme.shadow.elevation;
128738
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})`;
128739
129890
  const base = {
128740
129891
  sm: [{
128741
129892
  y: 1,
@@ -128795,7 +129946,7 @@ function generateShadowCssVars(theme) {
128795
129946
  const blurMul = soft ? 1.2 : 1;
128796
129947
  const alphaMul = soft ? .9 : 1.05;
128797
129948
  const fmt = (layers) => layers.map((l) => {
128798
- 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))))}`;
128799
129950
  }).join(", ");
128800
129951
  return {
128801
129952
  "--shadow-sm": fmt(base.sm),
@@ -128831,6 +129982,7 @@ function parseBorderWidth(widthClass) {
128831
129982
  init_types$9();
128832
129983
  init_constants$1();
128833
129984
  init_colorStyles();
129985
+ init_surfaces();
128834
129986
  /**
128835
129987
  * Corner radius map for accordion surfaces. Pill is capped here because FAQ
128836
129988
  * rows contain long text and expanded content; full capsules clip awkwardly.
@@ -128864,7 +130016,13 @@ function generateAccordionCss({ themeId, theme, accordionSystem }) {
128864
130016
  const questionColumnsLastItemSelector = `${questionColumnsItemSelector}:last-child`;
128865
130017
  const questionColumnsTriggerSelector = `${questionColumnsItemSelector} .accordion-trigger`;
128866
130018
  const rootRules = [];
128867
- 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
+ }
128868
130026
  const borderRadius = CORNER_MAP$2[accordionSystem.corners ?? theme.corners];
128869
130027
  rootRules.push(`border-radius: ${borderRadius}`);
128870
130028
  if (accordionSystem.border) {
@@ -130429,7 +131587,7 @@ function toHeroLineHeight(lineHeight) {
130429
131587
  }
130430
131588
  //#endregion
130431
131589
  //#region ../theme-core/src/status/generateStatusCss.ts
130432
- init_contextualColors();
131590
+ init_surfaces();
130433
131591
  /**
130434
131592
  * Corner radius map - derives alert border-radius from theme.corners
130435
131593
  */
@@ -130459,7 +131617,7 @@ ${root} .status-error { color: rgb(var(--tb-destructive)); }
130459
131617
  ${root} .status-success { color: rgb(var(--tb-success)); }
130460
131618
  ${root} .status-warning { color: rgb(var(--tb-warning)); }
130461
131619
  ${root} .status-info { color: rgb(var(--tb-info)); }
130462
- ${root} .status-muted { ${statusMutedColorDeclaration()} }`);
131620
+ ${root} .status-muted { color: ${surfaceForegroundValue("supporting")}; }`);
130463
131621
  cssBlocks.push(`/* Alert containers */
130464
131622
  ${root} .alert {
130465
131623
  padding: 1rem;
@@ -130513,9 +131671,6 @@ ${root} .button-link:hover {
130513
131671
  return cssBlocks.join("\n\n");
130514
131672
  }
130515
131673
  //#endregion
130516
- //#region ../theme-core/src/status/index.ts
130517
- init_contextualColors();
130518
- //#endregion
130519
131674
  //#region ../theme-core/src/progress/generateProgressCss.ts
130520
131675
  /**
130521
131676
  * Generate progress indicator CSS from theme settings.
@@ -130600,6 +131755,10 @@ ${root} .step-connector {
130600
131755
  }
130601
131756
  //#endregion
130602
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
+ }
130603
131762
  /**
130604
131763
  * Generate typography CSS for heading elements.
130605
131764
  *
@@ -130628,7 +131787,7 @@ ${root} :where(h1) {
130628
131787
  font-style: var(--fi-h1, var(--fi-heading, normal));
130629
131788
  letter-spacing: var(--ls-h1, var(--ls-heading));
130630
131789
  line-height: var(--lh-h1, var(--lh-heading));
130631
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h1, var(--hc-heading, inherit))));
131790
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(1))};
130632
131791
  }
130633
131792
 
130634
131793
  ${root} :where(h2) {
@@ -130637,7 +131796,7 @@ ${root} :where(h2) {
130637
131796
  font-style: var(--fi-h2, var(--fi-heading, normal));
130638
131797
  letter-spacing: var(--ls-h2, var(--ls-heading));
130639
131798
  line-height: var(--lh-h2, var(--lh-heading));
130640
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h2, var(--hc-heading, inherit))));
131799
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(2))};
130641
131800
  }
130642
131801
 
130643
131802
  ${root} :where(h3) {
@@ -130646,7 +131805,7 @@ ${root} :where(h3) {
130646
131805
  font-style: var(--fi-h3, var(--fi-heading, normal));
130647
131806
  letter-spacing: var(--ls-h3, var(--ls-heading));
130648
131807
  line-height: var(--lh-h3, var(--lh-heading));
130649
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h3, var(--hc-heading, inherit))));
131808
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(3))};
130650
131809
  }
130651
131810
 
130652
131811
  ${root} :where(h4) {
@@ -130655,7 +131814,7 @@ ${root} :where(h4) {
130655
131814
  font-style: var(--fi-h4, var(--fi-heading, normal));
130656
131815
  letter-spacing: var(--ls-h4, var(--ls-heading));
130657
131816
  line-height: var(--lh-h4, var(--lh-heading));
130658
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h4, var(--hc-heading, inherit))));
131817
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(4))};
130659
131818
  }
130660
131819
 
130661
131820
  ${root} :where(h5) {
@@ -130664,7 +131823,7 @@ ${root} :where(h5) {
130664
131823
  font-style: var(--fi-h5, var(--fi-heading, normal));
130665
131824
  letter-spacing: var(--ls-h5, var(--ls-heading));
130666
131825
  line-height: var(--lh-h5, var(--lh-heading));
130667
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h5, var(--hc-heading, inherit))));
131826
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(5))};
130668
131827
  }
130669
131828
 
130670
131829
  ${root} :where(h6) {
@@ -130673,7 +131832,7 @@ ${root} :where(h6) {
130673
131832
  font-style: var(--fi-h6, var(--fi-heading, normal));
130674
131833
  letter-spacing: var(--ls-h6, var(--ls-heading));
130675
131834
  line-height: var(--lh-h6, var(--lh-heading));
130676
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h6, var(--hc-heading, inherit))));
131835
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(6))};
130677
131836
  }`);
130678
131837
  cssBlocks.push(`/* Display variant for hero/splash headings */
130679
131838
  ${root} :where(.heading-display) {
@@ -131072,6 +132231,7 @@ const THEME_RADIUS_CSS_VARS = {
131072
132231
  block: "--rb-block-radius",
131073
132232
  button: "--rb-button-radius",
131074
132233
  input: "--rb-input-radius",
132234
+ panel: "--rb-panel-radius",
131075
132235
  legacyCard: "--radius-card",
131076
132236
  legacyControl: "--radius-control"
131077
132237
  };
@@ -131153,6 +132313,10 @@ ${`:where([data-theme-scope="${themeId}"]) :where([data-block="customer-portal"]
131153
132313
  /* Modal (shared rb-modal classes) */
131154
132314
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.35);
131155
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);
131156
132320
  --rb-modal-border: var(--cp-card-border);
131157
132321
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
131158
132322
  --rb-modal-radius: var(--cp-card-radius);
@@ -131878,6 +133042,7 @@ function buildThemeCssVars(theme) {
131878
133042
  const inputSystem = resolveThemeInputSystem(theme);
131879
133043
  const blockRadius = mapBlockRadius(theme.corners);
131880
133044
  const buttonRadius = mapButtonRadius(theme.corners);
133045
+ const panelRadius = mapPanelRadius(theme.corners);
131881
133046
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
131882
133047
  return {
131883
133048
  ...generateCssVars(theme.palette),
@@ -131886,6 +133051,7 @@ function buildThemeCssVars(theme) {
131886
133051
  ...generateShadowCssVars(theme),
131887
133052
  ["--font-heading"]: formatFontFamily(typography.headings.default.family),
131888
133053
  ["--font-body"]: formatFontFamily(typography.body.family),
133054
+ ["--font-eyebrow"]: typography.eyebrow?.family ? formatFontFamily(typography.eyebrow.family) : "var(--font-body)",
131889
133055
  ["--font-weight-heading"]: mapWeight(typography.headings.default.weight),
131890
133056
  ["--font-weight-body"]: mapWeight(typography.body.weight),
131891
133057
  ...typography.headings.h1.weight ? { ["--fw-h1"]: mapWeight(typography.headings.h1.weight) } : {},
@@ -131936,12 +133102,13 @@ function buildThemeCssVars(theme) {
131936
133102
  ["--fs-h3-fluid"]: sized.h3Fluid,
131937
133103
  ["--fs-h1-display"]: sized.h1Display,
131938
133104
  ["--fs-h1-display-fluid"]: sized.h1DisplayFluid,
131939
- ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom"),
133105
+ ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom", shadow.colorToken),
131940
133106
  ["--space-mult"]: mapSpaceMult(space),
131941
133107
  ["--motion-duration"]: mapMotionDuration(motion.level),
131942
133108
  ["--motion-ease"]: mapMotionEasing(motion.easing ?? "standard"),
131943
133109
  ["--rt-space-y"]: mapRhythm(space),
131944
133110
  [THEME_RADIUS_CSS_VARS.block]: blockRadius,
133111
+ [THEME_RADIUS_CSS_VARS.panel]: panelRadius,
131945
133112
  ["--rb-block-transition"]: mapBlockTransition(motion.level),
131946
133113
  [THEME_RADIUS_CSS_VARS.button]: buttonRadius,
131947
133114
  ["--rb-border-width"]: mapBorderWidth(border.width),
@@ -131995,20 +133162,22 @@ function mapWeight(w) {
131995
133162
  bold: 700
131996
133163
  }[w];
131997
133164
  }
131998
- function mapShadow(level, softness, position = "bottom") {
133165
+ function mapShadow(level, softness, position = "bottom", colorToken) {
131999
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})`;
132000
133169
  const offset = {
132001
133170
  low: 2,
132002
133171
  medium: 4,
132003
133172
  high: 6
132004
133173
  }[level];
132005
133174
  const xOffset = position === "bottom-right" ? offset : 0;
132006
- 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")}`;
132007
133176
  const soft = softness !== "crisp";
132008
133177
  switch (level) {
132009
- case "low": return soft ? `${xOffset}px 1px 2px rgba(0,0,0,.06)` : `${xOffset}px 1px 1px rgba(0,0,0,.12)`;
132010
- case "medium": return soft ? `${xOffset}px 10px 20px rgba(0,0,0,.08)` : `${xOffset}px 6px 12px rgba(0,0,0,.16)`;
132011
- 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")}`;
132012
133181
  }
132013
133182
  }
132014
133183
  function mapSpaceMult(space) {
@@ -132055,6 +133224,21 @@ function mapBlockRadius(corners) {
132055
133224
  }[corners];
132056
133225
  }
132057
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
+ /**
132058
133242
  * Map motion level to block transition duration.
132059
133243
  * These are Tier 2 vars used consistently across blocks.
132060
133244
  */
@@ -132291,7 +133475,7 @@ function hydrateValue(value, context) {
132291
133475
  const resolvedItems = value.map((item) => hydrateValue(item, context));
132292
133476
  return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
132293
133477
  }
132294
- if (isRecord$32(value)) {
133478
+ if (isRecord$34(value)) {
132295
133479
  if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
132296
133480
  if (isPageLink$1(value)) return hydratePageLink(value, context);
132297
133481
  if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
@@ -133048,8 +134232,12 @@ const containerResponsiveThemeCss = `/*
133048
134232
  text-transform: uppercase;
133049
134233
  }
133050
134234
 
133051
- /* 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). */
133052
134239
  .rb-eyebrow {
134240
+ font-family: var(--font-eyebrow, var(--font-body));
133053
134241
  font-size: 0.875rem;
133054
134242
  font-weight: 600;
133055
134243
  letter-spacing: 0.025em;
@@ -133064,11 +134252,11 @@ const containerResponsiveThemeCss = `/*
133064
134252
  width: fit-content;
133065
134253
  align-items: center;
133066
134254
  justify-content: center;
133067
- 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);
133068
134256
  border-radius: 9999px;
133069
- 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);
133070
134258
  padding: 0.5rem 1rem;
133071
- color: var(--section-text-color, rgb(var(--tb-text)));
134259
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
133072
134260
  line-height: 1;
133073
134261
  }
133074
134262
  .rb-eyebrow-treatment-pill.rb-eyebrow-treatment-accent {
@@ -133570,6 +134758,58 @@ const containerResponsiveThemeCss = `/*
133570
134758
  }
133571
134759
  }
133572
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
+
133573
134813
  }
133574
134814
 
133575
134815
  /* Alignment */
@@ -134774,6 +136014,11 @@ const containerResponsiveThemeCss = `/*
134774
136014
  :where(.theme-scope) .rb-modal {
134775
136015
  width: min(var(--rb-modal-max-width, 560px), 100%);
134776
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))));
134777
136022
  border: 1px solid var(--rb-modal-border, rgb(var(--tb-border)));
134778
136023
  border-radius: var(--rb-modal-radius, var(--radius-card));
134779
136024
  box-shadow: var(--rb-modal-shadow, var(--shadow-lg, var(--shadow-elev)));
@@ -134793,7 +136038,7 @@ const containerResponsiveThemeCss = `/*
134793
136038
  font-family: var(--font-heading);
134794
136039
  font-size: 1.0625rem;
134795
136040
  font-weight: 600;
134796
- color: rgb(var(--tb-text));
136041
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
134797
136042
  }
134798
136043
 
134799
136044
  :where(.theme-scope) .rb-modal__close {
@@ -134803,7 +136048,7 @@ const containerResponsiveThemeCss = `/*
134803
136048
  height: 2.25rem;
134804
136049
  padding: 0;
134805
136050
  line-height: 1;
134806
- color: rgb(var(--tb-mutedText));
136051
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
134807
136052
  cursor: pointer;
134808
136053
  display: grid;
134809
136054
  place-items: center;
@@ -134811,7 +136056,7 @@ const containerResponsiveThemeCss = `/*
134811
136056
  }
134812
136057
 
134813
136058
  :where(.theme-scope) .rb-modal__close:hover {
134814
- color: rgb(var(--tb-text));
136059
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
134815
136060
  background: rgba(var(--tb-border), 0.2);
134816
136061
  }
134817
136062
 
@@ -134822,7 +136067,7 @@ const containerResponsiveThemeCss = `/*
134822
136067
 
134823
136068
  :where(.theme-scope) .rb-modal__body {
134824
136069
  padding: 0.875rem 1rem 1rem;
134825
- color: rgb(var(--tb-text));
136070
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
134826
136071
  font-size: 0.9375rem;
134827
136072
  line-height: 1.45;
134828
136073
  }
@@ -134982,7 +136227,7 @@ const containerResponsiveThemeCss = `/*
134982
136227
  & h6 {
134983
136228
  font-family: var(--font-heading);
134984
136229
  /* Color is set by generateTypographyCss.ts with full cascade:
134985
- --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 */
134986
136231
  font-weight: var(--font-weight-heading);
134987
136232
  text-transform: var(--tt-heading);
134988
136233
  font-variant-caps: var(--fv-heading);
@@ -135130,7 +136375,7 @@ const containerResponsiveThemeCss = `/*
135130
136375
 
135131
136376
  /* Neutral prose uses theme text color by default */
135132
136377
  :where(.theme-scope) .rb-prose-neutral {
135133
- color: var(--section-text-color, rgb(var(--tb-text)));
136378
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
135134
136379
  }
135135
136380
 
135136
136381
  :where(.theme-scope) .rb-prose p,
@@ -135164,8 +136409,14 @@ const containerResponsiveThemeCss = `/*
135164
136409
 
135165
136410
  :where(.theme-scope) .rb-prose a {
135166
136411
  --rb-prose-effective-link-color: var(
135167
- --section-link-color,
135168
- 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
+ )
135169
136420
  );
135170
136421
  color: var(--rb-prose-effective-link-color);
135171
136422
  text-decoration-line: var(--rb-prose-link-decoration-line, underline);
@@ -135176,14 +136427,11 @@ const containerResponsiveThemeCss = `/*
135176
136427
  );
135177
136428
  text-underline-offset: var(--rb-prose-link-underline-offset, 0.14em);
135178
136429
  text-decoration-color: var(
135179
- --section-link-decoration-color,
135180
- var(
135181
- --rb-prose-link-decoration-color,
135182
- color-mix(
135183
- in srgb,
135184
- var(--rb-prose-effective-link-color) 35%,
135185
- transparent
135186
- )
136430
+ --rb-prose-link-decoration-color,
136431
+ color-mix(
136432
+ in srgb,
136433
+ var(--rb-prose-effective-link-color) 35%,
136434
+ transparent
135187
136435
  )
135188
136436
  );
135189
136437
  transition:
@@ -135207,7 +136455,7 @@ const containerResponsiveThemeCss = `/*
135207
136455
 
135208
136456
  :where(.theme-scope) .rb-prose blockquote {
135209
136457
  /* Blockquotes use muted text color */
135210
- 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))));
135211
136459
  border-left-color: rgb(var(--tb-border));
135212
136460
  }
135213
136461
 
@@ -136241,6 +137489,10 @@ const containerResponsiveThemeCss = `/*
136241
137489
  :where(.theme-scope) .card-surface {
136242
137490
  background: rgb(var(--tb-surface));
136243
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)));
136244
137496
  border: 1px solid rgb(var(--tb-border));
136245
137497
  border-radius: var(--radius-card);
136246
137498
  box-shadow: var(--shadow-elev);
@@ -136384,6 +137636,10 @@ const containerResponsiveThemeCss = `/*
136384
137636
  padding: clamp(1rem, 2vw, 1.5rem);
136385
137637
  background: var(--rb-reg-surface-bg, rgb(var(--tb-surface, 248 250 252)));
136386
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)))));
136387
137643
  transition: border-color var(--rb-block-transition, 150ms) ease;
136388
137644
  width: 100%;
136389
137645
  max-width: 800px;
@@ -139471,6 +140727,350 @@ const containerResponsiveThemeCss = `/*
139471
140727
  }
139472
140728
  }
139473
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
+
139474
141074
  /* -----------------------------------------------------------------------------
139475
141075
  * Event Calendar Modals
139476
141076
  * Modal overlays for event details and day events list
@@ -139898,7 +141498,7 @@ const containerResponsiveThemeCss = `/*
139898
141498
  }
139899
141499
 
139900
141500
  :where(.theme-scope) .rb-inline-text-accent-contrast {
139901
- color: var(--section-text-color, rgb(var(--tb-text)));
141501
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
139902
141502
  }
139903
141503
 
139904
141504
  :where(.theme-scope) .rb-inline-text-highlight {
@@ -139909,7 +141509,7 @@ const containerResponsiveThemeCss = `/*
139909
141509
  }
139910
141510
 
139911
141511
  :where(.theme-scope) .rb-inline-text-highlight-soft {
139912
- 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);
139913
141513
  }
139914
141514
 
139915
141515
  :where(.theme-scope) .rb-inline-text-highlight-accent {
@@ -139928,7 +141528,7 @@ const containerResponsiveThemeCss = `/*
139928
141528
 
139929
141529
  /* Eyebrow - color only (typography via .rb-eyebrow) */
139930
141530
  :where(.theme-scope) :where([data-block="hero"]) .hero-eyebrow:not(.rb-eyebrow-treatment-accent) {
139931
- color: var(--section-text-color, rgb(var(--tb-text)));
141531
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
139932
141532
  }
139933
141533
 
139934
141534
  /* Subheadline - supporting text below headline */
@@ -139938,7 +141538,7 @@ const containerResponsiveThemeCss = `/*
139938
141538
 
139939
141539
  :where(.theme-scope) :where([data-block="hero"]) .hero-subheadline {
139940
141540
  font-size: 1.125rem;
139941
- 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))));
139942
141542
  }
139943
141543
 
139944
141544
  @container rb-site (min-width: 640px) {
@@ -140029,7 +141629,7 @@ const containerResponsiveThemeCss = `/*
140029
141629
 
140030
141630
  /* CTA content/body text */
140031
141631
  :where(.theme-scope) :where([data-block="cta-full"]) .cta-content {
140032
- 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))));
140033
141633
  }
140034
141634
 
140035
141635
  /* CTA button row container */
@@ -140129,7 +141729,7 @@ const containerResponsiveThemeCss = `/*
140129
141729
  /* Form intro text */
140130
141730
  :where(.theme-scope) :where([data-block="form"]) .form-copy-intro {
140131
141731
  font-size: 1rem;
140132
- color: var(--section-text-color, rgb(var(--tb-text)));
141732
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
140133
141733
  }
140134
141734
 
140135
141735
  /* =============================================================================
@@ -140488,6 +142088,10 @@ const containerResponsiveThemeCss = `/*
140488
142088
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.6);
140489
142089
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
140490
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));
140491
142095
  --shop-card-radius: var(--rb-block-radius, var(--radius-card, 0.75rem));
140492
142096
  --shop-control-radius: var(--rb-input-radius, var(--radius-control, 0.375rem));
140493
142097
  }
@@ -140545,6 +142149,11 @@ const containerResponsiveThemeCss = `/*
140545
142149
  /* Product card */
140546
142150
  :where(.theme-scope) .shop__card {
140547
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));
140548
142157
  border: 1px solid rgb(var(--tb-border));
140549
142158
  border-radius: var(--shop-card-radius);
140550
142159
  padding: 1.5rem;
@@ -140699,6 +142308,11 @@ const containerResponsiveThemeCss = `/*
140699
142308
  border: 1px solid rgb(var(--tb-border));
140700
142309
  border-radius: var(--shop-card-radius);
140701
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));
140702
142316
  }
140703
142317
 
140704
142318
  :where(.theme-scope) :where([data-block="shop"]) .rb-state-icon--success {
@@ -140771,6 +142385,11 @@ const containerResponsiveThemeCss = `/*
140771
142385
  margin: 0 auto;
140772
142386
  padding: 2rem;
140773
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);
140774
142393
  border: 1px solid var(--cp-card-border);
140775
142394
  border-radius: var(--cp-card-radius);
140776
142395
  }
@@ -140899,6 +142518,11 @@ const containerResponsiveThemeCss = `/*
140899
142518
  padding: 3rem 2rem;
140900
142519
  text-align: center;
140901
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);
140902
142526
  border: 1px dashed var(--cp-card-border);
140903
142527
  border-radius: var(--cp-card-radius);
140904
142528
  }
@@ -140911,6 +142535,11 @@ const containerResponsiveThemeCss = `/*
140911
142535
  /* Card */
140912
142536
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card {
140913
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);
140914
142543
  border: 1px solid var(--cp-card-border);
140915
142544
  border-radius: var(--cp-card-radius);
140916
142545
  padding: 1.25rem;
@@ -141075,6 +142704,11 @@ const containerResponsiveThemeCss = `/*
141075
142704
  /* Table */
141076
142705
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table-wrap {
141077
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);
141078
142712
  border: 1px solid var(--cp-card-border);
141079
142713
  border-radius: var(--cp-card-radius);
141080
142714
  }
@@ -141636,6 +143270,143 @@ const containerResponsiveThemeCss = `/*
141636
143270
  }
141637
143271
 
141638
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
+
141639
143410
  /* Testimonials carousel tweaks: arrow styling + gutters + equal-height cards */
141640
143411
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-carousel.carousel-root .carousel-nav-btn {
141641
143412
  height: var(--rb-testimonial-carousel-arrow-size);
@@ -142782,7 +144553,7 @@ const containerResponsiveThemeCss = `/*
142782
144553
 
142783
144554
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
142784
144555
  font-size: 1rem;
142785
- color: var(--section-text-color, rgb(var(--tb-text)));
144556
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142786
144557
  opacity: 0.85;
142787
144558
  }
142788
144559
 
@@ -142831,7 +144602,7 @@ const containerResponsiveThemeCss = `/*
142831
144602
  margin-top: 0.75rem;
142832
144603
  font-size: 1rem;
142833
144604
  line-height: 1.6;
142834
- color: var(--section-text-color, rgb(var(--tb-text)));
144605
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142835
144606
  text-align: center;
142836
144607
  }
142837
144608
 
@@ -142913,7 +144684,7 @@ const containerResponsiveThemeCss = `/*
142913
144684
 
142914
144685
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .form-copy-intro,
142915
144686
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .newsletter-copy-subtitle {
142916
- color: var(--section-text-color, rgb(var(--tb-text)));
144687
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
142917
144688
  }
142918
144689
 
142919
144690
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .contact-newsletter-info {
@@ -143311,7 +145082,7 @@ const containerResponsiveThemeCss = `/*
143311
145082
 
143312
145083
  :where(.theme-scope) .event-compact-row-title {
143313
145084
  margin: 0;
143314
- 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)))));
143315
145086
  font-family: var(--font-heading, var(--font-body, inherit));
143316
145087
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.3rem);
143317
145088
  font-weight: 400;
@@ -143973,27 +145744,41 @@ const containerResponsiveThemeCss = `/*
143973
145744
  background: rgb(var(--tb-surface));
143974
145745
  }
143975
145746
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 1) {
145747
+ background: rgb(var(--tb-surface));
143976
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));
143977
145753
  }
143978
145754
 
143979
145755
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) > .rb-bg-surface {
143980
145756
  background: rgb(var(--tb-secondary));
143981
145757
  }
143982
145758
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) {
145759
+ background: rgb(var(--tb-secondary));
143983
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));
143984
145765
  }
143985
145766
 
143986
145767
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) > .rb-bg-surface {
143987
145768
  background: rgb(var(--tb-primary));
143988
145769
  }
143989
145770
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) {
145771
+ background: rgb(var(--tb-primary));
143990
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));
143991
145777
  }
143992
145778
 
143993
- /* Body copy carries an inline muted colour from the block; force it to the
143994
- * 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. */
143995
145781
  :where(.theme-scope) .rb-card-treatment-color-blocked .rb-feature-card-body {
143996
- color: inherit !important;
143997
145782
  opacity: 0.9;
143998
145783
  }
143999
145784
 
@@ -147855,7 +149640,7 @@ function applyBindings$1(bindings, context) {
147855
149640
  if (value !== void 0 && value !== null) setBindingValue(result, key, value);
147856
149641
  continue;
147857
149642
  }
147858
- if (isRecord$32(bindingSpec)) {
149643
+ if (isRecord$34(bindingSpec)) {
147859
149644
  const nested = applyBindings$1(bindingSpec, context);
147860
149645
  if (Object.keys(nested).length > 0) setBindingValue(result, key, nested);
147861
149646
  }
@@ -147916,7 +149701,7 @@ function setBindingValue(target, path, value) {
147916
149701
  current[Number(segment)] = value;
147917
149702
  return;
147918
149703
  }
147919
- if (isRecord$32(current)) current[segment] = value;
149704
+ if (isRecord$34(current)) current[segment] = value;
147920
149705
  return;
147921
149706
  }
147922
149707
  const nextWantsArray = typeof nextSegment === "string" && isIndex(nextSegment);
@@ -147925,15 +149710,15 @@ function setBindingValue(target, path, value) {
147925
149710
  const existing = current[index];
147926
149711
  if (nextWantsArray) {
147927
149712
  if (!Array.isArray(existing)) current[index] = [];
147928
- } else if (!isRecord$32(existing)) current[index] = {};
149713
+ } else if (!isRecord$34(existing)) current[index] = {};
147929
149714
  current = current[index];
147930
149715
  continue;
147931
149716
  }
147932
- if (isRecord$32(current)) {
149717
+ if (isRecord$34(current)) {
147933
149718
  const existing = current[segment];
147934
149719
  if (nextWantsArray) {
147935
149720
  if (!Array.isArray(existing)) current[segment] = [];
147936
- } else if (!isRecord$32(existing)) current[segment] = {};
149721
+ } else if (!isRecord$34(existing)) current[segment] = {};
147937
149722
  current = current[segment];
147938
149723
  continue;
147939
149724
  }
@@ -147971,7 +149756,7 @@ function getPath$1(source, path) {
147971
149756
  const segments = path.split(".").map((segment) => segment.trim()).filter(Boolean);
147972
149757
  let current = source;
147973
149758
  for (const segment of segments) {
147974
- if (!isRecord$32(current)) return void 0;
149759
+ if (!isRecord$34(current)) return void 0;
147975
149760
  current = current[segment];
147976
149761
  }
147977
149762
  return current;
@@ -148006,13 +149791,13 @@ function textToInlineText(value) {
148006
149791
  */
148007
149792
  function extractFirstParagraph$1(value) {
148008
149793
  const unwrapped = unwrapRichTextRoot(value);
148009
- if (!isRecord$32(unwrapped)) return null;
149794
+ if (!isRecord$34(unwrapped)) return null;
148010
149795
  const doc = unwrapped;
148011
149796
  if (!Array.isArray(doc.content)) return null;
148012
149797
  for (const node of doc.content) {
148013
- if (!isRecord$32(node)) continue;
149798
+ if (!isRecord$34(node)) continue;
148014
149799
  if (node.type !== "paragraph" || !Array.isArray(node.content)) continue;
148015
- 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();
148016
149801
  if (text.length > 0) return text;
148017
149802
  }
148018
149803
  return null;
@@ -148030,7 +149815,7 @@ function formatDate$1(value, options) {
148030
149815
  * Type guard to check if a value is a valid binding descriptor.
148031
149816
  */
148032
149817
  function isBindingDescriptor$2(value) {
148033
- if (!isRecord$32(value) || typeof value.source !== "string") return false;
149818
+ if (!isRecord$34(value) || typeof value.source !== "string") return false;
148034
149819
  if (!BINDING_SOURCES$1.includes(value.source)) return false;
148035
149820
  switch (value.source) {
148036
149821
  case "field":
@@ -148045,7 +149830,7 @@ function isBindingDescriptor$2(value) {
148045
149830
  * Type guard to check if a value is binding-descriptor-like (can be normalized).
148046
149831
  */
148047
149832
  function isBindingDescriptorLike$1(value) {
148048
- 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";
148049
149834
  }
148050
149835
  /**
148051
149836
  * Normalizes a binding input to a binding descriptor.
@@ -148071,7 +149856,7 @@ function normalizeBindingOutput$1(value) {
148071
149856
  }
148072
149857
  function normalizeValue(value) {
148073
149858
  if (Array.isArray(value)) return value.map((item) => normalizeValue(item));
148074
- if (!isRecord$32(value)) return value;
149859
+ if (!isRecord$34(value)) return value;
148075
149860
  if (isDocWrapper(value)) return normalizeValue(value.doc);
148076
149861
  const entries = Object.entries(value).map(([key, val]) => [key, normalizeValue(val)]);
148077
149862
  return Object.fromEntries(entries);
@@ -148093,7 +149878,7 @@ function isDocWrapper(value) {
148093
149878
  if (!("doc" in value)) return false;
148094
149879
  if (Object.keys(value).length !== 1) return false;
148095
149880
  const doc = value.doc;
148096
- return isRecord$32(doc) && typeof doc.type === "string" && doc.type === "doc";
149881
+ return isRecord$34(doc) && typeof doc.type === "string" && doc.type === "doc";
148097
149882
  }
148098
149883
  BINDING_TRANSFORM_VALUES$1.join(", ");
148099
149884
  //#endregion
@@ -148120,7 +149905,7 @@ const ImagePresets = {
148120
149905
  resize: "contain"
148121
149906
  }
148122
149907
  };
148123
- const isRecord$3 = isRecord$32;
149908
+ const isRecord$3 = isRecord$34;
148124
149909
  const normalizeBindingOutput = normalizeBindingOutput$1;
148125
149910
  const applyBindingsToContent = applyBindingsToContent$1;
148126
149911
  const builtInReferenceKindSet = /* @__PURE__ */ new Set([