@riverbankcms/sdk 0.104.0 → 0.104.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/{PreviewEditorSidebar-ywqcYjTB.mjs → PreviewEditorSidebar-CBMhU9p_.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-DApUNF6g.mjs → PreviewEditorUI-C5KEw4M8.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-DmHCcIMO.mjs → SdkPreviewModeRuntime-Iq12HjL7.mjs} +1147 -180
  4. package/dist/{SiteChromeCustomizeContext-BV9GU-3C.mjs → SiteChromeCustomizeContext-Cx0NMdyv.mjs} +1818 -951
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -0
  6. package/dist/_dts/api/src/bookingVerticals.d.ts +64 -1
  7. package/dist/_dts/blocks/src/primitives/layout/Grid.d.ts +12 -8
  8. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +3 -0
  9. package/dist/_dts/blocks/src/system/blocks/events/shared/layout.d.ts +11 -1
  10. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +7 -1
  11. package/dist/_dts/blocks/src/system/constants/events.d.ts +1 -1
  12. package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +12 -0
  13. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +2 -2
  14. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +14 -0
  15. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +33 -0
  16. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +28 -0
  17. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +32 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +1 -0
  19. package/dist/_dts/blocks/src/system/runtime/nodes/svg.d.ts +77 -0
  20. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +2 -0
  21. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +3 -40
  22. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +14 -0
  23. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +11 -0
  24. package/dist/_dts/core/src/branded.d.ts +5 -0
  25. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +18 -0
  26. package/dist/_dts/editor/src/index.d.ts +3 -1
  27. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +14 -6
  28. package/dist/_dts/editor/src/primitives/rich-text/RichTextToolbar.d.ts +23 -4
  29. package/dist/_dts/editor/src/primitives/rich-text/config.d.ts +6 -0
  30. package/dist/_dts/editor/src/primitives/rich-text/extensions/RichTextLink.d.ts +1 -0
  31. package/dist/_dts/editor/src/primitives/rich-text/paste.d.ts +10 -0
  32. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +2 -2
  33. package/dist/_dts/sdk/src/version.d.ts +1 -1
  34. package/dist/_dts/theme-core/src/ThemeScope.d.ts +1 -1
  35. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +29 -0
  36. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +6 -0
  37. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  38. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +20 -0
  39. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  40. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +4 -0
  41. package/dist/_dts/theme-core/src/buttons/types.d.ts +34 -0
  42. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  43. package/dist/_dts/theme-core/src/gradients/types.d.ts +27 -3
  44. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +51 -15
  45. package/dist/_dts/theme-core/src/palette/curated/brand-led.d.ts +13 -0
  46. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +12 -0
  47. package/dist/_dts/theme-core/src/palette/historicalThemePalette.d.ts +44 -0
  48. package/dist/_dts/theme-core/src/palette/index.d.ts +1 -0
  49. package/dist/_dts/theme-core/src/palette/legacyRuntimeProjection.d.ts +23 -6
  50. package/dist/_dts/theme-core/src/palette/legacySelection.d.ts +13 -2
  51. package/dist/_dts/theme-core/src/palette/paletteCompatibilityTransition.d.ts +0 -9
  52. package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +17 -2
  53. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +3 -4
  54. package/dist/_dts/theme-core/src/runtime/themeCssVarNames.d.ts +1 -0
  55. package/dist/_dts/theme-core/src/schema.d.ts +108 -26
  56. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +2 -1
  57. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +50 -1
  58. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  59. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  60. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +56 -1
  61. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  62. package/dist/_dts/theme-core/src/status/index.d.ts +0 -1
  63. package/dist/_dts/theme-core/src/surfaces/foregroundContract.d.ts +19 -0
  64. package/dist/_dts/theme-core/src/surfaces/foregroundRoles.d.ts +9 -0
  65. package/dist/_dts/theme-core/src/surfaces/index.d.ts +2 -0
  66. package/dist/_dts/ui/src/button.d.ts +1 -1
  67. package/dist/cli/index.mjs +1567 -470
  68. package/dist/client/{DiscountCodeDisclosure-Dit2aItR.mjs → DiscountCodeDisclosure-BXM73_E5.mjs} +1 -1
  69. package/dist/client/{EventCombined.client-BnREyCjf.mjs → EventCombined.client-DT5elP7j.mjs} +4 -4
  70. package/dist/client/{EventListing.client-0uHld51x.mjs → EventListing.client-pTYGfV9C.mjs} +2 -2
  71. package/dist/client/{LeafletStaticMap-DJcvSfmj.mjs → LeafletStaticMap-dQrhlUe3.mjs} +1 -1
  72. package/dist/client/{MagicLinkForm-EAsIktfw.mjs → MagicLinkForm-u6Dul4j5.mjs} +2 -2
  73. package/dist/client/{StepIndicator-CRR17tYI.mjs → StepIndicator-nWqineJ2.mjs} +2 -2
  74. package/dist/client/{accordion-B47HIuuH.mjs → accordion-CSJcTUyH.mjs} +1 -1
  75. package/dist/client/{bookingForm-I1E-8F9P.mjs → bookingForm-C73wOuVa.mjs} +6 -6
  76. package/dist/client/bookings.mjs +137 -1
  77. package/dist/client/{buttons-BbPn8OKA.mjs → buttons-DfYyqt8C.mjs} +138 -2
  78. package/dist/client/{carousel-OlM7SyBs.mjs → carousel-fMBb0JSc.mjs} +1 -1
  79. package/dist/client/{cart-BKpG5jz6.mjs → cart-BtaCwT3S.mjs} +3 -3
  80. package/dist/client/{checkout-Dmmr6qoU.mjs → checkout-DkTwZSnh.mjs} +3 -3
  81. package/dist/client/client.mjs +2336 -544
  82. package/dist/client/{colorStyles-DuW4Fjqd.mjs → colorStyles-Wyl6JujD.mjs} +45 -4
  83. package/dist/client/{courseRegistration-CflZiqGk.mjs → courseRegistration-DnLmapJu.mjs} +7 -7
  84. package/dist/client/{eventCalendar-BvoLWcp-.mjs → eventCalendar-BvLOc9KY.mjs} +165 -5
  85. package/dist/client/{eventCombined-DsrO8t_t.mjs → eventCombined-kShgJPQr.mjs} +2 -2
  86. package/dist/client/{eventDetails-C3hxgcJm.mjs → eventDetails-C5NTM0Vo.mjs} +3 -3
  87. package/dist/client/{eventListing-C-hb237X.mjs → eventListing-B82ZdKP6.mjs} +2 -2
  88. package/dist/client/{eventRegistration-B0gyzDGi.mjs → eventRegistration-qJVFqBWo.mjs} +7 -7
  89. package/dist/client/{form-C_RUi6oJ.mjs → form-BvAcKiuu.mjs} +2 -2
  90. package/dist/client/{headerSection-IKQiD2U0.mjs → headerSection-NvAiEHAg.mjs} +3 -3
  91. package/dist/client/hooks.mjs +1023 -337
  92. package/dist/client/{locationMap-8ZBrMzRJ.mjs → locationMap-D0j52xfI.mjs} +3 -3
  93. package/dist/client/{media-CZJKL7fi.mjs → media-BCW_g2cQ.mjs} +1 -1
  94. package/dist/client/{newsletterForm-CYk3ucwj.mjs → newsletterForm-B8_i93qH.mjs} +2 -2
  95. package/dist/client/{pricing-B5GmvfIH.mjs → pricing-DIYnyHOk.mjs} +1 -1
  96. package/dist/client/{productDetail-BjS2Dqzo.mjs → productDetail-w0eAHkuQ.mjs} +3 -3
  97. package/dist/client/{productList-BOHvC8My.mjs → productList-Vsguq5Xt.mjs} +3 -3
  98. package/dist/client/{propsDecoder-WS6UEJwZ.mjs → propsDecoder-CD2pJ1WB.mjs} +37 -2
  99. package/dist/client/rendering/client.mjs +1723 -762
  100. package/dist/client/rendering/islands.mjs +19 -19
  101. package/dist/client/rendering.mjs +2312 -520
  102. package/dist/client/{shop-CON03-wN.mjs → shop-Dgxs-Q8F.mjs} +6 -6
  103. package/dist/client/{shop-commerce-DlqrFgH8.mjs → shop-commerce-DJAhsTaT.mjs} +6 -6
  104. package/dist/client/{shop-commerce-store-l74-Kne6.mjs → shop-commerce-store-CfCXltXW.mjs} +1 -1
  105. package/dist/client/{shopShared-CQheEXSg.mjs → shopShared-CmDcPXUt.mjs} +2 -2
  106. package/dist/client/{useDiscountCodeUi-v6OluyWl.mjs → useDiscountCodeUi-CirrT2bM.mjs} +1 -1
  107. package/dist/client/{useEventFilters-BqSTcNOf.mjs → useEventFilters-CNZxlCcO.mjs} +5 -5
  108. package/dist/client/{usePolling-DMfADjIF.mjs → usePolling-Baks_iBI.mjs} +2 -2
  109. package/dist/preview-next/client/runtime.mjs +3 -3
  110. package/dist/{sdk-runtime-DWb08Xaz.mjs → sdk-runtime-BfNiFeNJ.mjs} +1 -1
  111. package/dist/{separator--6yjc914.mjs → separator-BhAR_Xmf.mjs} +1 -1
  112. package/dist/server/components.mjs +2301 -531
  113. package/dist/server/config-validation.mjs +1028 -337
  114. package/dist/server/config.mjs +1028 -337
  115. package/dist/server/data.mjs +1023 -337
  116. package/dist/server/index.mjs +1 -1
  117. package/dist/server/next.mjs +2304 -534
  118. package/dist/server/page-converter.mjs +1018 -324
  119. package/dist/server/prebuild.mjs +1 -1
  120. package/dist/server/rendering/server.mjs +2286 -521
  121. package/dist/server/rendering.mjs +2301 -531
  122. package/dist/server/routing.mjs +1100 -338
  123. package/dist/server/server.mjs +1024 -338
  124. package/dist/server/theme-bridge.mjs +1240 -77
  125. package/dist/server/theme.mjs +165 -5
  126. package/dist/styles/index.css +617 -34
  127. package/package.json +1 -1
  128. package/dist/_dts/blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.d.ts +0 -2
  129. package/dist/_dts/theme-core/src/status/contextualColors.d.ts +0 -6
