@riverbankcms/sdk 0.104.1 → 0.104.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/{PreviewEditorSidebar-CmaPXdKu.mjs → PreviewEditorSidebar-CBMhU9p_.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-C5xRTh2b.mjs → PreviewEditorUI-C5KEw4M8.mjs} +2 -2
  3. package/dist/{SdkPreviewModeRuntime-Eks51NcN.mjs → SdkPreviewModeRuntime-Iq12HjL7.mjs} +1142 -177
  4. package/dist/{SiteChromeCustomizeContext-Bt8zb3qu.mjs → SiteChromeCustomizeContext-Cx0NMdyv.mjs} +1640 -877
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -0
  6. package/dist/_dts/blocks/src/primitives/layout/Grid.d.ts +12 -8
  7. package/dist/_dts/blocks/src/system/blocks/events/event-calendar.d.ts +3 -0
  8. package/dist/_dts/blocks/src/system/blocks/events/shared/layout.d.ts +11 -1
  9. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +7 -1
  10. package/dist/_dts/blocks/src/system/constants/events.d.ts +1 -1
  11. package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +12 -0
  12. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +2 -2
  13. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +14 -0
  14. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +33 -0
  15. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/WeekBoardView.d.ts +28 -0
  16. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/eventCapacity.d.ts +32 -0
  17. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +1 -0
  18. package/dist/_dts/blocks/src/system/runtime/nodes/svg.d.ts +77 -0
  19. package/dist/_dts/blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.d.ts +2 -0
  20. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +3 -40
  21. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +14 -0
  22. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +11 -0
  23. package/dist/_dts/core/src/branded.d.ts +5 -0
  24. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +18 -0
  25. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +2 -2
  26. package/dist/_dts/sdk/src/version.d.ts +1 -1
  27. package/dist/_dts/theme-core/src/ThemeScope.d.ts +1 -1
  28. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +29 -0
  29. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +6 -0
  30. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  31. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +20 -0
  32. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  33. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +4 -0
  34. package/dist/_dts/theme-core/src/buttons/types.d.ts +34 -0
  35. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  36. package/dist/_dts/theme-core/src/gradients/types.d.ts +27 -3
  37. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +51 -15
  38. package/dist/_dts/theme-core/src/palette/curated/brand-led.d.ts +13 -0
  39. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +12 -0
  40. package/dist/_dts/theme-core/src/palette/historicalThemePalette.d.ts +44 -0
  41. package/dist/_dts/theme-core/src/palette/index.d.ts +1 -0
  42. package/dist/_dts/theme-core/src/palette/legacySelection.d.ts +13 -2
  43. package/dist/_dts/theme-core/src/palette/persistenceReadSource.d.ts +17 -2
  44. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +3 -4
  45. package/dist/_dts/theme-core/src/runtime/themeCssVarNames.d.ts +1 -0
  46. package/dist/_dts/theme-core/src/schema.d.ts +108 -26
  47. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +2 -1
  48. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +50 -1
  49. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +2 -2
  50. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +4 -2
  51. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +56 -1
  52. package/dist/_dts/theme-core/src/site-styles/typographyPresets.d.ts +16 -1
  53. package/dist/_dts/theme-core/src/status/index.d.ts +0 -1
  54. package/dist/_dts/theme-core/src/surfaces/foregroundContract.d.ts +19 -0
  55. package/dist/_dts/theme-core/src/surfaces/foregroundRoles.d.ts +9 -0
  56. package/dist/_dts/theme-core/src/surfaces/index.d.ts +2 -0
  57. package/dist/_dts/ui/src/button.d.ts +1 -1
  58. package/dist/cli/index.mjs +1558 -468
  59. package/dist/client/{DiscountCodeDisclosure-Dit2aItR.mjs → DiscountCodeDisclosure-BXM73_E5.mjs} +1 -1
  60. package/dist/client/{EventCombined.client-BnREyCjf.mjs → EventCombined.client-DT5elP7j.mjs} +4 -4
  61. package/dist/client/{EventListing.client-0uHld51x.mjs → EventListing.client-pTYGfV9C.mjs} +2 -2
  62. package/dist/client/{LeafletStaticMap-DJcvSfmj.mjs → LeafletStaticMap-dQrhlUe3.mjs} +1 -1
  63. package/dist/client/{MagicLinkForm-EAsIktfw.mjs → MagicLinkForm-u6Dul4j5.mjs} +2 -2
  64. package/dist/client/{StepIndicator-CRR17tYI.mjs → StepIndicator-nWqineJ2.mjs} +2 -2
  65. package/dist/client/{accordion-B47HIuuH.mjs → accordion-CSJcTUyH.mjs} +1 -1
  66. package/dist/client/{bookingForm-I1E-8F9P.mjs → bookingForm-C73wOuVa.mjs} +6 -6
  67. package/dist/client/bookings.mjs +137 -1
  68. package/dist/client/{buttons-BbPn8OKA.mjs → buttons-DfYyqt8C.mjs} +138 -2
  69. package/dist/client/{carousel-OlM7SyBs.mjs → carousel-fMBb0JSc.mjs} +1 -1
  70. package/dist/client/{cart-BKpG5jz6.mjs → cart-BtaCwT3S.mjs} +3 -3
  71. package/dist/client/{checkout-Dmmr6qoU.mjs → checkout-DkTwZSnh.mjs} +3 -3
  72. package/dist/client/client.mjs +2327 -542
  73. package/dist/client/{colorStyles-DuW4Fjqd.mjs → colorStyles-Wyl6JujD.mjs} +45 -4
  74. package/dist/client/{courseRegistration-CflZiqGk.mjs → courseRegistration-DnLmapJu.mjs} +7 -7
  75. package/dist/client/{eventCalendar-BvoLWcp-.mjs → eventCalendar-BvLOc9KY.mjs} +165 -5
  76. package/dist/client/{eventCombined-DsrO8t_t.mjs → eventCombined-kShgJPQr.mjs} +2 -2
  77. package/dist/client/{eventDetails-C3hxgcJm.mjs → eventDetails-C5NTM0Vo.mjs} +3 -3
  78. package/dist/client/{eventListing-C-hb237X.mjs → eventListing-B82ZdKP6.mjs} +2 -2
  79. package/dist/client/{eventRegistration-B0gyzDGi.mjs → eventRegistration-qJVFqBWo.mjs} +7 -7
  80. package/dist/client/{form-C_RUi6oJ.mjs → form-BvAcKiuu.mjs} +2 -2
  81. package/dist/client/{headerSection-IKQiD2U0.mjs → headerSection-NvAiEHAg.mjs} +3 -3
  82. package/dist/client/hooks.mjs +1034 -356
  83. package/dist/client/{locationMap-8ZBrMzRJ.mjs → locationMap-D0j52xfI.mjs} +3 -3
  84. package/dist/client/{media-CZJKL7fi.mjs → media-BCW_g2cQ.mjs} +1 -1
  85. package/dist/client/{newsletterForm-CYk3ucwj.mjs → newsletterForm-B8_i93qH.mjs} +2 -2
  86. package/dist/client/{pricing-B5GmvfIH.mjs → pricing-DIYnyHOk.mjs} +1 -1
  87. package/dist/client/{productDetail-BjS2Dqzo.mjs → productDetail-w0eAHkuQ.mjs} +3 -3
  88. package/dist/client/{productList-BOHvC8My.mjs → productList-Vsguq5Xt.mjs} +3 -3
  89. package/dist/client/{propsDecoder-WS6UEJwZ.mjs → propsDecoder-CD2pJ1WB.mjs} +37 -2
  90. package/dist/client/rendering/client.mjs +1722 -760
  91. package/dist/client/rendering/islands.mjs +19 -19
  92. package/dist/client/rendering.mjs +2303 -518
  93. package/dist/client/{shop-CON03-wN.mjs → shop-Dgxs-Q8F.mjs} +6 -6
  94. package/dist/client/{shop-commerce-DlqrFgH8.mjs → shop-commerce-DJAhsTaT.mjs} +6 -6
  95. package/dist/client/{shop-commerce-store-l74-Kne6.mjs → shop-commerce-store-CfCXltXW.mjs} +1 -1
  96. package/dist/client/{shopShared-CQheEXSg.mjs → shopShared-CmDcPXUt.mjs} +2 -2
  97. package/dist/client/{useDiscountCodeUi-v6OluyWl.mjs → useDiscountCodeUi-CirrT2bM.mjs} +1 -1
  98. package/dist/client/{useEventFilters-BqSTcNOf.mjs → useEventFilters-CNZxlCcO.mjs} +5 -5
  99. package/dist/client/{usePolling-DMfADjIF.mjs → usePolling-Baks_iBI.mjs} +2 -2
  100. package/dist/preview-next/client/runtime.mjs +3 -3
  101. package/dist/{sdk-runtime-BUmJ0DaT.mjs → sdk-runtime-BfNiFeNJ.mjs} +1 -1
  102. package/dist/{separator-Dd-JYok7.mjs → separator-BhAR_Xmf.mjs} +1 -1
  103. package/dist/server/components.mjs +2293 -531
  104. package/dist/server/config-validation.mjs +1040 -357
  105. package/dist/server/config.mjs +1040 -357
  106. package/dist/server/data.mjs +1034 -356
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/server/next.mjs +2296 -534
  109. package/dist/server/page-converter.mjs +1018 -324
  110. package/dist/server/prebuild.mjs +1 -1
  111. package/dist/server/rendering/server.mjs +2278 -521
  112. package/dist/server/rendering.mjs +2293 -531
  113. package/dist/server/routing.mjs +1092 -338
  114. package/dist/server/server.mjs +1016 -338
  115. package/dist/server/theme-bridge.mjs +1240 -77
  116. package/dist/server/theme.mjs +165 -5
  117. package/dist/styles/index.css +617 -34
  118. package/package.json +1 -1
  119. package/dist/_dts/blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.d.ts +0 -2
  120. package/dist/_dts/theme-core/src/status/contextualColors.d.ts +0 -6
@@ -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",
@@ -15880,6 +15957,7 @@ var curatedPalettes, curatedPalettesById, init_curated = __esmMin((() => {
15880
15957
  brandLedWarm,
15881
15958
  brandLedJewel,
15882
15959
  brandLedBurgundyGold,
15960
+ brandLedSpruce,
15883
15961
  warmNeutralClay,
15884
15962
  warmNeutralCream,
15885
15963
  warmNeutralSoftEarth,
@@ -15996,6 +16074,7 @@ var init_palette$1 = __esmMin((() => {
15996
16074
  init_expandPalette();
15997
16075
  init_generateCssVars();
15998
16076
  init_generateShades();
16077
+ init_historicalThemePalette();
15999
16078
  init_neutralScale();
16000
16079
  init_types$16();
16001
16080
  init_utils$5();
@@ -16465,7 +16544,7 @@ function asSpecialVariantId(value) {
16465
16544
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
16466
16545
  return value;
16467
16546
  }
16468
- 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;
16469
16548
  var init_types$14 = __esmMin((() => {
16470
16549
  init_themeColorTokens();
16471
16550
  VARIANT_ROLES = [
@@ -16625,6 +16704,10 @@ var init_types$14 = __esmMin((() => {
16625
16704
  widthClass: z$1.string(),
16626
16705
  colorToken: themeColorTokenSchema
16627
16706
  });
16707
+ buttonVariantAffordanceSchema = z$1.object({
16708
+ iconId: z$1.string().min(1),
16709
+ colorToken: themeColorTokenSchema.optional()
16710
+ });
16628
16711
  variantShadowSchema = z$1.object({
16629
16712
  elevation: z$1.enum([
16630
16713
  "none",
@@ -16665,7 +16748,8 @@ var init_types$14 = __esmMin((() => {
16665
16748
  border: buttonBorderSchema.optional(),
16666
16749
  hoverBackgroundToken: z$1.string().optional(),
16667
16750
  effects: variantEffectsSchema.optional(),
16668
- sizes: variantSizeOverridesSchema.optional()
16751
+ sizes: variantSizeOverridesSchema.optional(),
16752
+ affordance: buttonVariantAffordanceSchema.optional()
16669
16753
  });
16670
16754
  buttonSystemSchema = z$1.object({
16671
16755
  global: buttonGlobalSettingsSchema,
@@ -17215,6 +17299,132 @@ var init_editorial_link = __esmMin((() => {
17215
17299
  });
17216
17300
  }));
17217
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
17218
17428
  //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
17219
17429
  var inkStamp;
17220
17430
  var init_ink_stamp = __esmMin((() => {
@@ -17981,6 +18191,7 @@ var init_personalities = __esmMin((() => {
17981
18191
  init_confident_chip();
17982
18192
  init_earth_pill();
17983
18193
  init_editorial_link();
18194
+ init_flat_ink();
17984
18195
  init_ink_stamp();
17985
18196
  init_joy_stamp();
17986
18197
  init_ornate_ritual();
@@ -17995,6 +18206,7 @@ var init_personalities = __esmMin((() => {
17995
18206
  editorialLink,
17996
18207
  pebble,
17997
18208
  inkStamp,
18209
+ flatInk,
17998
18210
  brushedWash,
17999
18211
  showtimePill,
18000
18212
  joyStamp,
@@ -18464,6 +18676,50 @@ function getCompatibleHeaderStyleIds(layoutId) {
18464
18676
  return isHeaderStyleCompatibleWithLayout(getHeaderStyleOrThrow(styleId), layoutId);
18465
18677
  });
18466
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
+ }
18467
18723
  function themedHeaderShadow(theme) {
18468
18724
  switch (theme.shadow.elevation) {
18469
18725
  case "none": return;
@@ -18563,6 +18819,38 @@ function cleanBaseHeader(theme) {
18563
18819
  ctaGap: "default"
18564
18820
  };
18565
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
+ }
18566
18854
  function serifLineHeader(theme) {
18567
18855
  return {
18568
18856
  ...baseHeader(theme),
@@ -19141,6 +19429,13 @@ var init_headerLooks = __esmMin((() => {
19141
19429
  styleId: asHeaderStyleId("minimal")
19142
19430
  }
19143
19431
  },
19432
+ {
19433
+ lookId: asHeaderLookId("classic-centered-nav"),
19434
+ selection: {
19435
+ layoutId: asHeaderLayoutId("classic"),
19436
+ styleId: asHeaderStyleId("fine-line")
19437
+ }
19438
+ },
19144
19439
  {
19145
19440
  lookId: asHeaderLookId("brand-solid"),
19146
19441
  selection: {
@@ -19207,6 +19502,21 @@ var init_headerLooks = __esmMin((() => {
19207
19502
  logoAccommodations: inlineClassicLogoAccommodations,
19208
19503
  compile: cleanBaseHeader
19209
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
+ },
19210
19520
  {
19211
19521
  id: asHeaderLookId("brand-solid"),
19212
19522
  label: "Brand solid",
@@ -19767,7 +20077,7 @@ function defineTypographyPreset(preset) {
19767
20077
  id: asTypographyPresetId(preset.id)
19768
20078
  };
19769
20079
  }
19770
- 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;
19771
20081
  var init_typographyPresets = __esmMin((() => {
19772
20082
  bodyReadablePolicy = {
19773
20083
  recommendedCategories: ["sans-serif", "serif"],
@@ -20129,6 +20439,49 @@ var init_typographyPresets = __esmMin((() => {
20129
20439
  },
20130
20440
  scale: "balanced"
20131
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
+ };
20132
20485
  typographyPresets = [
20133
20486
  defineTypographyPreset({
20134
20487
  id: "typography-preset:modern-sans",
@@ -20388,6 +20741,32 @@ var init_typographyPresets = __esmMin((() => {
20388
20741
  }
20389
20742
  }
20390
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
20391
20770
  })
20392
20771
  ];
20393
20772
  new Map(typographyPresets.map((preset) => [preset.id, preset]));
@@ -22106,6 +22485,28 @@ var init_generateDefaultButtonSystem = __esmMin((() => {
22106
22485
  "high"
22107
22486
  ];
22108
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
+ }));
22109
22510
  //#endregion
22110
22511
  //#region ../theme-core/src/buttons/generateButtonCss.ts
22111
22512
  function rule(selector, declarations) {
@@ -22184,10 +22585,40 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
22184
22585
  out.push(variantFocusVisibleRule(variantId, themeId));
22185
22586
  const effects = variantEffectsCss(variant, themeId, tokens, theme);
22186
22587
  if (effects) out.push({ raw: effects });
22588
+ const affordance = variantAffordanceRule(variant, selector, tokens);
22589
+ if (affordance) out.push(affordance);
22187
22590
  out.push(...variantDisabledRules(variantId, themeId));
22188
22591
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
22189
22592
  return out;
22190
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
+ }
22191
22622
  function parseButtonVariantIdForCss(value) {
22192
22623
  const variantId = parseThemeButtonVariantId(value);
22193
22624
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
@@ -22334,7 +22765,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
22334
22765
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
22335
22766
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
22336
22767
  }
22337
- var BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
22768
+ var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
22338
22769
  var init_generateButtonCss = __esmMin((() => {
22339
22770
  init_types$14();
22340
22771
  init_classNames();
@@ -22343,6 +22774,8 @@ var init_generateButtonCss = __esmMin((() => {
22343
22774
  init_generateEffectsCSS();
22344
22775
  init_constants$2();
22345
22776
  init_generateDefaultButtonSystem();
22777
+ init_affordanceIcons();
22778
+ AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
22346
22779
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
22347
22780
  LETTER_SPACING_MAP = {
22348
22781
  tight: "-0.025em",
@@ -22369,6 +22802,7 @@ var init_buttons = __esmMin((() => {
22369
22802
  init_types$14();
22370
22803
  init_classNames();
22371
22804
  init_generateButtonCss();
22805
+ init_affordanceIcons();
22372
22806
  init_generateDefaultButtonSystem();
22373
22807
  init_constants$2();
22374
22808
  init_presets();
@@ -22609,21 +23043,80 @@ function generateDefaultCardSystem(theme) {
22609
23043
  }
22610
23044
  var init_generateDefaultCardSystem = __esmMin((() => {}));
22611
23045
  //#endregion
22612
- //#region ../theme-core/src/status/contextualColors.ts
22613
- function statusMutedColorValue() {
22614
- 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)`;
22615
23081
  }
22616
- function statusMutedColorDeclaration() {
22617
- 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
+ };
22618
23091
  }
22619
- function contextualMutedStatusColorDeclaration(value) {
22620
- 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]}`)];
22621
23095
  }
22622
- var STATUS_MUTED_COLOR_VAR, DEFAULT_STATUS_MUTED_COLOR, SURFACE_MUTED_STATUS_COLOR;
22623
- var init_contextualColors = __esmMin((() => {
22624
- STATUS_MUTED_COLOR_VAR = "--rb-status-muted-color";
22625
- DEFAULT_STATUS_MUTED_COLOR = "rgb(var(--tb-mutedText))";
22626
- 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();
22627
23120
  }));
22628
23121
  //#endregion
22629
23122
  //#region ../theme-core/src/cards/generateCardCss.ts
@@ -22670,8 +23163,10 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
22670
23163
  const direction = GRADIENT_DIRECTION_MAP$1[variant.background.direction] || "to right";
22671
23164
  rules.push(`background: linear-gradient(${direction}, ${fromColor}, ${toColor})`);
22672
23165
  } else rules.push(`background: transparent`);
22673
- if (variant.foregroundToken) rules.push(`color: ${tokens.getColor(variant.foregroundToken)}`);
22674
- 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
+ }
22675
23170
  if (variant.accentEdge) {
22676
23171
  const side = ACCENT_EDGE_SIDE_MAP$1[variant.accentEdge.edge];
22677
23172
  const width = ACCENT_EDGE_WIDTH_MAP$1[variant.accentEdge.width];
@@ -22709,7 +23204,7 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
22709
23204
  init_resolver$1();
22710
23205
  init_constants$1();
22711
23206
  init_generateDefaultCardSystem();
22712
- init_contextualColors();
23207
+ init_surfaces();
22713
23208
  PER_CORNER_RADIUS_MAP$1 = {
22714
23209
  square: "0",
22715
23210
  soft: "0.5rem",
@@ -22744,7 +23239,9 @@ var PER_CORNER_RADIUS_MAP$1, ACCENT_EDGE_WIDTH_MAP$1, ACCENT_EDGE_SIDE_MAP$1, CO
22744
23239
  pill: "1.5rem"
22745
23240
  };
22746
23241
  }));
22747
- var init_core$1 = __esmMin((() => {}));
23242
+ var init_core$1 = __esmMin((() => {
23243
+ init_surfaces();
23244
+ }));
22748
23245
  //#endregion
22749
23246
  //#region ../theme-core/src/cards/index.ts
22750
23247
  var init_cards = __esmMin((() => {
@@ -23037,16 +23534,22 @@ var init_types$9 = __esmMin((() => {
23037
23534
  /**
23038
23535
  * Gradient configuration types and schemas
23039
23536
  */
23040
- var gradientStopSchema, gradientConfigSchema;
23537
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
23041
23538
  var init_types$8 = __esmMin((() => {
23042
23539
  init_themeColorTokens();
23043
23540
  gradientStopSchema = z$1.object({
23044
23541
  color: themeColorTokenSchema,
23045
23542
  position: z$1.number().min(0).max(100)
23046
23543
  });
23544
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
23047
23545
  gradientConfigSchema = z$1.object({
23048
- type: z$1.enum(["linear", "radial"]),
23546
+ type: z$1.enum([
23547
+ "linear",
23548
+ "radial",
23549
+ "conic"
23550
+ ]).default("linear"),
23049
23551
  angle: z$1.number().min(0).max(360).optional(),
23552
+ shape: radialGradientShapeSchema.optional(),
23050
23553
  position: z$1.string().optional(),
23051
23554
  stops: z$1.array(gradientStopSchema).min(2)
23052
23555
  });
@@ -23491,9 +23994,12 @@ function parseToken(source) {
23491
23994
  if (parts.kind === "invalid") return { token: source };
23492
23995
  return {
23493
23996
  token: parts.token,
23494
- alpha: parts.opacityPercent === null ? void 0 : parts.opacityPercent / 100
23997
+ opacityPercent: parts.opacityPercent === null ? void 0 : parts.opacityPercent
23495
23998
  };
23496
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
+ }
23497
24003
  /**
23498
24004
  * Converts a theme color token to a CSS rgb value.
23499
24005
  * This is the primary function for applying theme colors to CSS properties.
@@ -23507,11 +24013,26 @@ function parseToken(source) {
23507
24013
  * rgbColorValue('raw:transparent') // => 'transparent'
23508
24014
  */
23509
24015
  function rgbColorValue(token) {
23510
- const { token: baseToken, alpha, raw } = parseToken(token);
24016
+ const { token: baseToken, opacityPercent, raw } = parseToken(token);
23511
24017
  if (raw) return raw;
23512
24018
  const cssVar = `${COLOR_VAR_PREFIX}${baseToken}`;
23513
- if (alpha === void 0) return `rgb(var(${cssVar}))`;
23514
- 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})`;
23515
24036
  }
23516
24037
  /**
23517
24038
  * Creates a backgroundColor style object from a theme token.
@@ -23529,6 +24050,9 @@ function backgroundColorStyle(token) {
23529
24050
  * @returns CSSProperties with color
23530
24051
  */
23531
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) };
23532
24056
  return { color: rgbColorValue(token) };
23533
24057
  }
23534
24058
  /**
@@ -23564,10 +24088,16 @@ function mergeStyles(...styles) {
23564
24088
  }
23565
24089
  return Object.keys(merged).length ? merged : void 0;
23566
24090
  }
23567
- var COLOR_VAR_PREFIX;
24091
+ var COLOR_VAR_PREFIX, SURFACE_TEXT_ROLE_BY_TOKEN;
23568
24092
  var init_colorStyles = __esmMin((() => {
24093
+ init_surfaces();
23569
24094
  init_colorTokenParts();
23570
24095
  COLOR_VAR_PREFIX = "--tb-";
24096
+ SURFACE_TEXT_ROLE_BY_TOKEN = {
24097
+ text: "text",
24098
+ heading: "heading",
24099
+ mutedText: "supporting"
24100
+ };
23571
24101
  }));
23572
24102
  //#endregion
23573
24103
  //#region ../theme-core/src/utils/tokenOrColor.ts
@@ -23674,7 +24204,7 @@ var init_tokenOrColor = __esmMin((() => {
23674
24204
  "white",
23675
24205
  "yellow"
23676
24206
  ]);
23677
- })), 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;
23678
24208
  var init_schema = __esmMin((() => {
23679
24209
  init_media$2();
23680
24210
  init_buttons();
@@ -23954,6 +24484,7 @@ var init_schema = __esmMin((() => {
23954
24484
  "majorThird",
23955
24485
  "perfectFourth"
23956
24486
  ]);
24487
+ eyebrowTypographyStyleSchema = z$1.object({ family: z$1.string().min(1) });
23957
24488
  typographySchema = z$1.object({
23958
24489
  body: bodyTypographyStyleSchema,
23959
24490
  headings: z$1.object({
@@ -23966,7 +24497,8 @@ var init_schema = __esmMin((() => {
23966
24497
  h6: headingTypographyOverridesSchema.optional()
23967
24498
  }),
23968
24499
  scale: typographyScaleSchema,
23969
- proseLinkStyle: proseLinkStyleSchema.optional()
24500
+ proseLinkStyle: proseLinkStyleSchema.optional(),
24501
+ eyebrow: eyebrowTypographyStyleSchema.optional()
23970
24502
  });
23971
24503
  spaceSchema = z$1.enum([
23972
24504
  "comfortable",
@@ -23991,7 +24523,8 @@ var init_schema = __esmMin((() => {
23991
24523
  "soft",
23992
24524
  "hard"
23993
24525
  ]).nullable(),
23994
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
24526
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
24527
+ colorToken: themeColorTokenSchema.optional()
23995
24528
  });
23996
24529
  border = z$1.object({
23997
24530
  width: z$1.enum([
@@ -24232,6 +24765,7 @@ var init_schema = __esmMin((() => {
24232
24765
  navWeight: navFontWeight.default("medium"),
24233
24766
  navTypography: z$1.enum(["body", "heading"]).optional(),
24234
24767
  navTextSize: navLinkStyleSchema.shape.textSize,
24768
+ navPlacement: z$1.enum(["end", "center"]).optional(),
24235
24769
  container: headerContainerSchema,
24236
24770
  border: headerBorderSchema,
24237
24771
  shadow: componentShadowSchema.optional(),
@@ -24990,7 +25524,8 @@ var init_curatedSiteStyles = __esmMin((() => {
24990
25524
  "site-style:bold-launch",
24991
25525
  "site-style:south-west-twerk-school",
24992
25526
  "site-style:kirtan-ornate",
24993
- "site-style:original-joy"
25527
+ "site-style:original-joy",
25528
+ "site-style:fulcrum"
24994
25529
  ];
24995
25530
  quietBudget = {
24996
25531
  accentDensity: "low",
@@ -26202,6 +26737,104 @@ var init_curatedSiteStyles = __esmMin((() => {
26202
26737
  buttonChoice("showtime-pill")
26203
26738
  ],
26204
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
+ ]
26205
26838
  })
26206
26839
  ];
26207
26840
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
@@ -28480,7 +29113,7 @@ var init_themeColorResolution = __esmMin((() => {
28480
29113
  init_tokenOrColor();
28481
29114
  }));
28482
29115
  //#endregion
28483
- //#region ../blocks/src/system/transforms/registry/_utils/sectionForegroundStyles.ts
29116
+ //#region ../blocks/src/system/transforms/registry/_utils/surfaceForegroundStyles.ts
28484
29117
  function readColorToken(input, key) {
28485
29118
  const value = input[key];
28486
29119
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
@@ -28489,20 +29122,20 @@ function resolveOptionalForegroundColor(value, context) {
28489
29122
  if (!value) return null;
28490
29123
  return resolveBackgroundColorValue(value, context);
28491
29124
  }
28492
- function resolveSectionForegroundStyles(value, context) {
29125
+ function resolveSurfaceForegroundStyles(value, context) {
28493
29126
  if (!value || typeof value !== "object") return {};
28494
29127
  const input = value;
28495
29128
  const resolvedText = resolveOptionalForegroundColor(readColorToken(input, "textColor"), context);
28496
29129
  if (!resolvedText) return {};
28497
- return {
28498
- color: resolvedText,
28499
- "--section-text-color": resolvedText,
28500
- "--section-heading-color": resolveOptionalForegroundColor(readColorToken(input, "headingColor"), context) ?? resolvedText,
28501
- "--section-link-color": resolveOptionalForegroundColor(readColorToken(input, "linkColor"), context) ?? resolvedText,
28502
- "--section-supporting-color": resolveOptionalForegroundColor(readColorToken(input, "supportingColor"), context) ?? resolvedText
28503
- };
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
+ }) };
28504
29136
  }
28505
- var init_sectionForegroundStyles = __esmMin((() => {
29137
+ var init_surfaceForegroundStyles = __esmMin((() => {
29138
+ init_surfaces();
28506
29139
  init_themeColorResolution();
28507
29140
  }));
28508
29141
  //#endregion
@@ -28534,7 +29167,7 @@ function isTileTreatment(value) {
28534
29167
  function isEventListTreatment(value) {
28535
29168
  return typeof value === "string" && eventListTreatmentSet.has(value);
28536
29169
  }
28537
- 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;
28538
29171
  var init_boxStyles = __esmMin((() => {
28539
29172
  init_core();
28540
29173
  init_spacing();
@@ -28542,8 +29175,7 @@ var init_boxStyles = __esmMin((() => {
28542
29175
  init_colorStyles();
28543
29176
  init_cards();
28544
29177
  init_blockColorTokens();
28545
- init_themeColorResolution();
28546
- init_sectionForegroundStyles();
29178
+ init_surfaceForegroundStyles();
28547
29179
  spacingTransform = {
28548
29180
  id: "boxStyles.spacing",
28549
29181
  kind: "string",
@@ -28769,45 +29401,11 @@ var init_boxStyles = __esmMin((() => {
28769
29401
  }, context);
28770
29402
  }
28771
29403
  };
28772
- sectionTextColorStyleTransform = {
28773
- id: "sectionStyles.resolveTextColorStyle",
28774
- kind: "formatter",
28775
- summary: "Resolve section text color token into a style object",
28776
- run: (value, options, context) => {
28777
- const fallbackToken = options?.fallbackToken;
28778
- if (typeof value === "string" && value.trim()) {
28779
- const colorValue = resolveBackgroundColorValue(value.trim(), context);
28780
- return {
28781
- color: colorValue,
28782
- "--section-text-color": colorValue
28783
- };
28784
- }
28785
- if (typeof fallbackToken === "string" && fallbackToken.trim()) {
28786
- const colorValue = resolveBackgroundColorValue(fallbackToken.trim(), context);
28787
- return {
28788
- color: colorValue,
28789
- "--section-text-color": colorValue
28790
- };
28791
- }
28792
- return {};
28793
- }
28794
- };
28795
- sectionHeadingColorStyleTransform = {
28796
- id: "sectionStyles.resolveHeadingColorStyle",
28797
- kind: "formatter",
28798
- summary: "Resolve section heading color token into a style object",
28799
- run: (value, options, context) => {
28800
- const fallbackToken = options?.fallbackToken;
28801
- if (typeof value === "string" && value.trim()) return { "--section-heading-color": resolveBackgroundColorValue(value.trim(), context) };
28802
- if (typeof fallbackToken === "string" && fallbackToken.trim()) return { "--section-heading-color": resolveBackgroundColorValue(fallbackToken.trim(), context) };
28803
- return {};
28804
- }
28805
- };
28806
29404
  sectionColorsStyleTransform = {
28807
29405
  id: "sectionStyles.resolveColorsStyle",
28808
29406
  kind: "formatter",
28809
- summary: "Resolve section foreground colors into a style object",
28810
- 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)
28811
29409
  };
28812
29410
  GAP_CLASS_MAP = {
28813
29411
  none: "rb-gap-semantic-none",
@@ -28855,8 +29453,6 @@ var init_boxStyles = __esmMin((() => {
28855
29453
  sectionClassNameTransform,
28856
29454
  containerStylesResolveClassName,
28857
29455
  containerStylesResolveBoxClassName,
28858
- sectionTextColorStyleTransform,
28859
- sectionHeadingColorStyleTransform,
28860
29456
  sectionColorsStyleTransform,
28861
29457
  semanticGapTransform,
28862
29458
  semanticGapValueTransform
@@ -29692,7 +30288,29 @@ var init_ctaRow = __esmMin((() => {
29692
30288
  fields: [createCtasRepeater({
29693
30289
  label: "Calls to action",
29694
30290
  itemLabel: "CTA",
29695
- 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
+ ] }
29696
30314
  })],
29697
30315
  layout: [ctaRow({
29698
30316
  collectionPath: "content.ctas",
@@ -29995,6 +30613,55 @@ function buildHighlightLayout() {
29995
30613
  function buildGridCardsLayout(className) {
29996
30614
  return el("div", { className }, buildResponsiveGridCards());
29997
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
+ }
29998
30665
  var grid$4, testimonialsCarouselFragment;
29999
30666
  var init_testimonialsCarousel = __esmMin((() => {
30000
30667
  init_types$5();
@@ -33819,7 +34486,7 @@ const defaultLayout = styledSection({
33819
34486
  children: styledContainer({
33820
34487
  baseClassName: "rb-relative rb-isolate",
33821
34488
  children: stack({
33822
- gap: "xl",
34489
+ gap: "lg",
33823
34490
  className: "rb-w-full rb-max-w-4xl rb-mx-auto"
33824
34491
  }, [headingLayout, accordionLayout])
33825
34492
  }),
@@ -33836,7 +34503,7 @@ const questionColumnsLayout = styledSection({
33836
34503
  children: styledContainer({
33837
34504
  baseClassName: "rb-relative rb-isolate",
33838
34505
  children: stack({
33839
- gap: "xl",
34506
+ gap: "lg",
33840
34507
  className: "rb-w-full"
33841
34508
  }, [headingLayout, questionColumnsAccordionLayout])
33842
34509
  }),
@@ -34001,7 +34668,26 @@ const formattingTransforms = [
34001
34668
  arrayLengthTransform,
34002
34669
  jsonArrayTransform,
34003
34670
  csvTransform,
34004
- 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
+ }
34005
34691
  ];
34006
34692
  //#endregion
34007
34693
  //#region ../blocks/src/system/transforms/registry/ui.ts
@@ -34585,6 +35271,7 @@ function splitSiteChromePlacementClasses(className) {
34585
35271
  init_colorConversion();
34586
35272
  init_core();
34587
35273
  init_colorStyles();
35274
+ init_surfaces();
34588
35275
  const joinClasses$4 = (parts) => parts.filter((part) => typeof part === "string" && part.trim().length > 0).join(" ").replace(/\s+/g, " ").trim();
34589
35276
  function resolveHeaderBrandDisplay(logo) {
34590
35277
  const display = logo?.brandDisplay ?? "logo-plus-title";
@@ -34654,6 +35341,26 @@ const headerLogoTextVisibleTransform = {
34654
35341
  return resolveHeaderBrandDisplay(asPartialObject(value)) !== "logo-only";
34655
35342
  }
34656
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
+ };
34657
35364
  const maxWidthClassTransform = {
34658
35365
  id: "layout.maxWidthClass",
34659
35366
  kind: "string",
@@ -34836,8 +35543,9 @@ const footerRootStyleTransform = {
34836
35543
  styleParts.push(backgroundColorStyle(token));
34837
35544
  }
34838
35545
  }
34839
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
34840
- 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 });
34841
35549
  styleParts.push(borderColorStyle("border"));
34842
35550
  return mergeStyles(...styleParts);
34843
35551
  }
@@ -34923,18 +35631,16 @@ const footerBottomBarStyleTransform = {
34923
35631
  const styleParts = [];
34924
35632
  const background = bottomBar?.background;
34925
35633
  if (background?.type === "color") styleParts.push(backgroundColorStyle(background.color ?? "surface"));
34926
- if (bottomBar?.textColor) styleParts.push(textColorStyle(bottomBar.textColor));
34927
35634
  const borderColorToken = bottomBar?.borderTop?.colorToken;
34928
35635
  if (borderColorToken) styleParts.push(borderColorStyle(borderColorToken));
34929
35636
  else styleParts.push(borderColorStyle("border"));
34930
35637
  const borderWidth = bottomBar?.borderTop?.width;
34931
35638
  if (borderWidth && borderWidth !== "none") styleParts.push({ borderTopWidth: borderWidth === "thin" ? "1px" : borderWidth === "medium" ? "2px" : "3px" });
34932
35639
  else if (borderWidth === "none") styleParts.push({ borderTopWidth: "0px" });
34933
- if (!bottomBar?.textColor) {
34934
- const visuals = resolveBackgroundVisualStyles(extractBackgroundColorToken(background, "surface"), context.theme);
34935
- if (visuals.textColorOverride) styleParts.push({ color: visuals.textColorOverride });
34936
- else if (visuals.textColorToken) styleParts.push(textColorStyle(visuals.textColorToken));
34937
- }
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 });
34938
35644
  return mergeStyles(...styleParts);
34939
35645
  }
34940
35646
  };
@@ -35069,6 +35775,7 @@ const layoutTransforms = [
35069
35775
  headerLogoClassTransform,
35070
35776
  headerLogoMediaClassTransform,
35071
35777
  headerLogoTextVisibleTransform,
35778
+ classicNavModeTransform,
35072
35779
  footerRootClassTransform,
35073
35780
  headerRootStyleTransform,
35074
35781
  headerSectionBackgroundTransform,
@@ -35505,7 +36212,18 @@ const classicLayout = inline({
35505
36212
  logoRow,
35506
36213
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
35507
36214
  headerCta
35508
- ], 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"));
35509
36227
  const centeredLayout = stack({
35510
36228
  gap: "md",
35511
36229
  align: "center",
@@ -35580,6 +36298,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
35580
36298
  }, [
35581
36299
  mobileHeaderBar,
35582
36300
  classicLayout,
36301
+ classicCenteredNavLayout,
35583
36302
  centeredLayout,
35584
36303
  transparentLayout,
35585
36304
  floatingLayout,
@@ -35627,6 +36346,7 @@ init_builder$1();
35627
36346
  init_fragments();
35628
36347
  init_defineBlock();
35629
36348
  init_colorStyles();
36349
+ init_surfaces();
35630
36350
  const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
35631
36351
  const whenTransformed = (from, transformId, equals = true) => (node) => ({
35632
36352
  ...node,
@@ -35796,7 +36516,7 @@ const footerLayout = section$1({
35796
36516
  style: { $bind: {
35797
36517
  from: "$root.theme.footer",
35798
36518
  transforms: [{ id: "layout.footerRootStyle" }],
35799
- fallback: mergeStyles(backgroundColorStyle("surface"), textColorStyle("text"), borderColorStyle("border"))
36519
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
35800
36520
  } }
35801
36521
  }, [
35802
36522
  simpleFooterLayout,
@@ -35858,7 +36578,7 @@ const backgroundImageClassName = "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full r
35858
36578
  */
35859
36579
  const wrapVariant$2 = (variantLayout) => styledSection({
35860
36580
  children: styledContainer({ children: stack({
35861
- gap: "xl",
36581
+ gap: "lg",
35862
36582
  className: "rb-relative"
35863
36583
  }, [...testimonialsHeadingFragment.layout, variantLayout]) }),
35864
36584
  baseClass: "",
@@ -35884,6 +36604,27 @@ const splitGridLayout = styledSection({
35884
36604
  spacing: "comfortable",
35885
36605
  imageClassName: backgroundImageClassName
35886
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
+ });
35887
36628
  const additionalFields = parseFieldDefinitions([
35888
36629
  ...testimonialsHeadingFragment.fields,
35889
36630
  {
@@ -35971,6 +36712,7 @@ const testimonialsBlockDefinition = {
35971
36712
  carousel: carouselLayout$1,
35972
36713
  grid: gridLayout$1,
35973
36714
  "split-grid": splitGridLayout,
36715
+ "featured-editorial": featuredEditorialLayout,
35974
36716
  highlight: highlightLayout
35975
36717
  },
35976
36718
  defaultVariant: "carousel",
@@ -35990,6 +36732,11 @@ const testimonialsBlockDefinition = {
35990
36732
  description: "Heading on the left with testimonial cards on the right",
35991
36733
  icon: "PanelLeft"
35992
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
+ },
35993
36740
  highlight: {
35994
36741
  label: "Highlight",
35995
36742
  description: "A single, centered testimonial with no carousel",
@@ -36533,7 +37280,7 @@ function grid$2(props, children) {
36533
37280
  const cardsLayout = styledSection({
36534
37281
  children: styledContainer({
36535
37282
  rootType: "stack",
36536
- rootProps: { gap: "xl" },
37283
+ rootProps: { gap: "lg" },
36537
37284
  children: [stack({
36538
37285
  gap: "sm",
36539
37286
  className: "rb-feature-cards-heading rb-mx-auto rb-max-w-3xl rb-text-center"
@@ -38485,8 +39232,11 @@ var init_filtering = __esmMin((() => {
38485
39232
  }));
38486
39233
  //#endregion
38487
39234
  //#region ../blocks/src/system/blocks/events/shared/layout.ts
38488
- function eventSectionHeaderLayoutNodes() {
38489
- 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];
38490
39240
  }
38491
39241
  var recoverEmptyHeadingWhenActive, recoverEmptyDescriptionWhenActive;
38492
39242
  var init_layout = __esmMin((() => {
@@ -38578,7 +39328,8 @@ var init_events$1 = __esmMin((() => {
38578
39328
  "combined",
38579
39329
  "calendar",
38580
39330
  "list",
38581
- "timetable"
39331
+ "timetable",
39332
+ "week-board"
38582
39333
  ];
38583
39334
  eventCalendarDefaultViewValues = ["month", "week"];
38584
39335
  eventCalendarListLayoutValues = [
@@ -41192,6 +41943,40 @@ function getEventAvailability(event) {
41192
41943
  isFull: false
41193
41944
  };
41194
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
+ }
41195
41980
  var init_eventCapacity = __esmMin((() => {}));
41196
41981
  //#endregion
41197
41982
  //#region ../blocks/src/system/runtime/nodes/events/shared/utils.ts
@@ -43899,7 +44684,7 @@ const eventCalendarLayout = [styledSection({
43899
44684
  children: styledContainer({
43900
44685
  rootType: "stack",
43901
44686
  rootProps: { gap: "lg" },
43902
- children: [...eventSectionHeaderLayoutNodes(), el("event-calendar", withApiBindings({
44687
+ children: [...eventSectionHeaderLayoutNodes({ splitClassName: "event-section-head event-section-head--split" }), el("event-calendar", withApiBindings({
43903
44688
  events: { $bind: { from: "data.events" } },
43904
44689
  stage: { $bind: {
43905
44690
  from: "$root.previewStage",
@@ -44010,6 +44795,10 @@ const eventCalendarAdditionalFields = [
44010
44795
  value: "timetable",
44011
44796
  label: "Timetable"
44012
44797
  },
44798
+ {
44799
+ value: "week-board",
44800
+ label: "Week board"
44801
+ },
44013
44802
  {
44014
44803
  value: "list",
44015
44804
  label: "List"
@@ -44192,7 +44981,8 @@ const eventCalendarAdditionalFields = [
44192
44981
  oneOf: [
44193
44982
  "combined",
44194
44983
  "calendar",
44195
- "timetable"
44984
+ "timetable",
44985
+ "week-board"
44196
44986
  ]
44197
44987
  }
44198
44988
  }
@@ -44295,7 +45085,8 @@ const eventCalendarAdditionalFields = [
44295
45085
  "combined",
44296
45086
  "calendar",
44297
45087
  "list",
44298
- "timetable"
45088
+ "timetable",
45089
+ "week-board"
44299
45090
  ]
44300
45091
  }
44301
45092
  }
@@ -44330,7 +45121,8 @@ const eventCalendarAdditionalFields = [
44330
45121
  "combined",
44331
45122
  "calendar",
44332
45123
  "list",
44333
- "timetable"
45124
+ "timetable",
45125
+ "week-board"
44334
45126
  ]
44335
45127
  }, {
44336
45128
  field: "showFilters",
@@ -44353,7 +45145,8 @@ const eventCalendarAdditionalFields = [
44353
45145
  "combined",
44354
45146
  "calendar",
44355
45147
  "list",
44356
- "timetable"
45148
+ "timetable",
45149
+ "week-board"
44357
45150
  ]
44358
45151
  }, {
44359
45152
  field: "showFilters",
@@ -44376,7 +45169,8 @@ const eventCalendarAdditionalFields = [
44376
45169
  "combined",
44377
45170
  "calendar",
44378
45171
  "list",
44379
- "timetable"
45172
+ "timetable",
45173
+ "week-board"
44380
45174
  ]
44381
45175
  }, {
44382
45176
  field: "showFilters",
@@ -44398,7 +45192,8 @@ const eventCalendarAdditionalFields = [
44398
45192
  oneOf: [
44399
45193
  "combined",
44400
45194
  "list",
44401
- "timetable"
45195
+ "timetable",
45196
+ "week-board"
44402
45197
  ]
44403
45198
  }, { allOf: [{
44404
45199
  field: "variant",
@@ -44574,6 +45369,7 @@ const eventCalendarVariants = {
44574
45369
  combined: eventCalendarLayout[0],
44575
45370
  calendar: eventCalendarLayout[0],
44576
45371
  timetable: eventCalendarLayout[0],
45372
+ "week-board": eventCalendarLayout[0],
44577
45373
  list: eventCalendarLayout[0]
44578
45374
  };
44579
45375
  const eventCalendarContentShape = {
@@ -44587,6 +45383,7 @@ const eventCalendarContentShape = {
44587
45383
  { value: "combined" },
44588
45384
  { value: "calendar" },
44589
45385
  { value: "timetable" },
45386
+ { value: "week-board" },
44590
45387
  { value: "list" }
44591
45388
  ]
44592
45389
  },
@@ -44653,6 +45450,7 @@ const eventCalendarBlockDefinition = {
44653
45450
  combined: { label: "Combined" },
44654
45451
  calendar: { label: "Calendar" },
44655
45452
  timetable: { label: "Timetable" },
45453
+ "week-board": { label: "Week board" },
44656
45454
  list: { label: "List" }
44657
45455
  }
44658
45456
  }, eventCalendarContentShape),
@@ -50502,6 +51300,12 @@ const systemBlockDefinitions = [
50502
51300
  family: "centered",
50503
51301
  weight: "featured",
50504
51302
  bias: "soft"
51303
+ }),
51304
+ layoutProfile({
51305
+ variantKey: "featured-editorial",
51306
+ family: "split",
51307
+ weight: "featured",
51308
+ bias: "soft"
50505
51309
  })
50506
51310
  ]
50507
51311
  })),
@@ -50634,6 +51438,11 @@ const systemBlockDefinitions = [
50634
51438
  variantKey: "timetable",
50635
51439
  family: "stack",
50636
51440
  weight: "standard"
51441
+ }),
51442
+ layoutProfile({
51443
+ variantKey: "week-board",
51444
+ family: "stack",
51445
+ weight: "standard"
50637
51446
  })
50638
51447
  ]
50639
51448
  })),
@@ -50994,7 +51803,15 @@ function gradientToCss(config, tokens) {
50994
51803
  const stops = config.stops.map((stop) => {
50995
51804
  return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
50996
51805
  }).join(", ");
50997
- 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
+ }
50998
51815
  return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
50999
51816
  }
51000
51817
  //#endregion
@@ -51023,7 +51840,7 @@ function backgroundVideoMobileClassNames(input) {
51023
51840
  //#region ../blocks/src/system/transforms/registry/background.ts
51024
51841
  init_background$1();
51025
51842
  init_themeColorResolution();
51026
- init_sectionForegroundStyles();
51843
+ init_surfaceForegroundStyles();
51027
51844
  init_media();
51028
51845
  const isString$2 = (value) => typeof value === "string" && value.trim().length > 0;
51029
51846
  const isNumber$2 = (value) => typeof value === "number" && !isNaN(value);
@@ -51080,8 +51897,8 @@ const backgroundTransforms = [
51080
51897
  {
51081
51898
  id: "background.resolveColorsStyle",
51082
51899
  kind: "formatter",
51083
- summary: "Resolve section foreground colors from a background object into scoped CSS vars",
51084
- 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)
51085
51902
  },
51086
51903
  {
51087
51904
  id: "background.resolveAllowOverflow",
@@ -51714,21 +52531,53 @@ function Inline({ as: Comp = "div", gap = "md", align = "center", justify = "sta
51714
52531
  //#endregion
51715
52532
  //#region ../blocks/src/primitives/layout/Grid.tsx
51716
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
+ ];
51717
52557
  function Grid({ as: Comp = "div", cols = {
51718
52558
  base: 1,
51719
52559
  md: 2
51720
- }, gap = "md", className, children, "data-slot": dataSlot, ...rest }) {
51721
- const colsObj = typeof cols === "number" ? { base: cols } : cols;
51722
- const colClasses = [
51723
- colsObj.base && `rb-grid-cols-${colsObj.base}`,
51724
- colsObj.sm && `rb-sm-grid-cols-${colsObj.sm}`,
51725
- colsObj.md && `rb-md-grid-cols-${colsObj.md}`,
51726
- colsObj.lg && `rb-lg-grid-cols-${colsObj.lg}`,
51727
- colsObj.xl && `rb-xl-grid-cols-${colsObj.xl}`
51728
- ];
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;
51729
52577
  return /* @__PURE__ */ jsx(Comp, {
51730
52578
  ...rest,
51731
- className: clsx("rb-grid", colClasses, {
52579
+ style: mergedStyle,
52580
+ className: clsx("rb-grid", hasTracks && "rb-grid-tracks", colClasses, {
51732
52581
  "rb-gap-0": gap === "none",
51733
52582
  "rb-gap-1": gap === "xs",
51734
52583
  "rb-gap-2": gap === "sm",
@@ -51974,125 +52823,6 @@ function Text$2({ as: Comp = "span", children, className = "", path, maxLength:
51974
52823
  });
51975
52824
  }
51976
52825
  //#endregion
51977
- //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
51978
- function coerceRichTextDoc(value) {
51979
- const raw = unwrapRichTextRoot(value);
51980
- if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
51981
- if (isRecord$25(raw) && typeof raw.type === "string") return raw;
51982
- return null;
51983
- }
51984
- var init_richText_coerce = __esmMin((() => {
51985
- init_richTextSchema();
51986
- init_typeGuards();
51987
- }));
51988
- //#endregion
51989
- //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
51990
- init_richText_coerce();
51991
- function renderInlineText(value) {
51992
- return value.map((run, index) => renderRun(run, index));
51993
- }
51994
- function renderRun(run, key) {
51995
- return (run.marks ?? []).reduceRight((child, mark, index) => renderMark(mark, `${String(key)}-${index}`, child), run.text);
51996
- }
51997
- function renderMark(mark, key, child) {
51998
- switch (mark.kind) {
51999
- case "strong": return /* @__PURE__ */ jsx("strong", { children: child }, key);
52000
- case "emphasis": return /* @__PURE__ */ jsx("em", { children: child }, key);
52001
- case "accent": return /* @__PURE__ */ jsx("span", {
52002
- className: `rb-inline-text-accent rb-inline-text-accent-${mark.tone}`,
52003
- children: child
52004
- }, key);
52005
- case "highlight": return /* @__PURE__ */ jsx("span", {
52006
- className: `rb-inline-text-highlight rb-inline-text-highlight-${mark.tone}`,
52007
- children: child
52008
- }, key);
52009
- }
52010
- }
52011
- //#endregion
52012
- //#region ../blocks/src/system/runtime/nodes/basic.tsx
52013
- init_buttons();
52014
- const TextNode = ({ value, children, blockId: _blockId, blockKind: _blockKind, blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, inlineTextFallbackPath, ...rest }) => {
52015
- const inlineText = parseInlineTextFromUnknown(value);
52016
- if (inlineText.ok && !isInlineTextEmpty(inlineText.value)) return /* @__PURE__ */ jsx(Text$2, {
52017
- ...rest,
52018
- children: renderInlineText(inlineText.value)
52019
- });
52020
- const fallbackValue = inlineTextFallbackPath ? readStringPath(blockContent, inlineTextFallbackPath) : null;
52021
- return /* @__PURE__ */ jsx(Text$2, {
52022
- ...rest,
52023
- children: fallbackValue ?? textNodeContent(value) ?? children
52024
- });
52025
- };
52026
- function textNodeContent(value) {
52027
- if (value === null || value === void 0) return null;
52028
- if (typeof value === "string" || typeof value === "number") return value;
52029
- return null;
52030
- }
52031
- function readStringPath(source, path) {
52032
- const value = getAtPath(source, path);
52033
- return typeof value === "string" ? value : null;
52034
- }
52035
- const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52036
- return /* @__PURE__ */ jsx(RichText$1, {
52037
- doc: coerceRichTextDoc(value) ?? void 0,
52038
- ...rest
52039
- });
52040
- };
52041
- 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 }) => {
52042
- const content = value ?? children;
52043
- if (!content) {
52044
- console.warn("[ButtonNode] No content to render - value and children are both empty");
52045
- return null;
52046
- }
52047
- const resolvedHref = typeof href === "string" ? href.trim() : "";
52048
- if (linkRequired && resolvedHref.length === 0) {
52049
- console.warn("[ButtonNode] Missing href for link-required button");
52050
- return null;
52051
- }
52052
- const resolvedVariantId = parseThemeButtonVariantId(variantId);
52053
- const combinedClassName = resolvedVariantId ? themeButtonClassName({
52054
- variant: resolvedVariantId,
52055
- size,
52056
- extraClassName: className
52057
- }) : className;
52058
- if (resolvedHref) return /* @__PURE__ */ jsx("a", {
52059
- href: resolvedHref,
52060
- target,
52061
- rel,
52062
- className: combinedClassName,
52063
- ...rest,
52064
- children: content
52065
- });
52066
- return /* @__PURE__ */ jsx("button", {
52067
- type,
52068
- disabled,
52069
- className: combinedClassName,
52070
- ...rest,
52071
- children: content
52072
- });
52073
- };
52074
- const LinkNode = ({ href, children, className, target, rel, linkRequired = false, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52075
- if (!children) return null;
52076
- const resolvedHref = typeof href === "string" ? href.trim() : "";
52077
- if (resolvedHref.length === 0) {
52078
- if (linkRequired && true) console.warn("[LinkNode] Missing href for link-required link");
52079
- if (linkRequired) return null;
52080
- return /* @__PURE__ */ jsx("span", {
52081
- className,
52082
- ...rest,
52083
- children
52084
- });
52085
- }
52086
- return /* @__PURE__ */ jsx("a", {
52087
- href: resolvedHref,
52088
- className,
52089
- target,
52090
- rel,
52091
- ...rest,
52092
- children
52093
- });
52094
- };
52095
- //#endregion
52096
52826
  //#region ../blocks/src/system/icons/cta.ts
52097
52827
  init_svg();
52098
52828
  /**
@@ -52193,6 +52923,177 @@ function getIconComponent(name) {
52193
52923
  return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
52194
52924
  }
52195
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
52196
53097
  //#region ../blocks/src/system/runtime/nodes/icon.tsx
52197
53098
  const IconNode = ({ value, title, className, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
52198
53099
  const parsedValue = parseBlockIconValue(value);
@@ -52914,6 +53815,78 @@ function SpinnerNode({ className, size = "md", color, strokeWidth = 3, srLabel,
52914
53815
  var init_spinner = __esmMin((() => {
52915
53816
  init_clsx();
52916
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
+ };
52917
53890
  function clearWorkflowFeedback(state) {
52918
53891
  return {
52919
53892
  ...state,
@@ -53694,7 +54667,6 @@ var init_booking_form_interactive = __esmMin((() => {
53694
54667
  }));
53695
54668
  //#endregion
53696
54669
  //#region ../blocks/src/system/runtime/nodes/booking-form.server.tsx
53697
- init_spinner();
53698
54670
  init_booking_form_interactive();
53699
54671
  /**
53700
54672
  * Server-safe placeholder for booking form.
@@ -56184,6 +57156,153 @@ var init_WeekAgendaView = __esmMin((() => {
56184
57156
  };
56185
57157
  }));
56186
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
56187
57306
  //#region ../blocks/src/system/runtime/nodes/events/shared/timetableModel.ts
56188
57307
  function buildTimetableModel(input) {
56189
57308
  const generic = buildTimetableModel$1({
@@ -56278,6 +57397,7 @@ init_clsx();
56278
57397
  init_EventListing_view();
56279
57398
  init_EventCalendar_interactive();
56280
57399
  init_WeekAgendaView();
57400
+ init_WeekBoardView();
56281
57401
  init_utils$3();
56282
57402
  init_timetableModel();
56283
57403
  init_buttons();
@@ -56622,6 +57742,17 @@ function renderTimetableSsr(display) {
56622
57742
  })]
56623
57743
  });
56624
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
+ }
56625
57756
  function formatHourLabel$1(hour) {
56626
57757
  if (hour === 0) return "12 AM";
56627
57758
  if (hour === 12) return "12 PM";
@@ -56648,6 +57779,9 @@ const EventCalendarSSR = (props) => {
56648
57779
  case "timetable":
56649
57780
  content = renderTimetableSsr(display);
56650
57781
  break;
57782
+ case "week-board":
57783
+ content = renderWeekBoardSsr(display);
57784
+ break;
56651
57785
  case "calendar":
56652
57786
  content = renderCalendarSsr(display);
56653
57787
  break;
@@ -57242,6 +58376,7 @@ init_media_server();
57242
58376
  const serverComponentRegistry = {
57243
58377
  div: DivNode,
57244
58378
  figure: FigureNode,
58379
+ svg: SvgNode,
57245
58380
  section: SectionNode,
57246
58381
  headerSection: header_section_server_default,
57247
58382
  stack: StackNode,
@@ -58720,9 +59855,12 @@ function formatFontFamily(family, fallback = "sans-serif") {
58720
59855
  }
58721
59856
  //#endregion
58722
59857
  //#region ../theme-core/src/styles/shadow.ts
59858
+ init_colorStyles();
58723
59859
  function generateShadowCssVars(theme) {
58724
59860
  const level = theme.shadow.elevation;
58725
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})`;
58726
59864
  const base = {
58727
59865
  sm: [{
58728
59866
  y: 1,
@@ -58782,7 +59920,7 @@ function generateShadowCssVars(theme) {
58782
59920
  const blurMul = soft ? 1.2 : 1;
58783
59921
  const alphaMul = soft ? .9 : 1.05;
58784
59922
  const fmt = (layers) => layers.map((l) => {
58785
- 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))))}`;
58786
59924
  }).join(", ");
58787
59925
  return {
58788
59926
  "--shadow-sm": fmt(base.sm),
@@ -58818,6 +59956,7 @@ function parseBorderWidth(widthClass) {
58818
59956
  init_types$10();
58819
59957
  init_constants$1();
58820
59958
  init_colorStyles();
59959
+ init_surfaces();
58821
59960
  /**
58822
59961
  * Corner radius map for accordion surfaces. Pill is capped here because FAQ
58823
59962
  * rows contain long text and expanded content; full capsules clip awkwardly.
@@ -58851,7 +59990,13 @@ function generateAccordionCss({ themeId, theme, accordionSystem }) {
58851
59990
  const questionColumnsLastItemSelector = `${questionColumnsItemSelector}:last-child`;
58852
59991
  const questionColumnsTriggerSelector = `${questionColumnsItemSelector} .accordion-trigger`;
58853
59992
  const rootRules = [];
58854
- 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
+ }
58855
60000
  const borderRadius = CORNER_MAP$2[accordionSystem.corners ?? theme.corners];
58856
60001
  rootRules.push(`border-radius: ${borderRadius}`);
58857
60002
  if (accordionSystem.border) {
@@ -60429,7 +61574,7 @@ function toHeroLineHeight(lineHeight) {
60429
61574
  }
60430
61575
  //#endregion
60431
61576
  //#region ../theme-core/src/status/generateStatusCss.ts
60432
- init_contextualColors();
61577
+ init_surfaces();
60433
61578
  /**
60434
61579
  * Corner radius map - derives alert border-radius from theme.corners
60435
61580
  */
@@ -60459,7 +61604,7 @@ ${root} .status-error { color: rgb(var(--tb-destructive)); }
60459
61604
  ${root} .status-success { color: rgb(var(--tb-success)); }
60460
61605
  ${root} .status-warning { color: rgb(var(--tb-warning)); }
60461
61606
  ${root} .status-info { color: rgb(var(--tb-info)); }
60462
- ${root} .status-muted { ${statusMutedColorDeclaration()} }`);
61607
+ ${root} .status-muted { color: ${surfaceForegroundValue("supporting")}; }`);
60463
61608
  cssBlocks.push(`/* Alert containers */
60464
61609
  ${root} .alert {
60465
61610
  padding: 1rem;
@@ -60513,9 +61658,6 @@ ${root} .button-link:hover {
60513
61658
  return cssBlocks.join("\n\n");
60514
61659
  }
60515
61660
  //#endregion
60516
- //#region ../theme-core/src/status/index.ts
60517
- init_contextualColors();
60518
- //#endregion
60519
61661
  //#region ../theme-core/src/progress/generateProgressCss.ts
60520
61662
  /**
60521
61663
  * Generate progress indicator CSS from theme settings.
@@ -60600,6 +61742,10 @@ ${root} .step-connector {
60600
61742
  }
60601
61743
  //#endregion
60602
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
+ }
60603
61749
  /**
60604
61750
  * Generate typography CSS for heading elements.
60605
61751
  *
@@ -60628,7 +61774,7 @@ ${root} :where(h1) {
60628
61774
  font-style: var(--fi-h1, var(--fi-heading, normal));
60629
61775
  letter-spacing: var(--ls-h1, var(--ls-heading));
60630
61776
  line-height: var(--lh-h1, var(--lh-heading));
60631
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h1, var(--hc-heading, inherit))));
61777
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(1))};
60632
61778
  }
60633
61779
 
60634
61780
  ${root} :where(h2) {
@@ -60637,7 +61783,7 @@ ${root} :where(h2) {
60637
61783
  font-style: var(--fi-h2, var(--fi-heading, normal));
60638
61784
  letter-spacing: var(--ls-h2, var(--ls-heading));
60639
61785
  line-height: var(--lh-h2, var(--lh-heading));
60640
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h2, var(--hc-heading, inherit))));
61786
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(2))};
60641
61787
  }
60642
61788
 
60643
61789
  ${root} :where(h3) {
@@ -60646,7 +61792,7 @@ ${root} :where(h3) {
60646
61792
  font-style: var(--fi-h3, var(--fi-heading, normal));
60647
61793
  letter-spacing: var(--ls-h3, var(--ls-heading));
60648
61794
  line-height: var(--lh-h3, var(--lh-heading));
60649
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h3, var(--hc-heading, inherit))));
61795
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(3))};
60650
61796
  }
60651
61797
 
60652
61798
  ${root} :where(h4) {
@@ -60655,7 +61801,7 @@ ${root} :where(h4) {
60655
61801
  font-style: var(--fi-h4, var(--fi-heading, normal));
60656
61802
  letter-spacing: var(--ls-h4, var(--ls-heading));
60657
61803
  line-height: var(--lh-h4, var(--lh-heading));
60658
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h4, var(--hc-heading, inherit))));
61804
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(4))};
60659
61805
  }
60660
61806
 
60661
61807
  ${root} :where(h5) {
@@ -60664,7 +61810,7 @@ ${root} :where(h5) {
60664
61810
  font-style: var(--fi-h5, var(--fi-heading, normal));
60665
61811
  letter-spacing: var(--ls-h5, var(--ls-heading));
60666
61812
  line-height: var(--lh-h5, var(--lh-heading));
60667
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h5, var(--hc-heading, inherit))));
61813
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(5))};
60668
61814
  }
60669
61815
 
60670
61816
  ${root} :where(h6) {
@@ -60673,7 +61819,7 @@ ${root} :where(h6) {
60673
61819
  font-style: var(--fi-h6, var(--fi-heading, normal));
60674
61820
  letter-spacing: var(--ls-h6, var(--ls-heading));
60675
61821
  line-height: var(--lh-h6, var(--lh-heading));
60676
- color: var(--section-heading-color, var(--section-text-color, var(--hc-h6, var(--hc-heading, inherit))));
61822
+ color: ${surfaceForegroundValue("heading", globalHeadingColorFallback(6))};
60677
61823
  }`);
60678
61824
  cssBlocks.push(`/* Display variant for hero/splash headings */
60679
61825
  ${root} :where(.heading-display) {
@@ -61072,6 +62218,7 @@ const THEME_RADIUS_CSS_VARS = {
61072
62218
  block: "--rb-block-radius",
61073
62219
  button: "--rb-button-radius",
61074
62220
  input: "--rb-input-radius",
62221
+ panel: "--rb-panel-radius",
61075
62222
  legacyCard: "--radius-card",
61076
62223
  legacyControl: "--radius-control"
61077
62224
  };
@@ -61153,6 +62300,10 @@ ${`:where([data-theme-scope="${themeId}"]) :where([data-block="customer-portal"]
61153
62300
  /* Modal (shared rb-modal classes) */
61154
62301
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.35);
61155
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);
61156
62307
  --rb-modal-border: var(--cp-card-border);
61157
62308
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
61158
62309
  --rb-modal-radius: var(--cp-card-radius);
@@ -61878,6 +63029,7 @@ function buildThemeCssVars(theme) {
61878
63029
  const inputSystem = resolveThemeInputSystem(theme);
61879
63030
  const blockRadius = mapBlockRadius(theme.corners);
61880
63031
  const buttonRadius = mapButtonRadius(theme.corners);
63032
+ const panelRadius = mapPanelRadius(theme.corners);
61881
63033
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
61882
63034
  return {
61883
63035
  ...generateCssVars(theme.palette),
@@ -61886,6 +63038,7 @@ function buildThemeCssVars(theme) {
61886
63038
  ...generateShadowCssVars(theme),
61887
63039
  ["--font-heading"]: formatFontFamily(typography.headings.default.family),
61888
63040
  ["--font-body"]: formatFontFamily(typography.body.family),
63041
+ ["--font-eyebrow"]: typography.eyebrow?.family ? formatFontFamily(typography.eyebrow.family) : "var(--font-body)",
61889
63042
  ["--font-weight-heading"]: mapWeight(typography.headings.default.weight),
61890
63043
  ["--font-weight-body"]: mapWeight(typography.body.weight),
61891
63044
  ...typography.headings.h1.weight ? { ["--fw-h1"]: mapWeight(typography.headings.h1.weight) } : {},
@@ -61936,12 +63089,13 @@ function buildThemeCssVars(theme) {
61936
63089
  ["--fs-h3-fluid"]: sized.h3Fluid,
61937
63090
  ["--fs-h1-display"]: sized.h1Display,
61938
63091
  ["--fs-h1-display-fluid"]: sized.h1DisplayFluid,
61939
- ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom"),
63092
+ ["--shadow-elev"]: mapShadow(shadow.elevation, shadow.softness, shadow.position || "bottom", shadow.colorToken),
61940
63093
  ["--space-mult"]: mapSpaceMult(space),
61941
63094
  ["--motion-duration"]: mapMotionDuration(motion.level),
61942
63095
  ["--motion-ease"]: mapMotionEasing(motion.easing ?? "standard"),
61943
63096
  ["--rt-space-y"]: mapRhythm(space),
61944
63097
  [THEME_RADIUS_CSS_VARS.block]: blockRadius,
63098
+ [THEME_RADIUS_CSS_VARS.panel]: panelRadius,
61945
63099
  ["--rb-block-transition"]: mapBlockTransition(motion.level),
61946
63100
  [THEME_RADIUS_CSS_VARS.button]: buttonRadius,
61947
63101
  ["--rb-border-width"]: mapBorderWidth(border.width),
@@ -61995,20 +63149,22 @@ function mapWeight(w) {
61995
63149
  bold: 700
61996
63150
  }[w];
61997
63151
  }
61998
- function mapShadow(level, softness, position = "bottom") {
63152
+ function mapShadow(level, softness, position = "bottom", colorToken) {
61999
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})`;
62000
63156
  const offset = {
62001
63157
  low: 2,
62002
63158
  medium: 4,
62003
63159
  high: 6
62004
63160
  }[level];
62005
63161
  const xOffset = position === "bottom-right" ? offset : 0;
62006
- 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")}`;
62007
63163
  const soft = softness !== "crisp";
62008
63164
  switch (level) {
62009
- case "low": return soft ? `${xOffset}px 1px 2px rgba(0,0,0,.06)` : `${xOffset}px 1px 1px rgba(0,0,0,.12)`;
62010
- case "medium": return soft ? `${xOffset}px 10px 20px rgba(0,0,0,.08)` : `${xOffset}px 6px 12px rgba(0,0,0,.16)`;
62011
- 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")}`;
62012
63168
  }
62013
63169
  }
62014
63170
  function mapSpaceMult(space) {
@@ -62055,6 +63211,21 @@ function mapBlockRadius(corners) {
62055
63211
  }[corners];
62056
63212
  }
62057
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
+ /**
62058
63229
  * Map motion level to block transition duration.
62059
63230
  * These are Tier 2 vars used consistently across blocks.
62060
63231
  */
@@ -63079,8 +64250,12 @@ const containerResponsiveThemeCss = `/*
63079
64250
  text-transform: uppercase;
63080
64251
  }
63081
64252
 
63082
- /* 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). */
63083
64257
  .rb-eyebrow {
64258
+ font-family: var(--font-eyebrow, var(--font-body));
63084
64259
  font-size: 0.875rem;
63085
64260
  font-weight: 600;
63086
64261
  letter-spacing: 0.025em;
@@ -63095,11 +64270,11 @@ const containerResponsiveThemeCss = `/*
63095
64270
  width: fit-content;
63096
64271
  align-items: center;
63097
64272
  justify-content: center;
63098
- 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);
63099
64274
  border-radius: 9999px;
63100
- 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);
63101
64276
  padding: 0.5rem 1rem;
63102
- color: var(--section-text-color, rgb(var(--tb-text)));
64277
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
63103
64278
  line-height: 1;
63104
64279
  }
63105
64280
  .rb-eyebrow-treatment-pill.rb-eyebrow-treatment-accent {
@@ -63601,6 +64776,58 @@ const containerResponsiveThemeCss = `/*
63601
64776
  }
63602
64777
  }
63603
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
+
63604
64831
  }
63605
64832
 
63606
64833
  /* Alignment */
@@ -64805,6 +66032,11 @@ const containerResponsiveThemeCss = `/*
64805
66032
  :where(.theme-scope) .rb-modal {
64806
66033
  width: min(var(--rb-modal-max-width, 560px), 100%);
64807
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))));
64808
66040
  border: 1px solid var(--rb-modal-border, rgb(var(--tb-border)));
64809
66041
  border-radius: var(--rb-modal-radius, var(--radius-card));
64810
66042
  box-shadow: var(--rb-modal-shadow, var(--shadow-lg, var(--shadow-elev)));
@@ -64824,7 +66056,7 @@ const containerResponsiveThemeCss = `/*
64824
66056
  font-family: var(--font-heading);
64825
66057
  font-size: 1.0625rem;
64826
66058
  font-weight: 600;
64827
- color: rgb(var(--tb-text));
66059
+ color: var(--rb-surface-heading-color, var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39))));
64828
66060
  }
64829
66061
 
64830
66062
  :where(.theme-scope) .rb-modal__close {
@@ -64834,7 +66066,7 @@ const containerResponsiveThemeCss = `/*
64834
66066
  height: 2.25rem;
64835
66067
  padding: 0;
64836
66068
  line-height: 1;
64837
- color: rgb(var(--tb-mutedText));
66069
+ color: var(--rb-surface-supporting-color, var(--rb-surface-text-color, rgb(var(--tb-mutedText, 100 116 139))));
64838
66070
  cursor: pointer;
64839
66071
  display: grid;
64840
66072
  place-items: center;
@@ -64842,7 +66074,7 @@ const containerResponsiveThemeCss = `/*
64842
66074
  }
64843
66075
 
64844
66076
  :where(.theme-scope) .rb-modal__close:hover {
64845
- color: rgb(var(--tb-text));
66077
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
64846
66078
  background: rgba(var(--tb-border), 0.2);
64847
66079
  }
64848
66080
 
@@ -64853,7 +66085,7 @@ const containerResponsiveThemeCss = `/*
64853
66085
 
64854
66086
  :where(.theme-scope) .rb-modal__body {
64855
66087
  padding: 0.875rem 1rem 1rem;
64856
- color: rgb(var(--tb-text));
66088
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
64857
66089
  font-size: 0.9375rem;
64858
66090
  line-height: 1.45;
64859
66091
  }
@@ -65013,7 +66245,7 @@ const containerResponsiveThemeCss = `/*
65013
66245
  & h6 {
65014
66246
  font-family: var(--font-heading);
65015
66247
  /* Color is set by generateTypographyCss.ts with full cascade:
65016
- --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 */
65017
66249
  font-weight: var(--font-weight-heading);
65018
66250
  text-transform: var(--tt-heading);
65019
66251
  font-variant-caps: var(--fv-heading);
@@ -65161,7 +66393,7 @@ const containerResponsiveThemeCss = `/*
65161
66393
 
65162
66394
  /* Neutral prose uses theme text color by default */
65163
66395
  :where(.theme-scope) .rb-prose-neutral {
65164
- color: var(--section-text-color, rgb(var(--tb-text)));
66396
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
65165
66397
  }
65166
66398
 
65167
66399
  :where(.theme-scope) .rb-prose p,
@@ -65195,8 +66427,14 @@ const containerResponsiveThemeCss = `/*
65195
66427
 
65196
66428
  :where(.theme-scope) .rb-prose a {
65197
66429
  --rb-prose-effective-link-color: var(
65198
- --section-link-color,
65199
- 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
+ )
65200
66438
  );
65201
66439
  color: var(--rb-prose-effective-link-color);
65202
66440
  text-decoration-line: var(--rb-prose-link-decoration-line, underline);
@@ -65207,14 +66445,11 @@ const containerResponsiveThemeCss = `/*
65207
66445
  );
65208
66446
  text-underline-offset: var(--rb-prose-link-underline-offset, 0.14em);
65209
66447
  text-decoration-color: var(
65210
- --section-link-decoration-color,
65211
- var(
65212
- --rb-prose-link-decoration-color,
65213
- color-mix(
65214
- in srgb,
65215
- var(--rb-prose-effective-link-color) 35%,
65216
- transparent
65217
- )
66448
+ --rb-prose-link-decoration-color,
66449
+ color-mix(
66450
+ in srgb,
66451
+ var(--rb-prose-effective-link-color) 35%,
66452
+ transparent
65218
66453
  )
65219
66454
  );
65220
66455
  transition:
@@ -65238,7 +66473,7 @@ const containerResponsiveThemeCss = `/*
65238
66473
 
65239
66474
  :where(.theme-scope) .rb-prose blockquote {
65240
66475
  /* Blockquotes use muted text color */
65241
- 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))));
65242
66477
  border-left-color: rgb(var(--tb-border));
65243
66478
  }
65244
66479
 
@@ -66272,6 +67507,10 @@ const containerResponsiveThemeCss = `/*
66272
67507
  :where(.theme-scope) .card-surface {
66273
67508
  background: rgb(var(--tb-surface));
66274
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)));
66275
67514
  border: 1px solid rgb(var(--tb-border));
66276
67515
  border-radius: var(--radius-card);
66277
67516
  box-shadow: var(--shadow-elev);
@@ -66415,6 +67654,10 @@ const containerResponsiveThemeCss = `/*
66415
67654
  padding: clamp(1rem, 2vw, 1.5rem);
66416
67655
  background: var(--rb-reg-surface-bg, rgb(var(--tb-surface, 248 250 252)));
66417
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)))));
66418
67661
  transition: border-color var(--rb-block-transition, 150ms) ease;
66419
67662
  width: 100%;
66420
67663
  max-width: 800px;
@@ -69502,6 +70745,350 @@ const containerResponsiveThemeCss = `/*
69502
70745
  }
69503
70746
  }
69504
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
+
69505
71092
  /* -----------------------------------------------------------------------------
69506
71093
  * Event Calendar Modals
69507
71094
  * Modal overlays for event details and day events list
@@ -69929,7 +71516,7 @@ const containerResponsiveThemeCss = `/*
69929
71516
  }
69930
71517
 
69931
71518
  :where(.theme-scope) .rb-inline-text-accent-contrast {
69932
- color: var(--section-text-color, rgb(var(--tb-text)));
71519
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
69933
71520
  }
69934
71521
 
69935
71522
  :where(.theme-scope) .rb-inline-text-highlight {
@@ -69940,7 +71527,7 @@ const containerResponsiveThemeCss = `/*
69940
71527
  }
69941
71528
 
69942
71529
  :where(.theme-scope) .rb-inline-text-highlight-soft {
69943
- 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);
69944
71531
  }
69945
71532
 
69946
71533
  :where(.theme-scope) .rb-inline-text-highlight-accent {
@@ -69959,7 +71546,7 @@ const containerResponsiveThemeCss = `/*
69959
71546
 
69960
71547
  /* Eyebrow - color only (typography via .rb-eyebrow) */
69961
71548
  :where(.theme-scope) :where([data-block="hero"]) .hero-eyebrow:not(.rb-eyebrow-treatment-accent) {
69962
- color: var(--section-text-color, rgb(var(--tb-text)));
71549
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
69963
71550
  }
69964
71551
 
69965
71552
  /* Subheadline - supporting text below headline */
@@ -69969,7 +71556,7 @@ const containerResponsiveThemeCss = `/*
69969
71556
 
69970
71557
  :where(.theme-scope) :where([data-block="hero"]) .hero-subheadline {
69971
71558
  font-size: 1.125rem;
69972
- 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))));
69973
71560
  }
69974
71561
 
69975
71562
  @container rb-site (min-width: 640px) {
@@ -70060,7 +71647,7 @@ const containerResponsiveThemeCss = `/*
70060
71647
 
70061
71648
  /* CTA content/body text */
70062
71649
  :where(.theme-scope) :where([data-block="cta-full"]) .cta-content {
70063
- 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))));
70064
71651
  }
70065
71652
 
70066
71653
  /* CTA button row container */
@@ -70160,7 +71747,7 @@ const containerResponsiveThemeCss = `/*
70160
71747
  /* Form intro text */
70161
71748
  :where(.theme-scope) :where([data-block="form"]) .form-copy-intro {
70162
71749
  font-size: 1rem;
70163
- color: var(--section-text-color, rgb(var(--tb-text)));
71750
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
70164
71751
  }
70165
71752
 
70166
71753
  /* =============================================================================
@@ -70519,6 +72106,10 @@ const containerResponsiveThemeCss = `/*
70519
72106
  --rb-modal-overlay-bg: rgb(var(--tb-text, 0 0 0) / 0.6);
70520
72107
  --rb-modal-shadow: var(--shadow-lg, var(--shadow-elev));
70521
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));
70522
72113
  --shop-card-radius: var(--rb-block-radius, var(--radius-card, 0.75rem));
70523
72114
  --shop-control-radius: var(--rb-input-radius, var(--radius-control, 0.375rem));
70524
72115
  }
@@ -70576,6 +72167,11 @@ const containerResponsiveThemeCss = `/*
70576
72167
  /* Product card */
70577
72168
  :where(.theme-scope) .shop__card {
70578
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));
70579
72175
  border: 1px solid rgb(var(--tb-border));
70580
72176
  border-radius: var(--shop-card-radius);
70581
72177
  padding: 1.5rem;
@@ -70730,6 +72326,11 @@ const containerResponsiveThemeCss = `/*
70730
72326
  border: 1px solid rgb(var(--tb-border));
70731
72327
  border-radius: var(--shop-card-radius);
70732
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));
70733
72334
  }
70734
72335
 
70735
72336
  :where(.theme-scope) :where([data-block="shop"]) .rb-state-icon--success {
@@ -70802,6 +72403,11 @@ const containerResponsiveThemeCss = `/*
70802
72403
  margin: 0 auto;
70803
72404
  padding: 2rem;
70804
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);
70805
72411
  border: 1px solid var(--cp-card-border);
70806
72412
  border-radius: var(--cp-card-radius);
70807
72413
  }
@@ -70930,6 +72536,11 @@ const containerResponsiveThemeCss = `/*
70930
72536
  padding: 3rem 2rem;
70931
72537
  text-align: center;
70932
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);
70933
72544
  border: 1px dashed var(--cp-card-border);
70934
72545
  border-radius: var(--cp-card-radius);
70935
72546
  }
@@ -70942,6 +72553,11 @@ const containerResponsiveThemeCss = `/*
70942
72553
  /* Card */
70943
72554
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-card {
70944
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);
70945
72561
  border: 1px solid var(--cp-card-border);
70946
72562
  border-radius: var(--cp-card-radius);
70947
72563
  padding: 1.25rem;
@@ -71106,6 +72722,11 @@ const containerResponsiveThemeCss = `/*
71106
72722
  /* Table */
71107
72723
  :where(.theme-scope) :where([data-block="customer-portal"]) .cp-table-wrap {
71108
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);
71109
72730
  border: 1px solid var(--cp-card-border);
71110
72731
  border-radius: var(--cp-card-radius);
71111
72732
  }
@@ -71667,6 +73288,143 @@ const containerResponsiveThemeCss = `/*
71667
73288
  }
71668
73289
 
71669
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
+
71670
73428
  /* Testimonials carousel tweaks: arrow styling + gutters + equal-height cards */
71671
73429
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-carousel.carousel-root .carousel-nav-btn {
71672
73430
  height: var(--rb-testimonial-carousel-arrow-size);
@@ -72813,7 +74571,7 @@ const containerResponsiveThemeCss = `/*
72813
74571
 
72814
74572
  :where(.theme-scope) :where([data-block="newsletter-signup"]) .newsletter-copy-subtitle {
72815
74573
  font-size: 1rem;
72816
- color: var(--section-text-color, rgb(var(--tb-text)));
74574
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72817
74575
  opacity: 0.85;
72818
74576
  }
72819
74577
 
@@ -72862,7 +74620,7 @@ const containerResponsiveThemeCss = `/*
72862
74620
  margin-top: 0.75rem;
72863
74621
  font-size: 1rem;
72864
74622
  line-height: 1.6;
72865
- color: var(--section-text-color, rgb(var(--tb-text)));
74623
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72866
74624
  text-align: center;
72867
74625
  }
72868
74626
 
@@ -72944,7 +74702,7 @@ const containerResponsiveThemeCss = `/*
72944
74702
 
72945
74703
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .form-copy-intro,
72946
74704
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .newsletter-copy-subtitle {
72947
- color: var(--section-text-color, rgb(var(--tb-text)));
74705
+ color: var(--rb-surface-text-color, rgb(var(--tb-text, 17 24 39)));
72948
74706
  }
72949
74707
 
72950
74708
  :where(.theme-scope) :where([data-block="contact-newsletter"]) .contact-newsletter-info {
@@ -73342,7 +75100,7 @@ const containerResponsiveThemeCss = `/*
73342
75100
 
73343
75101
  :where(.theme-scope) .event-compact-row-title {
73344
75102
  margin: 0;
73345
- 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)))));
73346
75104
  font-family: var(--font-heading, var(--font-body, inherit));
73347
75105
  font-size: clamp(1.05rem, 1rem + 0.35vw, 1.3rem);
73348
75106
  font-weight: 400;
@@ -74004,27 +75762,41 @@ const containerResponsiveThemeCss = `/*
74004
75762
  background: rgb(var(--tb-surface));
74005
75763
  }
74006
75764
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 1) {
75765
+ background: rgb(var(--tb-surface));
74007
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));
74008
75771
  }
74009
75772
 
74010
75773
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) > .rb-bg-surface {
74011
75774
  background: rgb(var(--tb-secondary));
74012
75775
  }
74013
75776
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 2) {
75777
+ background: rgb(var(--tb-secondary));
74014
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));
74015
75783
  }
74016
75784
 
74017
75785
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) > .rb-bg-surface {
74018
75786
  background: rgb(var(--tb-primary));
74019
75787
  }
74020
75788
  :where(.theme-scope) .rb-card-treatment-color-blocked:nth-child(3n + 3) {
75789
+ background: rgb(var(--tb-primary));
74021
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));
74022
75795
  }
74023
75796
 
74024
- /* Body copy carries an inline muted colour from the block; force it to the
74025
- * 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. */
74026
75799
  :where(.theme-scope) .rb-card-treatment-color-blocked .rb-feature-card-body {
74027
- color: inherit !important;
74028
75800
  opacity: 0.9;
74029
75801
  }
74030
75802
 
@@ -149614,7 +151386,7 @@ function buildDisplayFilterParams(display) {
149614
151386
  filterVenueId: display.filterVenueId
149615
151387
  });
149616
151388
  }
149617
- var EventCalendarClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
151389
+ var EventCalendarClient, EventCalendarWeekBoardClient, EventCalendarTimetableClient, EventCalendarGridClient, EventCalendarChrome;
149618
151390
  var init_EventCalendar_client = __esmMin((() => {
149619
151391
  init_EventCalendar_interactive();
149620
151392
  init_EventListing_client();
@@ -149627,6 +151399,7 @@ var init_EventCalendar_client = __esmMin((() => {
149627
151399
  init_EventModalContext();
149628
151400
  init_EventModals();
149629
151401
  init_WeekAgendaView();
151402
+ init_WeekBoardView();
149630
151403
  init_WeekTimetableView();
149631
151404
  init_buttons();
149632
151405
  init_listOptions();
@@ -149664,8 +151437,20 @@ var init_EventCalendar_client = __esmMin((() => {
149664
151437
  });
149665
151438
  if (display.displayMode === "list") return /* @__PURE__ */ jsx(EventListingController, { render: buildEventCalendarListingRender(render) });
149666
151439
  if (display.displayMode === "timetable") return /* @__PURE__ */ jsx(EventCalendarTimetableClient, { render });
151440
+ if (display.displayMode === "week-board") return /* @__PURE__ */ jsx(EventCalendarWeekBoardClient, { display });
149667
151441
  return /* @__PURE__ */ jsx(EventCalendarGridClient, { render });
149668
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
+ };
149669
151454
  EventCalendarTimetableClient = ({ render }) => {
149670
151455
  const { display, hydration } = render;
149671
151456
  const { filtersNode, listFilters } = useEventCalendarFilterState(display);
@@ -154421,7 +156206,7 @@ var SimpleCache = class {
154421
156206
  * 1. This constant
154422
156207
  * 2. The "version" field in package.json
154423
156208
  */
154424
- const SDK_VERSION = "0.104.1";
156209
+ const SDK_VERSION = "0.104.3";
154425
156210
  //#endregion
154426
156211
  //#region src/client/error.ts
154427
156212
  let _Symbol$for;