@@ -7970,11 +7970,11 @@ var init_fileStorage = __esmMin((() => {
7970
7970
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
7971
7971
  //#endregion
7972
7972
  //#region ../media-core/src/typeGuards.ts
7973
- function isRecord$28(value) {
7973
+ function isRecord$30(value) {
7974
7974
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7975
7975
  }
7976
7976
  function asRecord$3(value) {
7977
- return isRecord$28(value) ? value : void 0;
7977
+ return isRecord$30(value) ? value : void 0;
7978
7978
  }
7979
7979
  var init_typeGuards$1 = __esmMin((() => {}));
7980
7980
  function isFileJsonObject(value) {
@@ -7984,7 +7984,7 @@ function isFileJsonValue(value) {
7984
7984
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
7985
7985
  if (typeof value === "number") return Number.isFinite(value);
7986
7986
  if (Array.isArray(value)) return value.every(isFileJsonValue);
7987
- return isRecord$28(value) && isFileJsonObject(value);
7987
+ return isRecord$30(value) && isFileJsonObject(value);
7988
7988
  }
7989
7989
  var init_filePersistence = __esmMin((() => {
7990
7990
  init_src$3();
@@ -8394,7 +8394,7 @@ function isCmsMediaObjectType(value) {
8394
8394
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
8395
8395
  }
8396
8396
  function isCmsMediaObject(value) {
8397
- if (!isRecord$28(value)) return false;
8397
+ if (!isRecord$30(value)) return false;
8398
8398
  const type = value.type;
8399
8399
  if (!isCmsMediaObjectType(type)) return false;
8400
8400
  if ("attrs" in value) return false;
@@ -8405,7 +8405,7 @@ function collectMediaObjects(value, out, location = "") {
8405
8405
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
8406
8406
  return;
8407
8407
  }
8408
- if (!isRecord$28(value)) return;
8408
+ if (!isRecord$30(value)) return;
8409
8409
  if (isCmsMediaObject(value)) out.push({
8410
8410
  obj: value,
8411
8411
  location
@@ -8439,8 +8439,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
8439
8439
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
8440
8440
  return;
8441
8441
  }
8442
- if (!isRecord$28(value)) return;
8443
- if (value.type === "image" && isRecord$28(value.attrs)) out.push({
8442
+ if (!isRecord$30(value)) return;
8443
+ if (value.type === "image" && isRecord$30(value.attrs)) out.push({
8444
8444
  attrs: value.attrs,
8445
8445
  location: location ? `${location}.attrs` : "attrs"
8446
8446
  });
@@ -8745,6 +8745,9 @@ var init_validation_constants = __esmMin((() => {
8745
8745
  "richText",
8746
8746
  "media",
8747
8747
  "videoEmbed",
8748
+ "icon",
8749
+ "feature-card-icon",
8750
+ "svg",
8748
8751
  "button",
8749
8752
  "link",
8750
8753
  "carousel",
@@ -8774,11 +8777,13 @@ var init_validation_constants = __esmMin((() => {
8774
8777
  "value.jsonArray",
8775
8778
  "value.csv",
8776
8779
  "array.marqueeLoop",
8780
+ "value.mapToken",
8777
8781
  "layout.maxWidthClass",
8778
8782
  "layout.headerRootClass",
8779
8783
  "layout.footerRootClass",
8780
8784
  "layout.headerRootStyle",
8781
8785
  "layout.headerSectionBackground",
8786
+ "layout.classicNavMode",
8782
8787
  "layout.footerRootStyle",
8783
8788
  "ui.headerNavLinkClass",
8784
8789
  "ui.headingClassFromAlignment",
@@ -10654,7 +10659,7 @@ function getSemanticIconComponent(name) {
10654
10659
  //#endregion
10655
10660
  //#region ../blocks/src/system/icons/value.ts
10656
10661
  const NO_BLOCK_ICON_VALUE = { kind: "none" };
10657
- function isRecord$27(value) {
10662
+ function isRecord$29(value) {
10658
10663
  return typeof value === "object" && value !== null && !Array.isArray(value);
10659
10664
  }
10660
10665
  function parseBlockIconValue(value) {
@@ -10662,7 +10667,7 @@ function parseBlockIconValue(value) {
10662
10667
  kind: "semantic",
10663
10668
  iconId: value
10664
10669
  };
10665
- if (!isRecord$27(value)) return NO_BLOCK_ICON_VALUE;
10670
+ if (!isRecord$29(value)) return NO_BLOCK_ICON_VALUE;
10666
10671
  switch (value.kind) {
10667
10672
  case "none": return NO_BLOCK_ICON_VALUE;
10668
10673
  case "semantic": return isSemanticIconId(value.iconId) ? {
@@ -10735,7 +10740,7 @@ function buildGeneratedBlockIconRenderAssetLookupFromUnknown(value) {
10735
10740
  if (!Array.isArray(value)) return { kind: "invalid_asset_list" };
10736
10741
  const inputs = [];
10737
10742
  for (const [index, item] of value.entries()) {
10738
- if (!isRecord$27(item)) return {
10743
+ if (!isRecord$29(item)) return {
10739
10744
  kind: "invalid_asset_entry",
10740
10745
  index,
10741
10746
  reason: "not_object"
@@ -13280,6 +13285,246 @@ var init_all = __esmMin((() => {
13280
13285
  init_PaletteCard();
13281
13286
  }));
13282
13287
  //#endregion
13288
+ //#region ../theme-core/src/tokens/colorTokenParts.ts
13289
+ function parseOpacityPercent(source) {
13290
+ const trimmed = source.trim();
13291
+ if (!trimmed) return null;
13292
+ if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
13293
+ const value = Number(trimmed);
13294
+ if (!Number.isFinite(value)) return null;
13295
+ if (value < 0 || value > 100) return null;
13296
+ return value;
13297
+ }
13298
+ function parseColorTokenParts(source) {
13299
+ const trimmed = source.trim();
13300
+ if (trimmed.startsWith("raw:")) return {
13301
+ kind: "raw",
13302
+ value: trimmed.slice(4)
13303
+ };
13304
+ const [token, opacityRaw, extra] = trimmed.split("/");
13305
+ if (!token || extra !== void 0) return {
13306
+ kind: "invalid",
13307
+ token: trimmed
13308
+ };
13309
+ if (opacityRaw === void 0) return {
13310
+ kind: "token",
13311
+ token,
13312
+ opacityPercent: null
13313
+ };
13314
+ const opacityPercent = parseOpacityPercent(opacityRaw);
13315
+ if (opacityPercent === null) return {
13316
+ kind: "invalid",
13317
+ token: trimmed
13318
+ };
13319
+ return {
13320
+ kind: "token",
13321
+ token,
13322
+ opacityPercent
13323
+ };
13324
+ }
13325
+ var init_colorTokenParts = __esmMin((() => {}));
13326
+ function isBlockColorToken(value) {
13327
+ if (typeof value !== "string") return false;
13328
+ const parts = parseColorTokenParts(value);
13329
+ return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
13330
+ }
13331
+ function parseBlockColorToken(value) {
13332
+ if (!isBlockColorToken(value)) return null;
13333
+ return value.trim();
13334
+ }
13335
+ var blockColorTokenNames, blockColorTokenNameSet;
13336
+ var init_blockColorTokens = __esmMin((() => {
13337
+ init_colorTokenParts();
13338
+ blockColorTokenNames = [
13339
+ "text",
13340
+ "heading",
13341
+ "mutedText",
13342
+ "surface",
13343
+ "background",
13344
+ "foreground",
13345
+ "border",
13346
+ "primary",
13347
+ "secondary",
13348
+ "accent",
13349
+ "success",
13350
+ "warning",
13351
+ "info",
13352
+ "error",
13353
+ "destructive",
13354
+ "scrim",
13355
+ "shadow",
13356
+ "onPrimary",
13357
+ "onSecondary",
13358
+ "onAccent",
13359
+ "onSuccess",
13360
+ "onWarning",
13361
+ "onInfo",
13362
+ "onError",
13363
+ "onDestructive",
13364
+ "onSurface"
13365
+ ];
13366
+ blockColorTokenNameSet = new Set(blockColorTokenNames);
13367
+ }));
13368
+ //#endregion
13369
+ //#region ../theme-core/src/tokens/themeColorTokens.ts
13370
+ function isKnownBaseToken(value) {
13371
+ return themeColorBaseTokenSet.has(value);
13372
+ }
13373
+ function isKnownShadeToken(value) {
13374
+ const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
13375
+ if (!match) return false;
13376
+ const [, base, shade] = match;
13377
+ return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
13378
+ }
13379
+ function isThemeColorTokenBase(value) {
13380
+ return isKnownBaseToken(value) || isKnownShadeToken(value);
13381
+ }
13382
+ function isThemeColorToken(value) {
13383
+ if (typeof value !== "string") return false;
13384
+ const parts = parseColorTokenParts(value);
13385
+ return parts.kind === "token" && isThemeColorTokenBase(parts.token);
13386
+ }
13387
+ function parseThemeColorToken(value) {
13388
+ if (!isThemeColorToken(value)) return null;
13389
+ return value.trim();
13390
+ }
13391
+ var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
13392
+ var init_themeColorTokens = __esmMin((() => {
13393
+ init_blockColorTokens();
13394
+ init_colorTokenParts();
13395
+ PALETTE_TOKEN_NAMES = [
13396
+ "primary",
13397
+ "primaryForeground",
13398
+ "secondary",
13399
+ "accent",
13400
+ "success",
13401
+ "warning",
13402
+ "destructive",
13403
+ "background",
13404
+ "surface",
13405
+ "surfaceAlt",
13406
+ "muted",
13407
+ "text",
13408
+ "border"
13409
+ ];
13410
+ paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
13411
+ themeColorBaseTokenNames = [
13412
+ ...PALETTE_TOKEN_NAMES,
13413
+ ...blockColorTokenNames,
13414
+ "white",
13415
+ "neutral",
13416
+ "primaryText",
13417
+ "secondaryForeground",
13418
+ "accentForeground"
13419
+ ];
13420
+ themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
13421
+ themeColorShadeSteps = [
13422
+ "50",
13423
+ "100",
13424
+ "200",
13425
+ "300",
13426
+ "400",
13427
+ "500",
13428
+ "600",
13429
+ "700",
13430
+ "800",
13431
+ "900",
13432
+ "950"
13433
+ ];
13434
+ shadeStepSet = new Set(themeColorShadeSteps);
13435
+ themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
13436
+ }));
13437
+ //#endregion
13438
+ //#region ../theme-core/src/palette/colors.ts
13439
+ function normalizePaletteHex(value) {
13440
+ if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
13441
+ const normalized = value.toLowerCase();
13442
+ if (normalized.length === 7) return normalized;
13443
+ const triplet = normalized.slice(1);
13444
+ const red = triplet.charAt(0);
13445
+ const green = triplet.charAt(1);
13446
+ const blue = triplet.charAt(2);
13447
+ return `#${red}${red}${green}${green}${blue}${blue}`;
13448
+ }
13449
+ function paletteColorsFromEntries(entries) {
13450
+ const values = {};
13451
+ for (const entry of entries) {
13452
+ const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
13453
+ if (!parsedRole.success) return {
13454
+ ok: false,
13455
+ error: {
13456
+ kind: "unknown-role",
13457
+ role: entry.name
13458
+ }
13459
+ };
13460
+ const role = parsedRole.data;
13461
+ if (values[role] !== void 0) return {
13462
+ ok: false,
13463
+ error: {
13464
+ kind: "duplicate-role",
13465
+ role
13466
+ }
13467
+ };
13468
+ const hex = normalizePaletteHex(entry.hex);
13469
+ if (!hex) return {
13470
+ ok: false,
13471
+ error: {
13472
+ kind: "invalid-color",
13473
+ role,
13474
+ value: entry.hex
13475
+ }
13476
+ };
13477
+ values[role] = hex;
13478
+ }
13479
+ const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
13480
+ if (missing.length > 0) return {
13481
+ ok: false,
13482
+ error: {
13483
+ kind: "missing-roles",
13484
+ roles: missing
13485
+ }
13486
+ };
13487
+ return {
13488
+ ok: true,
13489
+ colors: paletteColorsSchema.parse(values)
13490
+ };
13491
+ }
13492
+ function requirePaletteColorsFromEntries(entries) {
13493
+ const result = paletteColorsFromEntries(entries);
13494
+ if (result.ok) return result.colors;
13495
+ throw new Error(`Invalid complete palette: ${result.error.kind}`);
13496
+ }
13497
+ var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema, paletteModeSchema, paletteColorsSchema, init_colors = __esmMin((() => {
13498
+ init_themeColorTokens();
13499
+ HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
13500
+ NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
13501
+ hexColorSchema = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
13502
+ paletteModeSchema = z$1.enum(["light", "dark"]);
13503
+ z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
13504
+ paletteColorsSchema = z$1.object({
13505
+ primary: hexColorSchema,
13506
+ primaryForeground: hexColorSchema,
13507
+ secondary: hexColorSchema,
13508
+ accent: hexColorSchema,
13509
+ success: hexColorSchema,
13510
+ warning: hexColorSchema,
13511
+ destructive: hexColorSchema,
13512
+ background: hexColorSchema,
13513
+ surface: hexColorSchema,
13514
+ surfaceAlt: hexColorSchema,
13515
+ muted: hexColorSchema,
13516
+ text: hexColorSchema,
13517
+ border: hexColorSchema
13518
+ }).strict().transform((value) => value);
13519
+ }));
13520
+ var init_historicalThemePalette = __esmMin((() => {
13521
+ init_themeColorTokens();
13522
+ init_colors();
13523
+ init_colorConversion();
13524
+ init_textColor();
13525
+ new Set(PALETTE_TOKEN_NAMES);
13526
+ }));
13527
+ //#endregion
13283
13528
  //#region ../theme-core/src/palette/types.ts
13284
13529
  var init_types$16 = __esmMin((() => {}));
13285
13530
  //#endregion
@@ -14406,240 +14651,6 @@ var init_browser = __esmMin((() => {
14406
14651
  var init_extractPalette = __esmMin((() => {
14407
14652
  init_browser();
14408
14653
  }));
14409
- //#endregion
14410
- //#region ../theme-core/src/tokens/colorTokenParts.ts
14411
- function parseOpacityPercent(source) {
14412
- const trimmed = source.trim();
14413
- if (!trimmed) return null;
14414
- if (!/^\d{1,3}(?:\.\d+)?$/.test(trimmed)) return null;
14415
- const value = Number(trimmed);
14416
- if (!Number.isFinite(value)) return null;
14417
- if (value < 0 || value > 100) return null;
14418
- return value;
14419
- }
14420
- function parseColorTokenParts(source) {
14421
- const trimmed = source.trim();
14422
- if (trimmed.startsWith("raw:")) return {
14423
- kind: "raw",
14424
- value: trimmed.slice(4)
14425
- };
14426
- const [token, opacityRaw, extra] = trimmed.split("/");
14427
- if (!token || extra !== void 0) return {
14428
- kind: "invalid",
14429
- token: trimmed
14430
- };
14431
- if (opacityRaw === void 0) return {
14432
- kind: "token",
14433
- token,
14434
- opacityPercent: null
14435
- };
14436
- const opacityPercent = parseOpacityPercent(opacityRaw);
14437
- if (opacityPercent === null) return {
14438
- kind: "invalid",
14439
- token: trimmed
14440
- };
14441
- return {
14442
- kind: "token",
14443
- token,
14444
- opacityPercent
14445
- };
14446
- }
14447
- var init_colorTokenParts = __esmMin((() => {}));
14448
- function isBlockColorToken(value) {
14449
- if (typeof value !== "string") return false;
14450
- const parts = parseColorTokenParts(value);
14451
- return parts.kind === "token" && blockColorTokenNameSet.has(parts.token);
14452
- }
14453
- function parseBlockColorToken(value) {
14454
- if (!isBlockColorToken(value)) return null;
14455
- return value.trim();
14456
- }
14457
- var blockColorTokenNames, blockColorTokenNameSet;
14458
- var init_blockColorTokens = __esmMin((() => {
14459
- init_colorTokenParts();
14460
- blockColorTokenNames = [
14461
- "text",
14462
- "heading",
14463
- "mutedText",
14464
- "surface",
14465
- "background",
14466
- "foreground",
14467
- "border",
14468
- "primary",
14469
- "secondary",
14470
- "accent",
14471
- "success",
14472
- "warning",
14473
- "info",
14474
- "error",
14475
- "destructive",
14476
- "scrim",
14477
- "shadow",
14478
- "onPrimary",
14479
- "onSecondary",
14480
- "onAccent",
14481
- "onSuccess",
14482
- "onWarning",
14483
- "onInfo",
14484
- "onError",
14485
- "onDestructive",
14486
- "onSurface"
14487
- ];
14488
- blockColorTokenNameSet = new Set(blockColorTokenNames);
14489
- }));
14490
- //#endregion
14491
- //#region ../theme-core/src/tokens/themeColorTokens.ts
14492
- function isKnownBaseToken(value) {
14493
- return themeColorBaseTokenSet.has(value);
14494
- }
14495
- function isKnownShadeToken(value) {
14496
- const match = value.match(/^([a-zA-Z][a-zA-Z0-9]*)(?:-([0-9]{2,3}))$/);
14497
- if (!match) return false;
14498
- const [, base, shade] = match;
14499
- return Boolean(base && shade && isKnownBaseToken(base) && shadeStepSet.has(shade));
14500
- }
14501
- function isThemeColorTokenBase(value) {
14502
- return isKnownBaseToken(value) || isKnownShadeToken(value);
14503
- }
14504
- function isThemeColorToken(value) {
14505
- if (typeof value !== "string") return false;
14506
- const parts = parseColorTokenParts(value);
14507
- return parts.kind === "token" && isThemeColorTokenBase(parts.token);
14508
- }
14509
- function parseThemeColorToken(value) {
14510
- if (!isThemeColorToken(value)) return null;
14511
- return value.trim();
14512
- }
14513
- var PALETTE_TOKEN_NAMES, paletteTokenNameSchema, themeColorBaseTokenNames, themeColorBaseTokenSet, themeColorShadeSteps, shadeStepSet, themeColorTokenSchema;
14514
- var init_themeColorTokens = __esmMin((() => {
14515
- init_blockColorTokens();
14516
- init_colorTokenParts();
14517
- PALETTE_TOKEN_NAMES = [
14518
- "primary",
14519
- "primaryForeground",
14520
- "secondary",
14521
- "accent",
14522
- "success",
14523
- "warning",
14524
- "destructive",
14525
- "background",
14526
- "surface",
14527
- "surfaceAlt",
14528
- "muted",
14529
- "text",
14530
- "border"
14531
- ];
14532
- paletteTokenNameSchema = z$1.enum(PALETTE_TOKEN_NAMES);
14533
- themeColorBaseTokenNames = [
14534
- ...PALETTE_TOKEN_NAMES,
14535
- ...blockColorTokenNames,
14536
- "white",
14537
- "neutral",
14538
- "primaryText",
14539
- "secondaryForeground",
14540
- "accentForeground"
14541
- ];
14542
- themeColorBaseTokenSet = new Set(themeColorBaseTokenNames);
14543
- themeColorShadeSteps = [
14544
- "50",
14545
- "100",
14546
- "200",
14547
- "300",
14548
- "400",
14549
- "500",
14550
- "600",
14551
- "700",
14552
- "800",
14553
- "900",
14554
- "950"
14555
- ];
14556
- shadeStepSet = new Set(themeColorShadeSteps);
14557
- themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
14558
- }));
14559
- //#endregion
14560
- //#region ../theme-core/src/palette/colors.ts
14561
- function normalizePaletteHex(value) {
14562
- if (!NORMALIZABLE_HEX_REGEX.test(value)) return null;
14563
- const normalized = value.toLowerCase();
14564
- if (normalized.length === 7) return normalized;
14565
- const triplet = normalized.slice(1);
14566
- const red = triplet.charAt(0);
14567
- const green = triplet.charAt(1);
14568
- const blue = triplet.charAt(2);
14569
- return `#${red}${red}${green}${green}${blue}${blue}`;
14570
- }
14571
- function paletteColorsFromEntries(entries) {
14572
- const values = {};
14573
- for (const entry of entries) {
14574
- const parsedRole = paletteTokenNameSchema.safeParse(entry.name);
14575
- if (!parsedRole.success) return {
14576
- ok: false,
14577
- error: {
14578
- kind: "unknown-role",
14579
- role: entry.name
14580
- }
14581
- };
14582
- const role = parsedRole.data;
14583
- if (values[role] !== void 0) return {
14584
- ok: false,
14585
- error: {
14586
- kind: "duplicate-role",
14587
- role
14588
- }
14589
- };
14590
- const hex = normalizePaletteHex(entry.hex);
14591
- if (!hex) return {
14592
- ok: false,
14593
- error: {
14594
- kind: "invalid-color",
14595
- role,
14596
- value: entry.hex
14597
- }
14598
- };
14599
- values[role] = hex;
14600
- }
14601
- const missing = PALETTE_TOKEN_NAMES.filter((role) => values[role] === void 0);
14602
- if (missing.length > 0) return {
14603
- ok: false,
14604
- error: {
14605
- kind: "missing-roles",
14606
- roles: missing
14607
- }
14608
- };
14609
- return {
14610
- ok: true,
14611
- colors: paletteColorsSchema.parse(values)
14612
- };
14613
- }
14614
- function requirePaletteColorsFromEntries(entries) {
14615
- const result = paletteColorsFromEntries(entries);
14616
- if (result.ok) return result.colors;
14617
- throw new Error(`Invalid complete palette: ${result.error.kind}`);
14618
- }
14619
- var HEX_COLOR_REGEX, NORMALIZABLE_HEX_REGEX, hexColorSchema, paletteModeSchema, paletteColorsSchema;
14620
- var init_colors = __esmMin((() => {
14621
- init_themeColorTokens();
14622
- HEX_COLOR_REGEX = /^#[0-9a-f]{6}$/;
14623
- NORMALIZABLE_HEX_REGEX = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
14624
- hexColorSchema = z$1.string().regex(HEX_COLOR_REGEX, "Hex must be #RRGGBB (lowercase)").transform((value) => value);
14625
- paletteModeSchema = z$1.enum(["light", "dark"]);
14626
- z$1.string().regex(/^[0-9a-f]{64}$/, "Palette hash must be a lowercase SHA-256 value").transform((value) => value);
14627
- paletteColorsSchema = z$1.object({
14628
- primary: hexColorSchema,
14629
- primaryForeground: hexColorSchema,
14630
- secondary: hexColorSchema,
14631
- accent: hexColorSchema,
14632
- success: hexColorSchema,
14633
- warning: hexColorSchema,
14634
- destructive: hexColorSchema,
14635
- background: hexColorSchema,
14636
- surface: hexColorSchema,
14637
- surfaceAlt: hexColorSchema,
14638
- muted: hexColorSchema,
14639
- text: hexColorSchema,
14640
- border: hexColorSchema
14641
- }).strict().transform((value) => value);
14642
- }));
14643
14654
  var init_editorState = __esmMin((() => {}));
14644
14655
  var init_libraryModel = __esmMin((() => {}));
14645
14656
  var init_themePaletteCompatibility = __esmMin((() => {
@@ -14650,6 +14661,7 @@ var init_legacySelection = __esmMin((() => {
14650
14661
  init_themeColorTokens();
14651
14662
  init_colors();
14652
14663
  init_themePaletteCompatibility();
14664
+ init_historicalThemePalette();
14653
14665
  }));
14654
14666
  //#endregion
14655
14667
  //#region ../theme-core/src/site-styles/styleTags.ts
@@ -14730,7 +14742,7 @@ var init_types$15 = __esmMin((() => {
14730
14742
  }));
14731
14743
  //#endregion
14732
14744
  //#region ../theme-core/src/palette/curated/brand-led.ts
14733
- var brandLedCool, brandLedWarm, brandLedJewel, brandLedBurgundyGold;
14745
+ var brandLedCool, brandLedWarm, brandLedJewel, brandLedSpruce, brandLedBurgundyGold;
14734
14746
  var init_brand_led = __esmMin((() => {
14735
14747
  init_types$15();
14736
14748
  brandLedCool = defineCuratedPalette({
@@ -14928,6 +14940,71 @@ var init_brand_led = __esmMin((() => {
14928
14940
  }
14929
14941
  ]
14930
14942
  });
14943
+ brandLedSpruce = defineCuratedPalette({
14944
+ id: "brand-led-spruce",
14945
+ name: "Brand-led — Spruce",
14946
+ description: "Spruce-ink primary and moss secondary with an amber accent over a green-mist ground and hairline sage borders.",
14947
+ tags: {
14948
+ tone: "classic",
14949
+ energy: "calm",
14950
+ era: "editorial"
14951
+ },
14952
+ mode: "light",
14953
+ colors: [
14954
+ {
14955
+ name: "primary",
14956
+ hex: "#14312b"
14957
+ },
14958
+ {
14959
+ name: "secondary",
14960
+ hex: "#356a59"
14961
+ },
14962
+ {
14963
+ name: "accent",
14964
+ hex: "#f08a4b"
14965
+ },
14966
+ {
14967
+ name: "success",
14968
+ hex: "#356a59"
14969
+ },
14970
+ {
14971
+ name: "warning",
14972
+ hex: "#f08a4b"
14973
+ },
14974
+ {
14975
+ name: "destructive",
14976
+ hex: "#b5561f"
14977
+ },
14978
+ {
14979
+ name: "background",
14980
+ hex: "#ecefe9"
14981
+ },
14982
+ {
14983
+ name: "surface",
14984
+ hex: "#ffffff"
14985
+ },
14986
+ {
14987
+ name: "surfaceAlt",
14988
+ hex: "#f4f6f1"
14989
+ },
14990
+ {
14991
+ name: "muted",
14992
+ hex: "#5c6a64"
14993
+ },
14994
+ {
14995
+ name: "text",
14996
+ hex: "#1c2a26"
14997
+ },
14998
+ {
14999
+ name: "primaryForeground",
15000
+ hex: "#f4f7f1"
15001
+ },
15002
+ {
15003
+ name: "border",
15004
+ hex: "#d7ddd2"
15005
+ }
15006
+ ]
15007
+ });
14931
15008
  brandLedBurgundyGold = defineCuratedPalette({
14932
15009
  id: "brand-led-burgundy-gold",
14933
15010
  name: "Brand-led — Burgundy Gold",
@@ -15868,8 +15945,7 @@ var init_warm_dark = __esmMin((() => {
15868
15945
  function findCuratedPalette(id) {
15869
15946
  return curatedPalettesById.get(id);
15870
15947
  }
15871
- var curatedPalettes, curatedPalettesById;
15872
- var init_curated = __esmMin((() => {
15948
+ var curatedPalettes, curatedPalettesById, init_curated = __esmMin((() => {
15873
15949
  init_brand_led();
15874
15950
  init_high_contrast();
15875
15951
  init_soft_natural();
@@ -15881,6 +15957,7 @@ var init_curated = __esmMin((() => {
15881
15957
  brandLedWarm,
15882
15958
  brandLedJewel,
15883
15959
  brandLedBurgundyGold,
15960
+ brandLedSpruce,
15884
15961
  warmNeutralClay,
15885
15962
  warmNeutralCream,
15886
15963
  warmNeutralSoftEarth,
@@ -15997,6 +16074,7 @@ var init_palette$1 = __esmMin((() => {
15997
16074
  init_expandPalette();
15998
16075
  init_generateCssVars();
15999
16076
  init_generateShades();
16077
+ init_historicalThemePalette();
16000
16078
  init_neutralScale();
16001
16079
  init_types$16();
16002
16080
  init_utils$5();
@@ -16466,7 +16544,7 @@ function asSpecialVariantId(value) {
16466
16544
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
16467
16545
  return value;
16468
16546
  }
16469
- 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;
16547
+ 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;
16470
16548
  var init_types$14 = __esmMin((() => {
16471
16549
  init_themeColorTokens();
16472
16550
  VARIANT_ROLES = [
@@ -16626,6 +16704,10 @@ var init_types$14 = __esmMin((() => {
16626
16704
  widthClass: z$1.string(),
16627
16705
  colorToken: themeColorTokenSchema
16628
16706
  });
16707
+ buttonVariantAffordanceSchema = z$1.object({
16708
+ iconId: z$1.string().min(1),
16709
+ colorToken: themeColorTokenSchema.optional()
16710
+ });
16629
16711
  variantShadowSchema = z$1.object({
16630
16712
  elevation: z$1.enum([
16631
16713
  "none",
@@ -16666,7 +16748,8 @@ var init_types$14 = __esmMin((() => {
16666
16748
  border: buttonBorderSchema.optional(),
16667
16749
  hoverBackgroundToken: z$1.string().optional(),
16668
16750
  effects: variantEffectsSchema.optional(),
16669
- sizes: variantSizeOverridesSchema.optional()
16751
+ sizes: variantSizeOverridesSchema.optional(),
16752
+ affordance: buttonVariantAffordanceSchema.optional()
16670
16753
  });
16671
16754
  buttonSystemSchema = z$1.object({
16672
16755
  global: buttonGlobalSettingsSchema,
@@ -17216,6 +17299,132 @@ var init_editorial_link = __esmMin((() => {
17216
17299
  });
17217
17300
  }));
17218
17301
  //#endregion
17302
+ //#region ../theme-core/src/buttons/personalities/flat-ink.ts
17303
+ var flatInk;
17304
+ var init_flat_ink = __esmMin((() => {
17305
+ init_types$13();
17306
+ flatInk = defineButtonPersonality({
17307
+ id: "flat-ink",
17308
+ name: "Flat Ink",
17309
+ description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
17310
+ tags: {
17311
+ tone: "classic",
17312
+ energy: "calm",
17313
+ motion: "subtle",
17314
+ era: "editorial"
17315
+ },
17316
+ buttonSystem: {
17317
+ global: {
17318
+ cornerStyle: "rounded",
17319
+ shadow: "low",
17320
+ textTransform: "none",
17321
+ fontWeight: 600,
17322
+ borderWidth: 1,
17323
+ typography: "body",
17324
+ letterSpacing: "tight",
17325
+ paddingPreset: "default",
17326
+ hoverTransform: "lift",
17327
+ hoverColor: "none"
17328
+ },
17329
+ sizes: {
17330
+ sm: {
17331
+ padding: "0.625rem 1.125rem",
17332
+ fontSize: "text-sm"
17333
+ },
17334
+ md: { padding: "0.8125rem 1.375rem" },
17335
+ lg: {
17336
+ padding: "0.9375rem 1.625rem",
17337
+ fontSize: "text-lg"
17338
+ },
17339
+ xl: {
17340
+ padding: "1.0625rem 2rem",
17341
+ fontSize: "text-xl"
17342
+ }
17343
+ },
17344
+ variants: [
17345
+ {
17346
+ id: "primary",
17347
+ name: "Primary",
17348
+ enabled: true,
17349
+ priority: 1,
17350
+ background: {
17351
+ type: "solid",
17352
+ colorToken: "primary"
17353
+ },
17354
+ textColorToken: "primaryForeground",
17355
+ borderRadius: "rounded-lg",
17356
+ affordance: {
17357
+ iconId: "ArrowRight",
17358
+ colorToken: "accent"
17359
+ },
17360
+ shadow: {
17361
+ elevation: "none",
17362
+ softness: null,
17363
+ position: "bottom"
17364
+ },
17365
+ effects: { hover: [{
17366
+ effectId: "lift",
17367
+ options: { translateY: "-2px" }
17368
+ }, {
17369
+ effectId: "background-on-hover",
17370
+ options: { colorToken: "secondary" }
17371
+ }] }
17372
+ },
17373
+ {
17374
+ id: "secondary",
17375
+ name: "Secondary",
17376
+ enabled: true,
17377
+ priority: 2,
17378
+ background: { type: "transparent" },
17379
+ textColorToken: "primary",
17380
+ borderRadius: "rounded-lg",
17381
+ border: {
17382
+ widthClass: "border",
17383
+ colorToken: "border"
17384
+ },
17385
+ shadow: {
17386
+ elevation: "none",
17387
+ softness: null,
17388
+ position: "bottom"
17389
+ },
17390
+ effects: { hover: [{
17391
+ effectId: "lift",
17392
+ options: { translateY: "-2px" }
17393
+ }, {
17394
+ effectId: "background-on-hover",
17395
+ options: { colorToken: "surfaceAlt" }
17396
+ }] }
17397
+ },
17398
+ {
17399
+ id: "accent",
17400
+ name: "Accent",
17401
+ enabled: true,
17402
+ priority: 3,
17403
+ background: {
17404
+ type: "solid",
17405
+ colorToken: "accent"
17406
+ },
17407
+ textColorToken: "accentForeground",
17408
+ borderRadius: "rounded-lg",
17409
+ shadow: {
17410
+ elevation: "none",
17411
+ softness: null,
17412
+ position: "bottom"
17413
+ },
17414
+ affordance: {
17415
+ iconId: "ArrowRight",
17416
+ colorToken: "accentForeground"
17417
+ },
17418
+ effects: { hover: [{
17419
+ effectId: "lift",
17420
+ options: { translateY: "-2px" }
17421
+ }] }
17422
+ }
17423
+ ]
17424
+ }
17425
+ });
17426
+ }));
17427
+ //#endregion
17219
17428
  //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
17220
17429
  var inkStamp;
17221
17430
  var init_ink_stamp = __esmMin((() => {
@@ -17982,6 +18191,7 @@ var init_personalities = __esmMin((() => {
17982
18191
  init_confident_chip();
17983
18192
  init_earth_pill();
17984
18193
  init_editorial_link();
18194
+ init_flat_ink();
17985
18195
  init_ink_stamp();
17986
18196
  init_joy_stamp();
17987
18197
  init_ornate_ritual();
@@ -17996,6 +18206,7 @@ var init_personalities = __esmMin((() => {
17996
18206
  editorialLink,
17997
18207
  pebble,
17998
18208
  inkStamp,
18209
+ flatInk,
17999
18210
  brushedWash,
18000
18211
  showtimePill,
18001
18212
  joyStamp,
@@ -18465,6 +18676,50 @@ function getCompatibleHeaderStyleIds(layoutId) {
18465
18676
  return isHeaderStyleCompatibleWithLayout(getHeaderStyleOrThrow(styleId), layoutId);
18466
18677
  });
18467
18678
  }
18679
+ function applyNavTypography(style, typography) {
18680
+ switch (typography) {
18681
+ case "plain": return style;
18682
+ case "heading": return {
18683
+ ...style,
18684
+ typography: "heading",
18685
+ fontWeight: "medium",
18686
+ letterSpacing: "wide"
18687
+ };
18688
+ case "quiet-caps": return {
18689
+ ...style,
18690
+ textTransform: "uppercase",
18691
+ textSize: "sm",
18692
+ letterSpacing: "wide"
18693
+ };
18694
+ case "brand-caps": return {
18695
+ ...style,
18696
+ textTransform: "uppercase",
18697
+ textSize: "sm",
18698
+ letterSpacing: "wider"
18699
+ };
18700
+ default: return assertNever$19(typography, "Unhandled header nav typography");
18701
+ }
18702
+ }
18703
+ function underlineNavLinkStyle(colorToken, underlineColorToken, typography = "plain") {
18704
+ return applyNavTypography({
18705
+ name: "Underline grow",
18706
+ typography: "body",
18707
+ fontWeight: "medium",
18708
+ textTransform: "none",
18709
+ italic: false,
18710
+ colorToken,
18711
+ padding: "compact",
18712
+ paddingX: "compact",
18713
+ borderRadius: "none",
18714
+ effects: { hover: [{
18715
+ effectId: "nav-underline",
18716
+ options: {
18717
+ style: "grow",
18718
+ ...underlineColorToken ? { colorToken: underlineColorToken } : {}
18719
+ }
18720
+ }] }
18721
+ }, typography);
18722
+ }
18468
18723
  function themedHeaderShadow(theme) {
18469
18724
  switch (theme.shadow.elevation) {
18470
18725
  case "none": return;
@@ -18564,6 +18819,38 @@ function cleanBaseHeader(theme) {
18564
18819
  ctaGap: "default"
18565
18820
  };
18566
18821
  }
18822
+ function classicCenteredNavHeader(theme) {
18823
+ return {
18824
+ ...baseHeader(theme),
18825
+ variant: "classic",
18826
+ navPlacement: "center",
18827
+ positioning: "sticky",
18828
+ shrinkOnScroll: false,
18829
+ background: {
18830
+ type: "color",
18831
+ color: "surface"
18832
+ },
18833
+ textColor: "text",
18834
+ navColor: "text",
18835
+ navStyle: "underline-grow",
18836
+ navWeight: "medium",
18837
+ navLinkStyle: underlineNavLinkStyle("text", "accent"),
18838
+ border: {
18839
+ style: "solid",
18840
+ width: "thin",
18841
+ position: "bottom",
18842
+ colorToken: "border"
18843
+ },
18844
+ ctaTreatment: "primary",
18845
+ ctaVariant: resolveHeaderCtaVariant(theme, "primary"),
18846
+ ctaGap: "default",
18847
+ logoText: {
18848
+ mobileMaxWidth: "sm",
18849
+ mobileWrapLines: 1,
18850
+ hideOnShrink: false
18851
+ }
18852
+ };
18853
+ }
18567
18854
  function serifLineHeader(theme) {
18568
18855
  return {
18569
18856
  ...baseHeader(theme),
@@ -19142,6 +19429,13 @@ var init_headerLooks = __esmMin((() => {
19142
19429
  styleId: asHeaderStyleId("minimal")
19143
19430
  }
19144
19431
  },
19432
+ {
19433
+ lookId: asHeaderLookId("classic-centered-nav"),
19434
+ selection: {
19435
+ layoutId: asHeaderLayoutId("classic"),
19436
+ styleId: asHeaderStyleId("fine-line")
19437
+ }
19438
+ },
19145
19439
  {
19146
19440
  lookId: asHeaderLookId("brand-solid"),
19147
19441
  selection: {
@@ -19208,6 +19502,21 @@ var init_headerLooks = __esmMin((() => {
19208
19502
  logoAccommodations: inlineClassicLogoAccommodations,
19209
19503
  compile: cleanBaseHeader
19210
19504
  },
19505
+ {
19506
+ id: asHeaderLookId("classic-centered-nav"),
19507
+ label: "Centered nav",
19508
+ visualTreatment: "solid-neutral",
19509
+ layoutBehavior: "sticky",
19510
+ configuration: {
19511
+ structure: "inline-classic",
19512
+ treatment: "solid-neutral",
19513
+ behavior: "sticky"
19514
+ },
19515
+ openingRequirement: "none",
19516
+ maxRecommendedNavItems: 6,
19517
+ logoAccommodations: inlineClassicLogoAccommodations,
19518
+ compile: classicCenteredNavHeader
19519
+ },
19211
19520
  {
19212
19521
  id: asHeaderLookId("brand-solid"),
19213
19522
  label: "Brand solid",
@@ -19768,7 +20077,7 @@ function defineTypographyPreset(preset) {
19768
20077
  id: asTypographyPresetId(preset.id)
19769
20078
  };
19770
20079
  }
19771
- var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, typographyPresets;
20080
+ var bodyReadablePolicy, headingFlexiblePolicy, displayHeadingPolicy, modernSansTypography, warmRoundedTypography, editorialSerifTypography, classicSerifTypography, luxeContrastTypography, kirtanOrnateTypography, boldDisplayTypography, originalJoyTypography, fulcrumTypography, typographyPresets;
19772
20081
  var init_typographyPresets = __esmMin((() => {
19773
20082
  bodyReadablePolicy = {
19774
20083
  recommendedCategories: ["sans-serif", "serif"],
@@ -20130,6 +20439,49 @@ var init_typographyPresets = __esmMin((() => {
20130
20439
  },
20131
20440
  scale: "balanced"
20132
20441
  };
20442
+ fulcrumTypography = {
20443
+ body: {
20444
+ family: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
20445
+ size: "lg",
20446
+ weight: "regular",
20447
+ lineHeight: "relaxed",
20448
+ letterSpacing: "normal"
20449
+ },
20450
+ headings: {
20451
+ default: {
20452
+ family: "Newsreader, Georgia, \"Times New Roman\", serif",
20453
+ weight: "medium",
20454
+ lineHeight: "normal",
20455
+ letterSpacing: "tight",
20456
+ colorToken: "primary",
20457
+ italic: null,
20458
+ case: null
20459
+ },
20460
+ h1: {
20461
+ size: "2xl",
20462
+ weight: "medium",
20463
+ lineHeight: "normal",
20464
+ letterSpacing: "tight",
20465
+ italic: null
20466
+ },
20467
+ h2: {
20468
+ size: "xl",
20469
+ weight: "medium",
20470
+ lineHeight: "normal",
20471
+ letterSpacing: "tight",
20472
+ italic: null
20473
+ },
20474
+ h3: {
20475
+ size: "md",
20476
+ weight: "semibold",
20477
+ lineHeight: "normal",
20478
+ letterSpacing: "normal",
20479
+ italic: null
20480
+ }
20481
+ },
20482
+ scale: "spacious",
20483
+ eyebrow: { family: "IBM Plex Mono, ui-monospace, \"SF Mono\", monospace" }
20484
+ };
20133
20485
  typographyPresets = [
20134
20486
  defineTypographyPreset({
20135
20487
  id: "typography-preset:modern-sans",
@@ -20389,6 +20741,32 @@ var init_typographyPresets = __esmMin((() => {
20389
20741
  }
20390
20742
  }
20391
20743
  }
20744
+ }),
20745
+ defineTypographyPreset({
20746
+ id: "typography-preset:fulcrum",
20747
+ name: "Fulcrum",
20748
+ description: "Newsreader serif headings over an IBM Plex Sans body, with an IBM Plex Mono eyebrow role for uppercase kickers and mono captions.",
20749
+ defaultFonts: {
20750
+ body: "IBM Plex Sans, system-ui, -apple-system, sans-serif",
20751
+ heading: "Newsreader, Georgia, \"Times New Roman\", serif"
20752
+ },
20753
+ recommendedFonts: {
20754
+ body: [
20755
+ "IBM Plex Sans",
20756
+ "Source Sans 3",
20757
+ "Inter"
20758
+ ],
20759
+ heading: [
20760
+ "Newsreader",
20761
+ "Source Serif 4",
20762
+ "Lora"
20763
+ ]
20764
+ },
20765
+ slotPolicies: {
20766
+ body: bodyReadablePolicy,
20767
+ heading: displayHeadingPolicy
20768
+ },
20769
+ typography: fulcrumTypography
20392
20770
  })
20393
20771
  ];
20394
20772
  new Map(typographyPresets.map((preset) => [preset.id, preset]));
@@ -22107,6 +22485,28 @@ var init_generateDefaultButtonSystem = __esmMin((() => {
22107
22485
  "high"
22108
22486
  ];
22109
22487
  }));
22488
+ /**
22489
+ * Build a `data:image/svg+xml,...` URL for an affordance icon, suitable for use
22490
+ * as a CSS `mask-image`. The stroke is painted solid black so the mask's alpha
22491
+ * traces the icon outline; the visible colour is supplied separately by the
22492
+ * `::after` rule's `background-color`. Returns `null` for unknown ids.
22493
+ */
22494
+ function affordanceIconMaskUrl(iconId) {
22495
+ const paths = AFFORDANCE_ICON_PATHS[iconId];
22496
+ if (!paths || paths.length === 0) return null;
22497
+ 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, " ")}`;
22498
+ }
22499
+ var AFFORDANCE_ICON_PATHS;
22500
+ var init_affordanceIcons = __esmMin((() => {
22501
+ AFFORDANCE_ICON_PATHS = {
22502
+ ArrowRight: ["M5 12h14", "m13 6 6 6-6 6"],
22503
+ ArrowLeft: ["M19 12H5", "m11 6-6 6 6 6"],
22504
+ ChevronRight: ["m9 18 6-6-6-6"],
22505
+ ChevronLeft: ["m15 18-6-6 6-6"],
22506
+ ChevronDown: ["m6 9 6 6 6-6"],
22507
+ ArrowUpRight: ["M7 17 17 7", "M7 7h10v10"]
22508
+ };
22509
+ }));
22110
22510
  //#endregion
22111
22511
  //#region ../theme-core/src/buttons/generateButtonCss.ts
22112
22512
  function rule(selector, declarations) {
@@ -22185,10 +22585,40 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
22185
22585
  out.push(variantFocusVisibleRule(variantId, themeId));
22186
22586
  const effects = variantEffectsCss(variant, themeId, tokens, theme);
22187
22587
  if (effects) out.push({ raw: effects });
22588
+ const affordance = variantAffordanceRule(variant, selector, tokens);
22589
+ if (affordance) out.push(affordance);
22188
22590
  out.push(...variantDisabledRules(variantId, themeId));
22189
22591
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
22190
22592
  return out;
22191
22593
  }
22594
+ /**
22595
+ * Emit the optional trailing affordance icon as a masked `::after`.
22596
+ *
22597
+ * Only variants that declare `affordance` with a known icon id produce a rule —
22598
+ * every other variant is byte-identical to before. The `:not(.rb-affordance-off)`
22599
+ * guard lets a `button` node that renders its own trailing icon suppress this
22600
+ * one (node overrides personality). Colour comes from the affordance token, or
22601
+ * `currentColor` (the button text colour) when no token is given.
22602
+ */
22603
+ function variantAffordanceRule(variant, selector, tokens) {
22604
+ const affordance = variant.affordance;
22605
+ if (!affordance) return null;
22606
+ const maskUrl = affordanceIconMaskUrl(affordance.iconId);
22607
+ if (!maskUrl) return null;
22608
+ const color = affordance.colorToken ? tokens.getColor(affordance.colorToken) : "currentColor";
22609
+ const mask = `url("${maskUrl}") no-repeat center / contain`;
22610
+ return rule(`${selector}:not(.${AFFORDANCE_SUPPRESS_CLASS})::after`, [
22611
+ ["content", "\"\""],
22612
+ ["display", "inline-block"],
22613
+ ["width", "1em"],
22614
+ ["height", "1em"],
22615
+ ["margin-inline-start", "0.5em"],
22616
+ ["flex", "0 0 auto"],
22617
+ ["background-color", color],
22618
+ ["-webkit-mask", mask],
22619
+ ["mask", mask]
22620
+ ]);
22621
+ }
22192
22622
  function parseButtonVariantIdForCss(value) {
22193
22623
  const variantId = parseThemeButtonVariantId(value);
22194
22624
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
@@ -22335,7 +22765,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
22335
22765
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
22336
22766
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
22337
22767
  }
22338
- var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
22768
+ var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
22339
22769
  var init_generateButtonCss = __esmMin((() => {
22340
22770
  init_types$14();
22341
22771
  init_classNames();
@@ -22344,6 +22774,8 @@ var init_generateButtonCss = __esmMin((() => {
22344
22774
  init_generateEffectsCSS();
22345
22775
  init_constants$2();
22346
22776
  init_generateDefaultButtonSystem();
22777
+ init_affordanceIcons();
22778
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
22347
22779
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
22348
22780
  LETTER_SPACING_MAP = {
22349
22781
  tight: "-0.025em",
@@ -22370,6 +22802,7 @@ var init_buttons = __esmMin((() => {
22370
22802
  init_types$14();
22371
22803
  init_classNames();
22372
22804
  init_generateButtonCss();
22805
+ init_affordanceIcons();
22373
22806
  init_generateDefaultButtonSystem();
22374
22807
  init_constants$2();
22375
22808
  init_presets();
@@ -22610,21 +23043,80 @@ function generateDefaultCardSystem(theme) {
22610
23043
  }
22611
23044
  var init_generateDefaultCardSystem = __esmMin((() => {}));
22612
23045
  //#endregion
22613
- //#region ../theme-core/src/status/contextualColors.ts
22614
- function statusMutedColorValue() {
22615
- return `var(${STATUS_MUTED_COLOR_VAR}, ${DEFAULT_STATUS_MUTED_COLOR})`;
23046
+ //#region ../theme-core/src/surfaces/foregroundRoles.ts
23047
+ var SURFACE_FOREGROUND_ROLES;
23048
+ var init_foregroundRoles = __esmMin((() => {
23049
+ SURFACE_FOREGROUND_ROLES = [
23050
+ "text",
23051
+ "heading",
23052
+ "link",
23053
+ "supporting"
23054
+ ];
23055
+ }));
23056
+ //#endregion
23057
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
23058
+ function requireSurfaceColorValue(role, value) {
23059
+ const normalized = value.trim();
23060
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
23061
+ return normalized;
23062
+ }
23063
+ function completeSurfaceForegrounds(input) {
23064
+ const text = requireSurfaceColorValue("text", input.text);
23065
+ return {
23066
+ text,
23067
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
23068
+ link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
23069
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
23070
+ };
23071
+ }
23072
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
23073
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
23074
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
23075
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
23076
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
23077
+ }
23078
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
23079
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
23080
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
22616
23081
  }
22617
- function statusMutedColorDeclaration() {
22618
- return `color: ${statusMutedColorValue()};`;
23082
+ function surfaceForegroundStyle(input) {
23083
+ const foregrounds = completeSurfaceForegrounds(input);
23084
+ return {
23085
+ color: foregrounds.text,
23086
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
23087
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
23088
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
23089
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
23090
+ };
22619
23091
  }
22620
- function contextualMutedStatusColorDeclaration(value) {
22621
- return `${STATUS_MUTED_COLOR_VAR}: ${value}`;
23092
+ function surfaceForegroundDeclarations(input) {
23093
+ const foregrounds = completeSurfaceForegrounds(input);
23094
+ return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
22622
23095
  }
22623
- var STATUS_MUTED_COLOR_VAR, DEFAULT_STATUS_MUTED_COLOR, SURFACE_MUTED_STATUS_COLOR;
22624
- var init_contextualColors = __esmMin((() => {
22625
- STATUS_MUTED_COLOR_VAR = "--rb-status-muted-color";
22626
- DEFAULT_STATUS_MUTED_COLOR = "rgb(var(--tb-mutedText))";
22627
- SURFACE_MUTED_STATUS_COLOR = "color-mix(in oklab, currentColor, transparent 18%)";
23096
+ var SURFACE_FOREGROUND_CSS_VARS, DEFAULT_SURFACE_TEXT_COLOR, DEFAULT_SURFACE_LINK_COLOR, DEFAULT_SURFACE_SUPPORTING_COLOR, DEFAULT_ROLE_FALLBACKS;
23097
+ var init_foregroundContract = __esmMin((() => {
23098
+ init_foregroundRoles();
23099
+ SURFACE_FOREGROUND_CSS_VARS = {
23100
+ text: "--rb-surface-text-color",
23101
+ heading: "--rb-surface-heading-color",
23102
+ link: "--rb-surface-link-color",
23103
+ supporting: "--rb-surface-supporting-color"
23104
+ };
23105
+ DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
23106
+ DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
23107
+ DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
23108
+ DEFAULT_ROLE_FALLBACKS = {
23109
+ text: DEFAULT_SURFACE_TEXT_COLOR,
23110
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
23111
+ link: DEFAULT_SURFACE_LINK_COLOR,
23112
+ supporting: DEFAULT_SURFACE_SUPPORTING_COLOR
23113
+ };
23114
+ }));
23115
+ //#endregion
23116
+ //#region ../theme-core/src/surfaces/index.ts
23117
+ var init_surfaces = __esmMin((() => {
23118
+ init_foregroundContract();
23119
+ init_foregroundRoles();
22628
23120
  }));
22629
23121
  //#endregion
22630
23122
  //#region ../theme-core/src/cards/generateCardCss.ts
@@ -22671,8 +23163,10 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
22671
23163
  const direction = GRADIENT_DIRECTION_MAP$1[variant.background.direction] || "to right";
22672
23164
  rules.push(`background: linear-gradient(${direction}, ${fromColor}, ${toColor})`);
22673
23165
  } else rules.push(`background: transparent`);
22674
- if (variant.foregroundToken) rules.push(`color: ${tokens.getColor(variant.foregroundToken)}`);
22675
- rules.push(contextualMutedStatusColorDeclaration(SURFACE_MUTED_STATUS_COLOR));
23166
+ if (variant.background.type !== "transparent") {
23167
+ const foreground = tokens.getColor(variant.foregroundToken ?? "text");
23168
+ rules.push(...surfaceForegroundDeclarations({ text: foreground }));
23169
+ }
22676
23170
  if (variant.accentEdge) {
22677
23171
  const side = ACCENT_EDGE_SIDE_MAP$1[variant.accentEdge.edge];
22678
23172
  const width = ACCENT_EDGE_WIDTH_MAP$1[variant.accentEdge.width];
@@ -22710,7 +23204,7 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
22710
23204
  init_resolver$1();
22711
23205
  init_constants$1();
22712
23206
  init_generateDefaultCardSystem();
22713
- init_contextualColors();
23207
+ init_surfaces();
22714
23208
  PER_CORNER_RADIUS_MAP$1 = {
22715
23209
  square: "0",
22716
23210
  soft: "0.5rem",
@@ -22745,7 +23239,9 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
22745
23239
  pill: "1.5rem"
22746
23240
  };
22747
23241
  }));
22748
- var init_core$1 = __esmMin((() => {}));
23242
+ var init_core$1 = __esmMin((() => {
23243
+ init_surfaces();
23244
+ }));
22749
23245
  //#endregion
22750
23246
  //#region ../theme-core/src/cards/index.ts
22751
23247
  var init_cards = __esmMin((() => {
@@ -23038,16 +23534,22 @@ var init_types$9 = __esmMin((() => {
23038
23534
  /**
23039
23535
  * Gradient configuration types and schemas
23040
23536
  */
23041
- var gradientStopSchema, gradientConfigSchema;
23537
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
23042
23538
  var init_types$8 = __esmMin((() => {
23043
23539
  init_themeColorTokens();
23044
23540
  gradientStopSchema = z$1.object({
23045
23541
  color: themeColorTokenSchema,
23046
23542
  position: z$1.number().min(0).max(100)
23047
23543
  });
23544
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
23048
23545
  gradientConfigSchema = z$1.object({
23049
- type: z$1.enum(["linear", "radial"]),
23546
+ type: z$1.enum([
23547
+ "linear",
23548
+ "radial",
23549
+ "conic"
23550
+ ]).default("linear"),
23050
23551
  angle: z$1.number().min(0).max(360).optional(),
23552
+ shape: radialGradientShapeSchema.optional(),
23051
23553
  position: z$1.string().optional(),
23052
23554
  stops: z$1.array(gradientStopSchema).min(2)
23053
23555
  });
@@ -23492,9 +23994,12 @@ function parseToken(source) {
23492
23994
  if (parts.kind === "invalid") return { token: source };
23493
23995
  return {
23494
23996
  token: parts.token,
23495
- alpha: parts.opacityPercent === null ? void 0 : parts.opacityPercent / 100
23997
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
23496
23998
  };
23497
23999
  }
24000
+ function surfaceRoleForTextToken(token) {
24001
+ return Object.prototype.hasOwnProperty.call(SURFACE_TEXT_ROLE_BY_TOKEN, token) ? SURFACE_TEXT_ROLE_BY_TOKEN[token] : null;
24002
+ }
23498
24003
  /**
23499
24004
  * Converts a theme color token to a CSS rgb value.
23500
24005
  * This is the primary function for applying theme colors to CSS properties.
@@ -23508,11 +24013,26 @@ function parseToken(source) {
23508
24013
  * rgbColorValue('raw:transparent') // => 'transparent'
23509
24014
  */
23510
24015
  function rgbColorValue(token) {
23511
- const { token: baseToken, alpha, raw } = parseToken(token);
24016
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
23512
24017
  if (raw) return raw;
23513
24018
  const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
23514
- if (alpha === void 0) return `rgb(var(${cssVar}))`;
23515
- return `rgb(var(${cssVar}) / ${alpha})`;
24019
+ if (opacityPercent === void 0) return `rgb(var(${cssVar}))`;
24020
+ return `rgb(var(${cssVar}) / ${opacityPercent / 100})`;
24021
+ }
24022
+ /**
24023
+ * Converts a theme color token to a CSS variable reference.
24024
+ * Note: This returns the base variable without rgb() wrapper, ignoring opacity.
24025
+ *
24026
+ * @param token - Theme color token
24027
+ * @returns CSS variable reference
24028
+ *
24029
+ * @example
24030
+ * cssVarValue('primary') // => 'var(--tb-primary)'
24031
+ * cssVarValue('surface/95') // => 'var(--tb-surface)' (opacity ignored)
24032
+ */
24033
+ function cssVarValue(token) {
24034
+ const { token: baseToken } = parseToken(token);
24035
+ return `var(${COLOR_VAR_PREFIX}${baseToken})`;
23516
24036
  }
23517
24037
  /**
23518
24038
  * Creates a backgroundColor style object from a theme token.
@@ -23530,6 +24050,9 @@ function backgroundColorStyle(token) {
23530
24050
  * @returns CSSProperties with color
23531
24051
  */
23532
24052
  function textColorStyle(token) {
24053
+ const parsed = parseToken(token);
24054
+ const surfaceRole = parsed.raw ? null : surfaceRoleForTextToken(parsed.token);
24055
+ if (surfaceRole) return { color: parsed.opacityPercent === void 0 ? surfaceForegroundValue(surfaceRole) : surfaceForegroundValueWithOpacity(surfaceRole, parsed.opacityPercent) };
23533
24056
  return { color: rgbColorValue(token) };
23534
24057
  }
23535
24058
  /**
@@ -23565,10 +24088,16 @@ function mergeStyles(...styles) {
23565
24088
  }
23566
24089
  return Object.keys(merged).length ? merged : void 0;
23567
24090
  }
23568
- var COLOR_VAR_PREFIX;
24091
+ var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
23569
24092
  var init_colorStyles = __esmMin((() => {
24093
+ init_surfaces();
23570
24094
  init_colorTokenParts();
23571
24095
  COLOR_VAR_PREFIX = "--tb-";
24096
+ SURFACE_TEXT_ROLE_BY_TOKEN = {
24097
+ text: "text",
24098
+ heading: "heading",
24099
+ mutedText: "supporting"
24100
+ };
23572
24101
  }));
23573
24102
  //#endregion
23574
24103
  //#region ../theme-core/src/utils/tokenOrColor.ts
@@ -23675,7 +24204,7 @@ var init_tokenOrColor = __esmMin((() => {
23675
24204
  "white",
23676
24205
  "yellow"
23677
24206
  ]);
23678
- })), 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;
24207
+ })), 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;
23679
24208
  var init_schema = __esmMin((() => {
23680
24209
  init_media$2();
23681
24210
  init_buttons();
@@ -23955,6 +24484,7 @@ var init_schema = __esmMin((() => {
23955
24484
  "majorThird",
23956
24485
  "perfectFourth"
23957
24486
  ]);
24487
+ eyebrowTypographyStyleSchema = z$1.object({ family: z$1.string().min(1) });
23958
24488
  typographySchema = z$1.object({
23959
24489
  body: bodyTypographyStyleSchema,
23960
24490
  headings: z$1.object({
@@ -23967,7 +24497,8 @@ var init_schema = __esmMin((() => {
23967
24497
  h6: headingTypographyOverridesSchema.optional()
23968
24498
  }),
23969
24499
  scale: typographyScaleSchema,
23970
- proseLinkStyle: proseLinkStyleSchema.optional()
24500
+ proseLinkStyle: proseLinkStyleSchema.optional(),
24501
+ eyebrow: eyebrowTypographyStyleSchema.optional()
23971
24502
  });
23972
24503
  spaceSchema = z$1.enum([
23973
24504
  "comfortable",
@@ -23992,7 +24523,8 @@ var init_schema = __esmMin((() => {
23992
24523
  "soft",
23993
24524
  "hard"
23994
24525
  ]).nullable(),
23995
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
24526
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
24527
+ colorToken: themeColorTokenSchema.optional()
23996
24528
  });
23997
24529
  border = z$1.object({
23998
24530
  width: z$1.enum([
@@ -24233,6 +24765,7 @@ var init_schema = __esmMin((() => {
24233
24765
  navWeight: navFontWeight.default("medium"),
24234
24766
  navTypography: z$1.enum(["body", "heading"]).optional(),
24235
24767
  navTextSize: navLinkStyleSchema.shape.textSize,
24768
+ navPlacement: z$1.enum(["end", "center"]).optional(),
24236
24769
  container: headerContainerSchema,
24237
24770
  border: headerBorderSchema,
24238
24771
  shadow: componentShadowSchema.optional(),
@@ -24991,7 +25524,8 @@ var init_curatedSiteStyles = __esmMin((() => {
24991
25524
  "site-style:bold-launch",
24992
25525
  "site-style:south-west-twerk-school",
24993
25526
  "site-style:kirtan-ornate",
24994
- "site-style:original-joy"
25527
+ "site-style:original-joy",
25528
+ "site-style:fulcrum"
24995
25529
  ];
24996
25530
  quietBudget = {
24997
25531
  accentDensity: "low",
@@ -26203,6 +26737,104 @@ var init_curatedSiteStyles = __esmMin((() => {
26203
26737
  buttonChoice("showtime-pill")
26204
26738
  ],
26205
26739
  paletteRecommendations: [paletteRecommendation("warm-dark-ember")]
26740
+ }),
26741
+ defineCuratedSiteStyle({
26742
+ id: "site-style:fulcrum",
26743
+ name: "Fulcrum",
26744
+ headingDecoration: {
26745
+ family: "short-center-rule",
26746
+ colorToken: "accent"
26747
+ },
26748
+ 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.",
26749
+ 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.",
26750
+ siteCreatorSelection: {
26751
+ kind: "site_creator_keyword_heuristic",
26752
+ priority: 28
26753
+ },
26754
+ selectionKeywordRules: [
26755
+ {
26756
+ kind: "substring",
26757
+ value: "physiotherap"
26758
+ },
26759
+ {
26760
+ kind: "word",
26761
+ value: "physio"
26762
+ },
26763
+ {
26764
+ kind: "phrase",
26765
+ value: "sports injury"
26766
+ },
26767
+ {
26768
+ kind: "phrase",
26769
+ value: "rehab clinic"
26770
+ },
26771
+ {
26772
+ kind: "substring",
26773
+ value: "musculoskeletal"
26774
+ },
26775
+ {
26776
+ kind: "phrase",
26777
+ value: "sports therapy"
26778
+ }
26779
+ ],
26780
+ tokenRecipes: {
26781
+ palette: "brand-led",
26782
+ contrast: "standard",
26783
+ radius: "rounded",
26784
+ shadow: "subtle",
26785
+ typography: "serif-editorial",
26786
+ spacing: "airy",
26787
+ motion: "subtle"
26788
+ },
26789
+ compositionBudget: quietBudget,
26790
+ typographyPresetChoices: [
26791
+ typographyChoice("typography-preset:fulcrum"),
26792
+ typographyChoice("typography-preset:editorial-serif"),
26793
+ typographyChoice("typography-preset:modern-sans")
26794
+ ],
26795
+ defaultTypographyPresetId: "typography-preset:fulcrum",
26796
+ themeOverrides: {
26797
+ shadow: { colorToken: "primary" },
26798
+ accordions: {
26799
+ background: null,
26800
+ spacing: "comfortable",
26801
+ corners: "square",
26802
+ border: null,
26803
+ shadow: null,
26804
+ icon: {
26805
+ style: "plus-minus",
26806
+ position: "right",
26807
+ size: "md",
26808
+ colorToken: "accent"
26809
+ },
26810
+ trigger: {
26811
+ textColorToken: "primary",
26812
+ fontWeight: "medium",
26813
+ fontFamily: "heading",
26814
+ fontScale: "md"
26815
+ },
26816
+ hover: { textColorToken: "secondary" },
26817
+ content: { textColorToken: "muted" }
26818
+ },
26819
+ testimonialQuote: serifDisplayQuote
26820
+ },
26821
+ recommendedHeaderLookIds: [
26822
+ "classic-centered-nav",
26823
+ "serif-line",
26824
+ "centered-calm",
26825
+ "clean-base"
26826
+ ],
26827
+ recommendedFooterLookIds: ["footer-editorial-columns", "footer-muted-grounding"],
26828
+ buttonPersonalityChoices: [
26829
+ buttonChoice("flat-ink"),
26830
+ buttonChoice("confident-chip"),
26831
+ buttonChoice("editorial-link")
26832
+ ],
26833
+ paletteRecommendations: [
26834
+ paletteRecommendation("brand-led-spruce"),
26835
+ paletteRecommendation("warm-neutral-forest"),
26836
+ paletteRecommendation("soft-natural-sage")
26837
+ ]
26206
26838
  })
26207
26839
  ];
26208
26840
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
@@ -28481,7 +29113,7 @@ var init_themeColorResolution = __esmMin((() => {
28481
29113
  init_tokenOrColor();
28482
29114
  }));
28483
29115
  //#endregion
28484
- //#region ../blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.ts
29116
+ //#region ../blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.ts
28485
29117
  function readColorToken(input, key) {
28486
29118
  const value = input[key];
28487
29119
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
@@ -28490,20 +29122,20 @@ function resolveOptionalForegroundColor(value, context) {
28490
29122
  if (!value) return null;
28491
29123
  return resolveBackgroundColorValue(value, context);
28492
29124
  }
28493
- function resolveSectionForegroundStyles(value, context) {
29125
+ function resolveSurfaceForegroundStyles(value, context) {
28494
29126
  if (!value || typeof value !== "object") return {};
28495
29127
  const input = value;
28496
29128
  const resolvedText = resolveOptionalForegroundColor(readColorToken(input, "textColor"), context);
28497
29129
  if (!resolvedText) return {};
28498
- return {
28499
- color: resolvedText,
28500
- "--section-text-color": resolvedText,
28501
- "--section-heading-color": resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? resolvedText,
28502
- "--section-link-color": resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? resolvedText,
28503
- "--section-supporting-color": resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? resolvedText
28504
- };
29130
+ return { ...surfaceForegroundStyle({
29131
+ text: resolvedText,
29132
+ heading: resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? void 0,
29133
+ link: resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? void 0,
29134
+ supporting: resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? void 0
29135
+ }) };
28505
29136
  }
28506
- var init_sectionForegroundStyles = __esmMin((() => {
29137
+ var init_surfaceForegroundStyles = __esmMin((() => {
29138
+ init_surfaces();
28507
29139
  init_themeColorResolution();
28508
29140
  }));
28509
29141
  //#endregion
@@ -28535,7 +29167,7 @@ function isTileTreatment(value) {
28535
29167
  function isEventListTreatment(value) {
28536
29168
  return typeof value === "string" && eventListTreatmentSet.has(value);
28537
29169
  }
28538
- 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;
29170
+ 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;
28539
29171
  var init_boxStyles = __esmMin((() => {
28540
29172
  init_core();
28541
29173
  init_spacing();
@@ -28543,8 +29175,7 @@ var init_boxStyles = __esmMin((() => {
28543
29175
  init_colorStyles();
28544
29176
  init_cards();
28545
29177
  init_blockColorTokens();
28546
- init_themeColorResolution();
28547
- init_sectionForegroundStyles();
29178
+ init_surfaceForegroundStyles();
28548
29179
  spacingTransform = {
28549
29180
  id: "boxStyles.spacing",
28550
29181
  kind: "string",
@@ -28770,45 +29401,11 @@ var init_boxStyles = __esmMin((() => {
28770
29401
  }, context);
28771
29402
  }
28772
29403
  };
28773
- sectionTextColorStyleTransform = {
28774
- id: "sectionStyles.resolveTextColorStyle",
28775
- kind: "formatter",
28776
- summary: "Resolve section text color token into a style object",
28777
- run: (value, options, context) => {
28778
- const fallbackToken = options?.fallbackToken;
28779
- if (typeof value === "string" && value.trim()) {
28780
- const colorValue = resolveBackgroundColorValue(value.trim(), context);
28781
- return {
28782
- color: colorValue,
28783
- "--section-text-color": colorValue
28784
- };
28785
- }
28786
- if (typeof fallbackToken === "string" && fallbackToken.trim()) {
28787
- const colorValue = resolveBackgroundColorValue(fallbackToken.trim(), context);
28788
- return {
28789
- color: colorValue,
28790
- "--section-text-color": colorValue
28791
- };
28792
- }
28793
- return {};
28794
- }
28795
- };
28796
- sectionHeadingColorStyleTransform = {
28797
- id: "sectionStyles.resolveHeadingColorStyle",
28798
- kind: "formatter",
28799
- summary: "Resolve section heading color token into a style object",
28800
- run: (value, options, context) => {
28801
- const fallbackToken = options?.fallbackToken;
28802
- if (typeof value === "string" && value.trim()) return { "--section-heading-color": resolveBackgroundColorValue(value.trim(), context) };
28803
- if (typeof fallbackToken === "string" && fallbackToken.trim()) return { "--section-heading-color": resolveBackgroundColorValue(fallbackToken.trim(), context) };
28804
- return {};
28805
- }
28806
- };
28807
29404
  sectionColorsStyleTransform = {
28808
29405
  id: "sectionStyles.resolveColorsStyle",
28809
29406
  kind: "formatter",
28810
- summary: "Resolve section foreground colors into a style object",
28811
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
29407
+ summary: "Resolve surface foreground colors into a style object",
29408
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
28812
29409
  };
28813
29410
  GAP_CLASS_MAP = {
28814
29411
  none: "rb-gap-semantic-none",
@@ -28856,8 +29453,6 @@ var init_boxStyles = __esmMin((() => {
28856
29453
  sectionClassNameTransform,
28857
29454
  containerStylesResolveClassName,
28858
29455
  containerStylesResolveBoxClassName,
28859
- sectionTextColorStyleTransform,
28860
- sectionHeadingColorStyleTransform,
28861
29456
  sectionColorsStyleTransform,
28862
29457
  semanticGapTransform,
28863
29458
  semanticGapValueTransform
@@ -29693,7 +30288,29 @@ var init_ctaRow = __esmMin((() => {
29693
30288
  fields: [createCtasRepeater({
29694
30289
  label: "Calls to action",
29695
30290
  itemLabel: "CTA",
29696
- maxItems: 3
30291
+ maxItems: 3,
30292
+ button: { variants: [
30293
+ {
30294
+ value: "primary",
30295
+ label: "Primary"
30296
+ },
30297
+ {
30298
+ value: "secondary",
30299
+ label: "Secondary"
30300
+ },
30301
+ {
30302
+ value: "outline",
30303
+ label: "Outline"
30304
+ },
30305
+ {
30306
+ value: "link",
30307
+ label: "Link"
30308
+ },
30309
+ {
30310
+ value: "accent",
30311
+ label: "Accent"
30312
+ }
30313
+ ] }
29697
30314
  })],
29698
30315
  layout: [ctaRow({
29699
30316
  collectionPath: "content.ctas",
@@ -29996,6 +30613,55 @@ function buildHighlightLayout() {
29996
30613
  function buildGridCardsLayout(className) {
29997
30614
  return el("div", { className }, buildResponsiveGridCards());
29998
30615
  }
30616
+ /**
30617
+ * Build a single "featured editorial" testimonial card.
30618
+ *
30619
+ * This card type deliberately renders NO avatar/headshot: an amber quote mark,
30620
+ * the quote body, then the author name and a context line. Colour + surface
30621
+ * treatment is driven entirely by `variantClass` (see testimonials.css):
30622
+ * - `rb-testimonials-fe-card--feature` → spruce-ink card (dark primary bg)
30623
+ * - `rb-testimonials-fe-card--plain` → white surface card
30624
+ *
30625
+ * Extra modifiers (`repeat`, `when`) are forwarded to the card node so the
30626
+ * caller can drive first-vs-rest branching.
30627
+ */
30628
+ function buildFeaturedEditorialCard(variantClass, ...mods) {
30629
+ const quoteMark = text({
30630
+ as: "span",
30631
+ className: "rb-testimonials-fe-qmark",
30632
+ "aria-hidden": "true"
30633
+ }, props({ value: "“" }));
30634
+ const quote = richText({ className: "rb-testimonials-fe-quote rb-max-w-none" }, bind("testimonial.content.body"), when("testimonial.content.body"));
30635
+ const meta = el("div", { className: "rb-testimonials-fe-meta" }, [text({
30636
+ as: "strong",
30637
+ className: "rb-testimonials-fe-name"
30638
+ }, bind("testimonial.content.name", { fallback: "Anonymous" })), text({
30639
+ as: "span",
30640
+ className: "rb-testimonials-fe-context"
30641
+ }, when("testimonial.content.jobTitle"), bind("testimonial.content.jobTitle"))]);
30642
+ return el("div", { className: `rb-testimonials-fe-card ${variantClass}` }, [
30643
+ quoteMark,
30644
+ quote,
30645
+ meta
30646
+ ], ...mods);
30647
+ }
30648
+ /**
30649
+ * Build the "featured editorial" layout: an asymmetric two-column arrangement
30650
+ * where the FIRST testimonial is a large featured (spruce-ink) card and the
30651
+ * remaining testimonials stack as white cards beside it.
30652
+ *
30653
+ * First-vs-rest branching is done without an offset primitive: the featured
30654
+ * card uses `repeat(..., { limit: 1 })` (entry 0 only), and the rest column
30655
+ * repeats over every entry but skips index 0 via `when("tIndex", { equals: 0,
30656
+ * not: true })`. The `$when` guard is re-evaluated per repeated item with the
30657
+ * index scope in context, so entry 0 produces no node in the rest column.
30658
+ */
30659
+ function buildFeaturedEditorialLayout() {
30660
+ 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", {
30661
+ equals: 0,
30662
+ not: true
30663
+ }))])]);
30664
+ }
29999
30665
  var grid$4, testimonialsCarouselFragment;
30000
30666
  var init_testimonialsCarousel = __esmMin((() => {
30001
30667
  init_types$5();
@@ -33820,7 +34486,7 @@ const defaultLayout = styledSection({
33820
34486
  children: styledContainer({
33821
34487
  baseClassName: "rb-relative rb-isolate",
33822
34488
  children: stack({
33823
- gap: "xl",
34489
+ gap: "lg",
33824
34490
  className: "rb-w-full rb-max-w-4xl rb-mx-auto"
33825
34491
  }, [headingLayout, accordionLayout])
33826
34492
  }),
@@ -33837,7 +34503,7 @@ const questionColumnsLayout = styledSection({
33837
34503
  children: styledContainer({
33838
34504
  baseClassName: "rb-relative rb-isolate",
33839
34505
  children: stack({
33840
- gap: "xl",
34506
+ gap: "lg",
33841
34507
  className: "rb-w-full"
33842
34508
  }, [headingLayout, questionColumnsAccordionLayout])
33843
34509
  }),
@@ -34002,7 +34668,26 @@ const formattingTransforms = [
34002
34668
  arrayLengthTransform,
34003
34669
  jsonArrayTransform,
34004
34670
  csvTransform,
34005
- marqueeLoopTransform
34671
+ marqueeLoopTransform,
34672
+ {
34673
+ id: "value.mapToken",
34674
+ kind: "formatter",
34675
+ summary: "Map a state/enum value to a theme token colour (rgb(var(--tb-<role>)))",
34676
+ schema: z$1.object({
34677
+ /**
34678
+ * Maps an input state/enum value (stringified) to a theme token ROLE name
34679
+ * (e.g. `secondary`, `accent`, `muted`, `border`). The role is wrapped to
34680
+ * `rgb(var(--tb-<role>))` so the result drops straight into a `style` binding.
34681
+ */
34682
+ cases: z$1.record(z$1.string(), z$1.string()),
34683
+ /** Role used when the value matches no case. Omit to yield `undefined`. */
34684
+ fallback: z$1.string().optional()
34685
+ }),
34686
+ run: (value, options) => {
34687
+ const role = options.cases[String(value)] ?? options.fallback;
34688
+ return role ? `rgb(var(--tb-${role}))` : void 0;
34689
+ }
34690
+ }
34006
34691
  ];
34007
34692
  //#endregion
34008
34693
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -34586,6 +35271,7 @@ function splitSiteChromePlacementClasses(className) {
34586
35271
  init_colorConversion();
34587
35272
  init_core();
34588
35273
  init_colorStyles();
35274
+ init_surfaces();
34589
35275
  const joinClasses$4 = (parts) => parts.filter((part) => typeof part === "string" && part.trim().length > 0).join(" ").replace(/\s+/g, " ").trim();
34590
35276
  function resolveHeaderBrandDisplay(logo) {
34591
35277
  const display = logo?.brandDisplay ?? "logo-plus-title";
@@ -34655,6 +35341,26 @@ const headerLogoTextVisibleTransform = {
34655
35341
  return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
34656
35342
  }
34657
35343
  };
35344
+ /**
35345
+ * Selects which classic-layout nav row should render.
35346
+ *
35347
+ * - `'inline'` → classic variant with the historical logo-left / nav-right row
35348
+ * - `'centered'`→ classic variant with a centred (flex-1) nav and a right CTA
35349
+ * - `'other'` → not a classic variant (centered/floating/transparent handle it)
35350
+ *
35351
+ * Consumed by the site-header block's `$when` gates so the two classic rows are
35352
+ * mutually exclusive without introducing a new top-level header variant.
35353
+ */
35354
+ const classicNavModeTransform = {
35355
+ id: "layout.classicNavMode",
35356
+ kind: "formatter",
35357
+ summary: "Resolve which classic-layout nav row to render",
35358
+ run: (value) => {
35359
+ const header = asPartialObject(value);
35360
+ if (header?.variant !== "classic") return "other";
35361
+ return header?.navPlacement === "center" ? "centered" : "inline";
35362
+ }
35363
+ };
34658
35364
  const maxWidthClassTransform = {
34659
35365
  id: "layout.maxWidthClass",
34660
35366
  kind: "string",
@@ -34837,8 +35543,9 @@ const footerRootStyleTransform = {
34837
35543
  styleParts.push(backgroundColorStyle(token));
34838
35544
  }
34839
35545
  }
34840
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
34841
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
35546
+ const foreground = visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
35547
+ if (!visuals.isTransparent && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
35548
+ else if (foreground) styleParts.push({ color: foreground });
34842
35549
  styleParts.push(borderColorStyle("border"));
34843
35550
  return mergeStyles(...styleParts);
34844
35551
  }
@@ -34924,18 +35631,16 @@ const footerBottomBarStyleTransform = {
34924
35631
  const styleParts = [];
34925
35632
  const background = bottomBar?.background;
34926
35633
  if (background?.type === "color") styleParts.push(backgroundColorStyle(background.color ?? "surface"));
34927
- if (bottomBar?.textColor) styleParts.push(textColorStyle(bottomBar.textColor));
34928
35634
  const borderColorToken = bottomBar?.borderTop?.colorToken;
34929
35635
  if (borderColorToken) styleParts.push(borderColorStyle(borderColorToken));
34930
35636
  else styleParts.push(borderColorStyle("border"));
34931
35637
  const borderWidth = bottomBar?.borderTop?.width;
34932
35638
  if (borderWidth && borderWidth !== "none") styleParts.push({ borderTopWidth: borderWidth === "thin" ? "1px" : borderWidth === "medium" ? "2px" : "3px" });
34933
35639
  else if (borderWidth === "none") styleParts.push({ borderTopWidth: "0px" });
34934
- if (!bottomBar?.textColor) {
34935
- const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
34936
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
34937
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
34938
- }
35640
+ const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
35641
+ const foreground = bottomBar?.textColor ? rgbColorValue(bottomBar.textColor) : visuals.textColorOverride ?? (visuals.textColorToken ? rgbColorValue(visuals.textColorToken) : null);
35642
+ if (background?.type === "color" && foreground) styleParts.push(surfaceForegroundStyle({ text: foreground }));
35643
+ else if (foreground && bottomBar?.textColor) styleParts.push({ color: foreground });
34939
35644
  return mergeStyles(...styleParts);
34940
35645
  }
34941
35646
  };
@@ -35070,6 +35775,7 @@ const layoutTransforms = [
35070
35775
  headerLogoClassTransform,
35071
35776
  headerLogoMediaClassTransform,
35072
35777
  headerLogoTextVisibleTransform,
35778
+ classicNavModeTransform,
35073
35779
  footerRootClassTransform,
35074
35780
  headerRootStyleTransform,
35075
35781
  headerSectionBackgroundTransform,
@@ -35506,7 +36212,18 @@ const classicLayout = inline({
35506
36212
  logoRow,
35507
36213
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
35508
36214
  headerCta
35509
- ], when("$root.theme.header.variant", { equals: "classic" }));
36215
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "inline"));
36216
+ const classicCenteredNavLayout = inline({
36217
+ className: bindProp("$root.theme.header.maxWidth", {
36218
+ transforms: pipe(tx("layout.maxWidthClass", { base: `rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6` })),
36219
+ fallback: `rb-container rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6`
36220
+ }),
36221
+ align: "center"
36222
+ }, [
36223
+ logoRow,
36224
+ createNavRow(`rb-flex-1 rb-justify-center ${desktopOnlyDisplay("flex")} rb-gap-6`, "center"),
36225
+ headerCta
36226
+ ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "centered"));
35510
36227
  const centeredLayout = stack({
35511
36228
  gap: "md",
35512
36229
  align: "center",
@@ -35581,6 +36298,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
35581
36298
  }, [
35582
36299
  mobileHeaderBar,
35583
36300
  classicLayout,
36301
+ classicCenteredNavLayout,
35584
36302
  centeredLayout,
35585
36303
  transparentLayout,
35586
36304
  floatingLayout,
@@ -35628,6 +36346,7 @@ init_builder$1();
35628
36346
  init_fragments();
35629
36347
  init_defineBlock();
35630
36348
  init_colorStyles();
36349
+ init_surfaces();
35631
36350
  const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
35632
36351
  const whenTransformed = (from, transformId, equals = true) => (node) => ({
35633
36352
  ...node,
@@ -35797,7 +36516,7 @@ const footerLayout = section$1({
35797
36516
  style: { $bind: {
35798
36517
  from: "$root.theme.footer",
35799
36518
  transforms: [{ id: "layout.footerRootStyle" }],
35800
- fallback: mergeStyles(backgroundColorStyle("surface"), textColorStyle("text"), borderColorStyle("border"))
36519
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
35801
36520
  } }
35802
36521
  }, [
35803
36522
  simpleFooterLayout,
@@ -35859,7 +36578,7 @@ const backgroundImageClassName = "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full r
35859
36578
  */
35860
36579
  const wrapVariant$2 = (variantLayout) => styledSection({
35861
36580
  children: styledContainer({ children: stack({
35862
- gap: "xl",
36581
+ gap: "lg",
35863
36582
  className: "rb-relative"
35864
36583
  }, [...testimonialsHeadingFragment.layout, variantLayout]) }),
35865
36584
  baseClass: "",
@@ -35885,6 +36604,27 @@ const splitGridLayout = styledSection({
35885
36604
  spacing: "comfortable",
35886
36605
  imageClassName: backgroundImageClassName
35887
36606
  });
36607
+ const featuredEditorialHead = el("div", { className: "rb-testimonials-fe-head" }, [text({
36608
+ as: "h2",
36609
+ className: "rb-text-left",
36610
+ headingDecoration: "off"
36611
+ }, when("content.heading"), bind("content.heading")), el("div", { className: "rb-testimonials-fe-leadin" }, [text({
36612
+ as: "p",
36613
+ className: "rb-prose",
36614
+ style: textColorStyle("mutedText")
36615
+ }, when("content.subheading"), bind("content.subheading"))])]);
36616
+ const featuredEditorialLayout = styledSection({
36617
+ children: styledContainer({
36618
+ baseClassName: "rb-relative rb-isolate",
36619
+ children: stack({
36620
+ gap: "lg",
36621
+ className: "rb-relative"
36622
+ }, [featuredEditorialHead, buildFeaturedEditorialLayout()])
36623
+ }),
36624
+ baseClass: "",
36625
+ spacing: "comfortable",
36626
+ imageClassName: backgroundImageClassName
36627
+ });
35888
36628
  const additionalFields = parseFieldDefinitions([
35889
36629
  ...testimonialsHeadingFragment.fields,
35890
36630
  {
@@ -35972,6 +36712,7 @@ const testimonialsBlockDefinition = {
35972
36712
  carousel: carouselLayout$1,
35973
36713
  grid: gridLayout$1,
35974
36714
  "split-grid": splitGridLayout,
36715
+ "featured-editorial": featuredEditorialLayout,
35975
36716
  highlight: highlightLayout
35976
36717
  },
35977
36718
  defaultVariant: "carousel",
@@ -35991,6 +36732,11 @@ const testimonialsBlockDefinition = {
35991
36732
  description: "Heading on the left with testimonial cards on the right",
35992
36733
  icon: "PanelLeft"
35993
36734
  },
36735
+ "featured-editorial": {
36736
+ label: "Featured editorial",
36737
+ description: "A large featured ink quote beside a column of stacked cards (no avatars)",
36738
+ icon: "Quote"
36739
+ },
35994
36740
  highlight: {
35995
36741
  label: "Highlight",
35996
36742
  description: "A single, centered testimonial with no carousel",
@@ -36534,7 +37280,7 @@ function grid$2(props, children) {
36534
37280
  const cardsLayout = styledSection({
36535
37281
  children: styledContainer({
36536
37282
  rootType: "stack",
36537
- rootProps: { gap: "xl" },
37283
+ rootProps: { gap: "lg" },
36538
37284
  children: [stack({
36539
37285
  gap: "sm",
36540
37286
  className: "rb-feature-cards-heading rb-mx-auto rb-max-w-3xl rb-text-center"
@@ -38486,8 +39232,11 @@ var init_filtering = __esmMin((() => {
38486
39232
  }));
38487
39233
  //#endregion
38488
39234
  //#region ../blocks/src/system/blocks/events/shared/layout.ts
38489
- function eventSectionHeaderLayoutNodes() {
38490
- 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 }))];
39235
+ function eventSectionHeaderLayoutNodes(options = {}) {
39236
+ const headingNode = text({ as: "h2" }, bind("content.heading"), when("content.heading", { authoringPresence: recoverEmptyHeadingWhenActive }));
39237
+ const descriptionNode = richText({ className: "rb-prose rb-max-w-none" }, bind("content.description"), when("content.description", { authoringPresence: recoverEmptyDescriptionWhenActive }));
39238
+ if (options.splitClassName) return [el("div", { className: options.splitClassName }, [headingNode, descriptionNode])];
39239
+ return [headingNode, descriptionNode];
38491
39240
  }
38492
39241
  var recoverEmptyHeadingWhenActive, recoverEmptyDescriptionWhenActive;
38493
39242
  var init_layout = __esmMin((() => {
@@ -38579,7 +39328,8 @@ var init_events$1 = __esmMin((() => {
38579
39328
  "combined",
38580
39329
  "calendar",
38581
39330
  "list",
38582
- "timetable"
39331
+ "timetable",
39332
+ "week-board"
38583
39333
  ];
38584
39334
  eventCalendarDefaultViewValues = ["month", "week"];
38585
39335
  eventCalendarListLayoutValues = [
@@ -41193,6 +41943,40 @@ function getEventAvailability(event) {
41193
41943
  isFull: false
41194
41944
  };
41195
41945
  }
41946
+ /**
41947
+ * Derive the three-state availability status (available / filling / waitlist)
41948
+ * plus a short pill label. Builds on {@link getEventAvailability} so the
41949
+ * capacity math (availableSpots with a `capacity - registeredCount` fallback)
41950
+ * stays consistent with the binary helper used elsewhere.
41951
+ */
41952
+ function getEventAvailabilityStatus(event, options) {
41953
+ const threshold = options?.fillingThreshold ?? 2;
41954
+ const { available, isFull } = getEventAvailability(event);
41955
+ if (available == null) return {
41956
+ status: "available",
41957
+ available: null,
41958
+ isFull: false,
41959
+ label: null
41960
+ };
41961
+ if (isFull) return {
41962
+ status: "waitlist",
41963
+ available: 0,
41964
+ isFull: true,
41965
+ label: event.waitlistEnabled ? "Waitlist" : "Full"
41966
+ };
41967
+ if (available <= threshold) return {
41968
+ status: "filling",
41969
+ available,
41970
+ isFull: false,
41971
+ label: `${available} left`
41972
+ };
41973
+ return {
41974
+ status: "available",
41975
+ available,
41976
+ isFull: false,
41977
+ label: `${available} places`
41978
+ };
41979
+ }
41196
41980
  var init_eventCapacity = __esmMin((() => {}));
41197
41981
  //#endregion
41198
41982
  //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
@@ -43900,7 +44684,7 @@ const eventCalendarLayout = [styledSection({
43900
44684
  children: styledContainer({
43901
44685
  rootType: "stack",
43902
44686
  rootProps: { gap: "lg" },
43903
- children: [...eventSectionHeaderLayoutNodes(), el("event-calendar", withApiBindings({
44687
+ children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
43904
44688
  events: { $bind: { from: "data.events" } },
43905
44689
  stage: { $bind: {
43906
44690
  from: "$root.previewStage",
@@ -44011,6 +44795,10 @@ const eventCalendarAdditionalFields = [
44011
44795
  value: "timetable",
44012
44796
  label: "Timetable"
44013
44797
  },
44798
+ {
44799
+ value: "week-board",
44800
+ label: "Week board"
44801
+ },
44014
44802
  {
44015
44803
  value: "list",
44016
44804
  label: "List"
@@ -44193,7 +44981,8 @@ const eventCalendarAdditionalFields = [
44193
44981
  oneOf: [
44194
44982
  "combined",
44195
44983
  "calendar",
44196
- "timetable"
44984
+ "timetable",
44985
+ "week-board"
44197
44986
  ]
44198
44987
  }
44199
44988
  }
@@ -44296,7 +45085,8 @@ const eventCalendarAdditionalFields = [
44296
45085
  "combined",
44297
45086
  "calendar",
44298
45087
  "list",
44299
- "timetable"
45088
+ "timetable",
45089
+ "week-board"
44300
45090
  ]
44301
45091
  }
44302
45092
  }
@@ -44331,7 +45121,8 @@ const eventCalendarAdditionalFields = [
44331
45121
  "combined",
44332
45122
  "calendar",
44333
45123
  "list",
44334
- "timetable"
45124
+ "timetable",
45125
+ "week-board"
44335
45126
  ]
44336
45127
  }, {
44337
45128
  field: "showFilters",
@@ -44354,7 +45145,8 @@ const eventCalendarAdditionalFields = [
44354
45145
  "combined",
44355
45146
  "calendar",
44356
45147
  "list",
44357
- "timetable"
45148
+ "timetable",
45149
+ "week-board"
44358
45150
  ]
44359
45151
  }, {
44360
45152
  field: "showFilters",
@@ -44377,7 +45169,8 @@ const eventCalendarAdditionalFields = [
44377
45169
  "combined",
44378
45170
  "calendar",
44379
45171
  "list",
44380
- "timetable"
45172
+ "timetable",
45173
+ "week-board"
44381
45174
  ]
44382
45175
  }, {
44383
45176
  field: "showFilters",
@@ -44399,7 +45192,8 @@ const eventCalendarAdditionalFields = [
44399
45192
  oneOf: [
44400
45193
  "combined",
44401
45194
  "list",
44402
- "timetable"
45195
+ "timetable",
45196
+ "week-board"
44403
45197
  ]
44404
45198
  }, { allOf: [{
44405
45199
  field: "variant",
@@ -44575,6 +45369,7 @@ const eventCalendarVariants = {
44575
45369
  combined: eventCalendarLayout[0],
44576
45370
  calendar: eventCalendarLayout[0],
44577
45371
  timetable: eventCalendarLayout[0],
45372
+ "week-board": eventCalendarLayout[0],
44578
45373
  list: eventCalendarLayout[0]
44579
45374
  };
44580
45375
  const eventCalendarContentShape = {
@@ -44588,6 +45383,7 @@ const eventCalendarContentShape = {
44588
45383
  { value: "combined" },
44589
45384
  { value: "calendar" },
44590
45385
  { value: "timetable" },
45386
+ { value: "week-board" },
44591
45387
  { value: "list" }
44592
45388
  ]
44593
45389
  },
@@ -44654,6 +45450,7 @@ const eventCalendarBlockDefinition = {
44654
45450
  combined: { label: "Combined" },
44655
45451
  calendar: { label: "Calendar" },
44656
45452
  timetable: { label: "Timetable" },
45453
+ "week-board": { label: "Week board" },
44657
45454
  list: { label: "List" }
44658
45455
  }
44659
45456
  }, eventCalendarContentShape),
@@ -50503,6 +51300,12 @@ const systemBlockDefinitions = [
50503
51300
  family: "centered",
50504
51301
  weight: "featured",
50505
51302
  bias: "soft"
51303
+ }),
51304
+ layoutProfile({
51305
+ variantKey: "featured-editorial",
51306
+ family: "split",
51307
+ weight: "featured",
51308
+ bias: "soft"
50506
51309
  })
50507
51310
  ]
50508
51311
  })),
@@ -50635,6 +51438,11 @@ const systemBlockDefinitions = [
50635
51438
  variantKey: "timetable",
50636
51439
  family: "stack",
50637
51440
  weight: "standard"
51441
+ }),
51442
+ layoutProfile({
51443
+ variantKey: "week-board",
51444
+ family: "stack",
51445
+ weight: "standard"
50638
51446
  })
50639
51447
  ]
50640
51448
  })),
@@ -50995,7 +51803,15 @@ function gradientToCss(config, tokens) {
50995
51803
  const stops = config.stops.map((stop) => {
50996
51804
  return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
50997
51805
  }).join(", ");
50998
- if (config.type === "radial") return `radial-gradient(circle at ${config.position ?? "center"}, ${stops})`;
51806
+ const type = config.type ?? "linear";
51807
+ if (type === "radial") {
51808
+ const position = config.position ?? "center";
51809
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
51810
+ }
51811
+ if (type === "conic") {
51812
+ const position = config.position ?? "center";
51813
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
51814
+ }
50999
51815
  return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
51000
51816
  }
51001
51817
  //#endregion
@@ -51024,7 +51840,7 @@ function backgroundVideoMobileClassNames(input) {
51024
51840
  //#region ../blocks/src/system/transforms/registry/background.ts
51025
51841
  init_background$1();
51026
51842
  init_themeColorResolution();
51027
- init_sectionForegroundStyles();
51843
+ init_surfaceForegroundStyles();
51028
51844
  init_media();
51029
51845
  const isString$2 = (value) => typeof value === "string" && value.trim().length > 0;
51030
51846
  const isNumber$2 = (value) => typeof value === "number" && !isNaN(value);
@@ -51081,8 +51897,8 @@ const backgroundTransforms = [
51081
51897
  {
51082
51898
  id: "background.resolveColorsStyle",
51083
51899
  kind: "formatter",
51084
- summary: "Resolve section foreground colors from a background object into scoped CSS vars",
51085
- run: (value, _options, context) => resolveSectionForegroundStyles(value, context)
51900
+ summary: "Resolve surface foreground colors from a background object into scoped CSS vars",
51901
+ run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
51086
51902
  },
51087
51903
  {
51088
51904
  id: "background.resolveAllowOverflow",
@@ -51715,21 +52531,53 @@ function Inline({ as: Comp = "div", gap = "md", align = "center", justify = "sta
51715
52531
  //#endregion
51716
52532
  //#region ../blocks/src/primitives/layout/Grid.tsx
51717
52533
  init_clsx();
52534
+ /** Utility class for a numeric column COUNT at a given breakpoint. */
52535
+ const COL_COUNT_CLASS = {
52536
+ base: (n) => `rb-grid-cols-${n}`,
52537
+ sm: (n) => `rb-sm-grid-cols-${n}`,
52538
+ md: (n) => `rb-md-grid-cols-${n}`,
52539
+ lg: (n) => `rb-lg-grid-cols-${n}`,
52540
+ xl: (n) => `rb-xl-grid-cols-${n}`
52541
+ };
52542
+ /** Inline custom property read by the `.rb-grid-tracks` utility per breakpoint. */
52543
+ const TRACK_VAR = {
52544
+ base: "--rb-gtc-base",
52545
+ sm: "--rb-gtc-sm",
52546
+ md: "--rb-gtc-md",
52547
+ lg: "--rb-gtc-lg",
52548
+ xl: "--rb-gtc-xl"
52549
+ };
52550
+ const GRID_BREAKPOINTS = [
52551
+ "base",
52552
+ "sm",
52553
+ "md",
52554
+ "lg",
52555
+ "xl"
52556
+ ];
51718
52557
  function Grid({ as: Comp = "div", cols = {
51719
52558
  base: 1,
51720
52559
  md: 2
51721
- }, gap = "md", className, children, "data-slot": dataSlot, ...rest }) {
51722
- const colsObj = typeof cols === "number" ? { base: cols } : cols;
51723
- const colClasses = [
51724
- colsObj.base && `rb-grid-cols-${colsObj.base}`,
51725
- colsObj.sm && `rb-sm-grid-cols-${colsObj.sm}`,
51726
- colsObj.md && `rb-md-grid-cols-${colsObj.md}`,
51727
- colsObj.lg && `rb-lg-grid-cols-${colsObj.lg}`,
51728
- colsObj.xl && `rb-xl-grid-cols-${colsObj.xl}`
51729
- ];
52560
+ }, gap = "md", className, style, children, "data-slot": dataSlot, ...rest }) {
52561
+ const colsObj = typeof cols === "number" || typeof cols === "string" ? { base: cols } : cols;
52562
+ const colClasses = [];
52563
+ const trackVars = {};
52564
+ let hasTracks = false;
52565
+ for (const bp of GRID_BREAKPOINTS) {
52566
+ const value = colsObj[bp];
52567
+ if (value == null) continue;
52568
+ if (typeof value === "string") {
52569
+ trackVars[TRACK_VAR[bp]] = value;
52570
+ hasTracks = true;
52571
+ } else colClasses.push(COL_COUNT_CLASS[bp](value));
52572
+ }
52573
+ const mergedStyle = hasTracks ? {
52574
+ ...trackVars,
52575
+ ...style
52576
+ } : style;
51730
52577
  return /* @__PURE__ */ jsx(Comp, {
51731
52578
  ...rest,
51732
- className: clsx("rb-grid", colClasses, {
52579
+ style: mergedStyle,
52580
+ className: clsx("rb-grid", hasTracks && "rb-grid-tracks", colClasses, {
51733
52581
  "rb-gap-0": gap === "none",
51734
52582
  "rb-gap-1": gap === "xs",
51735
52583
  "rb-gap-2": gap === "sm",
@@ -51975,125 +52823,6 @@ function Text$2({ as: Comp = "span", children, className = "", path, maxLength:
51975
52823
  });
51976
52824
  }
51977
52825
  //#endregion
51978
- //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
51979
- function coerceRichTextDoc(value) {
51980
- const raw = unwrapRichTextRoot(value);
51981
- if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
51982
- if (isRecord$25(raw) && typeof raw.type === "string") return raw;
51983
- return null;
51984
- }
51985
- var init_richText_coerce = __esmMin((() => {
51986
- init_richTextSchema();
51987
- init_typeGuards();
51988
- }));
51989
- //#endregion
51990
- //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
51991
- init_richText_coerce();
51992
- function renderInlineText(value) {
51993
- return value.map((run, index) => renderRun(run, index));
51994
- }
51995
- function renderRun(run, key) {
51996
- return (run.marks ?? []).reduceRight((child, mark, index) => renderMark(mark, `${String(key)}-${index}`, child), run.text);
51997
- }
51998
- function renderMark(mark, key, child) {
51999
- switch (mark.kind) {
52000
- case "strong": return /* @__PURE__ */ jsx("strong", { children: child }, key);
52001
- case "emphasis": return /* @__PURE__ */ jsx("em", { children: child }, key);
52002
- case "accent": return /* @__PURE__ */ jsx("span", {
52003
- className: `rb-inline-text-accent rb-inline-text-accent-${mark.tone}`,
52004
- children: child
52005
- }, key);
52006
- case "highlight": return /* @__PURE__ */ jsx("span", {
52007
- className: `rb-inline-text-highlight rb-inline-text-highlight-${mark.tone}`,
52008
- children: child
52009
- }, key);
52010
- }
52011
- }
52012
- //#endregion
52013
- //#region ../blocks/src/system/runtime/nodes/basic.tsx
52014
- init_buttons();
52015
- const TextNode = ({ value, children, blockId: _blockId, blockKind: _blockKind, blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, inlineTextFallbackPath, ...rest }) => {
52016
- const inlineText = parseInlineTextFromUnknown(value);
52017
- if (inlineText.ok && !isInlineTextEmpty(inlineText.value)) return /* @__PURE__ */ jsx(Text$2, {
52018
- ...rest,
52019
- children: renderInlineText(inlineText.value)
52020
- });
52021
- const fallbackValue = inlineTextFallbackPath ? readStringPath(blockContent, inlineTextFallbackPath) : null;
52022
- return /* @__PURE__ */ jsx(Text$2, {
52023
- ...rest,
52024
- children: fallbackValue ?? textNodeContent(value) ?? children
52025
- });
52026
- };
52027
- function textNodeContent(value) {
52028
- if (value === null || value === void 0) return null;
52029
- if (typeof value === "string" || typeof value === "number") return value;
52030
- return null;
52031
- }
52032
- function readStringPath(source, path) {
52033
- const value = getAtPath(source, path);
52034
- return typeof value === "string" ? value : null;
52035
- }
52036
- const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52037
- return /* @__PURE__ */ jsx(RichText$1, {
52038
- doc: coerceRichTextDoc(value) ?? void 0,
52039
- ...rest
52040
- });
52041
- };
52042
- 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 }) => {
52043
- const content = value ?? children;
52044
- if (!content) {
52045
- console.warn("[ButtonNode] No content to render - value and children are both empty");
52046
- return null;
52047
- }
52048
- const resolvedHref = typeof href === "string" ? href.trim() : "";
52049
- if (linkRequired && resolvedHref.length === 0) {
52050
- console.warn("[ButtonNode] Missing href for link-required button");
52051
- return null;
52052
- }
52053
- const resolvedVariantId = parseThemeButtonVariantId(variantId);
52054
- const combinedClassName = resolvedVariantId ? themeButtonClassName({
52055
- variant: resolvedVariantId,
52056
- size,
52057
- extraClassName: className
52058
- }) : className;
52059
- if (resolvedHref) return /* @__PURE__ */ jsx("a", {
52060
- href: resolvedHref,
52061
- target,
52062
- rel,
52063
- className: combinedClassName,
52064
- ...rest,
52065
- children: content
52066
- });
52067
- return /* @__PURE__ */ jsx("button", {
52068
- type,
52069
- disabled,
52070
- className: combinedClassName,
52071
- ...rest,
52072
- children: content
52073
- });
52074
- };
52075
- const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52076
- if (!children) return null;
52077
- const resolvedHref = typeof href === "string" ? href.trim() : "";
52078
- if (resolvedHref.length === 0) {
52079
- if (linkRequired && true) console.warn("[LinkNode] Missing href for link-required link");
52080
- if (linkRequired) return null;
52081
- return /* @__PURE__ */ jsx("span", {
52082
- className,
52083
- ...rest,
52084
- children
52085
- });
52086
- }
52087
- return /* @__PURE__ */ jsx("a", {
52088
- href: resolvedHref,
52089
- className,
52090
- target,
52091
- rel,
52092
- ...rest,
52093
- children
52094
- });
52095
- };
52096
- //#endregion
52097
52826
  //#region ../blocks/src/system/icons/cta.ts
52098
52827
  init_svg();
52099
52828
  /**
@@ -52194,6 +52923,177 @@ function getIconComponent(name) {
52194
52923
  return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
52195
52924
  }
52196
52925
  //#endregion
52926
+ //#region ../blocks/src/system/runtime/nodes/buttonAffordance.ts
52927
+ function normalize(value) {
52928
+ const trimmed = typeof value === "string" ? value.trim() : "";
52929
+ return trimmed.length > 0 ? trimmed : null;
52930
+ }
52931
+ /**
52932
+ * Resolve the trailing affordance a button should render. Node overrides
52933
+ * personality; returns `null` when nothing is configured.
52934
+ */
52935
+ function resolveButtonAffordance(input) {
52936
+ const nodeIcon = normalize(input.trailingIcon);
52937
+ if (nodeIcon) {
52938
+ const colorToken = normalize(input.trailingIconColorToken);
52939
+ return {
52940
+ iconId: nodeIcon,
52941
+ source: "node",
52942
+ ...colorToken ? { colorToken } : {}
52943
+ };
52944
+ }
52945
+ const personality = input.personalityAffordance;
52946
+ const personalityIcon = normalize(personality?.iconId);
52947
+ if (personality && personalityIcon) {
52948
+ const colorToken = normalize(personality.colorToken);
52949
+ return {
52950
+ iconId: personalityIcon,
52951
+ source: "personality",
52952
+ ...colorToken ? { colorToken } : {}
52953
+ };
52954
+ }
52955
+ return null;
52956
+ }
52957
+ //#endregion
52958
+ //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
52959
+ function coerceRichTextDoc(value) {
52960
+ const raw = unwrapRichTextRoot(value);
52961
+ if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
52962
+ if (isRecord$25(raw) && typeof raw.type === "string") return raw;
52963
+ return null;
52964
+ }
52965
+ var init_richText_coerce = __esmMin((() => {
52966
+ init_richTextSchema();
52967
+ init_typeGuards();
52968
+ }));
52969
+ //#endregion
52970
+ //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
52971
+ init_richText_coerce();
52972
+ function renderInlineText(value) {
52973
+ return value.map((run, index) => renderRun(run, index));
52974
+ }
52975
+ function renderRun(run, key) {
52976
+ return (run.marks ?? []).reduceRight((child, mark, index) => renderMark(mark, `${String(key)}-${index}`, child), run.text);
52977
+ }
52978
+ function renderMark(mark, key, child) {
52979
+ switch (mark.kind) {
52980
+ case "strong": return /* @__PURE__ */ jsx("strong", { children: child }, key);
52981
+ case "emphasis": return /* @__PURE__ */ jsx("em", { children: child }, key);
52982
+ case "accent": return /* @__PURE__ */ jsx("span", {
52983
+ className: `rb-inline-text-accent rb-inline-text-accent-${mark.tone}`,
52984
+ children: child
52985
+ }, key);
52986
+ case "highlight": return /* @__PURE__ */ jsx("span", {
52987
+ className: `rb-inline-text-highlight rb-inline-text-highlight-${mark.tone}`,
52988
+ children: child
52989
+ }, key);
52990
+ }
52991
+ }
52992
+ //#endregion
52993
+ //#region ../blocks/src/system/runtime/nodes/basic.tsx
52994
+ init_buttons();
52995
+ const TextNode = ({ value, children, blockId: _blockId, blockKind: _blockKind, blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, inlineTextFallbackPath, ...rest }) => {
52996
+ const inlineText = parseInlineTextFromUnknown(value);
52997
+ if (inlineText.ok && !isInlineTextEmpty(inlineText.value)) return /* @__PURE__ */ jsx(Text$2, {
52998
+ ...rest,
52999
+ children: renderInlineText(inlineText.value)
53000
+ });
53001
+ const fallbackValue = inlineTextFallbackPath ? readStringPath(blockContent, inlineTextFallbackPath) : null;
53002
+ return /* @__PURE__ */ jsx(Text$2, {
53003
+ ...rest,
53004
+ children: fallbackValue ?? textNodeContent(value) ?? children
53005
+ });
53006
+ };
53007
+ function textNodeContent(value) {
53008
+ if (value === null || value === void 0) return null;
53009
+ if (typeof value === "string" || typeof value === "number") return value;
53010
+ return null;
53011
+ }
53012
+ function readStringPath(source, path) {
53013
+ const value = getAtPath(source, path);
53014
+ return typeof value === "string" ? value : null;
53015
+ }
53016
+ const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
53017
+ return /* @__PURE__ */ jsx(RichText$1, {
53018
+ doc: coerceRichTextDoc(value) ?? void 0,
53019
+ ...rest
53020
+ });
53021
+ };
53022
+ /**
53023
+ * Render the resolved trailing affordance icon. Colour is applied via a theme
53024
+ * CSS var so it recolours with the palette; the icon stroke uses `currentColor`.
53025
+ */
53026
+ function renderTrailingAffordanceIcon(affordance) {
53027
+ if (!affordance) return null;
53028
+ const Icon = getIconComponent(affordance.iconId);
53029
+ if (!Icon) return null;
53030
+ return /* @__PURE__ */ jsx(Icon, {
53031
+ "aria-hidden": true,
53032
+ className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block",
53033
+ style: affordance.colorToken ? { color: `rgb(var(--tb-${affordance.colorToken}))` } : void 0
53034
+ });
53035
+ }
53036
+ 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 }) => {
53037
+ const content = value ?? children;
53038
+ if (!content) {
53039
+ console.warn("[ButtonNode] No content to render - value and children are both empty");
53040
+ return null;
53041
+ }
53042
+ const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({
53043
+ trailingIcon,
53044
+ trailingIconColorToken,
53045
+ personalityAffordance
53046
+ }));
53047
+ const resolvedHref = typeof href === "string" ? href.trim() : "";
53048
+ if (linkRequired && resolvedHref.length === 0) {
53049
+ console.warn("[ButtonNode] Missing href for link-required button");
53050
+ return null;
53051
+ }
53052
+ const extraClassName = affordanceIcon ? [className, AFFORDANCE_SUPPRESS_CLASS].filter(Boolean).join(" ") : className;
53053
+ const resolvedVariantId = parseThemeButtonVariantId(variantId);
53054
+ const combinedClassName = resolvedVariantId ? themeButtonClassName({
53055
+ variant: resolvedVariantId,
53056
+ size,
53057
+ extraClassName
53058
+ }) : extraClassName;
53059
+ if (resolvedHref) return /* @__PURE__ */ jsxs("a", {
53060
+ href: resolvedHref,
53061
+ target,
53062
+ rel,
53063
+ className: combinedClassName,
53064
+ ...rest,
53065
+ children: [content, affordanceIcon]
53066
+ });
53067
+ return /* @__PURE__ */ jsxs("button", {
53068
+ type,
53069
+ disabled,
53070
+ className: combinedClassName,
53071
+ ...rest,
53072
+ children: [content, affordanceIcon]
53073
+ });
53074
+ };
53075
+ const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
53076
+ if (!children) return null;
53077
+ const resolvedHref = typeof href === "string" ? href.trim() : "";
53078
+ if (resolvedHref.length === 0) {
53079
+ if (linkRequired && true) console.warn("[LinkNode] Missing href for link-required link");
53080
+ if (linkRequired) return null;
53081
+ return /* @__PURE__ */ jsx("span", {
53082
+ className,
53083
+ ...rest,
53084
+ children
53085
+ });
53086
+ }
53087
+ return /* @__PURE__ */ jsx("a", {
53088
+ href: resolvedHref,
53089
+ className,
53090
+ target,
53091
+ rel,
53092
+ ...rest,
53093
+ children
53094
+ });
53095
+ };
53096
+ //#endregion
52197
53097
  //#region ../blocks/src/system/runtime/nodes/icon.tsx
52198
53098
  const IconNode = ({ value, title, className, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52199
53099
  const parsedValue = parseBlockIconValue(value);
@@ -52915,6 +53815,78 @@ function SpinnerNode({ className, size = "md", color, strokeWidth = 3, srLabel,
52915
53815
  var init_spinner = __esmMin((() => {
52916
53816
  init_clsx();
52917
53817
  }));
53818
+ //#endregion
53819
+ //#region ../blocks/src/system/runtime/nodes/svg.tsx
53820
+ init_spinner();
53821
+ /**
53822
+ * Turn paint props into a CSS style object. Colour values pass through as-is so
53823
+ * they may reference theme tokens via `var()`, which only resolves in a CSS
53824
+ * property context (not in a bare presentation attribute).
53825
+ */
53826
+ function paintStyle(shape) {
53827
+ const style = {};
53828
+ if (shape.fill !== void 0) style.fill = shape.fill;
53829
+ if (shape.stroke !== void 0) style.stroke = shape.stroke;
53830
+ if (shape.strokeWidth !== void 0) style.strokeWidth = shape.strokeWidth;
53831
+ if (shape.fillOpacity !== void 0) style.fillOpacity = shape.fillOpacity;
53832
+ if (shape.strokeOpacity !== void 0) style.strokeOpacity = shape.strokeOpacity;
53833
+ if (shape.strokeLinecap !== void 0) style.strokeLinecap = shape.strokeLinecap;
53834
+ if (shape.strokeLinejoin !== void 0) style.strokeLinejoin = shape.strokeLinejoin;
53835
+ if (shape.strokeDasharray !== void 0) style.strokeDasharray = shape.strokeDasharray;
53836
+ return style;
53837
+ }
53838
+ function renderShape(shape, key) {
53839
+ const style = paintStyle(shape);
53840
+ switch (shape.kind) {
53841
+ case "path": return /* @__PURE__ */ jsx("path", {
53842
+ d: shape.d,
53843
+ style
53844
+ }, key);
53845
+ case "ellipse": return /* @__PURE__ */ jsx("ellipse", {
53846
+ cx: shape.cx,
53847
+ cy: shape.cy,
53848
+ rx: shape.rx,
53849
+ ry: shape.ry,
53850
+ style
53851
+ }, key);
53852
+ case "circle": return /* @__PURE__ */ jsx("circle", {
53853
+ cx: shape.cx,
53854
+ cy: shape.cy,
53855
+ r: shape.r,
53856
+ style
53857
+ }, key);
53858
+ case "rect": return /* @__PURE__ */ jsx("rect", {
53859
+ x: shape.x,
53860
+ y: shape.y,
53861
+ width: shape.width,
53862
+ height: shape.height,
53863
+ rx: shape.rx,
53864
+ ry: shape.ry,
53865
+ style
53866
+ }, key);
53867
+ case "line": return /* @__PURE__ */ jsx("line", {
53868
+ x1: shape.x1,
53869
+ y1: shape.y1,
53870
+ x2: shape.x2,
53871
+ y2: shape.y2,
53872
+ style
53873
+ }, key);
53874
+ default: return null;
53875
+ }
53876
+ }
53877
+ const SvgNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, viewBox, width, height, className, style, ariaHidden = true, shapes }) => {
53878
+ return /* @__PURE__ */ jsx("svg", {
53879
+ viewBox,
53880
+ width,
53881
+ height,
53882
+ className,
53883
+ style,
53884
+ "aria-hidden": ariaHidden,
53885
+ xmlns: "http://www.w3.org/2000/svg",
53886
+ fill: "none",
53887
+ children: (Array.isArray(shapes) ? shapes : []).map((shape, index) => renderShape(shape, index))
53888
+ });
53889
+ };
52918
53890
  function clearWorkflowFeedback(state) {
52919
53891
  return {
52920
53892
  ...state,
@@ -53695,7 +54667,6 @@ var init_booking_form_interactive = __esmMin((() => {
53695
54667
  }));
53696
54668
  //#endregion
53697
54669
  //#region ../blocks/src/system/runtime/nodes/booking-form.server.tsx
53698
- init_spinner();
53699
54670
  init_booking_form_interactive();
53700
54671
  /**
53701
54672
  * Server-safe placeholder for booking form.
@@ -56185,6 +57156,153 @@ var init_WeekAgendaView = __esmMin((() => {
56185
57156
  };
56186
57157
  }));
56187
57158
  //#endregion
57159
+ //#region ../blocks/src/system/runtime/nodes/events/shared/WeekBoardView.tsx
57160
+ /**
57161
+ * Format an event's start–end as a compact range, merging the shared meridiem.
57162
+ * "6:00 PM" + "7:00 PM" -> "6:00 – 7:00 PM"; "9:30 AM" + "10:15 AM" -> "9:30 – 10:15 AM".
57163
+ */
57164
+ function formatCompactTimeRange(event) {
57165
+ const timeZone = event.timeZone ?? null;
57166
+ const start = formatTime$3(event.startsAt, { timeZone });
57167
+ const end = formatTime$3(event.endsAt, { timeZone });
57168
+ const startMeridiem = start.slice(-2);
57169
+ const endMeridiem = end.slice(-2);
57170
+ if ((startMeridiem === "AM" || startMeridiem === "PM") && startMeridiem === endMeridiem) return `${start.slice(0, -3).trim()} – ${end}`;
57171
+ return `${start} – ${end}`;
57172
+ }
57173
+ var SHORT_DAY_NAMES, LEGEND_ITEMS, WeekBoardCard, WeekBoardView;
57174
+ var init_WeekBoardView = __esmMin((() => {
57175
+ init_clsx();
57176
+ init_buttons();
57177
+ init_eventCapacity();
57178
+ init_utils$3();
57179
+ SHORT_DAY_NAMES = [
57180
+ "Sun",
57181
+ "Mon",
57182
+ "Tue",
57183
+ "Wed",
57184
+ "Thu",
57185
+ "Fri",
57186
+ "Sat"
57187
+ ];
57188
+ LEGEND_ITEMS = [
57189
+ {
57190
+ status: "available",
57191
+ label: "Places available"
57192
+ },
57193
+ {
57194
+ status: "filling",
57195
+ label: "Filling up"
57196
+ },
57197
+ {
57198
+ status: "waitlist",
57199
+ label: "Waitlist"
57200
+ }
57201
+ ];
57202
+ WeekBoardCard = ({ event, showCapacity }) => {
57203
+ const linkProps = resolveEventLinkProps(event);
57204
+ const { status, label } = getEventAvailabilityStatus(event);
57205
+ const pill = showCapacity ? label : null;
57206
+ return /* @__PURE__ */ jsxs("a", {
57207
+ ...linkProps,
57208
+ className: "event-week-board-card",
57209
+ "data-status": status,
57210
+ children: [
57211
+ /* @__PURE__ */ jsx("span", {
57212
+ className: "event-week-board-card-title",
57213
+ children: event.title
57214
+ }),
57215
+ /* @__PURE__ */ jsx("span", {
57216
+ className: "event-week-board-card-time",
57217
+ children: formatCompactTimeRange(event)
57218
+ }),
57219
+ pill ? /* @__PURE__ */ jsx("span", {
57220
+ className: "event-week-board-card-pill",
57221
+ "data-status": status,
57222
+ children: pill
57223
+ }) : null
57224
+ ]
57225
+ });
57226
+ };
57227
+ 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" }) => {
57228
+ const eventsByDate = groupEventsByDate(events);
57229
+ const hasAnyEvents = days.some((date) => (eventsByDate.get(formatDateKey(date)) ?? []).length > 0);
57230
+ const ctaClassName = themeButtonClassName({
57231
+ variant: buttonVariant,
57232
+ size: "sm"
57233
+ });
57234
+ return /* @__PURE__ */ jsx("div", {
57235
+ className: "event-calendar event-calendar--week-board",
57236
+ "data-block": "event-calendar",
57237
+ children: /* @__PURE__ */ jsxs("div", {
57238
+ className: "event-week-board",
57239
+ style: { "--event-week-board-cols": String(days.length) },
57240
+ children: [
57241
+ /* @__PURE__ */ jsxs("div", {
57242
+ className: "event-week-board-top",
57243
+ children: [/* @__PURE__ */ jsx("span", {
57244
+ className: "event-week-board-title",
57245
+ children: title
57246
+ }), /* @__PURE__ */ jsx("div", {
57247
+ className: "event-week-board-legend",
57248
+ "aria-hidden": "true",
57249
+ children: LEGEND_ITEMS.map((item) => /* @__PURE__ */ jsxs("span", {
57250
+ className: "event-week-board-legend-item",
57251
+ children: [/* @__PURE__ */ jsx("i", {
57252
+ className: "event-week-board-legend-dot",
57253
+ "data-status": item.status
57254
+ }), item.label]
57255
+ }, item.status))
57256
+ })]
57257
+ }),
57258
+ /* @__PURE__ */ jsx("div", {
57259
+ className: "event-week-board-grid",
57260
+ children: days.map((date) => {
57261
+ const dateKey = formatDateKey(date);
57262
+ const dayEvents = eventsByDate.get(dateKey) ?? [];
57263
+ const today = isToday(date);
57264
+ return /* @__PURE__ */ jsxs("div", {
57265
+ className: clsx("event-week-board-day", dayEvents.length === 0 && "event-week-board-day--empty", today && "event-week-board-day--today"),
57266
+ children: [/* @__PURE__ */ jsxs("div", {
57267
+ className: "event-week-board-day-head",
57268
+ children: [/* @__PURE__ */ jsx("span", {
57269
+ className: "event-week-board-day-abbr",
57270
+ children: SHORT_DAY_NAMES[date.getDay()]
57271
+ }), /* @__PURE__ */ jsx("span", {
57272
+ className: "event-week-board-day-num",
57273
+ children: date.getDate()
57274
+ })]
57275
+ }), /* @__PURE__ */ jsx("div", {
57276
+ className: "event-week-board-day-body",
57277
+ children: dayEvents.map((event) => /* @__PURE__ */ jsx(WeekBoardCard, {
57278
+ event,
57279
+ showCapacity
57280
+ }, event.occurrenceId || event.id))
57281
+ })]
57282
+ }, dateKey);
57283
+ })
57284
+ }),
57285
+ /* @__PURE__ */ jsxs("div", {
57286
+ className: "event-week-board-foot",
57287
+ children: [/* @__PURE__ */ jsx("p", {
57288
+ className: "event-week-board-foot-note",
57289
+ children: hasAnyEvents ? footerNote : emptyMessage
57290
+ }), ctaHref ? /* @__PURE__ */ jsx("a", {
57291
+ className: ctaClassName,
57292
+ href: ctaHref,
57293
+ children: ctaLabel
57294
+ }) : /* @__PURE__ */ jsx("button", {
57295
+ type: "button",
57296
+ className: ctaClassName,
57297
+ children: ctaLabel
57298
+ })]
57299
+ })
57300
+ ]
57301
+ })
57302
+ });
57303
+ };
57304
+ }));
57305
+ //#endregion
56188
57306
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
56189
57307
  function buildTimetableModel(input) {
56190
57308
  const generic = buildTimetableModel$1({
@@ -56279,6 +57397,7 @@ init_clsx();
56279
57397
  init_EventListing_view();
56280
57398
  init_EventCalendar_interactive();
56281
57399
  init_WeekAgendaView();
57400
+ init_WeekBoardView();
56282
57401
  init_utils$3();
56283
57402
  init_timetableModel();
56284
57403
  init_buttons();
@@ -56623,6 +57742,17 @@ function renderTimetableSsr(display) {
56623
57742
  })]
56624
57743
  });
56625
57744
  }
57745
+ function renderWeekBoardSsr(display) {
57746
+ const days = getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek);
57747
+ return /* @__PURE__ */ jsx(WeekBoardView, {
57748
+ days,
57749
+ events: [...display.events],
57750
+ showCapacity: display.showCapacity,
57751
+ emptyMessage: display.emptyMessage,
57752
+ ctaLabel: display.buttonText,
57753
+ buttonVariant: display.buttonVariant
57754
+ });
57755
+ }
56626
57756
  function formatHourLabel$1(hour) {
56627
57757
  if (hour === 0) return "12 AM";
56628
57758
  if (hour === 12) return "12 PM";
@@ -56649,6 +57779,9 @@ const EventCalendarSSR = (props) => {
56649
57779
  case "timetable":
56650
57780
  content = renderTimetableSsr(display);
56651
57781
  break;
57782
+ case "week-board":
57783
+ content = renderWeekBoardSsr(display);
57784
+ break;
56652
57785
  case "calendar":
56653
57786
  content = renderCalendarSsr(display);
56654
57787
  break;
@@ -57243,6 +58376,7 @@ init_media_server();
57243
58376
  const serverComponentRegistry = {
57244
58377
  div: DivNode,
57245
58378
  figure: FigureNode,
58379
+ svg: SvgNode,
57246
58380
  section: SectionNode,
57247
58381
  headerSection: header_section_server_default,
57248
58382
  stack: StackNode,
@@ -58721,9 +59855,12 @@ function formatFontFamily(family, fallback = "sans-serif") {
58721
59855
  }
58722
59856
  //#endregion
58723
59857
  //#region ../theme-core/src/styles/shadow.ts
59858
+ init_colorStyles();
58724
59859
  function generateShadowCssVars(theme) {
58725
59860
  const level = theme.shadow.elevation;
58726
59861
  const soft = theme.shadow.softness !== "crisp";
59862
+ const tintVar = theme.shadow.colorToken ? cssVarValue(theme.shadow.colorToken) : null;
59863
+ const shadowColor = (a) => tintVar ? `rgb(${tintVar} / ${a})` : `rgba(0, 0, 0, ${a})`;
58727
59864
  const base = {
58728
59865
  sm: [{
58729
59866
  y: 1,
@@ -58783,7 +59920,7 @@ function generateShadowCssVars(theme) {
58783
59920
  const blurMul = soft ? 1.2 : 1;
58784
59921
  const alphaMul = soft ? .9 : 1.05;
58785
59922
  const fmt = (layers) => layers.map((l) => {
58786
- 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)))})`;
59923
+ 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))))}`;
58787
59924
  }).join(", ");
58788
59925
  return {
58789
59926
  "--shadow-sm": fmt(base.sm),
@@ -58819,6 +59956,7 @@ function parseBorderWidth(widthClass) {
58819
59956
  init_types$10();
58820
59957
  init_constants$1();
58821
59958
  init_colorStyles();
59959
+ init_surfaces();
58822
59960
  /**
58823
59961
  * Corner radius map for accordion surfaces. Pill is capped here because FAQ
58824
59962
  * rows contain long text and expanded content; full capsules clip awkwardly.
@@ -58852,7 +59990,13 @@ function generateAccordionCss({ themeId, theme, accordionSystem }) {
58852
59990
  const questionColumnsLastItemSelector = `${questionColumnsItemSelector}:last-child`;
58853
59991
  const questionColumnsTriggerSelector = `${questionColumnsItemSelector} .accordion-trigger`;
58854
59992
  const rootRules = [];
58855
- if (accordionSystem.background) rootRules.push(`background-color: ${rgbColorValue(accordionSystem.background.colorToken)}`);
59993
+ if (accordionSystem.background) {
59994
+ rootRules.push(`background-color: ${rgbColorValue(accordionSystem.background.colorToken)}`);
59995
+ rootRules.push(...surfaceForegroundDeclarations({
59996
+ text: rgbColorValue(accordionSystem.content.textColorToken),
59997
+ heading: rgbColorValue(accordionSystem.trigger.textColorToken)
59998
+ }));
59999
+ }
58856
60000
  const borderRadius = CORNER_MAP$2[accordionSystem.corners ?? theme.corners];
58857
60001
  rootRules.push(`border-radius: ${borderRadius}`);
58858
60002
  if (accordionSystem.border) {
@@ -60430,7 +61574,7 @@ function toHeroLineHeight(lineHeight) {
60430
61574
  }
60431
61575
  //#endregion
60432
61576
  //#region ../theme-core/src/status/generateStatusCss.ts
60433
- init_contextualColors();
61577
+ init_surfaces();
60434
61578
  /**
60435
61579
  * Corner radius map - derives alert border-radius from theme.corners
60436
61580
  */
@@ -60460,7 +61604,7 @@ ${root} .status-error { color: rgb(var(--tb-destructive)); }
60460
61604
  ${root} .status-success { color: rgb(var(--tb-success)); }
60461
61605
  ${root} .status-warning { color: rgb(var(--tb-warning)); }
60462
61606
  ${root} .status-info { color: rgb(var(--tb-info)); }
60463
- ${root} .status-muted { ${statusMutedColorDeclaration()} }`);
61607
+ ${root} .status-muted { color: ${surfaceForegroundValue("supporting")}; }`);
60464
61608
  cssBlocks.push(`/* Alert containers */
60465
61609
  ${root} .alert {
60466
61610
  padding: 1rem;
@@ -60514,9 +61658,6 @@ ${root} .button-link:hover {
60514
61658
  return cssBlocks.join("\n\n");
60515
61659
  }
60516
61660
  //#endregion
60517
- //#region ../theme-core/src/status/index.ts
60518
- init_contextualColors();
60519
- //#endregion
60520
61661
  //#region ../theme-core/src/progress/generateProgressCss.ts
60521
61662
  /**
60522
61663
  * Generate progress indicator CSS from theme settings.
@@ -60601,6 +61742,10 @@ ${root} .step-connector {
60601
61742
  }
60602
61743
  //#endregion
60603
61744
  //#region ../theme-core/src/typography/generateTypographyCss.ts
61745
+ init_surfaces();
61746
+ function globalHeadingColorFallback(level) {
61747
+ return `var(--hc-h${level}, var(--hc-heading, ${DEFAULT_SURFACE_TEXT_COLOR}))`;
61748
+ }
60604
61749
  /**
60605
61750
  * Generate typography CSS for heading elements.
60606
61751
  *
@@ -60629,7 +61774,7 @@ ${root} :where(h1) {
60629
61774
  font-style: var(--fi-h1, var(--fi-heading, normal));
60630
61775
  letter-spacing: var(--ls-h1, var(--ls-heading));
60631
61776
  line-height: var(--lh-h1, var(--lh-heading));
60632
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h1, var(--hc-heading, inherit))));
61777
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(1))};
60633
61778
  }
60634
61779
 
60635
61780
  ${root} :where(h2) {
@@ -60638,7 +61783,7 @@ ${root} :where(h2) {
60638
61783
  font-style: var(--fi-h2, var(--fi-heading, normal));
60639
61784
  letter-spacing: var(--ls-h2, var(--ls-heading));
60640
61785
  line-height: var(--lh-h2, var(--lh-heading));
60641
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h2, var(--hc-heading, inherit))));
61786
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(2))};
60642
61787
  }
60643
61788
 
60644
61789
  ${root} :where(h3) {
@@ -60647,7 +61792,7 @@ ${root} :where(h3) {
60647
61792
  font-style: var(--fi-h3, var(--fi-heading, normal));
60648
61793
  letter-spacing: var(--ls-h3, var(--ls-heading));
60649
61794
  line-height: var(--lh-h3, var(--lh-heading));
60650
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h3, var(--hc-heading, inherit))));
61795
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(3))};
60651
61796
  }
60652
61797
 
60653
61798
  ${root} :where(h4) {
@@ -60656,7 +61801,7 @@ ${root} :where(h4) {
60656
61801
  font-style: var(--fi-h4, var(--fi-heading, normal));
60657
61802
  letter-spacing: var(--ls-h4, var(--ls-heading));
60658
61803
  line-height: var(--lh-h4, var(--lh-heading));
60659
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h4, var(--hc-heading, inherit))));
61804
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(4))};
60660
61805
  }
60661
61806
 
60662
61807
  ${root} :where(h5) {
@@ -60665,7 +61810,7 @@ ${root} :where(h5) {
60665
61810
  font-style: var(--fi-h5, var(--fi-heading, normal));
60666
61811
  letter-spacing: var(--ls-h5, var(--ls-heading));
60667
61812
  line-height: var(--lh-h5, var(--lh-heading));
60668
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h5, var(--hc-heading, inherit))));
61813
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(5))};
60669
61814
  }
60670
61815
 
60671
61816
  ${root} :where(h6) {
@@ -60674,7 +61819,7 @@ ${root} :where(h6) {
60674
61819
  font-style: var(--fi-h6, var(--fi-heading, normal));
60675
61820
  letter-spacing: var(--ls-h6, var(--ls-heading));
60676
61821
  line-height: var(--lh-h6, var(--lh-heading));
60677
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h6, var(--hc-heading, inherit))));
61822
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(6))};
60678
61823
  }`);
60679
61824
  cssBlocks.push(`/* Display variant for hero/splash headings */
60680
61825
  ${root} :where(.heading-display) {
@@ -61073,6 +62218,7 @@ const THEME_RADIUS_CSS_VARS = {
61073
62218
  block: "--rb-block-radius",
61074
62219
  button: "--rb-button-radius",
61075
62220
  input: "--rb-input-radius",
62221
+ panel: "--rb-panel-radius",
61076
62222
  legacyCard: "--radius-card",
61077
62223
  legacyControl: "--radius-control"
61078
62224
  };
@@ -61154,6 +62300,10 @@ ${`:where([data-theme-scope="${themeId}"]) :where([data-block="customer-portal"]
61154
62300
  /* Modal (shared rb-modal classes) */
61155
62301
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.35);
61156
62302
  --rb-modal-bg: var(--cp-card-bg);
62303
+ --rb-modal-text: var(--cp-text);
62304
+ --rb-modal-heading: var(--cp-text);
62305
+ --rb-modal-link: var(--cp-primary);
62306
+ --rb-modal-supporting: var(--cp-muted);
61157
62307
  --rb-modal-border: var(--cp-card-border);
61158
62308
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
61159
62309
  --rb-modal-radius: var(--cp-card-radius);
@@ -61879,6 +63029,7 @@ function buildThemeCssVars(theme) {
61879
63029
  const inputSystem = resolveThemeInputSystem(theme);
61880
63030
  const blockRadius = mapBlockRadius(theme.corners);
61881
63031
  const buttonRadius = mapButtonRadius(theme.corners);
63032
+ const panelRadius = mapPanelRadius(theme.corners);
61882
63033
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
61883
63034
  return {
61884
63035
  ...generateCssVars(theme.palette),
@@ -61887,6 +63038,7 @@ function buildThemeCssVars(theme) {
61887
63038
  ...generateShadowCssVars(theme),
61888
63039
  ["--font-heading"]: formatFontFamily(typography.headings.default.family),
61889
63040
  ["--font-body"]: formatFontFamily(typography.body.family),
63041
+ ["--font-eyebrow"]: typography.eyebrow?.family ? formatFontFamily(typography.eyebrow.family) : "var(--font-body)",
61890
63042
  ["--font-weight-heading"]: mapWeight(typography.headings.default.weight),
61891
63043
  ["--font-weight-body"]: mapWeight(typography.body.weight),
61892
63044
  ...typography.headings.h1.weight ? { ["--fw-h1"]: mapWeight(typography.headings.h1.weight) } : {},
@@ -61937,12 +63089,13 @@ function buildThemeCssVars(theme) {
61937
63089
  ["--fs-h3-fluid"]: sized.h3Fluid,
61938
63090
  ["--fs-h1-display"]: sized.h1Display,
61939
63091
  ["--fs-h1-display-fluid"]: sized.h1DisplayFluid,
61940
- ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom"),
63092
+ ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom", shadow.colorToken),
61941
63093
  ["--space-mult"]: mapSpaceMult(space),
61942
63094
  ["--motion-duration"]: mapMotionDuration(motion.level),
61943
63095
  ["--motion-ease"]: mapMotionEasing(motion.easing ?? "standard"),
61944
63096
  ["--rt-space-y"]: mapRhythm(space),
61945
63097
  [THEME_RADIUS_CSS_VARS.block]: blockRadius,
63098
+ [THEME_RADIUS_CSS_VARS.panel]: panelRadius,
61946
63099
  ["--rb-block-transition"]: mapBlockTransition(motion.level),
61947
63100
  [THEME_RADIUS_CSS_VARS.button]: buttonRadius,
61948
63101
  ["--rb-border-width"]: mapBorderWidth(border.width),
@@ -61996,20 +63149,22 @@ function mapWeight(w) {
61996
63149
  bold: 700
61997
63150
  }[w];
61998
63151
  }
61999
- function mapShadow(level, softness, position = "bottom") {
63152
+ function mapShadow(level, softness, position = "bottom", colorToken) {
62000
63153
  if (level === "none") return "none";
63154
+ const tintVar = colorToken ? cssVarValue(colorToken) : null;
63155
+ const shadowColor = (a) => tintVar ? `rgb(${tintVar} / ${a})` : `rgba(0,0,0,${a})`;
62001
63156
  const offset = {
62002
63157
  low: 2,
62003
63158
  medium: 4,
62004
63159
  high: 6
62005
63160
  }[level];
62006
63161
  const xOffset = position === "bottom-right" ? offset : 0;
62007
- if (softness === "hard") return `${xOffset}px ${offset}px 0 0 rgba(0,0,0,1)`;
63162
+ if (softness === "hard") return `${xOffset}px ${offset}px 0 0 ${shadowColor("1")}`;
62008
63163
  const soft = softness !== "crisp";
62009
63164
  switch (level) {
62010
- case "low": return soft ? `${xOffset}px 1px 2px rgba(0,0,0,.06)` : `${xOffset}px 1px 1px rgba(0,0,0,.12)`;
62011
- case "medium": return soft ? `${xOffset}px 10px 20px rgba(0,0,0,.08)` : `${xOffset}px 6px 12px rgba(0,0,0,.16)`;
62012
- case "high": return soft ? `${xOffset}px 25px 50px rgba(0,0,0,.18)` : `${xOffset}px 20px 30px rgba(0,0,0,.28)`;
63165
+ case "low": return soft ? `${xOffset}px 1px 2px ${shadowColor(".06")}` : `${xOffset}px 1px 1px ${shadowColor(".12")}`;
63166
+ case "medium": return soft ? `${xOffset}px 10px 20px ${shadowColor(".08")}` : `${xOffset}px 6px 12px ${shadowColor(".16")}`;
63167
+ case "high": return soft ? `${xOffset}px 25px 50px ${shadowColor(".18")}` : `${xOffset}px 20px 30px ${shadowColor(".28")}`;
62013
63168
  }
62014
63169
  }
62015
63170
  function mapSpaceMult(space) {
@@ -62056,6 +63211,21 @@ function mapBlockRadius(corners) {
62056
63211
  }[corners];
62057
63212
  }
62058
63213
  /**
63214
+ * Map corner style to large-panel radius CSS value (Tier 2 `--rb-panel-radius`).
63215
+ * Derived from the same `corners` enum, one step more generous than the
63216
+ * block/card radius so large surfaces can carry a softer corner without a new
63217
+ * schema field. `rounded` lands on 20px (1.25rem), matching the physio mockup's
63218
+ * large-panel radius.
63219
+ */
63220
+ function mapPanelRadius(corners) {
63221
+ return {
63222
+ square: "0",
63223
+ soft: "0.75rem",
63224
+ rounded: "1.25rem",
63225
+ pill: "2rem"
63226
+ }[corners];
63227
+ }
63228
+ /**
62059
63229
  * Map motion level to block transition duration.
62060
63230
  * These are Tier 2 vars used consistently across blocks.
62061
63231
  */
@@ -63080,8 +64250,12 @@ const containerResponsiveThemeCss = `/*
63080
64250
  text-transform: uppercase;
63081
64251
  }
63082
64252
 
63083
- /* Eyebrow text - small uppercase labels for section introductions */
64253
+ /* Eyebrow text - small uppercase labels for section introductions.
64254
+ font-family resolves to the optional eyebrow/mono font role, falling back
64255
+ to the body font when the theme sets none (so existing themes are
64256
+ unchanged). */
63084
64257
  .rb-eyebrow {
64258
+ font-family: var(--font-eyebrow, var(--font-body));
63085
64259
  font-size: 0.875rem;
63086
64260
  font-weight: 600;
63087
64261
  letter-spacing: 0.025em;
@@ -63096,11 +64270,11 @@ const containerResponsiveThemeCss = `/*
63096
64270
  width: fit-content;
63097
64271
  align-items: center;
63098
64272
  justify-content: center;
63099
- border: 1px solid color-mix(in srgb, var(--section-text-color, rgb(var(--tb-text))) 46%, transparent);
64273
+ border: 1px solid color-mix(in srgb, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 46%, transparent);
63100
64274
  border-radius: 9999px;
63101
- background: color-mix(in srgb, var(--section-text-color, rgb(var(--tb-text))) 14%, transparent);
64275
+ background: color-mix(in srgb, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 14%, transparent);
63102
64276
  padding: 0.5rem 1rem;
63103
- color: var(--section-text-color, rgb(var(--tb-text)));
64277
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
63104
64278
  line-height: 1;
63105
64279
  }
63106
64280
  .rb-eyebrow-treatment-pill.rb-eyebrow-treatment-accent {
@@ -63602,6 +64776,58 @@ const containerResponsiveThemeCss = `/*
63602
64776
  }
63603
64777
  }
63604
64778
 
64779
+ }
64780
+
64781
+ /*
64782
+ * Responsive fractional grid tracks (rb-grid-tracks).
64783
+ *
64784
+ * Asymmetric AND responsive grid-template-columns, driven by inline custom
64785
+ * properties the Grid primitive sets per breakpoint from string track
64786
+ * templates:
64787
+ * --rb-gtc-base / --rb-gtc-sm / --rb-gtc-md / --rb-gtc-lg / --rb-gtc-xl
64788
+ * Each breakpoint falls back to the next smaller one, so only the breakpoints
64789
+ * an author actually sets take effect (e.g. base '1fr' + lg '1fr 0.9fr'
64790
+ * collapses to a single column below lg). Authored here (not per node) so the
64791
+ * @media -> @container conversion (container responsive mode) applies too.
64792
+ */
64793
+ .rb-grid-tracks {
64794
+ grid-template-columns: var(--rb-gtc-base, 1fr);
64795
+ }
64796
+ @container rb-site (min-width: 640px) {
64797
+
64798
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
64799
+ .rb-grid-tracks {
64800
+ grid-template-columns: var(--rb-gtc-sm, var(--rb-gtc-base, 1fr));
64801
+ }
64802
+ }
64803
+
64804
+ }
64805
+ @container rb-site (min-width: 768px) {
64806
+
64807
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
64808
+ .rb-grid-tracks {
64809
+ grid-template-columns: var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr)));
64810
+ }
64811
+ }
64812
+
64813
+ }
64814
+ @container rb-site (min-width: 1024px) {
64815
+
64816
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
64817
+ .rb-grid-tracks {
64818
+ grid-template-columns: var(--rb-gtc-lg, var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr))));
64819
+ }
64820
+ }
64821
+
64822
+ }
64823
+ @container rb-site (min-width: 1280px) {
64824
+
64825
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
64826
+ .rb-grid-tracks {
64827
+ grid-template-columns: var(--rb-gtc-xl, var(--rb-gtc-lg, var(--rb-gtc-md, var(--rb-gtc-sm, var(--rb-gtc-base, 1fr)))));
64828
+ }
64829
+ }
64830
+
63605
64831
  }
63606
64832
 
63607
64833
  /* Alignment */
@@ -64806,6 +66032,11 @@ const containerResponsiveThemeCss = `/*
64806
66032
  :where(.theme-scope) .rb-modal {
64807
66033
  width: min(var(--rb-modal-max-width, 560px), 100%);
64808
66034
  background: var(--rb-modal-bg, rgb(var(--tb-surface)));
66035
+ color: var(--rb-modal-text, rgb(var(--tb-text, 17 24 39)));
66036
+ --rb-surface-text-color: var(--rb-modal-text, rgb(var(--tb-text, 17 24 39)));
66037
+ --rb-surface-heading-color: var(--rb-modal-heading, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
66038
+ --rb-surface-link-color: var(--rb-modal-link, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
66039
+ --rb-surface-supporting-color: var(--rb-modal-supporting, var(--rb-modal-text, rgb(var(--tb-text, 17 24 39))));
64809
66040
  border: 1px solid var(--rb-modal-border, rgb(var(--tb-border)));
64810
66041
  border-radius: var(--rb-modal-radius, var(--radius-card));
64811
66042
  box-shadow: var(--rb-modal-shadow, var(--shadow-lg, var(--shadow-elev)));
@@ -64825,7 +66056,7 @@ const containerResponsiveThemeCss = `/*
64825
66056
  font-family: var(--font-heading);
64826
66057
  font-size: 1.0625rem;
64827
66058
  font-weight: 600;
64828
- color: rgb(var(--tb-text));
66059
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
64829
66060
  }
64830
66061
 
64831
66062
  :where(.theme-scope) .rb-modal__close {
@@ -64835,7 +66066,7 @@ const containerResponsiveThemeCss = `/*
64835
66066
  height: 2.25rem;
64836
66067
  padding: 0;
64837
66068
  line-height: 1;
64838
- color: rgb(var(--tb-mutedText));
66069
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
64839
66070
  cursor: pointer;
64840
66071
  display: grid;
64841
66072
  place-items: center;
@@ -64843,7 +66074,7 @@ const containerResponsiveThemeCss = `/*
64843
66074
  }
64844
66075
 
64845
66076
  :where(.theme-scope) .rb-modal__close:hover {
64846
- color: rgb(var(--tb-text));
66077
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
64847
66078
  background: rgba(var(--tb-border), 0.2);
64848
66079
  }
64849
66080
 
@@ -64854,7 +66085,7 @@ const containerResponsiveThemeCss = `/*
64854
66085
 
64855
66086
  :where(.theme-scope) .rb-modal__body {
64856
66087
  padding: 0.875rem 1rem 1rem;
64857
- color: rgb(var(--tb-text));
66088
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
64858
66089
  font-size: 0.9375rem;
64859
66090
  line-height: 1.45;
64860
66091
  }
@@ -65014,7 +66245,7 @@ const containerResponsiveThemeCss = `/*
65014
66245
  & h6 {
65015
66246
  font-family: var(--font-heading);
65016
66247
  /* Color is set by generateTypographyCss.ts with full cascade:
65017
- --section-heading-color -> --section-text-color -> --hc-hN -> --hc-heading -> inherit */
66248
+ --rb-surface-heading-color -> --rb-surface-text-color -> --hc-hN -> --hc-heading -> global text */
65018
66249
  font-weight: var(--font-weight-heading);
65019
66250
  text-transform: var(--tt-heading);
65020
66251
  font-variant-caps: var(--fv-heading);
@@ -65162,7 +66393,7 @@ const containerResponsiveThemeCss = `/*
65162
66393
 
65163
66394
  /* Neutral prose uses theme text color by default */
65164
66395
  :where(.theme-scope) .rb-prose-neutral {
65165
- color: var(--section-text-color, rgb(var(--tb-text)));
66396
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
65166
66397
  }
65167
66398
 
65168
66399
  :where(.theme-scope) .rb-prose p,
@@ -65196,8 +66427,14 @@ const containerResponsiveThemeCss = `/*
65196
66427
 
65197
66428
  :where(.theme-scope) .rb-prose a {
65198
66429
  --rb-prose-effective-link-color: var(
65199
- --section-link-color,
65200
- var(--rb-prose-link-color, rgb(var(--tb-primary)))
66430
+ --rb-surface-link-color,
66431
+ var(
66432
+ --rb-surface-text-color,
66433
+ var(
66434
+ --rb-prose-link-color,
66435
+ rgb(var(--tb-primary, var(--tb-text, 17 24 39)))
66436
+ )
66437
+ )
65201
66438
  );
65202
66439
  color: var(--rb-prose-effective-link-color);
65203
66440
  text-decoration-line: var(--rb-prose-link-decoration-line, underline);
@@ -65208,14 +66445,11 @@ const containerResponsiveThemeCss = `/*
65208
66445
  );
65209
66446
  text-underline-offset: var(--rb-prose-link-underline-offset, 0.14em);
65210
66447
  text-decoration-color: var(
65211
- --section-link-decoration-color,
65212
- var(
65213
- --rb-prose-link-decoration-color,
65214
- color-mix(
65215
- in srgb,
65216
- var(--rb-prose-effective-link-color) 35%,
65217
- transparent
65218
- )
66448
+ --rb-prose-link-decoration-color,
66449
+ color-mix(
66450
+ in srgb,
66451
+ var(--rb-prose-effective-link-color) 35%,
66452
+ transparent
65219
66453
  )
65220
66454
  );
65221
66455
  transition:
@@ -65239,7 +66473,7 @@ const containerResponsiveThemeCss = `/*
65239
66473
 
65240
66474
  :where(.theme-scope) .rb-prose blockquote {
65241
66475
  /* Blockquotes use muted text color */
65242
- color: var(--section-supporting-color, rgb(var(--tb-mutedText)));
66476
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
65243
66477
  border-left-color: rgb(var(--tb-border));
65244
66478
  }
65245
66479
 
@@ -66273,6 +67507,10 @@ const containerResponsiveThemeCss = `/*
66273
67507
  :where(.theme-scope) .card-surface {
66274
67508
  background: rgb(var(--tb-surface));
66275
67509
  color: rgb(var(--tb-onSurface, var(--tb-text)));
67510
+ --rb-surface-text-color: rgb(var(--tb-onSurface, var(--tb-text)));
67511
+ --rb-surface-heading-color: rgb(var(--tb-onSurface, var(--tb-text)));
67512
+ --rb-surface-link-color: rgb(var(--tb-onSurface, var(--tb-text)));
67513
+ --rb-surface-supporting-color: rgb(var(--tb-onSurface, var(--tb-text)));
66276
67514
  border: 1px solid rgb(var(--tb-border));
66277
67515
  border-radius: var(--radius-card);
66278
67516
  box-shadow: var(--shadow-elev);
@@ -66416,6 +67654,10 @@ const containerResponsiveThemeCss = `/*
66416
67654
  padding: clamp(1rem, 2vw, 1.5rem);
66417
67655
  background: var(--rb-reg-surface-bg, rgb(var(--tb-surface, 248 250 252)));
66418
67656
  color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
67657
+ --rb-surface-text-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
67658
+ --rb-surface-heading-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
67659
+ --rb-surface-link-color: var(--rb-reg-on-surface, rgb(var(--tb-onSurface, var(--tb-text, 15 23 42))));
67660
+ --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)))));
66419
67661
  transition: border-color var(--rb-block-transition, 150ms) ease;
66420
67662
  width: 100%;
66421
67663
  max-width: 800px;
@@ -69503,6 +70745,350 @@ const containerResponsiveThemeCss = `/*
69503
70745
  }
69504
70746
  }
69505
70747
 
70748
+ /* -----------------------------------------------------------------------------
70749
+ * Week Board View
70750
+ * Compact "class day-board": day columns side by side, one card per class,
70751
+ * three-state availability (available / filling / waitlist), and a footer CTA.
70752
+ * ----------------------------------------------------------------------------- */
70753
+
70754
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board {
70755
+ /* Status accent tokens — map the three availability states onto theme colours.
70756
+ * available -> secondary, filling -> accent, waitlist -> muted text. */
70757
+ --ec-status-available: rgb(var(--tb-secondary));
70758
+ --ec-status-filling: rgb(var(--tb-accent));
70759
+ --ec-status-waitlist: rgba(var(--tb-text), 0.4);
70760
+ --event-week-board-cols: 7;
70761
+
70762
+ border: 1px solid var(--ec-border);
70763
+ border-radius: var(--rb-block-radius);
70764
+ background-color: var(--ec-surface);
70765
+ color: var(--ec-text);
70766
+ overflow: hidden;
70767
+ box-shadow: 0 14px 34px -24px rgba(var(--tb-text), 0.35);
70768
+ }
70769
+
70770
+ /* Top bar: title + legend */
70771
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-top {
70772
+ display: flex;
70773
+ align-items: center;
70774
+ justify-content: space-between;
70775
+ gap: 1rem;
70776
+ flex-wrap: wrap;
70777
+ padding: 1.1rem 1.5rem;
70778
+ background-color: var(--ec-header-bg);
70779
+ border-bottom: 1px solid var(--ec-border-subtle);
70780
+ }
70781
+
70782
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-title {
70783
+ font-size: 0.8125rem;
70784
+ font-weight: 600;
70785
+ letter-spacing: 0.12em;
70786
+ text-transform: uppercase;
70787
+ color: rgb(var(--tb-primary));
70788
+ }
70789
+
70790
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend {
70791
+ display: flex;
70792
+ align-items: center;
70793
+ gap: 1.1rem;
70794
+ flex-wrap: wrap;
70795
+ font-size: 0.6875rem;
70796
+ letter-spacing: 0.03em;
70797
+ opacity: 0.75;
70798
+ }
70799
+
70800
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-item {
70801
+ display: inline-flex;
70802
+ align-items: center;
70803
+ gap: 0.4rem;
70804
+ }
70805
+
70806
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot {
70807
+ width: 0.55rem;
70808
+ height: 0.55rem;
70809
+ border-radius: 50%;
70810
+ display: inline-block;
70811
+ }
70812
+
70813
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="available"] {
70814
+ background-color: var(--ec-status-available);
70815
+ }
70816
+
70817
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="filling"] {
70818
+ background-color: var(--ec-status-filling);
70819
+ }
70820
+
70821
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend-dot[data-status="waitlist"] {
70822
+ background-color: var(--ec-status-waitlist);
70823
+ }
70824
+
70825
+ /* Day columns grid */
70826
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-grid {
70827
+ display: grid;
70828
+ grid-template-columns: repeat(var(--event-week-board-cols), minmax(0, 1fr));
70829
+ }
70830
+
70831
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day {
70832
+ display: flex;
70833
+ flex-direction: column;
70834
+ min-height: 15rem;
70835
+ /* Tabular column rule. Driven by the theme border tokens so borderless site
70836
+ * styles (border.width: 'none' -> --rb-border-width: 0) render no grid at all,
70837
+ * while hairline/thin/thick themes get a crisp full-strength divider. */
70838
+ border-right: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
70839
+ }
70840
+
70841
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day:last-child {
70842
+ border-right: none;
70843
+ }
70844
+
70845
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-head {
70846
+ display: flex;
70847
+ align-items: baseline;
70848
+ gap: 0.4rem;
70849
+ padding: 0.9rem 0.9rem 0.65rem;
70850
+ /* Header-row underline — same border-token gating as the column rules. */
70851
+ border-bottom: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
70852
+ }
70853
+
70854
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--today .event-week-board-day-head {
70855
+ background-color: var(--ec-today-bg);
70856
+ }
70857
+
70858
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-abbr {
70859
+ font-size: 0.6875rem;
70860
+ font-weight: 600;
70861
+ letter-spacing: 0.1em;
70862
+ text-transform: uppercase;
70863
+ opacity: 0.65;
70864
+ }
70865
+
70866
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--today .event-week-board-day-abbr {
70867
+ opacity: 1;
70868
+ color: var(--ec-today-text);
70869
+ }
70870
+
70871
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-num {
70872
+ font-size: 0.8125rem;
70873
+ font-weight: 600;
70874
+ opacity: 0.5;
70875
+ }
70876
+
70877
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-body {
70878
+ display: flex;
70879
+ flex-direction: column;
70880
+ gap: 0.65rem;
70881
+ padding: 0.9rem;
70882
+ flex: 1;
70883
+ }
70884
+
70885
+ /* Class card */
70886
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
70887
+ display: flex;
70888
+ flex-direction: column;
70889
+ gap: 0.45rem;
70890
+ padding: 0.8rem 0.85rem;
70891
+ border: 1px solid var(--ec-border-subtle);
70892
+ border-left: 3px solid var(--ec-status-available);
70893
+ border-radius: calc(var(--rb-block-radius) / 1.5);
70894
+ background-color: var(--ec-surface);
70895
+ color: inherit;
70896
+ text-decoration: none;
70897
+ transition:
70898
+ transform var(--rb-block-transition) ease,
70899
+ box-shadow var(--rb-block-transition) ease,
70900
+ border-color var(--rb-block-transition) ease;
70901
+ }
70902
+
70903
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card[data-status="filling"] {
70904
+ border-left-color: var(--ec-status-filling);
70905
+ }
70906
+
70907
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card[data-status="waitlist"] {
70908
+ border-left-color: var(--ec-status-waitlist);
70909
+ }
70910
+
70911
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card:hover {
70912
+ transform: translateY(-2px);
70913
+ box-shadow: 0 6px 16px -8px rgba(var(--tb-text), 0.28);
70914
+ border-color: rgba(var(--tb-primary), 0.4);
70915
+ }
70916
+
70917
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card:focus-visible {
70918
+ outline: 2px solid rgb(var(--tb-primary));
70919
+ outline-offset: 2px;
70920
+ }
70921
+
70922
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-title {
70923
+ font-family: var(--font-heading, inherit);
70924
+ font-size: 0.9375rem;
70925
+ font-weight: 600;
70926
+ line-height: 1.2;
70927
+ }
70928
+
70929
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-time {
70930
+ font-size: 0.75rem;
70931
+ letter-spacing: 0.01em;
70932
+ opacity: 0.7;
70933
+ }
70934
+
70935
+ /* Capacity pill */
70936
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill {
70937
+ align-self: flex-start;
70938
+ display: inline-flex;
70939
+ align-items: center;
70940
+ padding: 0.15rem 0.6rem;
70941
+ border-radius: 999px;
70942
+ font-size: 0.6875rem;
70943
+ font-weight: 600;
70944
+ letter-spacing: 0.02em;
70945
+ /* Available (default): a calm neutral/muted pill — not a coloured outline.
70946
+ * Filling -> amber and waitlist -> muted outline are handled by the
70947
+ * data-status overrides below. */
70948
+ border: 1px solid var(--ec-border);
70949
+ background-color: rgba(var(--tb-text), 0.06);
70950
+ color: rgba(var(--tb-text), 0.62);
70951
+ border-color: var(--ec-border);
70952
+ }
70953
+
70954
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill[data-status="filling"] {
70955
+ background-color: rgba(var(--tb-accent), 0.14);
70956
+ color: var(--ec-status-filling);
70957
+ border-color: rgba(var(--tb-accent), 0.32);
70958
+ }
70959
+
70960
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card-pill[data-status="waitlist"] {
70961
+ background-color: transparent;
70962
+ color: rgba(var(--tb-text), 0.6);
70963
+ border-color: var(--ec-border);
70964
+ }
70965
+
70966
+ /* Footer */
70967
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-foot {
70968
+ display: flex;
70969
+ align-items: center;
70970
+ justify-content: space-between;
70971
+ gap: 1rem;
70972
+ flex-wrap: wrap;
70973
+ padding: 1.1rem 1.5rem;
70974
+ background-color: var(--ec-header-bg);
70975
+ border-top: 1px solid var(--ec-border-subtle);
70976
+ }
70977
+
70978
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-foot-note {
70979
+ margin: 0;
70980
+ font-size: 0.875rem;
70981
+ opacity: 0.75;
70982
+ }
70983
+
70984
+ /* Responsive: collapse day columns to a stacked list on narrow viewports */
70985
+ @container rb-site (max-width: 1023px) {
70986
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
70987
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-grid {
70988
+ grid-template-columns: 1fr;
70989
+ }
70990
+
70991
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day {
70992
+ min-height: 0;
70993
+ border-right: none;
70994
+ border-bottom: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
70995
+ }
70996
+
70997
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day:last-child {
70998
+ border-bottom: none;
70999
+ }
71000
+
71001
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day--empty {
71002
+ display: none;
71003
+ }
71004
+
71005
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-head {
71006
+ border-bottom: none;
71007
+ padding-bottom: 0.25rem;
71008
+ }
71009
+
71010
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-day-body {
71011
+ flex-direction: row;
71012
+ flex-wrap: wrap;
71013
+ padding-top: 0.35rem;
71014
+ }
71015
+
71016
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
71017
+ flex: 1 1 14rem;
71018
+ }
71019
+ }
71020
+ }
71021
+
71022
+ @container rb-site (max-width: 639px) {
71023
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
71024
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-legend {
71025
+ display: none;
71026
+ }
71027
+
71028
+ :where(.theme-scope) :where([data-block="event-calendar"]) .event-week-board-card {
71029
+ flex: 1 1 100%;
71030
+ }
71031
+ }
71032
+ }
71033
+
71034
+ /* -----------------------------------------------------------------------------
71035
+ * Week-board section band
71036
+ * Give the whole week-board section (head + panel) a subtle surface band so it
71037
+ * reads as a distinct zone from the page — the "testimonials band" pattern.
71038
+ * Painted as a pseudo-element above the section's fallback background layer
71039
+ * (z-index -10) but behind the content, so no block-content wiring is needed.
71040
+ * Surface + hairline rules are token-referenced: on a borderless site style
71041
+ * (--rb-border-width: 0) the band keeps its surface tint but drops the rules.
71042
+ * ----------------------------------------------------------------------------- */
71043
+ :where(.theme-scope) [data-slot="section"]:has(.event-calendar--week-board)::before {
71044
+ content: "";
71045
+ position: absolute;
71046
+ inset: 0;
71047
+ z-index: -9;
71048
+ background-color: rgb(var(--tb-surfaceAlt));
71049
+ border-block: var(--rb-border-width, 1px) solid rgb(var(--tb-border));
71050
+ pointer-events: none;
71051
+ }
71052
+
71053
+ /* -----------------------------------------------------------------------------
71054
+ * Event section head — split (heading left, intro right)
71055
+ * Rendered by the block frame (outside [data-block="event-calendar"]) via
71056
+ * eventSectionHeaderLayoutNodes({ splitClassName }). Lays the heading and its
71057
+ * supporting intro out as a two-column head on wide viewports, stacking on
71058
+ * narrow ones. The section band above provides the distinct background.
71059
+ * ----------------------------------------------------------------------------- */
71060
+ :where(.theme-scope) .event-section-head--split {
71061
+ display: flex;
71062
+ align-items: flex-end;
71063
+ justify-content: space-between;
71064
+ gap: clamp(1.5rem, 4vw, 3.5rem);
71065
+ flex-wrap: wrap;
71066
+ }
71067
+
71068
+ :where(.theme-scope) .event-section-head--split > :where(h1, h2, h3) {
71069
+ margin: 0;
71070
+ }
71071
+
71072
+ :where(.theme-scope) .event-section-head--split > .rb-prose {
71073
+ flex: 1 1 22rem;
71074
+ max-width: 34rem;
71075
+ margin: 0;
71076
+ }
71077
+
71078
+ @container rb-site (max-width: 767px) {
71079
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
71080
+ :where(.theme-scope) .event-section-head--split {
71081
+ flex-direction: column;
71082
+ align-items: flex-start;
71083
+ gap: 0.75rem;
71084
+ }
71085
+
71086
+ :where(.theme-scope) .event-section-head--split > .rb-prose {
71087
+ flex-basis: auto;
71088
+ }
71089
+ }
71090
+ }
71091
+
69506
71092
  /* -----------------------------------------------------------------------------
69507
71093
  * Event Calendar Modals
69508
71094
  * Modal overlays for event details and day events list
@@ -69930,7 +71516,7 @@ const containerResponsiveThemeCss = `/*
69930
71516
  }
69931
71517
 
69932
71518
  :where(.theme-scope) .rb-inline-text-accent-contrast {
69933
- color: var(--section-text-color, rgb(var(--tb-text)));
71519
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
69934
71520
  }
69935
71521
 
69936
71522
  :where(.theme-scope) .rb-inline-text-highlight {
@@ -69941,7 +71527,7 @@ const containerResponsiveThemeCss = `/*
69941
71527
  }
69942
71528
 
69943
71529
  :where(.theme-scope) .rb-inline-text-highlight-soft {
69944
- background: color-mix(in oklab, var(--section-text-color, rgb(var(--tb-text))) 14%, transparent);
71530
+ background: color-mix(in oklab, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))) 14%, transparent);
69945
71531
  }
69946
71532
 
69947
71533
  :where(.theme-scope) .rb-inline-text-highlight-accent {
@@ -69960,7 +71546,7 @@ const containerResponsiveThemeCss = `/*
69960
71546
 
69961
71547
  /* Eyebrow - color only (typography via .rb-eyebrow) */
69962
71548
  :where(.theme-scope) :where([data-block="hero"]) .hero-eyebrow:not(.rb-eyebrow-treatment-accent) {
69963
- color: var(--section-text-color, rgb(var(--tb-text)));
71549
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
69964
71550
  }
69965
71551
 
69966
71552
  /* Subheadline - supporting text below headline */
@@ -69970,7 +71556,7 @@ const containerResponsiveThemeCss = `/*
69970
71556
 
69971
71557
  :where(.theme-scope) :where([data-block="hero"]) .hero-subheadline {
69972
71558
  font-size: 1.125rem;
69973
- color: var(--section-supporting-color, var(--section-text-color, rgb(var(--tb-text))));
71559
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
69974
71560
  }
69975
71561
 
69976
71562
  @container rb-site (min-width: 640px) {
@@ -70061,7 +71647,7 @@ const containerResponsiveThemeCss = `/*
70061
71647
 
70062
71648
  /* CTA content/body text */
70063
71649
  :where(.theme-scope) :where([data-block="cta-full"]) .cta-content {
70064
- color: var(--section-supporting-color, rgb(var(--tb-mutedText)));
71650
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
70065
71651
  }
70066
71652
 
70067
71653
  /* CTA button row container */
@@ -70161,7 +71747,7 @@ const containerResponsiveThemeCss = `/*
70161
71747
  /* Form intro text */
70162
71748
  :where(.theme-scope) :where([data-block="form"]) .form-copy-intro {
70163
71749
  font-size: 1rem;
70164
- color: var(--section-text-color, rgb(var(--tb-text)));
71750
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
70165
71751
  }
70166
71752
 
70167
71753
  /* =============================================================================
@@ -70520,6 +72106,10 @@ const containerResponsiveThemeCss = `/*
70520
72106
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.6);
70521
72107
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
70522
72108
  --rb-modal-z-index: 20000;
72109
+ --rb-modal-text: rgb(var(--tb-text, 17 24 39));
72110
+ --rb-modal-heading: rgb(var(--tb-text, 17 24 39));
72111
+ --rb-modal-link: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
72112
+ --rb-modal-supporting: rgb(var(--tb-mutedText, 100 116 139));
70523
72113
  --shop-card-radius: var(--rb-block-radius, var(--radius-card, 0.75rem));
70524
72114
  --shop-control-radius: var(--rb-input-radius, var(--radius-control, 0.375rem));
70525
72115
  }
@@ -70577,6 +72167,11 @@ const containerResponsiveThemeCss = `/*
70577
72167
  /* Product card */
70578
72168
  :where(.theme-scope) .shop__card {
70579
72169
  background: rgb(var(--tb-surface));
72170
+ color: rgb(var(--tb-text, 17 24 39));
72171
+ --rb-surface-text-color: rgb(var(--tb-text, 17 24 39));
72172
+ --rb-surface-heading-color: rgb(var(--tb-text, 17 24 39));
72173
+ --rb-surface-link-color: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
72174
+ --rb-surface-supporting-color: rgb(var(--tb-mutedText, 100 116 139));
70580
72175
  border: 1px solid rgb(var(--tb-border));
70581
72176
  border-radius: var(--shop-card-radius);
70582
72177
  padding: 1.5rem;
@@ -70731,6 +72326,11 @@ const containerResponsiveThemeCss = `/*
70731
72326
  border: 1px solid rgb(var(--tb-border));
70732
72327
  border-radius: var(--shop-card-radius);
70733
72328
  background: rgb(var(--tb-surface));
72329
+ color: rgb(var(--tb-text, 17 24 39));
72330
+ --rb-surface-text-color: rgb(var(--tb-text, 17 24 39));
72331
+ --rb-surface-heading-color: rgb(var(--tb-text, 17 24 39));
72332
+ --rb-surface-link-color: rgb(var(--tb-primary, var(--tb-text, 17 24 39)));
72333
+ --rb-surface-supporting-color: rgb(var(--tb-mutedText, 100 116 139));
70734
72334
  }
70735
72335
 
70736
72336
  :where(.theme-scope) :where([data-block="shop"]) .rb-state-icon--success {
@@ -70803,6 +72403,11 @@ const containerResponsiveThemeCss = `/*
70803
72403
  margin: 0 auto;
70804
72404
  padding: 2rem;
70805
72405
  background: var(--cp-card-bg);
72406
+ color: var(--cp-text);
72407
+ --rb-surface-text-color: var(--cp-text);
72408
+ --rb-surface-heading-color: var(--cp-text);
72409
+ --rb-surface-link-color: var(--cp-primary);
72410
+ --rb-surface-supporting-color: var(--cp-muted);
70806
72411
  border: 1px solid var(--cp-card-border);
70807
72412
  border-radius: var(--cp-card-radius);
70808
72413
  }
@@ -70931,6 +72536,11 @@ const containerResponsiveThemeCss = `/*
70931
72536
  padding: 3rem 2rem;
70932
72537
  text-align: center;
70933
72538
  background: var(--cp-card-bg);
72539
+ color: var(--cp-text);
72540
+ --rb-surface-text-color: var(--cp-text);
72541
+ --rb-surface-heading-color: var(--cp-text);
72542
+ --rb-surface-link-color: var(--cp-primary);
72543
+ --rb-surface-supporting-color: var(--cp-muted);
70934
72544
  border: 1px dashed var(--cp-card-border);
70935
72545
  border-radius: var(--cp-card-radius);
70936
72546
  }
@@ -70943,6 +72553,11 @@ const containerResponsiveThemeCss = `/*
70943
72553
  /* Card */
70944
72554
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card {
70945
72555
  background: var(--cp-card-bg);
72556
+ color: var(--cp-text);
72557
+ --rb-surface-text-color: var(--cp-text);
72558
+ --rb-surface-heading-color: var(--cp-text);
72559
+ --rb-surface-link-color: var(--cp-primary);
72560
+ --rb-surface-supporting-color: var(--cp-muted);
70946
72561
  border: 1px solid var(--cp-card-border);
70947
72562
  border-radius: var(--cp-card-radius);
70948
72563
  padding: 1.25rem;
@@ -71107,6 +72722,11 @@ const containerResponsiveThemeCss = `/*
71107
72722
  /* Table */
71108
72723
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table-wrap {
71109
72724
  background: var(--cp-card-bg);
72725
+ color: var(--cp-text);
72726
+ --rb-surface-text-color: var(--cp-text);
72727
+ --rb-surface-heading-color: var(--cp-text);
72728
+ --rb-surface-link-color: var(--cp-primary);
72729
+ --rb-surface-supporting-color: var(--cp-muted);
71110
72730
  border: 1px solid var(--cp-card-border);
71111
72731
  border-radius: var(--cp-card-radius);
71112
72732
  }
@@ -71668,6 +73288,143 @@ const containerResponsiveThemeCss = `/*
71668
73288
  }
71669
73289
 
71670
73290
 
73291
+ /* =============================================================================
73292
+ * Variant: featured-editorial
73293
+ *
73294
+ * An asymmetric layout: a large featured (spruce-ink) quote card beside a
73295
+ * column of stacked white cards. Renders NO avatars. Colours are palette
73296
+ * tokens only. Node structure is built in testimonialsCarousel.ts.
73297
+ * ============================================================================= */
73298
+
73299
+ /* Section head: heading left, lead-in line to the right; stacks on mobile. */
73300
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-head {
73301
+ display: flex;
73302
+ flex-direction: column;
73303
+ align-items: flex-start;
73304
+ gap: 0.875rem;
73305
+ }
73306
+
73307
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-leadin {
73308
+ max-width: 30rem;
73309
+ }
73310
+
73311
+ @container rb-site (min-width: 768px) {
73312
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
73313
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-head {
73314
+ flex-direction: row;
73315
+ align-items: flex-end;
73316
+ justify-content: space-between;
73317
+ gap: 1.5rem;
73318
+ }
73319
+ }
73320
+ }
73321
+
73322
+ /* Card grid: featured (wider) beside the stacked column. Single column on
73323
+ * small screens. */
73324
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-grid {
73325
+ display: grid;
73326
+ grid-template-columns: minmax(0, 1fr);
73327
+ gap: 1.25rem;
73328
+ align-items: stretch;
73329
+ }
73330
+
73331
+ @container rb-site (min-width: 1024px) {
73332
+ @scope ([data-rb-responsive-mode="container"]) to (:scope [data-rb-responsive-mode]) {
73333
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-grid {
73334
+ grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
73335
+ }
73336
+ }
73337
+ }
73338
+
73339
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-col {
73340
+ display: grid;
73341
+ gap: 1.25rem;
73342
+ align-content: start;
73343
+ }
73344
+
73345
+ /* Base card (white surface) */
73346
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card {
73347
+ display: flex;
73348
+ flex-direction: column;
73349
+ height: 100%;
73350
+ border-radius: var(--rb-block-radius);
73351
+ padding: 1.875rem 1.875rem 1.625rem;
73352
+ background: rgb(var(--tb-surface));
73353
+ border: 1px solid rgba(var(--tb-border), 0.9);
73354
+ box-shadow: 0 1px 2px rgba(var(--tb-shadow, 0 0 0), 0.05);
73355
+ }
73356
+
73357
+ /* Featured (spruce-ink) card */
73358
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature {
73359
+ padding: 2.5rem;
73360
+ background: rgb(var(--tb-primary));
73361
+ border-color: transparent;
73362
+ color: rgb(var(--tb-onPrimary));
73363
+ }
73364
+
73365
+ /* Amber quote mark, oversized serif */
73366
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-qmark {
73367
+ display: block;
73368
+ height: 1.6rem;
73369
+ font-family: var(--font-heading, Georgia, serif);
73370
+ font-style: italic;
73371
+ font-size: 3.375rem;
73372
+ line-height: 0.6;
73373
+ color: rgb(var(--tb-secondary));
73374
+ }
73375
+
73376
+ /* Quote body. The inner <p> is targeted directly (not via :where) so the
73377
+ * serif display font and sizing win over the theme's base paragraph rule. */
73378
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-quote {
73379
+ flex: 1 1 auto;
73380
+ margin-top: 1.25rem;
73381
+ }
73382
+
73383
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-quote p {
73384
+ margin: 0;
73385
+ font-family: var(--font-heading, Georgia, serif);
73386
+ font-size: 1.15rem;
73387
+ line-height: 1.5;
73388
+ color: rgb(var(--tb-text));
73389
+ }
73390
+
73391
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-quote p {
73392
+ color: rgb(var(--tb-onPrimary));
73393
+ font-size: clamp(1.375rem, 2.4vw, 1.6875rem);
73394
+ line-height: 1.42;
73395
+ letter-spacing: -0.01em;
73396
+ }
73397
+
73398
+ /* Attribution: name (bold) + context line, no avatar */
73399
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-meta {
73400
+ display: flex;
73401
+ flex-direction: column;
73402
+ gap: 0.25rem;
73403
+ margin-top: 1.625rem;
73404
+ }
73405
+
73406
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-name {
73407
+ font-weight: 600;
73408
+ font-size: 0.97rem;
73409
+ color: rgb(var(--tb-text));
73410
+ }
73411
+
73412
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-context {
73413
+ font-size: 0.78rem;
73414
+ letter-spacing: 0.02em;
73415
+ color: rgb(var(--tb-mutedText));
73416
+ }
73417
+
73418
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-name {
73419
+ color: rgb(var(--tb-onPrimary));
73420
+ }
73421
+
73422
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-fe-card--feature .rb-testimonials-fe-context {
73423
+ color: rgb(var(--tb-onPrimary));
73424
+ opacity: 0.7;
73425
+ }
73426
+
73427
+
71671
73428
  /* Testimonials carousel tweaks: arrow styling + gutters + equal-height cards */
71672
73429
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-carousel.carousel-root .carousel-nav-btn {
71673
73430
  height: var(--rb-testimonial-carousel-arrow-size);
@@ -72814,7 +74571,7 @@ const containerResponsiveThemeCss = `/*
72814
74571
 
72815
74572
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
72816
74573
  font-size: 1rem;
72817
- color: var(--section-text-color, rgb(var(--tb-text)));
74574
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72818
74575
  opacity: 0.85;
72819
74576
  }
72820
74577
 
@@ -72863,7 +74620,7 @@ const containerResponsiveThemeCss = `/*
72863
74620
  margin-top: 0.75rem;
72864
74621
  font-size: 1rem;
72865
74622
  line-height: 1.6;
72866
- color: var(--section-text-color, rgb(var(--tb-text)));
74623
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72867
74624
  text-align: center;
72868
74625
  }
72869
74626
 
@@ -72945,7 +74702,7 @@ const containerResponsiveThemeCss = `/*
72945
74702
 
72946
74703
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .form-copy-intro,
72947
74704
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .newsletter-copy-subtitle {
72948
- color: var(--section-text-color, rgb(var(--tb-text)));
74705
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72949
74706
  }
72950
74707
 
72951
74708
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .contact-newsletter-info {
@@ -73343,7 +75100,7 @@ const containerResponsiveThemeCss = `/*
73343
75100
 
73344
75101
  :where(.theme-scope) .event-compact-row-title {
73345
75102
  margin: 0;
73346
- color: var(--section-heading-color, rgb(var(--tb-primary, 0 0 0)));
75103
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-primary, var(--tb-text, 17 24 39)))));
73347
75104
  font-family: var(--font-heading, var(--font-body, inherit));
73348
75105
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.3rem);
73349
75106
  font-weight: 400;
@@ -74005,27 +75762,41 @@ const containerResponsiveThemeCss = `/*
74005
75762
  background: rgb(var(--tb-surface));
74006
75763
  }
74007
75764
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 1) {
75765
+ background: rgb(var(--tb-surface));
74008
75766
  color: rgb(var(--tb-onSurface));
75767
+ --rb-surface-text-color: rgb(var(--tb-onSurface));
75768
+ --rb-surface-heading-color: rgb(var(--tb-onSurface));
75769
+ --rb-surface-link-color: rgb(var(--tb-onSurface));
75770
+ --rb-surface-supporting-color: rgb(var(--tb-onSurface));
74009
75771
  }
74010
75772
 
74011
75773
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) > .rb-bg-surface {
74012
75774
  background: rgb(var(--tb-secondary));
74013
75775
  }
74014
75776
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) {
75777
+ background: rgb(var(--tb-secondary));
74015
75778
  color: rgb(var(--tb-onSecondary));
75779
+ --rb-surface-text-color: rgb(var(--tb-onSecondary));
75780
+ --rb-surface-heading-color: rgb(var(--tb-onSecondary));
75781
+ --rb-surface-link-color: rgb(var(--tb-onSecondary));
75782
+ --rb-surface-supporting-color: rgb(var(--tb-onSecondary));
74016
75783
  }
74017
75784
 
74018
75785
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) > .rb-bg-surface {
74019
75786
  background: rgb(var(--tb-primary));
74020
75787
  }
74021
75788
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) {
75789
+ background: rgb(var(--tb-primary));
74022
75790
  color: rgb(var(--tb-onPrimary));
75791
+ --rb-surface-text-color: rgb(var(--tb-onPrimary));
75792
+ --rb-surface-heading-color: rgb(var(--tb-onPrimary));
75793
+ --rb-surface-link-color: rgb(var(--tb-onPrimary));
75794
+ --rb-surface-supporting-color: rgb(var(--tb-onPrimary));
74023
75795
  }
74024
75796
 
74025
- /* Body copy carries an inline muted colour from the block; force it to the
74026
- * card's on-colour so it reads on every block (inline style needs !important). */
75797
+ /* Keep the intended visual hierarchy; the body color itself now resolves via
75798
+ * the nearest surface provider instead of requiring an inline override. */
74027
75799
  :where(.theme-scope) .rb-card-treatment-color-blocked .rb-feature-card-body {
74028
- color: inherit !important;
74029
75800
  opacity: 0.9;
74030
75801
  }
74031
75802
 
@@ -75627,6 +77398,8 @@ const VERTICAL_IDS = [
75627
77398
  "yoga_wellness",
75628
77399
  "fitness_pt",
75629
77400
  "dance_school",
77401
+ "physiotherapy_physical_health",
77402
+ "massage_bodywork",
75630
77403
  "therapist_practitioner",
75631
77404
  "beauty_spa",
75632
77405
  "consultant_coach",
@@ -75662,6 +77435,12 @@ const VERTICAL_BOOKING_PRESETS = [
75662
77435
  preset("dance_school.workshops", "dance_school", "workshop", "Workshop", "Workshops", "One-off workshops, masterclasses, or intensives."),
75663
77436
  preset("dance_school.private_lessons", "dance_school", "appointment", "Private lesson", "Private lessons", "One-to-one lessons or coaching sessions."),
75664
77437
  preset("dance_school.shows", "dance_school", "performance", "Show", "Shows", "Ticketed performances, showcases, and recitals."),
77438
+ preset("physiotherapy_physical_health.appointments", "physiotherapy_physical_health", "appointment", "Appointment", "Appointments", "Assessments, treatments, follow-ups, and rehabilitation sessions."),
77439
+ preset("physiotherapy_physical_health.rehab_classes", "physiotherapy_physical_health", "class", "Rehab class", "Rehab classes", "Regular rehabilitation, mobility, strength, or recovery classes."),
77440
+ preset("physiotherapy_physical_health.workshops", "physiotherapy_physical_health", "workshop", "Workshop", "Workshops", "One-off workshops, talks, or practical group sessions."),
77441
+ preset("massage_bodywork.treatments", "massage_bodywork", "appointment", "Treatment", "Treatments", "Massage treatments, bodywork sessions, and one-to-one appointments."),
77442
+ preset("massage_bodywork.group_sessions", "massage_bodywork", "class", "Group session", "Group sessions", "Regular bodywork, somatic movement, or self-massage sessions."),
77443
+ preset("massage_bodywork.workshops", "massage_bodywork", "workshop", "Workshop", "Workshops", "One-off bodywork, self-massage, or somatic practice workshops."),
75665
77444
  preset("therapist_practitioner.appointments", "therapist_practitioner", "appointment", "Appointment", "Appointments", "Sessions, consultations, treatments, or assessments."),
75666
77445
  preset("therapist_practitioner.workshops", "therapist_practitioner", "workshop", "Workshop", "Workshops", "One-off group workshops, talks, or wellbeing sessions."),
75667
77446
  preset("therapist_practitioner.retreats", "therapist_practitioner", "retreat", "Retreat", "Retreats", "Multi-day retreats or immersive group experiences."),
@@ -149607,7 +151386,7 @@ function buildDisplayFilterParams(display) {
149607
151386
  filterVenueId: display.filterVenueId
149608
151387
  });
149609
151388
  }
149610
- var EventCalendarClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
151389
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
149611
151390
  var init_EventCalendar_client = __esmMin((() => {
149612
151391
  init_EventCalendar_interactive();
149613
151392
  init_EventListing_client();
@@ -149620,6 +151399,7 @@ var init_EventCalendar_client = __esmMin((() => {
149620
151399
  init_EventModalContext();
149621
151400
  init_EventModals();
149622
151401
  init_WeekAgendaView();
151402
+ init_WeekBoardView();
149623
151403
  init_WeekTimetableView();
149624
151404
  init_buttons();
149625
151405
  init_listOptions();
@@ -149657,8 +151437,20 @@ var init_EventCalendar_client = __esmMin((() => {
149657
151437
  });
149658
151438
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
149659
151439
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
151440
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
149660
151441
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
149661
151442
  };
151443
+ EventCalendarWeekBoardClient = ({ display }) => {
151444
+ const days = useMemo(() => getWeekCalendarDayTuple(/* @__PURE__ */ new Date(), display.startOfWeek), [display.startOfWeek]);
151445
+ return /* @__PURE__ */ jsx(WeekBoardView, {
151446
+ days,
151447
+ events: [...display.events],
151448
+ showCapacity: display.showCapacity,
151449
+ emptyMessage: display.emptyMessage,
151450
+ ctaLabel: display.buttonText,
151451
+ buttonVariant: display.buttonVariant
151452
+ });
151453
+ };
149662
151454
  EventCalendarTimetableClient = ({ render }) => {
149663
151455
  const { display, hydration } = render;
149664
151456
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
@@ -154414,7 +156206,7 @@ var SimpleCache = class {
154414
156206
  * 1. This constant
154415
156207
  * 2. The "version" field in package.json
154416
156208
  */
154417
- const SDK_VERSION = "0.104.0";
156209
+ const SDK_VERSION = "0.104.3";
154418
156210
  //#endregion
154419
156211
  //#region src/client/error.ts
154420
156212
  let _Symbol$for;