@riverbankcms/sdk 0.111.0 → 0.118.0

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 (193) hide show
  1. package/dist/{PreviewEditorSidebar-CTR6LUhN.mjs → PreviewEditorSidebar-BBcK1DjD.mjs} +4 -4
  2. package/dist/{PreviewEditorUI-DZg15Zip.mjs → PreviewEditorUI-CuBFoYes.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-kkmjklLG.mjs → PreviewQueryProvider-nKUT4TL-.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-DeOTAFvR.mjs → SdkPreviewModeRuntime-BWIO_Dsi.mjs} +2579 -34325
  5. package/dist/{SiteChromeCustomizeContext-DOSDLCiJ.mjs → SiteChromeCustomizeContext-CciG60M5.mjs} +64575 -32787
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +5211 -639
  7. package/dist/_dts/ai/src/designer/themePatch.d.ts +1 -1
  8. package/dist/_dts/api/src/bookingAdjustments.d.ts +30 -36
  9. package/dist/_dts/api/src/bookingRecords.d.ts +6 -74
  10. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +3 -3
  11. package/dist/_dts/api/src/contentRuntime.d.ts +5 -1
  12. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
  13. package/dist/_dts/api/src/endpoints.d.ts +35 -0
  14. package/dist/_dts/api/src/event-presentation.d.ts +4 -0
  15. package/dist/_dts/api/src/index.d.ts +2 -2
  16. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +2 -2
  17. package/dist/_dts/api/src/sdk-event-upsert.d.ts +2 -2
  18. package/dist/_dts/api/src/sdkContracts.d.ts +85 -7
  19. package/dist/_dts/api/src/siteBanner.d.ts +8 -8
  20. package/dist/_dts/api/src/siteOperations.d.ts +1 -1
  21. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +32 -4
  22. package/dist/_dts/block-form/src/widgets/RichTextField/richTextFieldDefaults.d.ts +3 -12
  23. package/dist/_dts/block-form/src/widgets/RichTextField/richTextFieldSchema.d.ts +1 -5
  24. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -10
  25. package/dist/_dts/blocks/src/index.d.ts +3 -6
  26. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +2 -2
  27. package/dist/_dts/blocks/src/system/blocks/body-text.d.ts +2 -2
  28. package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +2 -2
  29. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +2 -8
  30. package/dist/_dts/blocks/src/system/blocks/feature-card-icons.d.ts +2 -2
  31. package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +3 -3
  32. package/dist/_dts/blocks/src/system/blocks/form.d.ts +2 -15
  33. package/dist/_dts/blocks/src/system/blocks/intro.d.ts +2 -2
  34. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +66 -66
  35. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +2 -16
  36. package/dist/_dts/blocks/src/system/blocks/site-footer.d.ts +0 -3
  37. package/dist/_dts/blocks/src/system/fragments/index.d.ts +0 -1
  38. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +19 -2
  39. package/dist/_dts/blocks/src/system/manifest/richTextSchema.d.ts +8 -70
  40. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +1 -0
  41. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +6 -0
  42. package/dist/_dts/blocks/src/system/node/schema.d.ts +4 -4
  43. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +1 -10
  44. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +5 -21
  45. package/dist/_dts/blocks/src/system/runtime/nodes/richText-coerce.d.ts +14 -2
  46. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -1
  47. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +1 -1
  48. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +17 -1
  49. package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +1 -1
  50. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +1 -1
  51. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +3 -2
  52. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +2 -2
  53. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +1 -1
  54. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +1 -1
  55. package/dist/_dts/content-model/src/content-types/builtins.d.ts +3 -15
  56. package/dist/_dts/content-model/src/content-types/entryValidation.d.ts +2 -0
  57. package/dist/_dts/content-model/src/content-types/schema.d.ts +1 -1
  58. package/dist/_dts/content-model/src/templates/defaults.d.ts +1 -21
  59. package/dist/_dts/core/src/editor-state.d.ts +14 -1
  60. package/dist/_dts/core/src/footer-composition.d.ts +2 -1
  61. package/dist/_dts/core/src/index.d.ts +1 -0
  62. package/dist/_dts/core/src/rich-text.d.ts +16 -0
  63. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +178 -48
  64. package/dist/_dts/editor/src/index.d.ts +1 -1
  65. package/dist/_dts/editor/src/primitives/rich-text/utils.d.ts +3 -5
  66. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +1 -1
  67. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +2 -1
  68. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +2 -1
  69. package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +15 -0
  70. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +3 -7
  71. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +12 -0
  72. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +1 -0
  73. package/dist/_dts/editor-blocks/src/block-editor/utils.d.ts +1 -1
  74. package/dist/_dts/editor-blocks/src/index.d.ts +6 -5
  75. package/dist/_dts/editor-blocks/src/widgets/rich-text/RichTextField.d.ts +2 -2
  76. package/dist/_dts/media-core/src/contentMediaAudit.d.ts +104 -0
  77. package/dist/_dts/media-core/src/contentMediaAuditFieldAdapter.d.ts +8 -0
  78. package/dist/_dts/media-core/src/contentMediaSnapshotAudit.d.ts +22 -0
  79. package/dist/_dts/media-core/src/index.d.ts +3 -1
  80. package/dist/_dts/sdk/src/cli/commands/event.d.ts +18 -1
  81. package/dist/_dts/sdk/src/cli/commands/push/execute/theme.d.ts +2 -16
  82. package/dist/_dts/sdk/src/cli/content/reader.d.ts +8 -5
  83. package/dist/_dts/sdk/src/client/management/events.d.ts +2 -1
  84. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  85. package/dist/_dts/sdk/src/client/management/types.d.ts +36 -9
  86. package/dist/_dts/sdk/src/config/typed-entries.d.ts +7 -7
  87. package/dist/_dts/sdk/src/config/validation.d.ts +7 -7
  88. package/dist/_dts/sdk/src/contracts/content.d.ts +5 -15
  89. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  90. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -25
  91. package/dist/_dts/sdk/src/contracts/theme.d.ts +2 -18
  92. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +1 -1
  93. package/dist/_dts/sdk/src/manifest/three-pass-converter.d.ts +4 -4
  94. package/dist/_dts/sdk/src/rendering/helpers/bindings.d.ts +1 -2
  95. package/dist/_dts/sdk/src/rendering/helpers/index.d.ts +1 -1
  96. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -13
  97. package/dist/_dts/sdk/src/theme/index.d.ts +0 -29
  98. package/dist/_dts/sdk/src/version.d.ts +1 -1
  99. package/dist/_dts/site-commands/src/commands.d.ts +31 -18
  100. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +2 -2
  101. package/dist/_dts/theme-core/src/buttons/core.d.ts +0 -1
  102. package/dist/_dts/theme-core/src/buttons/effectClassification.d.ts +22 -9
  103. package/dist/_dts/theme-core/src/buttons/effects/presets/background.d.ts +1 -2
  104. package/dist/_dts/theme-core/src/buttons/effects/presets/border.d.ts +1 -2
  105. package/dist/_dts/theme-core/src/buttons/effects/presets/overlay.d.ts +3 -1
  106. package/dist/_dts/theme-core/src/buttons/effects/presets/shadow.d.ts +2 -2
  107. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +8 -18
  108. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +2 -2
  109. package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +5 -5
  110. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -4
  111. package/dist/_dts/theme-core/src/buttons/parseThemeForPersistence.d.ts +36 -0
  112. package/dist/_dts/theme-core/src/buttons/types.d.ts +1638 -93
  113. package/dist/_dts/theme-core/src/cards/types.d.ts +13 -13
  114. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +969 -69
  115. package/dist/_dts/theme-core/src/navigation/types.d.ts +2 -2
  116. package/dist/_dts/theme-core/src/recommend/generateThemes.d.ts +0 -1
  117. package/dist/_dts/theme-core/src/schema.d.ts +1100 -116
  118. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  119. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +14 -14
  120. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +2 -2
  121. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +4 -4
  122. package/dist/cli/index.mjs +5706 -4852
  123. package/dist/cli/init-docs/content/cli-reference.md +40 -1
  124. package/dist/cli/init-docs/content/content-management.md +6 -0
  125. package/dist/client/{DiscountCodeDisclosure-C4xvTBux.mjs → DiscountCodeDisclosure-DIWj-P9v.mjs} +1 -1
  126. package/dist/client/{EventCombined.client-Cr7G131j.mjs → EventCombined.client-De8YWBSr.mjs} +2 -2
  127. package/dist/client/{EventListing.client-CAjbseNy.mjs → EventListing.client-seHTjimY.mjs} +2 -2
  128. package/dist/client/{LeafletStaticMap-BMlWfwz3.mjs → LeafletStaticMap-BmQxFcJW.mjs} +1 -1
  129. package/dist/client/{MagicLinkForm-ChdFz96y.mjs → MagicLinkForm-OoJAIUIj.mjs} +1 -1
  130. package/dist/client/{StepIndicator-7D3GaBeM.mjs → StepIndicator-CiZ8kdPk.mjs} +2 -2
  131. package/dist/client/{accordion-D8JTs2Si.mjs → accordion-6lnN__XJ.mjs} +1 -1
  132. package/dist/client/{bookingForm-H3DCRBHs.mjs → bookingForm-5uyqhONU.mjs} +6 -6
  133. package/dist/client/bookings.mjs +2219 -527
  134. package/dist/client/{carousel-DMr_QWlz.mjs → carousel-Dtnifil_.mjs} +1 -1
  135. package/dist/client/{cart-DWMbfBdR.mjs → cart-5Tc5S7NV.mjs} +3 -3
  136. package/dist/client/{checkout-zmfdkXLx.mjs → checkout-CYKKN5Hr.mjs} +3 -3
  137. package/dist/client/client.mjs +1652 -1580
  138. package/dist/client/{colorTokenParts-FSS3al6l.mjs → colorStyles-BWpj_h4C.mjs} +88 -1
  139. package/dist/client/{courseRegistration-Z_mn18jy.mjs → courseRegistration-CxCBybB4.mjs} +6 -6
  140. package/dist/client/{eventCalendar-CYp0YJGF.mjs → eventCalendar-Xj2jZS9X.mjs} +4 -4
  141. package/dist/client/{eventCombined-rKyYZUa9.mjs → eventCombined-CgcMoOgM.mjs} +2 -2
  142. package/dist/client/{eventDetails-X0ZaUuMj.mjs → eventDetails-CEAH8Edc.mjs} +3 -3
  143. package/dist/client/{eventListing-W1SuL7EP.mjs → eventListing-qyPVQ0wP.mjs} +2 -2
  144. package/dist/client/{eventRegistration-ClWricui.mjs → eventRegistration-DDu79CtL.mjs} +6 -6
  145. package/dist/client/{form--eKPwAAD.mjs → form-Bc7JKI7I.mjs} +1 -1
  146. package/dist/client/{headerSection-BSeGr-FS.mjs → headerSection-vTku_LEl.mjs} +2 -2
  147. package/dist/client/hooks.mjs +373 -555
  148. package/dist/client/{locationMap-BpOrtNYn.mjs → locationMap-Bg7X4Jna.mjs} +3 -3
  149. package/dist/client/{media-DoF0dcVx.mjs → media-CNE1Z-wb.mjs} +1 -2
  150. package/dist/client/{newsletterForm-Bt7it7Dy.mjs → newsletterForm-lpylVdp5.mjs} +1 -1
  151. package/dist/client/{pricing-BTjSDDr4.mjs → pricing-DE8fjJiT.mjs} +1 -1
  152. package/dist/client/{productDetail-ICnVTcCg.mjs → productDetail-D7Bo2RMH.mjs} +3 -3
  153. package/dist/client/{productList-ZHr6D604.mjs → productList-VjnZqiqN.mjs} +3 -3
  154. package/dist/client/{propsDecoder-wWN0tBDF.mjs → propsDecoder-DreFXjNP.mjs} +2212 -621
  155. package/dist/client/rendering/client.mjs +21612 -21646
  156. package/dist/client/rendering/islands.mjs +20 -20
  157. package/dist/client/rendering.mjs +1528 -1546
  158. package/dist/client/{shop-C1u_BUn0.mjs → shop-IRsHHbf7.mjs} +5 -5
  159. package/dist/client/{shop-commerce-CleZdRha.mjs → shop-commerce-gnI8PieZ.mjs} +27 -10
  160. package/dist/client/{shop-commerce-store-ycnoB2Ce.mjs → shop-commerce-store-BTbrhObn.mjs} +1 -1
  161. package/dist/client/{shopShared-CPhByt2a.mjs → shopShared-D6KS2_qk.mjs} +3 -3
  162. package/dist/client/{useDiscountCodeUi-cStSQI6C.mjs → useDiscountCodeUi-DCccGCxV.mjs} +1 -1
  163. package/dist/client/{useEventFilters-DKPN7hSY.mjs → useEventFilters-eGs3rPZQ.mjs} +3 -104
  164. package/dist/client/{usePolling-BKAd6pkZ.mjs → usePolling-CvSU2sur.mjs} +2 -2
  165. package/dist/preview-next/before-render.mjs +57 -0
  166. package/dist/preview-next/client/runtime.mjs +4 -4
  167. package/dist/preview-next/middleware.mjs +57 -0
  168. package/dist/{previewAuthStore-BkT1D06A.mjs → previewAuthStore-DN7vcRsv.mjs} +57 -0
  169. package/dist/{sdk-runtime-hu3wr3ng.mjs → sdk-runtime-vW8QbyPN.mjs} +2 -2
  170. package/dist/{separator-Bln8izQ9.mjs → separator-DJ4bkeY3.mjs} +1 -1
  171. package/dist/server/components.mjs +3638 -3696
  172. package/dist/server/config-template-validation.mjs +4 -23
  173. package/dist/server/config-validation.mjs +373 -555
  174. package/dist/server/config.mjs +410 -558
  175. package/dist/server/data.mjs +373 -555
  176. package/dist/server/index.mjs +58 -1
  177. package/dist/server/next.mjs +32384 -32394
  178. package/dist/server/page-converter.mjs +369 -526
  179. package/dist/server/prebuild.mjs +1 -1
  180. package/dist/server/rendering/server.mjs +5329 -3174
  181. package/dist/server/rendering.mjs +3645 -3712
  182. package/dist/server/routing.mjs +758 -966
  183. package/dist/server/server.mjs +448 -632
  184. package/dist/server/theme-bridge.mjs +472 -525
  185. package/dist/server/theme.mjs +1074 -392
  186. package/package.json +1 -1
  187. package/dist/_dts/blocks/src/primitives/content/components/Button.d.ts +0 -40
  188. package/dist/_dts/blocks/src/system/fragments/library/footerBottomText.d.ts +0 -19
  189. package/dist/_dts/media-core/src/legacyMediaValue.d.ts +0 -11
  190. package/dist/_dts/theme-core/src/styles/buttons.d.ts +0 -27
  191. package/dist/_dts/theme-core/src/styles/buttonsLibrary.d.ts +0 -2
  192. package/dist/_dts/theme-core/src/styles/glow.d.ts +0 -3
  193. package/dist/client/colorStyles-gcTh5yZT.mjs +0 -89
@@ -6667,6 +6667,63 @@ const API_ENDPOINTS$1 = {
6667
6667
  auth: "service",
6668
6668
  responseKind: "json"
6669
6669
  },
6670
+ sdkListEventOccurrences: {
6671
+ path: "/sdk/{siteId}/events/{identifier}/occurrences",
6672
+ method: "GET",
6673
+ auth: "service",
6674
+ responseKind: "json",
6675
+ errors: [
6676
+ "resource:not_found",
6677
+ "validation:invalid_input",
6678
+ "server:internal_error"
6679
+ ]
6680
+ },
6681
+ sdkAddEventOccurrence: {
6682
+ path: "/sdk/{siteId}/events/{identifier}/occurrences",
6683
+ method: "POST",
6684
+ auth: "service",
6685
+ responseKind: "json",
6686
+ errors: [
6687
+ "resource:not_found",
6688
+ "validation:invalid_input",
6689
+ "resource:conflict",
6690
+ "server:internal_error"
6691
+ ]
6692
+ },
6693
+ sdkUpdateEventOccurrence: {
6694
+ path: "/sdk/{siteId}/events/{identifier}/occurrences/{occurrenceId}",
6695
+ method: "PATCH",
6696
+ auth: "service",
6697
+ responseKind: "json",
6698
+ errors: [
6699
+ "resource:not_found",
6700
+ "validation:invalid_input",
6701
+ "resource:conflict",
6702
+ "server:internal_error"
6703
+ ]
6704
+ },
6705
+ sdkCancelEventOccurrence: {
6706
+ path: "/sdk/{siteId}/events/{identifier}/occurrences/{occurrenceId}/cancel",
6707
+ method: "POST",
6708
+ auth: "service",
6709
+ responseKind: "json",
6710
+ errors: [
6711
+ "resource:not_found",
6712
+ "resource:conflict",
6713
+ "server:internal_error"
6714
+ ]
6715
+ },
6716
+ sdkDeleteEventOccurrence: {
6717
+ path: "/sdk/{siteId}/events/{identifier}/occurrences/{occurrenceId}",
6718
+ method: "DELETE",
6719
+ auth: "service",
6720
+ responseKind: "json",
6721
+ errors: [
6722
+ "resource:not_found",
6723
+ "resource:conflict",
6724
+ "server:internal_error"
6725
+ ]
6726
+ },
6670
6727
  sdkListCourses: {
6671
6728
  path: "/sdk/{siteId}/courses",
6672
6729
  method: "GET",
@@ -7222,20 +7279,20 @@ function isApiError(result) {
7222
7279
  function isApiSuccess(result) {
7223
7280
  return result.success === true;
7224
7281
  }
7225
- function isRecord$32(value) {
7282
+ function isRecord$35(value) {
7226
7283
  return typeof value === "object" && value !== null && !Array.isArray(value);
7227
7284
  }
7228
7285
  function isFieldError(value) {
7229
- return isRecord$32(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7286
+ return isRecord$35(value) && typeof value.field === "string" && typeof value.code === "string" && typeof value.message === "string";
7230
7287
  }
7231
7288
  function fieldErrorsFromUnknown(value) {
7232
7289
  if (!Array.isArray(value)) return null;
7233
7290
  return value.every(isFieldError) ? value : null;
7234
7291
  }
7235
7292
  function extractEnvelopeErrorObject(body) {
7236
- if (!isRecord$32(body)) return null;
7293
+ if (!isRecord$35(body)) return null;
7237
7294
  const error = body.error;
7238
- if (!isRecord$32(error)) return null;
7295
+ if (!isRecord$35(error)) return null;
7239
7296
  if ("success" in body && body.success !== false) return null;
7240
7297
  return error;
7241
7298
  }
@@ -7499,7 +7556,7 @@ var init_event_pricing = __esmMin((() => {
7499
7556
  //#endregion
7500
7557
  //#region ../core/src/event-page-surface-subject.ts
7501
7558
  function parseEventPageSurfaceSubject(value) {
7502
- if (!isRecord$31(value)) return err$2({ kind: "notObject" });
7559
+ if (!isRecord$34(value)) return err$2({ kind: "notObject" });
7503
7560
  switch (value.kind) {
7504
7561
  case "eventSeries": {
7505
7562
  const eventSeriesId = parseEventSeriesId(value.eventSeriesId);
@@ -7542,7 +7599,7 @@ function parseEventPageSurfaceSubject(value) {
7542
7599
  });
7543
7600
  }
7544
7601
  }
7545
- function isRecord$31(value) {
7602
+ function isRecord$34(value) {
7546
7603
  return typeof value === "object" && value !== null && !Array.isArray(value);
7547
7604
  }
7548
7605
  var init_event_page_surface_subject = __esmMin((() => {
@@ -7956,8 +8013,40 @@ var init_public_url_validation = __esmMin((() => {}));
7956
8013
  var init_public_profile = __esmMin((() => {
7957
8014
  init_public_url_validation();
7958
8015
  init_result();
8016
+ }));
8017
+ //#endregion
8018
+ //#region ../core/src/rich-text.ts
8019
+ function isRecord$32(value) {
8020
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8021
+ }
8022
+ function hasOnlyKeys(value, allowed) {
8023
+ return Object.keys(value).every((key) => allowed.has(key));
8024
+ }
8025
+ function isDenseArrayOf(value, predicate) {
8026
+ for (let index = 0; index < value.length; index += 1) if (!(index in value) || !predicate(value[index])) return false;
8027
+ return true;
8028
+ }
8029
+ function isTipTapMark(value) {
8030
+ return isRecord$32(value) && hasOnlyKeys(value, markKeys) && typeof value.type === "string" && value.type.length > 0 && (value.attrs === void 0 || isRecord$32(value.attrs));
8031
+ }
8032
+ function isTipTapNode(value) {
8033
+ if (!isRecord$32(value) || !hasOnlyKeys(value, nodeKeys) || typeof value.type !== "string" || value.type.length === 0 || value.type === "doc" || value.attrs !== void 0 && !isRecord$32(value.attrs) || value.marks !== void 0 && (!Array.isArray(value.marks) || !isDenseArrayOf(value.marks, isTipTapMark)) || value.content !== void 0 && (!Array.isArray(value.content) || !isDenseArrayOf(value.content, isTipTapNode))) return false;
8034
+ if (value.type === "text") return typeof value.text === "string" && value.text.length > 0 && value.content === void 0;
8035
+ return value.text === void 0;
8036
+ }
8037
+ var nodeKeys, markKeys;
8038
+ var init_rich_text = __esmMin((() => {
8039
+ nodeKeys = /* @__PURE__ */ new Set([
8040
+ "type",
8041
+ "content",
8042
+ "text",
8043
+ "attrs",
8044
+ "marks"
8045
+ ]);
8046
+ markKeys = /* @__PURE__ */ new Set(["type", "attrs"]);
7959
8047
  })), sectionKinds;
7960
8048
  var init_footer_composition = __esmMin((() => {
8049
+ init_rich_text();
7961
8050
  init_result();
7962
8051
  sectionKinds = [
7963
8052
  "brand",
@@ -8070,6 +8159,7 @@ var init_src$3 = __esmMin((() => {
8070
8159
  init_participant_identity();
8071
8160
  init_public_url_validation();
8072
8161
  init_public_profile();
8162
+ init_rich_text();
8073
8163
  init_footer_composition();
8074
8164
  init_number_input();
8075
8165
  init_field_errors();
@@ -8369,7 +8459,7 @@ function formatKeyAsLabel(key) {
8369
8459
  return key.replace(/([A-Z])/g, " $1").replace(/[-_]/g, " ").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
8370
8460
  }
8371
8461
  var init_augmentManifest = __esmMin((() => {}));
8372
- var init_types$17 = __esmMin((() => {}));
8462
+ var init_types$16 = __esmMin((() => {}));
8373
8463
  //#endregion
8374
8464
  //#region ../media-core/src/fileSafety.ts
8375
8465
  function containsUnsafePathSegmentCharacter(value) {
@@ -8494,11 +8584,11 @@ var init_storagePathDomain = __esmMin((() => {}));
8494
8584
  var init_fileAssetLegacyProjection = __esmMin((() => {}));
8495
8585
  //#endregion
8496
8586
  //#region ../media-core/src/typeGuards.ts
8497
- function isRecord$27(value) {
8587
+ function isRecord$29(value) {
8498
8588
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8499
8589
  }
8500
8590
  function asRecord$3(value) {
8501
- return isRecord$27(value) ? value : void 0;
8591
+ return isRecord$29(value) ? value : void 0;
8502
8592
  }
8503
8593
  var init_typeGuards$1 = __esmMin((() => {}));
8504
8594
  function isFileJsonObject(value) {
@@ -8508,7 +8598,7 @@ function isFileJsonValue(value) {
8508
8598
  if (value === null || typeof value === "string" || typeof value === "boolean") return true;
8509
8599
  if (typeof value === "number") return Number.isFinite(value);
8510
8600
  if (Array.isArray(value)) return value.every(isFileJsonValue);
8511
- return isRecord$27(value) && isFileJsonObject(value);
8601
+ return isRecord$29(value) && isFileJsonObject(value);
8512
8602
  }
8513
8603
  var init_filePersistence = __esmMin((() => {
8514
8604
  init_src$3();
@@ -8873,7 +8963,7 @@ function isCmsMediaObjectType(value) {
8873
8963
  return typeof value === "string" && CMS_MEDIA_OBJECT_TYPES.includes(value);
8874
8964
  }
8875
8965
  function isCmsMediaObject(value) {
8876
- if (!isRecord$27(value)) return false;
8966
+ if (!isRecord$29(value)) return false;
8877
8967
  const type = value.type;
8878
8968
  if (!isCmsMediaObjectType(type)) return false;
8879
8969
  if ("attrs" in value) return false;
@@ -8884,13 +8974,25 @@ function collectMediaObjects(value, out, location = "") {
8884
8974
  value.forEach((item, index) => collectMediaObjects(item, out, `${location}[${index}]`));
8885
8975
  return;
8886
8976
  }
8887
- if (!isRecord$27(value)) return;
8977
+ if (!isRecord$29(value)) return;
8888
8978
  if (isCmsMediaObject(value)) out.push({
8889
8979
  obj: value,
8890
8980
  location
8891
8981
  });
8892
8982
  for (const [key, child] of Object.entries(value)) collectMediaObjects(child, out, location ? `${location}.${key}` : key);
8893
8983
  }
8984
+ /**
8985
+ * Strip environment-specific keys from a CMS media object.
8986
+ * @mutates Mutates the passed object in-place.
8987
+ */
8988
+ function deleteEnvSpecificKeys(obj) {
8989
+ delete obj.assetId;
8990
+ delete obj.storageBucket;
8991
+ delete obj.storagePath;
8992
+ delete obj.src;
8993
+ delete obj.mimeType;
8994
+ if (looksLikeUuid(obj.id)) delete obj.id;
8995
+ }
8894
8996
  var CMS_MEDIA_OBJECT_TYPES;
8895
8997
  var init_mediaRefNormalizer = __esmMin((() => {
8896
8998
  init_typeGuards$1();
@@ -8918,8 +9020,8 @@ function walkAndCollectImageAttrs(value, out, location = "") {
8918
9020
  value.forEach((item, index) => walkAndCollectImageAttrs(item, out, `${location}[${index}]`));
8919
9021
  return;
8920
9022
  }
8921
- if (!isRecord$27(value)) return;
8922
- if (value.type === "image" && isRecord$27(value.attrs)) out.push({
9023
+ if (!isRecord$29(value)) return;
9024
+ if (value.type === "image" && isRecord$29(value.attrs)) out.push({
8923
9025
  attrs: value.attrs,
8924
9026
  location: location ? `${location}.attrs` : "attrs"
8925
9027
  });
@@ -8978,25 +9080,239 @@ function mediaIdentifierOrFallback(current, fallback) {
8978
9080
  }
8979
9081
  var init_renderableMediaAsset = __esmMin((() => {}));
8980
9082
  //#endregion
8981
- //#region ../media-core/src/legacyMediaValue.ts
8982
- function legacyStringMediaTypeForField(field) {
8983
- if (field.type === "file") return field.fileKinds?.[0] ?? "document";
8984
- return field.mediaKinds?.[0] ?? "image";
9083
+ //#region ../media-core/src/contentMediaAudit.ts
9084
+ function isRecord$28(value) {
9085
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8985
9086
  }
8986
- function normalizeLegacyStringMediaValueForField(value, field) {
8987
- if (typeof value !== "string") return value;
8988
- const src = value.trim();
8989
- if (!src) return value;
8990
- return {
8991
- type: legacyStringMediaTypeForField(field),
8992
- src
8993
- };
9087
+ function summarizeContentMediaValue(value) {
9088
+ if (typeof value === "string") {
9089
+ const trimmed = value.trim();
9090
+ if (!trimmed) return "blank string";
9091
+ return trimmed.length <= 160 ? trimmed : `${trimmed.slice(0, 157)}...`;
9092
+ }
9093
+ if (value === null) return "null";
9094
+ if (Array.isArray(value)) return `array(${value.length})`;
9095
+ if (isRecord$28(value)) return `object(${Object.keys(value).sort().join(",")})`;
9096
+ return typeof value;
8994
9097
  }
8995
- var init_legacyMediaValue = __esmMin((() => {}));
9098
+ function auditMediaValue(context, path, allowedMediaTypes, value) {
9099
+ const expectedMediaType = allowedMediaTypes[0];
9100
+ if (value === void 0 || value === null) return [];
9101
+ if (typeof value === "string") {
9102
+ if (!value.trim()) return [{
9103
+ tag: "blank-string",
9104
+ context,
9105
+ path,
9106
+ valueSummary: summarizeContentMediaValue(value),
9107
+ expectedMediaType
9108
+ }];
9109
+ return [{
9110
+ tag: "legacy-string",
9111
+ context,
9112
+ path,
9113
+ valueSummary: summarizeContentMediaValue(value),
9114
+ originalValue: value,
9115
+ expectedMediaType,
9116
+ allowedMediaTypes
9117
+ }];
9118
+ }
9119
+ const hasValidIdentifier = isRecord$28(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
9120
+ const hasValidExplicitType = isRecord$28(value) && (!("type" in value) || typeof value.type === "string" && allowedMediaTypes.includes(value.type));
9121
+ const hasRetiredEnvironmentField = isRecord$28(value) && ("assetId" in value || "storagePath" in value || "storageBucket" in value || "src" in value || "mimeType" in value || looksLikeUuid(value.id));
9122
+ if (hasValidIdentifier && hasValidExplicitType && !hasRetiredEnvironmentField) return [];
9123
+ return [{
9124
+ tag: "malformed-object",
9125
+ context,
9126
+ path,
9127
+ valueSummary: summarizeContentMediaValue(value),
9128
+ expectedMediaType
9129
+ }];
9130
+ }
9131
+ function auditFields(context, fields, value, parentPath) {
9132
+ if (!isRecord$28(value)) return [];
9133
+ const findings = [];
9134
+ for (const field of fields) {
9135
+ if (!(field.id in value)) continue;
9136
+ const fieldValue = value[field.id];
9137
+ const fieldPath = [...parentPath, field.id];
9138
+ switch (field.kind) {
9139
+ case "media":
9140
+ findings.push(...auditMediaValue(context, fieldPath, field.allowedMediaTypes, fieldValue));
9141
+ break;
9142
+ case "object":
9143
+ findings.push(...auditFields(context, field.fields, fieldValue, fieldPath));
9144
+ break;
9145
+ case "repeater":
9146
+ if (!Array.isArray(fieldValue)) break;
9147
+ for (const [index, item] of fieldValue.entries()) {
9148
+ const itemPath = [...fieldPath, index];
9149
+ if (!isRecord$28(item)) {
9150
+ findings.push({
9151
+ tag: "missing-schema",
9152
+ context,
9153
+ path: itemPath,
9154
+ valueSummary: summarizeContentMediaValue(item)
9155
+ });
9156
+ continue;
9157
+ }
9158
+ if (field.mode === "fields") {
9159
+ findings.push(...auditFields(context, field.fields, item, itemPath));
9160
+ continue;
9161
+ }
9162
+ const discriminator = field.discriminator ?? "_type";
9163
+ const typeId = item[discriminator];
9164
+ const variant = typeof typeId === "string" ? field.variants.find((candidate) => candidate.typeId === typeId) : void 0;
9165
+ if (variant) findings.push(...auditFields(context, variant.fields, item, itemPath));
9166
+ else findings.push({
9167
+ tag: "missing-schema",
9168
+ context,
9169
+ path: [...itemPath, discriminator],
9170
+ valueSummary: summarizeContentMediaValue(typeId)
9171
+ });
9172
+ }
9173
+ break;
9174
+ }
9175
+ }
9176
+ return findings;
9177
+ }
9178
+ var init_contentMediaAudit = __esmMin((() => {
9179
+ init_mediaRefNormalizer();
9180
+ }));
9181
+ //#endregion
9182
+ //#region ../media-core/src/contentMediaAuditFieldAdapter.ts
9183
+ function isRecord$27(value) {
9184
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9185
+ }
9186
+ function unknownArray(value) {
9187
+ return Array.isArray(value) ? value : null;
9188
+ }
9189
+ function fieldsArray(value) {
9190
+ const directFields = unknownArray(value);
9191
+ if (directFields) return directFields;
9192
+ if (!isRecord$27(value)) return null;
9193
+ return unknownArray(value.fields);
9194
+ }
9195
+ function nestedFields(field) {
9196
+ const directFields = unknownArray(field.fields);
9197
+ if (directFields) return directFields;
9198
+ return fieldsArray(field.schema) ?? [];
9199
+ }
9200
+ function allowedMediaTypes(field, fieldType, defaultFileKinds) {
9201
+ const configured = fieldType === "media" ? field.mediaKinds : field.fileKinds;
9202
+ const parsed = Array.isArray(configured) ? configured.filter((value) => typeof value === "string" && contentMediaTypes.has(value)) : [];
9203
+ if (parsed.length > 0) return parsed;
9204
+ return fieldType === "media" ? ["image"] : defaultFileKinds;
9205
+ }
9206
+ function mergeVariants(variants) {
9207
+ const merged = /* @__PURE__ */ new Map();
9208
+ for (const variant of variants) merged.set(variant.typeId, mergeFields([...merged.get(variant.typeId) ?? [], ...variant.fields]));
9209
+ return [...merged].map(([typeId, fields]) => ({
9210
+ typeId,
9211
+ fields
9212
+ }));
9213
+ }
9214
+ function mergeFields(fields) {
9215
+ const merged = [];
9216
+ for (const field of fields) {
9217
+ const index = merged.findIndex((candidate) => candidate.kind === field.kind && candidate.id === field.id);
9218
+ const existing = index === -1 ? void 0 : merged[index];
9219
+ if (!existing) {
9220
+ merged.push(field);
9221
+ continue;
9222
+ }
9223
+ if (existing.kind === "media" && field.kind === "media") {
9224
+ merged[index] = {
9225
+ ...existing,
9226
+ allowedMediaTypes: [.../* @__PURE__ */ new Set([...existing.allowedMediaTypes, ...field.allowedMediaTypes])]
9227
+ };
9228
+ continue;
9229
+ }
9230
+ if (existing.kind === "object" && field.kind === "object") {
9231
+ merged[index] = {
9232
+ ...existing,
9233
+ fields: mergeFields([...existing.fields, ...field.fields])
9234
+ };
9235
+ continue;
9236
+ }
9237
+ if (existing.kind === "repeater" && field.kind === "repeater" && existing.mode === "fields" && field.mode === "fields") {
9238
+ merged[index] = {
9239
+ ...existing,
9240
+ fields: mergeFields([...existing.fields, ...field.fields])
9241
+ };
9242
+ continue;
9243
+ }
9244
+ if (existing.kind === "repeater" && field.kind === "repeater" && existing.mode === "variants" && field.mode === "variants") {
9245
+ merged[index] = {
9246
+ ...existing,
9247
+ variants: mergeVariants([...existing.variants, ...field.variants])
9248
+ };
9249
+ continue;
9250
+ }
9251
+ merged.push(field);
9252
+ }
9253
+ return merged;
9254
+ }
9255
+ function adaptFields(rawFields, flattenRepeaterGroups = false, defaultFileKinds = ["document"]) {
9256
+ return mergeFields(rawFields.flatMap((rawField) => {
9257
+ if (!isRecord$27(rawField)) return [];
9258
+ const { id, type } = rawField;
9259
+ if (typeof id !== "string" || !id || typeof type !== "string") return [];
9260
+ if (type === "media" || type === "file") return [{
9261
+ kind: "media",
9262
+ id,
9263
+ allowedMediaTypes: allowedMediaTypes(rawField, type, defaultFileKinds)
9264
+ }];
9265
+ if (flattenRepeaterGroups && type === "group" && isRecord$27(rawField.ui) && rawField.ui.flattenInRepeater === true) return adaptFields(nestedFields(rawField), false, defaultFileKinds);
9266
+ if (type === "group" || type === "modal") return [{
9267
+ kind: "object",
9268
+ id,
9269
+ fields: adaptFields(nestedFields(rawField), false, defaultFileKinds)
9270
+ }];
9271
+ if (type === "tabGroup") return [{
9272
+ kind: "object",
9273
+ id,
9274
+ fields: adaptFields((unknownArray(rawField.tabs) ?? []).flatMap((tab) => isRecord$27(tab) ? unknownArray(tab.fields) ?? [] : []), false, defaultFileKinds)
9275
+ }];
9276
+ if (type !== "repeater") return [];
9277
+ if (isRecord$27(rawField.itemTypes)) return [{
9278
+ kind: "repeater",
9279
+ id,
9280
+ mode: "variants",
9281
+ variants: Object.entries(rawField.itemTypes).flatMap(([typeId, itemType]) => isRecord$27(itemType) && Array.isArray(itemType.fields) ? [{
9282
+ typeId,
9283
+ fields: adaptFields(itemType.fields, true, defaultFileKinds)
9284
+ }] : []),
9285
+ discriminator: "_type"
9286
+ }];
9287
+ return [{
9288
+ kind: "repeater",
9289
+ id,
9290
+ mode: "fields",
9291
+ fields: adaptFields(nestedFields(rawField), true, defaultFileKinds)
9292
+ }];
9293
+ }));
9294
+ }
9295
+ var contentMediaTypes;
9296
+ var init_contentMediaAuditFieldAdapter = __esmMin((() => {
9297
+ contentMediaTypes = /* @__PURE__ */ new Set([
9298
+ "image",
9299
+ "video",
9300
+ "audio",
9301
+ "document",
9302
+ "spreadsheet",
9303
+ "archive"
9304
+ ]);
9305
+ }));
9306
+ var init_contentMediaSnapshotAudit = __esmMin((() => {
9307
+ init_src$3();
9308
+ init_contentMediaAudit();
9309
+ init_contentMediaAuditFieldAdapter();
9310
+ init_identifiers();
9311
+ }));
8996
9312
  //#endregion
8997
9313
  //#region ../media-core/src/index.ts
8998
9314
  var init_src$2 = __esmMin((() => {
8999
- init_types$17();
9315
+ init_types$16();
9000
9316
  init_fileDomain();
9001
9317
  init_fileStorage();
9002
9318
  init_storagePathDomain();
@@ -9042,7 +9358,9 @@ var init_src$2 = __esmMin((() => {
9042
9358
  init_mediaUsageProjection();
9043
9359
  init_portableMediaReferences();
9044
9360
  init_renderableMediaAsset();
9045
- init_legacyMediaValue();
9361
+ init_contentMediaAudit();
9362
+ init_contentMediaAuditFieldAdapter();
9363
+ init_contentMediaSnapshotAudit();
9046
9364
  }));
9047
9365
  //#endregion
9048
9366
  //#region ../blocks/src/system/types/link.ts
@@ -9373,6 +9691,16 @@ function isDisplayMediaKind(kind) {
9373
9691
  function assertNeverSelectSource(value) {
9374
9692
  throw new Error(`Unhandled select source: ${JSON.stringify(value)}`);
9375
9693
  }
9694
+ function hasMediaDefaultIdentifier(value) {
9695
+ return value !== null && typeof value === "object" && !Array.isArray(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0;
9696
+ }
9697
+ function validateMediaFieldDefault(field, ctx) {
9698
+ if (field.defaultValue !== void 0 && field.defaultValue !== null && !hasMediaDefaultIdentifier(field.defaultValue)) ctx.addIssue({
9699
+ code: z$1.ZodIssueCode.custom,
9700
+ path: ["defaultValue"],
9701
+ message: `${field.type} defaultValue must be null or an object with a non-empty identifier`
9702
+ });
9703
+ }
9376
9704
  function getFieldSchemaInternal() {
9377
9705
  if (_fieldSchemaInternal) return _fieldSchemaInternal;
9378
9706
  _fieldSchemaInternal = z$1.discriminatedUnion("type", [
@@ -9449,7 +9777,7 @@ function createSdkSelectField(input) {
9449
9777
  }
9450
9778
  }));
9451
9779
  }
9452
- var visibilityLevels, MEDIA_KINDS, DISPLAY_MEDIA_KINDS, PUBLIC_FILE_FIELD_KINDS, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, visibleWhenPredicateSchema, visibleWhenSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, inlineTextFieldSchema, mediaFieldSchema, fileFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens$1, colorTokens$1, spacingTokens$1, radiusTokens$1, styleTokenSchema, behaviourSchema, quickFieldPrioritySchema, previewCustomizeManifestCurationSchema, blockCategoryEnum, blockContentSourceKinds, blockContentSourceSchema;
9780
+ var visibilityLevels, MEDIA_KINDS, DISPLAY_MEDIA_KINDS, DEFAULT_MEDIA_FIELD_KINDS, PUBLIC_FILE_FIELD_KINDS, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, visibleWhenPredicateSchema, visibleWhenSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, inlineTextFieldSchema, mediaFieldSchema, fileFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens$1, colorTokens$1, spacingTokens$1, radiusTokens$1, styleTokenSchema, behaviourSchema, quickFieldPrioritySchema, previewCustomizeManifestCurationSchema, blockCategoryEnum, blockContentSourceKinds, blockContentSourceSchema;
9453
9781
  var init_schema$1 = __esmMin((() => {
9454
9782
  init_node();
9455
9783
  init_repeaterGrid();
@@ -9472,6 +9800,7 @@ var init_schema$1 = __esmMin((() => {
9472
9800
  "video",
9473
9801
  "audio"
9474
9802
  ];
9803
+ DEFAULT_MEDIA_FIELD_KINDS = ["image"];
9475
9804
  PUBLIC_FILE_FIELD_KINDS = [
9476
9805
  "document",
9477
9806
  "spreadsheet",
@@ -9668,16 +9997,16 @@ var init_schema$1 = __esmMin((() => {
9668
9997
  });
9669
9998
  mediaFieldSchema = baseFieldSchema.extend({
9670
9999
  type: z$1.literal("media"),
9671
- mediaKinds: z$1.array(z$1.enum(MEDIA_KINDS)).default(["image"]).transform((kinds) => {
10000
+ mediaKinds: z$1.array(z$1.enum(MEDIA_KINDS)).default([...DEFAULT_MEDIA_FIELD_KINDS]).transform((kinds) => {
9672
10001
  const displayKinds = kinds.filter(isDisplayMediaKind);
9673
- return displayKinds.length > 0 ? displayKinds : ["image"];
10002
+ return displayKinds.length > 0 ? displayKinds : [...DEFAULT_MEDIA_FIELD_KINDS];
9674
10003
  }),
9675
10004
  aspectRatio: z$1.string().optional()
9676
- });
10005
+ }).superRefine(validateMediaFieldDefault);
9677
10006
  fileFieldSchema = baseFieldSchema.extend({
9678
10007
  type: z$1.literal("file"),
9679
10008
  fileKinds: z$1.array(z$1.enum(PUBLIC_FILE_FIELD_KINDS)).default([...PUBLIC_FILE_FIELD_KINDS])
9680
- });
10009
+ }).superRefine(validateMediaFieldDefault);
9681
10010
  booleanFieldSchema = baseFieldSchema.extend({ type: z$1.literal("boolean") });
9682
10011
  dateFieldSchema = baseFieldSchema.extend({ type: z$1.literal("date") });
9683
10012
  timeFieldSchema = baseFieldSchema.extend({ type: z$1.literal("time") });
@@ -11301,8 +11630,83 @@ function resolveBlockIconRenderValue(value, generatedAssets = /* @__PURE__ */ ne
11301
11630
  }
11302
11631
  }
11303
11632
  //#endregion
11633
+ //#region ../blocks/src/lib/typeGuards.ts
11634
+ /**
11635
+ * Strict record guard: excludes null, primitives, and arrays.
11636
+ */
11637
+ function isRecord$25(value) {
11638
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11639
+ }
11640
+ /**
11641
+ * Non-null object guard: includes arrays for behavior parity with legacy helpers.
11642
+ *
11643
+ * NOTE: This intentionally narrows to UnknownRecord for compatibility with existing
11644
+ * callsites even though arrays pass at runtime. Follow-up cleanup should replace
11645
+ * this API with a more precise predicate type and migrate consumers.
11646
+ */
11647
+ function isObjectRecord$1(value) {
11648
+ return typeof value === "object" && value !== null;
11649
+ }
11650
+ var init_typeGuards = __esmMin((() => {}));
11651
+ //#endregion
11652
+ //#region ../blocks/src/system/manifest/richTextSchema.ts
11653
+ /**
11654
+ * Type guard for {@link RichTextDoc}.
11655
+ *
11656
+ * Returns `true` only for the canonical unwrapped form. The shared structural
11657
+ * contract lives in `@riverbankcms/core`; parity tests keep its dependency-free
11658
+ * guard aligned with this detailed Zod validator.
11659
+ */
11660
+ function isRichTextDoc(value) {
11661
+ return RichTextDocSchema.safeParse(value).success;
11662
+ }
11663
+ var TipTapMarkSchema, TipTapNodeSchema, RichTextDocSchema;
11664
+ var init_richTextSchema = __esmMin((() => {
11665
+ init_typeGuards();
11666
+ TipTapMarkSchema = z$1.object({
11667
+ type: z$1.string().min(1),
11668
+ attrs: z$1.record(z$1.string(), z$1.unknown()).optional()
11669
+ }).strict();
11670
+ TipTapNodeSchema = z$1.lazy(() => z$1.object({
11671
+ type: z$1.string().min(1),
11672
+ content: z$1.array(TipTapNodeSchema).optional(),
11673
+ text: z$1.string().optional(),
11674
+ attrs: z$1.record(z$1.string(), z$1.unknown()).optional(),
11675
+ marks: z$1.array(TipTapMarkSchema).optional()
11676
+ }).strict().superRefine((node, ctx) => {
11677
+ if (node.type === "doc") ctx.addIssue({
11678
+ code: "custom",
11679
+ path: ["type"],
11680
+ message: "Document nodes are only valid at the rich-text root"
11681
+ });
11682
+ if (node.type === "text") {
11683
+ if (node.text === void 0 || node.text.length === 0) ctx.addIssue({
11684
+ code: "custom",
11685
+ path: ["text"],
11686
+ message: "Text nodes require a non-empty text value"
11687
+ });
11688
+ if (node.content !== void 0) ctx.addIssue({
11689
+ code: "custom",
11690
+ path: ["content"],
11691
+ message: "Text nodes cannot contain child nodes"
11692
+ });
11693
+ return;
11694
+ }
11695
+ if (node.text !== void 0) ctx.addIssue({
11696
+ code: "custom",
11697
+ path: ["text"],
11698
+ message: "Only text nodes can contain a text value"
11699
+ });
11700
+ }));
11701
+ RichTextDocSchema = z$1.object({
11702
+ type: z$1.literal("doc"),
11703
+ content: z$1.array(TipTapNodeSchema)
11704
+ }).strict();
11705
+ }));
11706
+ //#endregion
11304
11707
  //#region ../blocks/src/system/manifest/fieldValidation/index.ts
11305
11708
  init_src$2();
11709
+ init_richTextSchema();
11306
11710
  const TEL_RE = /^[+()0-9\s-]{3,}$/;
11307
11711
  const SLUG_PATTERN = /^(?:[a-z0-9]+(?:-[a-z0-9]+)*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*))*$/;
11308
11712
  const ALLOWED_URL_PROTOCOLS = ["http:", "https:"];
@@ -11359,7 +11763,7 @@ function fieldIssueToMessage(issue) {
11359
11763
  case "tooManyItems": return `${issue.label} must have at most ${issue.maximum} ${pluralize(issue.itemLabel, issue.maximum)}`;
11360
11764
  case "invalidRichText": return `${issue.label} must be valid rich text`;
11361
11765
  case "invalidInlineText": return `${issue.label} must be valid styled text`;
11362
- case "invalidMedia": return `${issue.label} must be a valid media item`;
11766
+ case "invalidMedia": return `${issue.label} must be a media object with an identifier`;
11363
11767
  case "invalidLink": return `${issue.label} must be a valid link`;
11364
11768
  case "invalidReference": return `${issue.label} must reference a valid item`;
11365
11769
  default: return assertNever$17(issue);
@@ -11447,7 +11851,7 @@ function deriveFieldValidationPlan(field, path = [field.id]) {
11447
11851
  case "media":
11448
11852
  case "file": return {
11449
11853
  ...makePlan("media", "object", field, path, required, commonConstraints(required, { kind: "mediaObject" })),
11450
- legacyStringType: legacyStringMediaTypeForField(field)
11854
+ allowedMediaTypes: field.type === "media" ? field.mediaKinds ?? DEFAULT_MEDIA_FIELD_KINDS : field.fileKinds ?? PUBLIC_FILE_FIELD_KINDS
11451
11855
  };
11452
11856
  case "link": return makePlan("link", "object", field, path, required, commonConstraints(required, { kind: "linkObject" }));
11453
11857
  case "boolean": return makePlan("boolean", "boolean", field, path, required, requiredConstraints(required));
@@ -11459,12 +11863,25 @@ function deriveFieldValidationPlan(field, path = [field.id]) {
11459
11863
  case "group":
11460
11864
  case "modal": return {
11461
11865
  ...makePlan("group", "object", field, path, required, requiredConstraints(required)),
11462
- children: deriveNestedFieldPlans(field.schema?.fields ?? [], path),
11866
+ childSelection: {
11867
+ kind: "all",
11868
+ fields: deriveNestedFieldPlans(field.schema?.fields ?? [], path)
11869
+ },
11463
11870
  allowNullChildren: field.type === "group" && field.ui?.widget === "locationPicker"
11464
11871
  };
11465
11872
  case "tabGroup": return {
11466
11873
  ...makePlan("group", "object", field, path, required, requiredConstraints(required)),
11467
- children: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path))
11874
+ childSelection: field.activeTabField ? {
11875
+ kind: "discriminatedTabs",
11876
+ activeTabField: field.activeTabField,
11877
+ tabs: field.tabs.map((tab) => ({
11878
+ typeId: tab.id,
11879
+ fields: deriveNestedFieldPlans(tab.fields, path)
11880
+ }))
11881
+ } : {
11882
+ kind: "all",
11883
+ fields: field.tabs.flatMap((tab) => deriveNestedFieldPlans(tab.fields, path))
11884
+ }
11468
11885
  };
11469
11886
  case "presetOrCustom":
11470
11887
  case "contentTypeSelect":
@@ -11559,10 +11976,59 @@ function normalizeStoredContentValues(plans, content, options = {}) {
11559
11976
  normalizeInlineTextFallbacks(plans, normalized, ctx);
11560
11977
  return normalized;
11561
11978
  }
11979
+ function allGroupChildPlans(plan) {
11980
+ switch (plan.childSelection.kind) {
11981
+ case "all": return plan.childSelection.fields;
11982
+ case "discriminatedTabs": return plan.childSelection.tabs.flatMap((tab) => tab.fields);
11983
+ default: return assertNever$17(plan.childSelection);
11984
+ }
11985
+ }
11986
+ function selectedGroupChildPlans(plan, value) {
11987
+ if (plan.childSelection.kind === "all") return plan.childSelection.fields;
11988
+ if (!isPlainObject$4(value)) return [];
11989
+ const selectedType = value[plan.childSelection.activeTabField];
11990
+ return plan.childSelection.tabs.find((tab) => tab.typeId === selectedType)?.fields ?? [];
11991
+ }
11992
+ function canonicalizeFieldValueForWrite(plan, value) {
11993
+ switch (plan.kind) {
11994
+ case "media": {
11995
+ if (!isPlainObject$4(value)) return value;
11996
+ const canonical = { ...value };
11997
+ if (typeof canonical.identifier === "string" && canonical.identifier.trim().length > 0) deleteEnvSpecificKeys(canonical);
11998
+ return canonical;
11999
+ }
12000
+ case "group": return canonicalizeObjectForWrite(selectedGroupChildPlans(plan, value), value);
12001
+ case "repeater":
12002
+ if (!isUnknownArray$3(value)) return value;
12003
+ return value.map((item) => {
12004
+ if (!isPlainObject$4(item)) return item;
12005
+ const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
12006
+ return childPlans ? canonicalizeObjectForWrite(childPlans, item) : item;
12007
+ });
12008
+ case "string":
12009
+ case "number":
12010
+ case "boolean":
12011
+ case "richText":
12012
+ case "inlineText":
12013
+ case "link":
12014
+ case "select":
12015
+ case "passthrough": return value;
12016
+ default: return assertNever$17(plan);
12017
+ }
12018
+ }
12019
+ function canonicalizeObjectForWrite(plans, value) {
12020
+ if (!isPlainObject$4(value)) return value;
12021
+ const canonical = { ...value };
12022
+ for (const plan of plans) {
12023
+ if (!(plan.fieldId in canonical)) continue;
12024
+ canonical[plan.fieldId] = canonicalizeFieldValueForWrite(plan, canonical[plan.fieldId]);
12025
+ }
12026
+ return canonical;
12027
+ }
11562
12028
  function normalizeStoredFieldValueWithContext(plan, value, ctx) {
11563
12029
  if (value === null && !plan.required) return;
11564
12030
  switch (plan.kind) {
11565
- case "group": return normalizeStoredObjectChildren(plan.children, value, childValidationContext(plan, ctx));
12031
+ case "group": return normalizeStoredObjectChildren(selectedGroupChildPlans(plan, value), value, childValidationContext(plan, ctx));
11566
12032
  case "repeater": return normalizeStoredRepeaterItems(plan, value, ctx);
11567
12033
  case "string":
11568
12034
  case "number":
@@ -11584,7 +12050,7 @@ function normalizeStoredObjectChildren(children, value, ctx) {
11584
12050
  return normalized;
11585
12051
  }
11586
12052
  function normalizeStoredRepeaterItems(plan, value, ctx) {
11587
- if (!isUnknownArray$4(value)) return value;
12053
+ if (!isUnknownArray$3(value)) return value;
11588
12054
  return value.map((item) => {
11589
12055
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
11590
12056
  const itemRecord = item;
@@ -11601,7 +12067,7 @@ function normalizeFieldValue(plan, value, ctx) {
11601
12067
  switch (plan.kind) {
11602
12068
  case "number": return normalizeNumberInput(value, ctx.allowNull);
11603
12069
  case "string": return acceptsOptionalBlankAsMissing(plan, value) ? void 0 : value;
11604
- case "group": return normalizeObjectChildren(plan.children, value, childValidationContext(plan, ctx));
12070
+ case "group": return normalizeObjectChildren(selectedGroupChildPlans(plan, value), value, childValidationContext(plan, ctx));
11605
12071
  case "repeater": return normalizeRepeaterItems(plan, value, ctx);
11606
12072
  case "boolean":
11607
12073
  case "richText":
@@ -11609,17 +12075,10 @@ function normalizeFieldValue(plan, value, ctx) {
11609
12075
  case "link":
11610
12076
  case "select":
11611
12077
  case "passthrough": return value;
11612
- case "media": return normalizeMediaInput(plan, value);
12078
+ case "media": return value;
11613
12079
  default: return assertNever$17(plan);
11614
12080
  }
11615
12081
  }
11616
- function normalizeMediaInput(plan, value) {
11617
- return normalizeLegacyStringMediaValueForField(value, {
11618
- type: plan.fieldType,
11619
- mediaKinds: plan.fieldType === "media" ? [plan.legacyStringType] : void 0,
11620
- fileKinds: plan.fieldType === "file" ? [plan.legacyStringType] : void 0
11621
- });
11622
- }
11623
12082
  function normalizeObjectChildren(children, value, ctx) {
11624
12083
  if (!value || typeof value !== "object" || Array.isArray(value)) return value;
11625
12084
  const normalized = { ...value };
@@ -11643,7 +12102,7 @@ function getAtFieldPath(source, path) {
11643
12102
  }, source);
11644
12103
  }
11645
12104
  function normalizeRepeaterItems(plan, value, ctx) {
11646
- if (!isUnknownArray$4(value)) return value;
12105
+ if (!isUnknownArray$3(value)) return value;
11647
12106
  return value.map((item) => {
11648
12107
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
11649
12108
  const itemRecord = item;
@@ -11671,7 +12130,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
11671
12130
  case "select": return validateSelectPlan(plan, value);
11672
12131
  case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
11673
12132
  case "inlineText": return validateInlineTextPlan(plan, value);
11674
- case "media": return isPlainObject$4(value) ? [] : [issue(plan, "invalidMedia")];
12133
+ case "media": return isPlainObject$4(value) && typeof value.identifier === "string" && value.identifier.trim().length > 0 && (value.type === void 0 || typeof value.type === "string" && plan.allowedMediaTypes.includes(value.type)) ? [] : [issue(plan, "invalidMedia")];
11675
12134
  case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
11676
12135
  case "repeater": return validateRepeaterPlan(plan, value, ctx);
11677
12136
  case "group": return validateGroupPlan(plan, value, ctx);
@@ -11764,9 +12223,26 @@ function validateRepeaterPlan(plan, value, ctx) {
11764
12223
  }), ...value.flatMap((item, index) => validateRepeaterItem(plan, item, index, ctx))];
11765
12224
  }
11766
12225
  function validateRepeaterItem(plan, item, index, ctx) {
11767
- if (!isPlainObject$4(item)) return [];
12226
+ if (!isPlainObject$4(item)) return [{
12227
+ kind: "wrongType",
12228
+ path: [...plan.path, index],
12229
+ fieldId: plan.fieldId,
12230
+ label: plan.label,
12231
+ expected: "an object"
12232
+ }];
11768
12233
  const itemType = item._type;
11769
- const fields = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemType)?.fields : plan.repeatedItemPlan;
12234
+ const variant = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((candidate) => candidate.typeId === itemType) : void 0;
12235
+ if (plan.repeatedItemVariants && !variant) return [{
12236
+ kind: "invalidOption",
12237
+ path: [
12238
+ ...plan.path,
12239
+ index,
12240
+ "_type"
12241
+ ],
12242
+ fieldId: "_type",
12243
+ label: `${plan.label} item type`
12244
+ }];
12245
+ const fields = variant?.fields ?? plan.repeatedItemPlan;
11770
12246
  if (!fields) return [];
11771
12247
  return fields.flatMap((childPlan) => {
11772
12248
  return validateNormalizedFieldValue(materializeRepeaterItemPlan(childPlan, plan.path, index), item[childPlan.fieldId], ctx);
@@ -11774,8 +12250,17 @@ function validateRepeaterItem(plan, item, index, ctx) {
11774
12250
  }
11775
12251
  function validateGroupPlan(plan, value, ctx) {
11776
12252
  if (!isPlainObject$4(value)) return [issue(plan, "wrongType", { expected: "an object" })];
12253
+ if (plan.childSelection.kind === "discriminatedTabs") {
12254
+ const selectedType = value[plan.childSelection.activeTabField];
12255
+ if (selectedType !== void 0 && selectedType !== null && !plan.childSelection.tabs.some((tab) => tab.typeId === selectedType)) return [{
12256
+ kind: "invalidOption",
12257
+ path: [...plan.path, plan.childSelection.activeTabField],
12258
+ fieldId: plan.childSelection.activeTabField,
12259
+ label: `${plan.label} type`
12260
+ }];
12261
+ }
11777
12262
  const childCtx = childValidationContext(plan, ctx);
11778
- return plan.children.flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
12263
+ return selectedGroupChildPlans(plan, value).flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
11779
12264
  }
11780
12265
  function childValidationContext(plan, ctx) {
11781
12266
  return plan.allowNullChildren ? {
@@ -11792,7 +12277,16 @@ function rebaseFieldPlanPath(plan, fromPrefix, toPrefix) {
11792
12277
  case "group": return {
11793
12278
  ...plan,
11794
12279
  path,
11795
- children: plan.children.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
12280
+ childSelection: plan.childSelection.kind === "all" ? {
12281
+ kind: "all",
12282
+ fields: plan.childSelection.fields.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
12283
+ } : {
12284
+ ...plan.childSelection,
12285
+ tabs: plan.childSelection.tabs.map((tab) => ({
12286
+ ...tab,
12287
+ fields: tab.fields.map((childPlan) => rebaseFieldPlanPath(childPlan, fromPrefix, toPrefix))
12288
+ }))
12289
+ }
11796
12290
  };
11797
12291
  case "repeater": return {
11798
12292
  ...plan,
@@ -11948,7 +12442,7 @@ function findFieldValidationPlan(plans, path) {
11948
12442
  }
11949
12443
  function findNestedFieldValidationPlan(plan, path) {
11950
12444
  switch (plan.kind) {
11951
- case "group": return findFieldValidationPlan(plan.children, path);
12445
+ case "group": return findFieldValidationPlan(allGroupChildPlans(plan), path);
11952
12446
  case "repeater": {
11953
12447
  const index = path[plan.path.length];
11954
12448
  if (typeof index !== "number") return null;
@@ -11976,7 +12470,7 @@ function validateExplicitNullsForPush(plans, content, ctx) {
11976
12470
  function validateExplicitNullForPushPlan(plan, value, ctx) {
11977
12471
  if (value === null) return !plan.required && !ctx.allowNull && !acceptsOptionalNullValue(plan) ? validateFieldValue(plan, value, { allowNull: false }) : [];
11978
12472
  switch (plan.kind) {
11979
- case "group": return validateExplicitNullsForPush(plan.children, value, childValidationContext(plan, ctx));
12473
+ case "group": return validateExplicitNullsForPush(selectedGroupChildPlans(plan, value), value, childValidationContext(plan, ctx));
11980
12474
  case "repeater": return validateExplicitNullsForPushRepeater(plan, value, ctx);
11981
12475
  case "string":
11982
12476
  case "number":
@@ -11991,7 +12485,7 @@ function validateExplicitNullForPushPlan(plan, value, ctx) {
11991
12485
  }
11992
12486
  }
11993
12487
  function validateExplicitNullsForPushRepeater(plan, value, ctx) {
11994
- if (!isUnknownArray$4(value)) return [];
12488
+ if (!isUnknownArray$3(value)) return [];
11995
12489
  return value.flatMap((item, index) => {
11996
12490
  if (!isPlainObject$4(item)) return [];
11997
12491
  const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
@@ -12079,27 +12573,21 @@ function isEmptyValue$1(value) {
12079
12573
  function isPlainObject$4(value) {
12080
12574
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
12081
12575
  }
12082
- function isUnknownArray$4(value) {
12576
+ function isUnknownArray$3(value) {
12083
12577
  return Array.isArray(value);
12084
12578
  }
12085
12579
  function isValidRichTextDoc(value) {
12086
- const doc = richTextDoc(value);
12087
- return Boolean(isPlainObject$4(doc) && doc.type === "doc");
12580
+ return isRichTextDoc(value);
12088
12581
  }
12089
12582
  function isEmptyRichTextDoc(value) {
12090
- const doc = richTextDoc(value);
12091
- if (!isPlainObject$4(doc)) return false;
12092
- if (doc.type !== "doc") return false;
12093
- const content = doc.content;
12583
+ if (!isPlainObject$4(value)) return false;
12584
+ if (value.type !== "doc") return false;
12585
+ const content = value.content;
12094
12586
  if (!Array.isArray(content) || content.length === 0) return true;
12095
12587
  if (content.length !== 1) return false;
12096
12588
  const first = content[0];
12097
12589
  return first?.type === "paragraph" && (!Array.isArray(first.content) || first.content.length === 0);
12098
12590
  }
12099
- function richTextDoc(value) {
12100
- if (!isPlainObject$4(value)) return value;
12101
- return isPlainObject$4(value.doc) ? value.doc : value;
12102
- }
12103
12591
  //#endregion
12104
12592
  //#region ../blocks/src/system/manifest/registry.ts
12105
12593
  const REGISTRY_SYMBOL$1 = Symbol.for("@riverbankcms/blocks/manifest-registry");
@@ -12123,11 +12611,14 @@ function preprocessEmptyValues(content) {
12123
12611
  return result;
12124
12612
  }
12125
12613
  function createManifestValidator(manifestOrFields, options = {}) {
12614
+ return createManifestValidatorWithNormalizer(manifestOrFields, options, normalizeStoredContentValues);
12615
+ }
12616
+ function createManifestValidatorWithNormalizer(manifestOrFields, options, normalize) {
12126
12617
  const isDraft = options.mode === "draft";
12127
12618
  const plans = derivePlansFromManifestOrFields(manifestOrFields);
12128
12619
  const baseSchema = deriveContentZodFromPlans(plans, options);
12129
- if (isDraft) return z$1.preprocess((content) => preprocessEmptyValues(normalizeStoredContentValues(plans, content, options)), baseSchema);
12130
- return z$1.preprocess((content) => normalizeStoredContentValues(plans, content, options), baseSchema);
12620
+ if (isDraft) return z$1.preprocess((content) => preprocessEmptyValues(normalize(plans, content, options)), baseSchema);
12621
+ return z$1.preprocess((content) => normalize(plans, content, options), baseSchema);
12131
12622
  }
12132
12623
  function deriveContentZodFromPlans(plans, options) {
12133
12624
  const shape = {};
@@ -12468,7 +12959,7 @@ function defineBlockDesignCapability(capability) {
12468
12959
  };
12469
12960
  }
12470
12961
  var plainFrame, tileTreatmentValues, eventListTreatmentValues, eyebrowTreatmentValues, visibleHeadingDecorationFamilyValues, headingDecorationOverrideValues, headingDecorationColorTokenValues, noHeadingDecoration, accordionIconSetValues, accordionIconColorTokenValues, accordionIconMotionValues;
12471
- var init_types$16 = __esmMin((() => {
12962
+ var init_types$15 = __esmMin((() => {
12472
12963
  plainFrame = { kind: "plain" };
12473
12964
  tileTreatmentValues = [
12474
12965
  "default",
@@ -12533,14 +13024,14 @@ function defineBlockAppearancePreset(preset) {
12533
13024
  return preset;
12534
13025
  }
12535
13026
  var init_appearancePresetResolution = __esmMin((() => {
12536
- init_types$16();
13027
+ init_types$15();
12537
13028
  }));
12538
13029
  //#endregion
12539
13030
  //#region ../theme-core/src/site-styles/blockAppearancePresets.ts
12540
13031
  var blockAppearancePresets;
12541
13032
  var init_blockAppearancePresets = __esmMin((() => {
12542
13033
  init_appearancePresetResolution();
12543
- init_types$16();
13034
+ init_types$15();
12544
13035
  blockAppearancePresets = [
12545
13036
  defineBlockAppearancePreset({
12546
13037
  kind: "block-design",
@@ -13353,168 +13844,10 @@ function assertUniqueLayoutProfileKeys(profiles) {
13353
13844
  if (duplicates.length > 0) throw new Error(`Duplicate block layout design profiles: ${duplicates.join(", ")}`);
13354
13845
  }
13355
13846
  var init_blockFlow = __esmMin((() => {
13356
- init_types$16();
13847
+ init_types$15();
13357
13848
  }));
13358
13849
  var init_classic_professional = __esmMin((() => {}));
13359
- //#endregion
13360
- //#region ../theme-core/src/mock-themes/modern-minimal.ts
13361
- var modernMinimalTheme;
13362
- var init_modern_minimal = __esmMin((() => {
13363
- modernMinimalTheme = {
13364
- name: "Modern Minimal",
13365
- description: "Clean, monochromatic design with subtle styling and modern typography",
13366
- rationale: "Perfect for professional services, portfolios, and content-focused sites that need a clean, trustworthy appearance",
13367
- axes: {
13368
- tone: "minimal",
13369
- energy: "calm",
13370
- density: "airy",
13371
- mediaBias: "text",
13372
- conversionBias: "low",
13373
- motion: "subtle"
13374
- },
13375
- palette: {
13376
- colors: [
13377
- {
13378
- name: "primary",
13379
- hex: "#1f2937"
13380
- },
13381
- {
13382
- name: "primaryForeground",
13383
- hex: "#ffffff"
13384
- },
13385
- {
13386
- name: "secondary",
13387
- hex: "#6b7280"
13388
- },
13389
- {
13390
- name: "accent",
13391
- hex: "#3b82f6"
13392
- },
13393
- {
13394
- name: "success",
13395
- hex: "#10b981"
13396
- },
13397
- {
13398
- name: "warning",
13399
- hex: "#f59e0b"
13400
- },
13401
- {
13402
- name: "destructive",
13403
- hex: "#ef4444"
13404
- },
13405
- {
13406
- name: "background",
13407
- hex: "#ffffff"
13408
- },
13409
- {
13410
- name: "surface",
13411
- hex: "#ffffff"
13412
- },
13413
- {
13414
- name: "surfaceAlt",
13415
- hex: "#f9fafb"
13416
- },
13417
- {
13418
- name: "muted",
13419
- hex: "#f3f4f6"
13420
- },
13421
- {
13422
- name: "text",
13423
- hex: "#1f2937"
13424
- },
13425
- {
13426
- name: "border",
13427
- hex: "#e5e7eb"
13428
- }
13429
- ],
13430
- meta: { mode: "light" }
13431
- },
13432
- typography: {
13433
- headings: {
13434
- default: {
13435
- family: "Inter, system-ui, sans-serif",
13436
- weight: "medium",
13437
- letterSpacing: "tight",
13438
- lineHeight: "normal",
13439
- case: "normal",
13440
- italic: null
13441
- },
13442
- h1: {
13443
- weight: "semibold",
13444
- letterSpacing: "tight",
13445
- size: "xl",
13446
- lineHeight: "normal",
13447
- italic: null
13448
- },
13449
- h2: {
13450
- weight: "medium",
13451
- letterSpacing: "normal",
13452
- size: "lg",
13453
- lineHeight: "normal",
13454
- italic: null
13455
- },
13456
- h3: {
13457
- weight: "medium",
13458
- letterSpacing: "normal",
13459
- size: "md",
13460
- lineHeight: "normal",
13461
- italic: null
13462
- }
13463
- },
13464
- body: {
13465
- family: "Inter, system-ui, sans-serif",
13466
- weight: "regular",
13467
- size: "md",
13468
- letterSpacing: "normal",
13469
- lineHeight: "relaxed"
13470
- },
13471
- scale: "minorThird"
13472
- },
13473
- space: "comfortable",
13474
- corners: "rounded",
13475
- border: {
13476
- width: "hairline",
13477
- style: "solid"
13478
- },
13479
- shadow: {
13480
- elevation: "low",
13481
- softness: "soft",
13482
- position: "bottom"
13483
- },
13484
- motion: {
13485
- level: "low",
13486
- easing: "standard"
13487
- },
13488
- header: {
13489
- variant: "classic",
13490
- positioning: "static",
13491
- shrinkOnScroll: false,
13492
- maxWidth: "container",
13493
- logoOverride: null,
13494
- background: {
13495
- type: "color",
13496
- color: "surface"
13497
- },
13498
- navStyle: "minimal",
13499
- navWeight: "medium",
13500
- navContainer: {
13501
- type: "none",
13502
- opacity: 0,
13503
- tint: null
13504
- }
13505
- },
13506
- footer: {
13507
- variant: "simple",
13508
- maxWidth: "container",
13509
- background: {
13510
- type: "color",
13511
- color: "surface"
13512
- },
13513
- navStyle: "minimal",
13514
- navWeight: "medium"
13515
- }
13516
- };
13517
- }));
13850
+ var init_modern_minimal = __esmMin((() => {}));
13518
13851
  var init_vibrant_creative = __esmMin((() => {}));
13519
13852
  //#endregion
13520
13853
  //#region ../theme-core/src/palette/generateCssVars.ts
@@ -13840,7 +14173,7 @@ var init_all = __esmMin((() => {
13840
14173
  }));
13841
14174
  //#endregion
13842
14175
  //#region ../theme-core/src/palette/types.ts
13843
- var init_types$15 = __esmMin((() => {}));
14176
+ var init_types$14 = __esmMin((() => {}));
13844
14177
  //#endregion
13845
14178
  //#region ../../node_modules/.pnpm/@vibrant+image@4.0.4/node_modules/@vibrant/image/dist/esm/histogram.js
13846
14179
  var Histogram;
@@ -15293,7 +15626,7 @@ function defineCuratedPalette(input) {
15293
15626
  };
15294
15627
  }
15295
15628
  var curatedPaletteAuthoringKeySchema;
15296
- var init_types$14 = __esmMin((() => {
15629
+ var init_types$13 = __esmMin((() => {
15297
15630
  init_styleTags();
15298
15631
  init_themeColorTokens();
15299
15632
  init_colors();
@@ -15334,7 +15667,7 @@ var init_types$14 = __esmMin((() => {
15334
15667
  //#region ../theme-core/src/palette/curated/brand-led.ts
15335
15668
  var brandLedCool, brandLedWarm, brandLedJewel, brandLedSpruce, brandLedBurgundyGold;
15336
15669
  var init_brand_led = __esmMin((() => {
15337
- init_types$14();
15670
+ init_types$13();
15338
15671
  brandLedCool = defineCuratedPalette({
15339
15672
  authoringKey: "brand-led-cool",
15340
15673
  name: "Brand-led — Cool",
@@ -15665,7 +15998,7 @@ var init_brand_led = __esmMin((() => {
15665
15998
  //#region ../theme-core/src/palette/curated/high-contrast.ts
15666
15999
  var highContrastInk, highContrastCharcoal, highContrastMonochrome;
15667
16000
  var init_high_contrast = __esmMin((() => {
15668
- init_types$14();
16001
+ init_types$13();
15669
16002
  highContrastInk = defineCuratedPalette({
15670
16003
  authoringKey: "high-contrast-ink",
15671
16004
  name: "High Contrast — Ink",
@@ -15866,7 +16199,7 @@ var init_high_contrast = __esmMin((() => {
15866
16199
  //#region ../theme-core/src/palette/curated/soft-natural.ts
15867
16200
  var softNaturalSage, softNaturalStone, softNaturalWatercolor, softNaturalLilac;
15868
16201
  var init_soft_natural = __esmMin((() => {
15869
- init_types$14();
16202
+ init_types$13();
15870
16203
  softNaturalSage = defineCuratedPalette({
15871
16204
  authoringKey: "soft-natural-sage",
15872
16205
  name: "Soft Natural — Sage",
@@ -16132,7 +16465,7 @@ var init_soft_natural = __esmMin((() => {
16132
16465
  //#region ../theme-core/src/palette/curated/warm-neutral.ts
16133
16466
  var warmNeutralClay, warmNeutralCream, warmNeutralSoftEarth, warmNeutralForest;
16134
16467
  var init_warm_neutral = __esmMin((() => {
16135
- init_types$14();
16468
+ init_types$13();
16136
16469
  warmNeutralClay = defineCuratedPalette({
16137
16470
  authoringKey: "warm-neutral-clay",
16138
16471
  name: "Warm Neutral — Clay",
@@ -16398,7 +16731,7 @@ var init_warm_neutral = __esmMin((() => {
16398
16731
  //#region ../theme-core/src/palette/curated/warm-dark.ts
16399
16732
  var warmDarkEmber, warmDarkKirtanGold;
16400
16733
  var init_warm_dark = __esmMin((() => {
16401
- init_types$14();
16734
+ init_types$13();
16402
16735
  warmDarkEmber = defineCuratedPalette({
16403
16736
  authoringKey: "warm-dark-ember",
16404
16737
  name: "Warm Dark — Ember",
@@ -16564,7 +16897,7 @@ var init_curated = __esmMin((() => {
16564
16897
  init_soft_natural();
16565
16898
  init_warm_neutral();
16566
16899
  init_warm_dark();
16567
- init_types$14();
16900
+ init_types$13();
16568
16901
  curatedPalettes = [
16569
16902
  admitCuratedPaletteDefinition(brandLedCool),
16570
16903
  admitCuratedPaletteDefinition(brandLedWarm),
@@ -16696,7 +17029,7 @@ var init_palette$1 = __esmMin((() => {
16696
17029
  init_generateCssVars();
16697
17030
  init_generateShades();
16698
17031
  init_neutralScale();
16699
- init_types$15();
17032
+ init_types$14();
16700
17033
  init_utils$6();
16701
17034
  init_paletteAccess();
16702
17035
  init_extractPalette();
@@ -16937,7 +17270,7 @@ var init_backgroundAppearance = __esmMin((() => {
16937
17270
  backgroundAppearanceColorTokenNameSet = new Set(backgroundAppearanceColorTokenNames);
16938
17271
  }));
16939
17272
  var init_compositionBudget = __esmMin((() => {
16940
- init_types$16();
17273
+ init_types$15();
16941
17274
  }));
16942
17275
  var init_schemaVersionedJson = __esmMin((() => {}));
16943
17276
  //#endregion
@@ -16955,7 +17288,7 @@ function boundaryRuntimeMetricsForTransition(transition) {
16955
17288
  }
16956
17289
  var sectionBoundaryRuntimeMetricsByTransition, noneBoundaryOption, softBoundaryOption, spaciousBoundaryOption;
16957
17290
  var init_sectionTransitions = __esmMin((() => {
16958
- init_types$16();
17291
+ init_types$15();
16959
17292
  sectionBoundaryRuntimeMetricsByTransition = {
16960
17293
  none: null,
16961
17294
  "soft-fade-short": boundaryRuntimeMetrics("gradient", "medium", "6rem + 2px"),
@@ -17044,7 +17377,7 @@ function boundaryKey$1(previousBlockId, nextBlockId) {
17044
17377
  }
17045
17378
  var pageDesignUserPinnedAppearanceChoiceSchema, pageDesignUserPinnedBoundaryChoiceSchema, pageDesignBoundaryTreatmentSchema, pageDesignUserPinnedBoundaryTreatmentChoiceSchema, pageDesignBlockLookPinSchema, pageDesignBoundaryPinSchema, legacyPageDesignBoundaryPinSchema;
17046
17379
  var init_pageDesignIntent = __esmMin((() => {
17047
- init_types$16();
17380
+ init_types$15();
17048
17381
  init_schemaVersionedJson();
17049
17382
  init_sectionTransitions();
17050
17383
  asBoundaryOptionId("break:unknown");
@@ -17149,109 +17482,7 @@ var init_pageDesignIntent = __esmMin((() => {
17149
17482
  var init_contentTemplateDesignIntent = __esmMin((() => {
17150
17483
  init_pageDesignIntent();
17151
17484
  init_sectionTransitions();
17152
- init_types$16();
17153
- }));
17154
- //#endregion
17155
- //#region ../theme-core/src/buttons/effectClassification.ts
17156
- function getButtonEffectPolicy(effectId) {
17157
- return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
17158
- }
17159
- function classifyButtonEffectId(effectId) {
17160
- return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
17161
- }
17162
- var BUTTON_EFFECT_POLICIES;
17163
- var init_effectClassification = __esmMin((() => {
17164
- BUTTON_EFFECT_POLICIES = {
17165
- "darken-background": {
17166
- classification: "colour-transition",
17167
- transition: {
17168
- kind: "adjust-shade",
17169
- direction: "darker"
17170
- }
17171
- },
17172
- "lighten-background": {
17173
- classification: "colour-transition",
17174
- transition: {
17175
- kind: "adjust-shade",
17176
- direction: "lighter"
17177
- }
17178
- },
17179
- "background-on-hover": {
17180
- classification: "colour-transition",
17181
- transition: { kind: "replace-background" }
17182
- },
17183
- "background-on-hover-alpha": {
17184
- classification: "unsupported-colour",
17185
- reason: "alpha_requires_surface"
17186
- },
17187
- "fade-background": {
17188
- classification: "unsupported-colour",
17189
- reason: "changes_element_opacity"
17190
- },
17191
- "opacity-reduce": {
17192
- classification: "unsupported-colour",
17193
- reason: "changes_element_opacity"
17194
- },
17195
- "gradient-text": {
17196
- classification: "unsupported-colour",
17197
- reason: "changes_foreground"
17198
- },
17199
- "text-color-change": {
17200
- classification: "unsupported-colour",
17201
- reason: "changes_foreground"
17202
- },
17203
- "border-color-change": {
17204
- classification: "unsupported-colour",
17205
- reason: "changes_border"
17206
- },
17207
- "aurora-glow": {
17208
- classification: "unsupported-background-overlay",
17209
- reason: "unresolved_background_overlay"
17210
- },
17211
- "cosmic-stardust": {
17212
- classification: "unsupported-background-overlay",
17213
- reason: "unresolved_background_overlay"
17214
- },
17215
- "gradient-border-fill": {
17216
- classification: "unsupported-background-overlay",
17217
- reason: "unresolved_background_overlay"
17218
- },
17219
- "animated-gradient-border-fill": {
17220
- classification: "unsupported-background-overlay",
17221
- reason: "unresolved_background_overlay"
17222
- },
17223
- "nav-underline": {
17224
- classification: "not-button",
17225
- reason: "not_button_effect"
17226
- },
17227
- "nav-frosted-base": {
17228
- classification: "not-button",
17229
- reason: "not_button_effect"
17230
- },
17231
- "nav-frosted-hover": {
17232
- classification: "not-button",
17233
- reason: "not_button_effect"
17234
- },
17235
- "nav-frosted-active": {
17236
- classification: "not-button",
17237
- reason: "not_button_effect"
17238
- },
17239
- "animated-gradient": { classification: "non-colour" },
17240
- "border-glow": { classification: "non-colour" },
17241
- "drop-shadow": { classification: "non-colour" },
17242
- "inner-shadow": { classification: "non-colour" },
17243
- "neumorphic-shadow": { classification: "non-colour" },
17244
- "outer-glow": { classification: "non-colour" },
17245
- "retro-3d-shadow": { classification: "non-colour" },
17246
- "scale-up": { classification: "non-colour" },
17247
- "scale-down": { classification: "non-colour" },
17248
- lift: { classification: "non-colour" },
17249
- "press-down": { classification: "non-colour" },
17250
- pop: { classification: "non-colour" },
17251
- "border-bottom-grow": { classification: "non-colour" },
17252
- "sketchy-border": { classification: "non-colour" },
17253
- "pulse-animation": { classification: "non-colour" }
17254
- };
17485
+ init_types$15();
17255
17486
  }));
17256
17487
  //#endregion
17257
17488
  //#region ../theme-core/src/buttons/types.ts
@@ -17259,8 +17490,9 @@ function isVariantRole(value) {
17259
17490
  return VARIANT_ROLES.includes(value);
17260
17491
  }
17261
17492
  function asSpecialVariantId(value) {
17262
- if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
17263
- return value;
17493
+ const parsed = buttonVariantIdSchema.safeParse(value);
17494
+ if (!parsed.success) throw new Error("SpecialVariantId must be a CSS-safe button variant ID");
17495
+ return parsed.data;
17264
17496
  }
17265
17497
  function parseOpaqueButtonColourToken(value) {
17266
17498
  const token = parseThemeColorToken(value);
@@ -17271,144 +17503,8 @@ function parseOpaqueButtonColourToken(value) {
17271
17503
  function unsafeAsOpaqueButtonColourToken(value) {
17272
17504
  return value;
17273
17505
  }
17274
- function normalizeLegacyButtonVariantInput(input) {
17275
- if (!isUnknownRecord(input)) return input;
17276
- const background = input.background;
17277
- if (!isUnknownRecord(background)) return input;
17278
- if (!(background.type === "transparent" || Object.prototype.hasOwnProperty.call(input, "textColorToken") || isUnknownRecord(input.border) && Object.prototype.hasOwnProperty.call(input.border, "colorToken") || hasLegacyButtonEffects(input.effects) || hasLegacyAlphaToken(input, background))) return input;
17279
- const { textColorToken, ...withoutLegacyText } = input;
17280
- const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
17281
- const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
17282
- const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
17283
- const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
17284
- if (background.type === "transparent") return {
17285
- ...withoutLegacyText,
17286
- background: {
17287
- type: "surface",
17288
- role: "link"
17289
- },
17290
- border: normalizedBorder,
17291
- affordance: normalizedAffordance,
17292
- effects: normalizedEffects,
17293
- hoverBackgroundToken
17294
- };
17295
- if (background.type === "gradient") {
17296
- const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
17297
- return {
17298
- ...withoutLegacyText,
17299
- background: {
17300
- ...background,
17301
- stops,
17302
- foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
17303
- },
17304
- border: normalizedBorder,
17305
- affordance: normalizedAffordance,
17306
- effects: normalizedEffects,
17307
- hoverBackgroundToken
17308
- };
17309
- }
17310
- return {
17311
- ...withoutLegacyText,
17312
- background: background.type === "solid" ? {
17313
- ...background,
17314
- colorToken: stripLegacyTokenAlpha(background.colorToken)
17315
- } : background,
17316
- border: normalizedBorder,
17317
- affordance: normalizedAffordance,
17318
- effects: normalizedEffects,
17319
- hoverBackgroundToken
17320
- };
17321
- }
17322
- function normalizeLegacyButtonGlobalInput(input) {
17323
- if (!isUnknownRecord(input)) return input;
17324
- const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
17325
- return hoverColorToken === input.hoverColorToken ? input : {
17326
- ...input,
17327
- hoverColorToken
17328
- };
17329
- }
17330
- function hasLegacyAlphaToken(input, background) {
17331
- const stops = isUnknownArray$3(background.stops) ? background.stops : [];
17332
- return [
17333
- input.hoverBackgroundToken,
17334
- background.colorToken,
17335
- background.foregroundToken,
17336
- ...stops
17337
- ].some((token) => stripLegacyTokenAlpha(token) !== token);
17338
- }
17339
- function stripLegacyTokenAlpha(value) {
17340
- if (typeof value !== "string") return value;
17341
- const slashIndex = value.indexOf("/");
17342
- return slashIndex < 0 ? value : value.slice(0, slashIndex);
17343
- }
17344
- function hasLegacyButtonEffects(input) {
17345
- if (!isUnknownRecord(input)) return false;
17346
- return [
17347
- "base",
17348
- "hover",
17349
- "active",
17350
- "focus"
17351
- ].some((state) => {
17352
- const effects = input[state];
17353
- return Array.isArray(effects) && effects.some((effect) => {
17354
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
17355
- const classification = classifyButtonEffectId(effect.effectId);
17356
- if (classification !== "colour-transition" && classification !== "non-colour") return true;
17357
- return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
17358
- });
17359
- });
17360
- }
17361
- function normalizeLegacyButtonEffects(input, backgroundType) {
17362
- if (!isUnknownRecord(input)) return input;
17363
- const normalized = {};
17364
- for (const state of [
17365
- "base",
17366
- "hover",
17367
- "active",
17368
- "focus"
17369
- ]) {
17370
- const effects = input[state];
17371
- if (!Array.isArray(effects)) continue;
17372
- const safeEffects = effects.flatMap((effect) => {
17373
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
17374
- const classification = classifyButtonEffectId(effect.effectId);
17375
- if (classification === "non-colour") return [effect];
17376
- if (classification !== "colour-transition") return [];
17377
- if (effect.effectId === "background-on-hover") {
17378
- const options = isUnknownRecord(effect.options) ? effect.options : null;
17379
- const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
17380
- return colorToken === null ? [] : [{
17381
- ...effect,
17382
- options: {
17383
- ...options,
17384
- colorToken
17385
- }
17386
- }];
17387
- }
17388
- if (backgroundType !== "solid") return [];
17389
- const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
17390
- const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
17391
- return [{
17392
- ...effect,
17393
- options: {
17394
- ...isUnknownRecord(effect.options) ? effect.options : {},
17395
- amount
17396
- }
17397
- }];
17398
- });
17399
- if (safeEffects.length > 0) normalized[state] = safeEffects;
17400
- }
17401
- return Object.keys(normalized).length === 0 ? void 0 : normalized;
17402
- }
17403
- function isUnknownRecord(value) {
17404
- return typeof value === "object" && value !== null && !Array.isArray(value);
17405
- }
17406
- function isUnknownArray$3(value) {
17407
- return Array.isArray(value);
17408
- }
17409
- var VARIANT_ROLES, DEFAULT_VARIANT_ALIAS_ID, opaqueButtonColourTokenSchema, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, canonicalButtonGlobalSettingsSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonColourTreatmentSchema, buttonBackgroundSchema, effectApplicationSchema$1, buttonBorderSchema, buttonVariantAffordanceSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, canonicalButtonVariantSchema, buttonVariantSchema, buttonSystemSchema;
17410
- var init_types$13 = __esmMin((() => {
17411
- init_effectClassification();
17506
+ var VARIANT_ROLES, buttonVariantIdSchema, DEFAULT_VARIANT_ALIAS_ID, opaqueButtonColourTokenSchema, buttonShadeAmountSchema, buttonShadowIntensitySchema, buttonEffectApplicationSchema, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, buttonGlobalSettingsBaseSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonColourTreatmentSchema, buttonBackgroundSchema, buttonBorderSchema, buttonVariantAffordanceSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, buttonVariantSchema, buttonSystemSchema;
17507
+ var init_types$12 = __esmMin((() => {
17412
17508
  init_themeColorTokens();
17413
17509
  init_colorTokenParts();
17414
17510
  VARIANT_ROLES = [
@@ -17420,12 +17516,109 @@ var init_types$13 = __esmMin((() => {
17420
17516
  "tertiary",
17421
17517
  "accent"
17422
17518
  ];
17519
+ buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only");
17423
17520
  DEFAULT_VARIANT_ALIAS_ID = "default";
17424
17521
  opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
17425
17522
  const token = parseOpaqueButtonColourToken(value);
17426
17523
  if (token === null) throw new Error("Invariant: opaque button token passed its schema");
17427
17524
  return token;
17428
17525
  });
17526
+ buttonShadeAmountSchema = z$1.number().finite().min(0).max(900).multipleOf(100);
17527
+ buttonShadowIntensitySchema = z$1.enum([
17528
+ "subtle",
17529
+ "medium",
17530
+ "strong"
17531
+ ]);
17532
+ buttonEffectApplicationSchema = z$1.discriminatedUnion("effectId", [
17533
+ z$1.strictObject({
17534
+ effectId: z$1.literal("darken-background"),
17535
+ options: z$1.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
17536
+ }),
17537
+ z$1.strictObject({
17538
+ effectId: z$1.literal("lighten-background"),
17539
+ options: z$1.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
17540
+ }),
17541
+ z$1.strictObject({
17542
+ effectId: z$1.literal("background-on-hover"),
17543
+ options: z$1.strictObject({ colorToken: opaqueButtonColourTokenSchema.optional() }).optional()
17544
+ }),
17545
+ z$1.strictObject({
17546
+ effectId: z$1.literal("animated-gradient"),
17547
+ options: z$1.strictObject({ direction: z$1.enum(["horizontal", "vertical"]).optional() }).optional()
17548
+ }),
17549
+ z$1.strictObject({
17550
+ effectId: z$1.literal("drop-shadow"),
17551
+ options: z$1.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
17552
+ }),
17553
+ z$1.strictObject({
17554
+ effectId: z$1.literal("inner-shadow"),
17555
+ options: z$1.strictObject({}).optional()
17556
+ }),
17557
+ z$1.strictObject({
17558
+ effectId: z$1.literal("neumorphic-shadow"),
17559
+ options: z$1.strictObject({
17560
+ mode: z$1.enum(["raised", "pressed"]).optional(),
17561
+ intensity: buttonShadowIntensitySchema.optional()
17562
+ }).optional()
17563
+ }),
17564
+ z$1.strictObject({
17565
+ effectId: z$1.literal("retro-3d-shadow"),
17566
+ options: z$1.strictObject({}).optional()
17567
+ }),
17568
+ z$1.strictObject({
17569
+ effectId: z$1.literal("scale-up"),
17570
+ options: z$1.strictObject({ scale: z$1.enum([
17571
+ "1.02",
17572
+ "1.03",
17573
+ "1.05",
17574
+ "1.10"
17575
+ ]).optional() }).optional()
17576
+ }),
17577
+ z$1.strictObject({
17578
+ effectId: z$1.literal("scale-down"),
17579
+ options: z$1.strictObject({ scale: z$1.enum([
17580
+ "0.90",
17581
+ "0.95",
17582
+ "0.97",
17583
+ "0.98"
17584
+ ]).optional() }).optional()
17585
+ }),
17586
+ z$1.strictObject({
17587
+ effectId: z$1.literal("lift"),
17588
+ options: z$1.strictObject({ amount: z$1.enum([
17589
+ "0.25",
17590
+ "0.5",
17591
+ "1"
17592
+ ]).optional() }).optional()
17593
+ }),
17594
+ z$1.strictObject({
17595
+ effectId: z$1.literal("press-down"),
17596
+ options: z$1.strictObject({}).optional()
17597
+ }),
17598
+ z$1.strictObject({
17599
+ effectId: z$1.literal("pop"),
17600
+ options: z$1.strictObject({ intensity: z$1.enum([
17601
+ "subtle",
17602
+ "medium",
17603
+ "dramatic"
17604
+ ]).optional() }).optional()
17605
+ }),
17606
+ z$1.strictObject({
17607
+ effectId: z$1.literal("border-bottom-grow"),
17608
+ options: z$1.strictObject({
17609
+ height: z$1.union([z$1.literal(1), z$1.literal(2)]).optional(),
17610
+ origin: z$1.enum([
17611
+ "left",
17612
+ "center",
17613
+ "right"
17614
+ ]).optional()
17615
+ }).optional()
17616
+ }),
17617
+ z$1.strictObject({
17618
+ effectId: z$1.literal("sketchy-border"),
17619
+ options: z$1.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
17620
+ })
17621
+ ]);
17429
17622
  cornerStyleSchema = z$1.enum([
17430
17623
  "square",
17431
17624
  "rounded",
@@ -17460,13 +17653,7 @@ var init_types$13 = __esmMin((() => {
17460
17653
  "scale",
17461
17654
  "press"
17462
17655
  ]);
17463
- hoverColorSchema = z$1.enum([
17464
- "none",
17465
- "brighten",
17466
- "darken",
17467
- "saturate",
17468
- "token"
17469
- ]);
17656
+ z$1.enum(["none", "token"]);
17470
17657
  buttonPaddingPresetSchema = z$1.enum([
17471
17658
  "compact",
17472
17659
  "default",
@@ -17514,7 +17701,7 @@ var init_types$13 = __esmMin((() => {
17514
17701
  lg,
17515
17702
  xl: xl ?? lg
17516
17703
  }));
17517
- canonicalButtonGlobalSettingsSchema = z$1.object({
17704
+ buttonGlobalSettingsBaseSchema = z$1.strictObject({
17518
17705
  cornerStyle: cornerStyleSchema,
17519
17706
  cornerRadius: z$1.number().min(0).max(24).optional(),
17520
17707
  /**
@@ -17527,30 +17714,23 @@ var init_types$13 = __esmMin((() => {
17527
17714
  shadow: shadowSizeSchema.optional(),
17528
17715
  textTransform: textTransformSchema,
17529
17716
  fontWeight: fontWeightSchema,
17530
- /**
17531
- * @deprecated Set per-variant via `variant.border.widthClass` instead.
17532
- * Schema field is preserved so existing presets parse; the value is unread
17533
- * by the current generator and will be removed once the legacy
17534
- * `primitives/content/components/Button.tsx` slot exports are deleted.
17535
- */
17536
- borderWidth: z$1.union([
17537
- z$1.literal(1),
17538
- z$1.literal(2),
17539
- z$1.literal(3)
17540
- ]),
17541
17717
  typography: buttonTypographySchema.optional(),
17542
17718
  fontSize: z$1.string().optional(),
17543
17719
  letterSpacing: letterSpacingSchema.optional(),
17544
17720
  italic: z$1.boolean().optional(),
17545
17721
  paddingPreset: buttonPaddingPresetSchema.optional(),
17546
17722
  hoverTransform: hoverTransformSchema,
17547
- hoverColor: hoverColorSchema,
17548
- hoverColorToken: opaqueButtonColourTokenSchema.optional(),
17549
17723
  gradientStyle: gradientStyleSchema.optional(),
17550
17724
  gradientAngle: z$1.number().min(0).max(360).optional(),
17551
17725
  gradientSharpness: gradientSharpnessSchema.optional()
17552
17726
  });
17553
- buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
17727
+ buttonGlobalSettingsSchema = z$1.discriminatedUnion("hoverColor", [buttonGlobalSettingsBaseSchema.extend({
17728
+ hoverColor: z$1.literal("none"),
17729
+ hoverColorToken: z$1.never().optional()
17730
+ }), buttonGlobalSettingsBaseSchema.extend({
17731
+ hoverColor: z$1.literal("token"),
17732
+ hoverColorToken: opaqueButtonColourTokenSchema
17733
+ })]);
17554
17734
  gradientDirectionSchema$1 = z$1.enum([
17555
17735
  "to-r",
17556
17736
  "to-l",
@@ -17562,11 +17742,11 @@ var init_types$13 = __esmMin((() => {
17562
17742
  "to-bl"
17563
17743
  ]);
17564
17744
  buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
17565
- z$1.object({
17745
+ z$1.strictObject({
17566
17746
  type: z$1.literal("solid"),
17567
17747
  colorToken: opaqueButtonColourTokenSchema
17568
17748
  }),
17569
- z$1.object({
17749
+ z$1.strictObject({
17570
17750
  type: z$1.literal("gradient"),
17571
17751
  stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
17572
17752
  const [first, second, ...rest] = stops;
@@ -17580,19 +17760,15 @@ var init_types$13 = __esmMin((() => {
17580
17760
  direction: gradientDirectionSchema$1,
17581
17761
  foregroundToken: opaqueButtonColourTokenSchema
17582
17762
  }),
17583
- z$1.object({
17763
+ z$1.strictObject({
17584
17764
  type: z$1.literal("surface"),
17585
17765
  role: z$1.literal("link")
17586
17766
  })
17587
17767
  ]);
17588
17768
  buttonBackgroundSchema = buttonColourTreatmentSchema;
17589
- effectApplicationSchema$1 = z$1.object({
17590
- effectId: z$1.string(),
17591
- options: z$1.record(z$1.string(), z$1.json()).optional()
17592
- });
17593
- buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
17594
- buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
17595
- variantShadowSchema = z$1.object({
17769
+ buttonBorderSchema = z$1.strictObject({ widthClass: z$1.string() });
17770
+ buttonVariantAffordanceSchema = z$1.strictObject({ iconId: z$1.string().min(1) });
17771
+ variantShadowSchema = z$1.strictObject({
17596
17772
  elevation: z$1.enum([
17597
17773
  "none",
17598
17774
  "low",
@@ -17605,13 +17781,13 @@ var init_types$13 = __esmMin((() => {
17605
17781
  "hard"
17606
17782
  ]).nullable(),
17607
17783
  position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
17608
- colorToken: themeColorTokenSchema.optional()
17784
+ colorToken: opaqueButtonColourTokenSchema.optional()
17609
17785
  });
17610
- variantEffectsSchema = z$1.object({
17611
- base: z$1.array(effectApplicationSchema$1).optional(),
17612
- hover: z$1.array(effectApplicationSchema$1).optional(),
17613
- active: z$1.array(effectApplicationSchema$1).optional(),
17614
- focus: z$1.array(effectApplicationSchema$1).optional()
17786
+ variantEffectsSchema = z$1.strictObject({
17787
+ base: z$1.array(buttonEffectApplicationSchema).optional(),
17788
+ hover: z$1.array(buttonEffectApplicationSchema).optional(),
17789
+ active: z$1.array(buttonEffectApplicationSchema).optional(),
17790
+ focus: z$1.array(buttonEffectApplicationSchema).optional()
17615
17791
  });
17616
17792
  variantSizeOverridesSchema = z$1.object({
17617
17793
  sm: buttonSizeConfigSchema.optional(),
@@ -17619,8 +17795,8 @@ var init_types$13 = __esmMin((() => {
17619
17795
  lg: buttonSizeConfigSchema.optional(),
17620
17796
  xl: buttonSizeConfigSchema.optional()
17621
17797
  });
17622
- canonicalButtonVariantSchema = z$1.object({
17623
- id: z$1.string(),
17798
+ buttonVariantSchema = z$1.strictObject({
17799
+ id: buttonVariantIdSchema,
17624
17800
  name: z$1.string().min(1).max(20),
17625
17801
  enabled: z$1.boolean(),
17626
17802
  priority: prioritySchema,
@@ -17634,11 +17810,24 @@ var init_types$13 = __esmMin((() => {
17634
17810
  sizes: variantSizeOverridesSchema.optional(),
17635
17811
  affordance: buttonVariantAffordanceSchema.optional()
17636
17812
  });
17637
- buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
17638
- buttonSystemSchema = z$1.object({
17813
+ buttonSystemSchema = z$1.strictObject({
17639
17814
  global: buttonGlobalSettingsSchema,
17640
17815
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
17641
17816
  sizes: buttonSizesSchema.optional()
17817
+ }).superRefine((system, ctx) => {
17818
+ const seen = /* @__PURE__ */ new Set();
17819
+ system.variants.forEach((variant, index) => {
17820
+ if (seen.has(variant.id)) ctx.addIssue({
17821
+ code: "custom",
17822
+ path: [
17823
+ "variants",
17824
+ index,
17825
+ "id"
17826
+ ],
17827
+ message: `Duplicate button variant ID: ${variant.id}`
17828
+ });
17829
+ seen.add(variant.id);
17830
+ });
17642
17831
  });
17643
17832
  }));
17644
17833
  //#endregion
@@ -17722,7 +17911,7 @@ function rolePriority(role) {
17722
17911
  }
17723
17912
  var PUBLIC_BUTTON_ROLES;
17724
17913
  var init_domain = __esmMin((() => {
17725
- init_types$13();
17914
+ init_types$12();
17726
17915
  PUBLIC_BUTTON_ROLES = [
17727
17916
  "primary",
17728
17917
  "secondary",
@@ -17778,7 +17967,7 @@ var init_selection = __esmMin((() => {
17778
17967
  var quietArrowRecipe;
17779
17968
  var init_quietArrow = __esmMin((() => {
17780
17969
  init_domain();
17781
- init_types$13();
17970
+ init_types$12();
17782
17971
  init_selection();
17783
17972
  quietArrowRecipe = defineButtonStyleRecipe({
17784
17973
  id: "quiet-arrow",
@@ -17808,7 +17997,6 @@ var init_quietArrow = __esmMin((() => {
17808
17997
  cornerStyle: "rounded",
17809
17998
  textTransform: "uppercase",
17810
17999
  fontWeight: 500,
17811
- borderWidth: 1,
17812
18000
  typography: "body",
17813
18001
  fontSize: "text-sm",
17814
18002
  letterSpacing: "loose",
@@ -17872,7 +18060,7 @@ var init_quietArrow = __esmMin((() => {
17872
18060
  affordance: { iconId: "ArrowRight" },
17873
18061
  effects: { hover: [{
17874
18062
  effectId: "background-on-hover",
17875
- options: { colorToken: "surfaceAlt" }
18063
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
17876
18064
  }] }
17877
18065
  }
17878
18066
  },
@@ -17968,7 +18156,7 @@ function normalizeAppearanceOverrides(overrides) {
17968
18156
  }
17969
18157
  var emptyParametersSchema;
17970
18158
  var init_defineStaticButtonStyleRecipe = __esmMin((() => {
17971
- init_types$13();
18159
+ init_types$12();
17972
18160
  init_domain();
17973
18161
  emptyParametersSchema = z$1.object({}).strict();
17974
18162
  }));
@@ -17977,6 +18165,7 @@ var init_defineStaticButtonStyleRecipe = __esmMin((() => {
17977
18165
  var softPillRecipe, earthPillRecipe, confidentChipRecipe, editorialSizes, editorialLinkRecipe, pebbleRecipe, brushedWashRecipe, inkStampRecipe, flatInkRecipe, showtimePillRecipe, joyStampRecipe, ornateGhostSizes, ornateRitualRecipe;
17978
18166
  var init_staticRecipes = __esmMin((() => {
17979
18167
  init_defineStaticButtonStyleRecipe();
18168
+ init_types$12();
17980
18169
  softPillRecipe = defineStaticButtonStyleRecipe({
17981
18170
  id: "soft-pill",
17982
18171
  accessibilityLabel: "Rounded pill buttons with a gentle hover lift",
@@ -17992,7 +18181,6 @@ var init_staticRecipes = __esmMin((() => {
17992
18181
  shadow: "low",
17993
18182
  textTransform: "none",
17994
18183
  fontWeight: 500,
17995
- borderWidth: 2,
17996
18184
  hoverTransform: "lift",
17997
18185
  hoverColor: "none"
17998
18186
  },
@@ -18011,10 +18199,7 @@ var init_staticRecipes = __esmMin((() => {
18011
18199
  position: "bottom"
18012
18200
  },
18013
18201
  effects: {
18014
- hover: [{
18015
- effectId: "lift",
18016
- options: { translateY: "-1px" }
18017
- }],
18202
+ hover: [{ effectId: "lift" }],
18018
18203
  active: [{
18019
18204
  effectId: "scale-down",
18020
18205
  options: { scale: "0.98" }
@@ -18033,7 +18218,7 @@ var init_staticRecipes = __esmMin((() => {
18033
18218
  border: { widthClass: "border-2" },
18034
18219
  effects: { hover: [{
18035
18220
  effectId: "background-on-hover",
18036
- options: { colorToken: "surface" }
18221
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18037
18222
  }] }
18038
18223
  }
18039
18224
  },
@@ -18048,7 +18233,7 @@ var init_staticRecipes = __esmMin((() => {
18048
18233
  border: { widthClass: "border" },
18049
18234
  effects: { hover: [{
18050
18235
  effectId: "background-on-hover",
18051
- options: { colorToken: "surface" }
18236
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18052
18237
  }] }
18053
18238
  }
18054
18239
  },
@@ -18062,7 +18247,7 @@ var init_staticRecipes = __esmMin((() => {
18062
18247
  borderRadius: "rounded-full",
18063
18248
  effects: { hover: [{
18064
18249
  effectId: "background-on-hover",
18065
- options: { colorToken: "surface" }
18250
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18066
18251
  }] }
18067
18252
  }
18068
18253
  },
@@ -18092,7 +18277,6 @@ var init_staticRecipes = __esmMin((() => {
18092
18277
  shadow: "low",
18093
18278
  textTransform: "none",
18094
18279
  fontWeight: 500,
18095
- borderWidth: 1,
18096
18280
  hoverTransform: "lift",
18097
18281
  hoverColor: "none",
18098
18282
  typography: "body",
@@ -18128,12 +18312,9 @@ var init_staticRecipes = __esmMin((() => {
18128
18312
  position: "bottom"
18129
18313
  },
18130
18314
  effects: {
18131
- hover: [{
18132
- effectId: "lift",
18133
- options: { translateY: "-1px" }
18134
- }, {
18315
+ hover: [{ effectId: "lift" }, {
18135
18316
  effectId: "background-on-hover",
18136
- options: { colorToken: "accent" }
18317
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("accent") }
18137
18318
  }],
18138
18319
  active: [{
18139
18320
  effectId: "scale-down",
@@ -18153,7 +18334,7 @@ var init_staticRecipes = __esmMin((() => {
18153
18334
  border: { widthClass: "border" },
18154
18335
  effects: { hover: [{
18155
18336
  effectId: "background-on-hover",
18156
- options: { colorToken: "muted" }
18337
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("muted") }
18157
18338
  }] }
18158
18339
  }
18159
18340
  },
@@ -18168,7 +18349,7 @@ var init_staticRecipes = __esmMin((() => {
18168
18349
  border: { widthClass: "border" },
18169
18350
  effects: { hover: [{
18170
18351
  effectId: "background-on-hover",
18171
- options: { colorToken: "surfaceAlt" }
18352
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
18172
18353
  }] }
18173
18354
  }
18174
18355
  },
@@ -18228,7 +18409,6 @@ var init_staticRecipes = __esmMin((() => {
18228
18409
  shadow: "medium",
18229
18410
  textTransform: "none",
18230
18411
  fontWeight: 600,
18231
- borderWidth: 1,
18232
18412
  hoverTransform: "none",
18233
18413
  hoverColor: "none"
18234
18414
  },
@@ -18269,7 +18449,7 @@ var init_staticRecipes = __esmMin((() => {
18269
18449
  border: { widthClass: "border" },
18270
18450
  effects: { hover: [{
18271
18451
  effectId: "background-on-hover",
18272
- options: { colorToken: "background" }
18452
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("background") }
18273
18453
  }] }
18274
18454
  }
18275
18455
  },
@@ -18284,7 +18464,7 @@ var init_staticRecipes = __esmMin((() => {
18284
18464
  border: { widthClass: "border" },
18285
18465
  effects: { hover: [{
18286
18466
  effectId: "background-on-hover",
18287
- options: { colorToken: "surface" }
18467
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18288
18468
  }] }
18289
18469
  }
18290
18470
  },
@@ -18298,7 +18478,7 @@ var init_staticRecipes = __esmMin((() => {
18298
18478
  borderRadius: "rounded-md",
18299
18479
  effects: { hover: [{
18300
18480
  effectId: "background-on-hover",
18301
- options: { colorToken: "surface" }
18481
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18302
18482
  }] }
18303
18483
  }
18304
18484
  },
@@ -18333,7 +18513,6 @@ var init_staticRecipes = __esmMin((() => {
18333
18513
  cornerStyle: "square",
18334
18514
  textTransform: "none",
18335
18515
  fontWeight: 500,
18336
- borderWidth: 1,
18337
18516
  hoverTransform: "none",
18338
18517
  hoverColor: "none"
18339
18518
  },
@@ -18351,7 +18530,6 @@ var init_staticRecipes = __esmMin((() => {
18351
18530
  effectId: "border-bottom-grow",
18352
18531
  options: {
18353
18532
  height: 2,
18354
- colorToken: "text",
18355
18533
  origin: "left"
18356
18534
  }
18357
18535
  }] }
@@ -18370,7 +18548,6 @@ var init_staticRecipes = __esmMin((() => {
18370
18548
  effectId: "border-bottom-grow",
18371
18549
  options: {
18372
18550
  height: 1,
18373
- colorToken: "mutedText",
18374
18551
  origin: "left"
18375
18552
  }
18376
18553
  }] }
@@ -18389,7 +18566,6 @@ var init_staticRecipes = __esmMin((() => {
18389
18566
  effectId: "border-bottom-grow",
18390
18567
  options: {
18391
18568
  height: 1,
18392
- colorToken: "accent",
18393
18569
  origin: "left"
18394
18570
  }
18395
18571
  }] }
@@ -18413,7 +18589,6 @@ var init_staticRecipes = __esmMin((() => {
18413
18589
  effectId: "border-bottom-grow",
18414
18590
  options: {
18415
18591
  height: 2,
18416
- colorToken: "accent",
18417
18592
  origin: "left"
18418
18593
  }
18419
18594
  }] } }
@@ -18435,7 +18610,6 @@ var init_staticRecipes = __esmMin((() => {
18435
18610
  cornerStyle: "pill",
18436
18611
  textTransform: "none",
18437
18612
  fontWeight: 500,
18438
- borderWidth: 2,
18439
18613
  hoverTransform: "none",
18440
18614
  hoverColor: "none"
18441
18615
  },
@@ -18480,7 +18654,7 @@ var init_staticRecipes = __esmMin((() => {
18480
18654
  border: { widthClass: "border-2" },
18481
18655
  effects: { hover: [{
18482
18656
  effectId: "background-on-hover",
18483
- options: { colorToken: "accent" }
18657
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("accent") }
18484
18658
  }] }
18485
18659
  }
18486
18660
  },
@@ -18495,7 +18669,7 @@ var init_staticRecipes = __esmMin((() => {
18495
18669
  border: { widthClass: "border" },
18496
18670
  effects: { hover: [{
18497
18671
  effectId: "background-on-hover",
18498
- options: { colorToken: "surface" }
18672
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18499
18673
  }] }
18500
18674
  }
18501
18675
  },
@@ -18550,7 +18724,6 @@ var init_staticRecipes = __esmMin((() => {
18550
18724
  shadow: "low",
18551
18725
  textTransform: "none",
18552
18726
  fontWeight: 500,
18553
- borderWidth: 1,
18554
18727
  hoverTransform: "none",
18555
18728
  hoverColor: "none"
18556
18729
  },
@@ -18615,7 +18788,7 @@ var init_staticRecipes = __esmMin((() => {
18615
18788
  border: { widthClass: "border" },
18616
18789
  effects: { hover: [{
18617
18790
  effectId: "background-on-hover",
18618
- options: { colorToken: "surface" }
18791
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18619
18792
  }] }
18620
18793
  }
18621
18794
  },
@@ -18629,7 +18802,7 @@ var init_staticRecipes = __esmMin((() => {
18629
18802
  borderRadius: "rounded-lg",
18630
18803
  effects: { hover: [{
18631
18804
  effectId: "background-on-hover",
18632
- options: { colorToken: "surface" }
18805
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18633
18806
  }] }
18634
18807
  }
18635
18808
  },
@@ -18658,7 +18831,6 @@ var init_staticRecipes = __esmMin((() => {
18658
18831
  cornerStyle: "rounded",
18659
18832
  textTransform: "uppercase",
18660
18833
  fontWeight: 600,
18661
- borderWidth: 1,
18662
18834
  hoverTransform: "none",
18663
18835
  hoverColor: "none",
18664
18836
  letterSpacing: "loose"
@@ -18716,7 +18888,7 @@ var init_staticRecipes = __esmMin((() => {
18716
18888
  border: { widthClass: "border-2" },
18717
18889
  effects: { hover: [{
18718
18890
  effectId: "background-on-hover",
18719
- options: { colorToken: "surface" }
18891
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18720
18892
  }] }
18721
18893
  }
18722
18894
  },
@@ -18731,7 +18903,7 @@ var init_staticRecipes = __esmMin((() => {
18731
18903
  border: { widthClass: "border-2" },
18732
18904
  effects: { hover: [{
18733
18905
  effectId: "background-on-hover",
18734
- options: { colorToken: "surface" }
18906
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18735
18907
  }] }
18736
18908
  }
18737
18909
  },
@@ -18765,7 +18937,6 @@ var init_staticRecipes = __esmMin((() => {
18765
18937
  effectId: "border-bottom-grow",
18766
18938
  options: {
18767
18939
  height: 1,
18768
- colorToken: "accent",
18769
18940
  origin: "left"
18770
18941
  }
18771
18942
  }] }
@@ -18796,7 +18967,6 @@ var init_staticRecipes = __esmMin((() => {
18796
18967
  cornerStyle: "rounded",
18797
18968
  textTransform: "none",
18798
18969
  fontWeight: 600,
18799
- borderWidth: 1,
18800
18970
  typography: "body",
18801
18971
  letterSpacing: "tight",
18802
18972
  paddingPreset: "default",
@@ -18828,12 +18998,9 @@ var init_staticRecipes = __esmMin((() => {
18828
18998
  },
18829
18999
  borderRadius: "rounded-lg",
18830
19000
  affordance: { iconId: "ArrowRight" },
18831
- effects: { hover: [{
18832
- effectId: "lift",
18833
- options: { translateY: "-2px" }
18834
- }, {
19001
+ effects: { hover: [{ effectId: "lift" }, {
18835
19002
  effectId: "background-on-hover",
18836
- options: { colorToken: "secondary" }
19003
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("secondary") }
18837
19004
  }] }
18838
19005
  }
18839
19006
  },
@@ -18846,12 +19013,9 @@ var init_staticRecipes = __esmMin((() => {
18846
19013
  },
18847
19014
  borderRadius: "rounded-lg",
18848
19015
  border: { widthClass: "border" },
18849
- effects: { hover: [{
18850
- effectId: "lift",
18851
- options: { translateY: "-2px" }
18852
- }, {
19016
+ effects: { hover: [{ effectId: "lift" }, {
18853
19017
  effectId: "background-on-hover",
18854
- options: { colorToken: "surfaceAlt" }
19018
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
18855
19019
  }] }
18856
19020
  }
18857
19021
  },
@@ -18864,12 +19028,9 @@ var init_staticRecipes = __esmMin((() => {
18864
19028
  },
18865
19029
  borderRadius: "rounded-lg",
18866
19030
  border: { widthClass: "border" },
18867
- effects: { hover: [{
18868
- effectId: "lift",
18869
- options: { translateY: "-2px" }
18870
- }, {
19031
+ effects: { hover: [{ effectId: "lift" }, {
18871
19032
  effectId: "background-on-hover",
18872
- options: { colorToken: "surfaceAlt" }
19033
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
18873
19034
  }] }
18874
19035
  }
18875
19036
  },
@@ -18881,10 +19042,7 @@ var init_staticRecipes = __esmMin((() => {
18881
19042
  role: "link"
18882
19043
  },
18883
19044
  borderRadius: "rounded-lg",
18884
- effects: { hover: [{
18885
- effectId: "lift",
18886
- options: { translateY: "-2px" }
18887
- }] }
19045
+ effects: { hover: [{ effectId: "lift" }] }
18888
19046
  }
18889
19047
  },
18890
19048
  accent: {
@@ -18896,10 +19054,7 @@ var init_staticRecipes = __esmMin((() => {
18896
19054
  },
18897
19055
  borderRadius: "rounded-lg",
18898
19056
  affordance: { iconId: "ArrowRight" },
18899
- effects: { hover: [{
18900
- effectId: "lift",
18901
- options: { translateY: "-2px" }
18902
- }] }
19057
+ effects: { hover: [{ effectId: "lift" }] }
18903
19058
  }
18904
19059
  }
18905
19060
  }
@@ -18920,9 +19075,8 @@ var init_staticRecipes = __esmMin((() => {
18920
19075
  shadow: "low",
18921
19076
  textTransform: "uppercase",
18922
19077
  fontWeight: 700,
18923
- borderWidth: 2,
18924
19078
  hoverTransform: "lift",
18925
- hoverColor: "darken",
19079
+ hoverColor: "none",
18926
19080
  typography: "body",
18927
19081
  paddingPreset: "spacious",
18928
19082
  italic: false
@@ -18980,7 +19134,7 @@ var init_staticRecipes = __esmMin((() => {
18980
19134
  border: { widthClass: "border-2" },
18981
19135
  effects: { hover: [{
18982
19136
  effectId: "background-on-hover",
18983
- options: { colorToken: "background" }
19137
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("background") }
18984
19138
  }] }
18985
19139
  }
18986
19140
  },
@@ -18994,7 +19148,7 @@ var init_staticRecipes = __esmMin((() => {
18994
19148
  borderRadius: "rounded-full",
18995
19149
  effects: { hover: [{
18996
19150
  effectId: "background-on-hover",
18997
- options: { colorToken: "surface" }
19151
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
18998
19152
  }] }
18999
19153
  }
19000
19154
  },
@@ -19029,7 +19183,6 @@ var init_staticRecipes = __esmMin((() => {
19029
19183
  typography: "heading",
19030
19184
  fontWeight: 700,
19031
19185
  fontSize: "text-lg",
19032
- borderWidth: 2,
19033
19186
  hoverTransform: "none",
19034
19187
  hoverColor: "none"
19035
19188
  },
@@ -19064,7 +19217,7 @@ var init_staticRecipes = __esmMin((() => {
19064
19217
  elevation: "high",
19065
19218
  softness: "hard",
19066
19219
  position: "bottom-right",
19067
- colorToken: "text"
19220
+ colorToken: unsafeAsOpaqueButtonColourToken("text")
19068
19221
  },
19069
19222
  effects: { hover: [{ effectId: "press-down" }] }
19070
19223
  }
@@ -19082,7 +19235,7 @@ var init_staticRecipes = __esmMin((() => {
19082
19235
  elevation: "high",
19083
19236
  softness: "hard",
19084
19237
  position: "bottom-right",
19085
- colorToken: "secondary"
19238
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
19086
19239
  },
19087
19240
  effects: { hover: [{ effectId: "press-down" }] }
19088
19241
  }
@@ -19145,7 +19298,6 @@ var init_staticRecipes = __esmMin((() => {
19145
19298
  cornerStyle: "rounded",
19146
19299
  textTransform: "uppercase",
19147
19300
  fontWeight: 600,
19148
- borderWidth: 1,
19149
19301
  hoverTransform: "none",
19150
19302
  hoverColor: "none",
19151
19303
  letterSpacing: "loose"
@@ -19181,7 +19333,7 @@ var init_staticRecipes = __esmMin((() => {
19181
19333
  effects: {
19182
19334
  hover: [{
19183
19335
  effectId: "background-on-hover",
19184
- options: { colorToken: "primary-100" }
19336
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("primary-100") }
19185
19337
  }],
19186
19338
  active: [{
19187
19339
  effectId: "scale-down",
@@ -19201,7 +19353,7 @@ var init_staticRecipes = __esmMin((() => {
19201
19353
  border: { widthClass: "border" },
19202
19354
  effects: { hover: [{
19203
19355
  effectId: "background-on-hover",
19204
- options: { colorToken: "surface" }
19356
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
19205
19357
  }] }
19206
19358
  }
19207
19359
  },
@@ -19216,7 +19368,7 @@ var init_staticRecipes = __esmMin((() => {
19216
19368
  border: { widthClass: "border" },
19217
19369
  effects: { hover: [{
19218
19370
  effectId: "background-on-hover",
19219
- options: { colorToken: "muted" }
19371
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("muted") }
19220
19372
  }] }
19221
19373
  }
19222
19374
  },
@@ -19233,7 +19385,6 @@ var init_staticRecipes = __esmMin((() => {
19233
19385
  effectId: "border-bottom-grow",
19234
19386
  options: {
19235
19387
  height: 1,
19236
- colorToken: "accent",
19237
19388
  origin: "left"
19238
19389
  }
19239
19390
  }] }
@@ -19634,7 +19785,7 @@ var init_testimonialQuotePresets = __esmMin((() => {
19634
19785
  * Gradient configuration types and schemas
19635
19786
  */
19636
19787
  var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
19637
- var init_types$12 = __esmMin((() => {
19788
+ var init_types$11 = __esmMin((() => {
19638
19789
  init_themeColorTokens();
19639
19790
  gradientStopSchema = z$1.object({
19640
19791
  color: themeColorTokenSchema,
@@ -19894,15 +20045,15 @@ var init_utils$4 = __esmMin((() => {}));
19894
20045
  //#endregion
19895
20046
  //#region ../theme-core/src/gradients/index.ts
19896
20047
  var init_gradients = __esmMin((() => {
19897
- init_types$12();
20048
+ init_types$11();
19898
20049
  init_presets$1();
19899
20050
  init_utils$4();
19900
20051
  }));
19901
20052
  var init_customizableSurfaces = __esmMin((() => {
19902
- init_types$16();
20053
+ init_types$15();
19903
20054
  })), logoTextConfidenceValues, logoAssetShapeValues, logoKindValues, logoDensityValues, logoContainsTextSchema, logoAnalysisSourceSchema, brandDisplayModeValues, logoAccommodationPatternValues, logoSizePolicyValues;
19904
20055
  var init_logoBranding = __esmMin((() => {
19905
- init_types$16();
20056
+ init_types$15();
19906
20057
  logoTextConfidenceValues = [
19907
20058
  "low",
19908
20059
  "medium",
@@ -20375,7 +20526,7 @@ var init_headerLooks = __esmMin((() => {
20375
20526
  init_headerCtaVariants();
20376
20527
  init_customizableSurfaces();
20377
20528
  init_logoBranding();
20378
- init_types$16();
20529
+ init_types$15();
20379
20530
  titleOnlyLogoAccommodation = {
20380
20531
  pattern: "title-only",
20381
20532
  supportedShapes: [
@@ -21051,7 +21202,7 @@ function emphasizedFooterLinks(theme) {
21051
21202
  }
21052
21203
  var footerLookCatalog;
21053
21204
  var init_footerLooks = __esmMin((() => {
21054
- init_types$16();
21205
+ init_types$15();
21055
21206
  footerLookCatalog = defineExactCatalog()([{
21056
21207
  id: asFooterLookId("footer-links-quiet"),
21057
21208
  label: "Quiet links",
@@ -21067,7 +21218,7 @@ var init_footerLooks = __esmMin((() => {
21067
21218
  }));
21068
21219
  var init_curatedChoices = __esmMin((() => {})), generatedContentFrames, userContentFrames, generatedDesignOptionCatalog, userDesignOptionCatalog;
21069
21220
  var init_sourceCatalogs = __esmMin((() => {
21070
- init_types$16();
21221
+ init_types$15();
21071
21222
  generatedContentFrames = [
21072
21223
  plainFrame,
21073
21224
  panelFrame("inset"),
@@ -21652,6 +21803,713 @@ var init_media$2 = __esmMin((() => {
21652
21803
  });
21653
21804
  }));
21654
21805
  //#endregion
21806
+ //#region ../theme-core/src/surfaces/foregroundRoles.ts
21807
+ var SURFACE_FOREGROUND_ROLES;
21808
+ var init_foregroundRoles = __esmMin((() => {
21809
+ SURFACE_FOREGROUND_ROLES = [
21810
+ "text",
21811
+ "heading",
21812
+ "link",
21813
+ "supporting"
21814
+ ];
21815
+ }));
21816
+ //#endregion
21817
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
21818
+ function requireSurfaceColorValue(role, value) {
21819
+ const normalized = value.trim();
21820
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
21821
+ return normalized;
21822
+ }
21823
+ function completeSurfaceForegrounds(input) {
21824
+ const text = requireSurfaceColorValue("text", input.text);
21825
+ return {
21826
+ text,
21827
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
21828
+ link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
21829
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
21830
+ };
21831
+ }
21832
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
21833
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
21834
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
21835
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
21836
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
21837
+ }
21838
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
21839
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
21840
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
21841
+ }
21842
+ function surfaceForegroundStyle(input) {
21843
+ const foregrounds = completeSurfaceForegrounds(input);
21844
+ return {
21845
+ color: foregrounds.text,
21846
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
21847
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
21848
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
21849
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
21850
+ };
21851
+ }
21852
+ function surfaceForegroundDeclarations(input) {
21853
+ const foregrounds = completeSurfaceForegrounds(input);
21854
+ return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
21855
+ }
21856
+ var SURFACE_FOREGROUND_CSS_VARS, DEFAULT_SURFACE_TEXT_COLOR, DEFAULT_SURFACE_LINK_COLOR, DEFAULT_SURFACE_SUPPORTING_COLOR, DEFAULT_ROLE_FALLBACKS;
21857
+ var init_foregroundContract = __esmMin((() => {
21858
+ init_foregroundRoles();
21859
+ SURFACE_FOREGROUND_CSS_VARS = {
21860
+ text: "--rb-surface-text-color",
21861
+ heading: "--rb-surface-heading-color",
21862
+ link: "--rb-surface-link-color",
21863
+ supporting: "--rb-surface-supporting-color"
21864
+ };
21865
+ DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
21866
+ DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
21867
+ DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
21868
+ DEFAULT_ROLE_FALLBACKS = {
21869
+ text: DEFAULT_SURFACE_TEXT_COLOR,
21870
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
21871
+ link: DEFAULT_SURFACE_LINK_COLOR,
21872
+ supporting: DEFAULT_SURFACE_SUPPORTING_COLOR
21873
+ };
21874
+ }));
21875
+ //#endregion
21876
+ //#region ../theme-core/src/buttons/constants.ts
21877
+ /**
21878
+ * Generate shadow CSS value dynamically based on elevation, softness, and position
21879
+ *
21880
+ * This replaces the static shadow maps with a single dynamic function.
21881
+ * Benefits: single source of truth, easy to adjust algorithm, no redundancy.
21882
+ *
21883
+ * @param elevation - Shadow elevation level
21884
+ * @param softness - Shadow softness/blur style
21885
+ * @param position - Shadow position (bottom or bottom-right diagonal)
21886
+ * @returns CSS box-shadow value
21887
+ */
21888
+ function generateShadowValue$1(elevation, softness, position = "bottom", color) {
21889
+ if (elevation === "none") return "none";
21890
+ const config = {
21891
+ low: {
21892
+ blur: 4,
21893
+ spread: 0
21894
+ },
21895
+ medium: {
21896
+ blur: 8,
21897
+ spread: -1
21898
+ },
21899
+ high: {
21900
+ blur: 12,
21901
+ spread: -2
21902
+ }
21903
+ }[elevation];
21904
+ const baseOffset = ELEVATION_OFFSET[elevation];
21905
+ const xOffset = position === "bottom-right" ? baseOffset : 0;
21906
+ const yOffset = baseOffset;
21907
+ switch (softness) {
21908
+ case null:
21909
+ case "soft": return `${xOffset}px ${yOffset}px ${config.blur}px ${config.spread}px ${color ?? "rgb(0 0 0 / 0.3)"}`;
21910
+ case "hard": return `${xOffset}px ${yOffset}px 0 0 ${color ?? "rgb(0 0 0 / 1)"}`;
21911
+ case "crisp": return `${xOffset}px ${yOffset}px ${baseOffset}px ${config.spread}px ${color ?? "rgb(0 0 0 / 0.4)"}`;
21912
+ }
21913
+ }
21914
+ var GRADIENT_DIRECTION_MAP$2, BORDER_RADIUS_MAP, ELEVATION_OFFSET, BORDER_WIDTH_MAP$4, FONT_SIZE_MAP, DEFAULT_BUTTON_SIZES;
21915
+ var init_constants$2 = __esmMin((() => {
21916
+ GRADIENT_DIRECTION_MAP$2 = {
21917
+ "to-r": "to right",
21918
+ "to-l": "to left",
21919
+ "to-t": "to top",
21920
+ "to-b": "to bottom",
21921
+ "to-br": "to bottom right",
21922
+ "to-bl": "to bottom left",
21923
+ "to-tr": "to top right",
21924
+ "to-tl": "to top left"
21925
+ };
21926
+ BORDER_RADIUS_MAP = {
21927
+ "rounded-none": "0",
21928
+ "rounded-sm": "0.125rem",
21929
+ "rounded": "0.25rem",
21930
+ "rounded-md": "0.375rem",
21931
+ "rounded-lg": "0.5rem",
21932
+ "rounded-xl": "0.75rem",
21933
+ "rounded-2xl": "1rem",
21934
+ "rounded-3xl": "1.5rem",
21935
+ "rounded-full": "9999px"
21936
+ };
21937
+ ELEVATION_OFFSET = {
21938
+ none: 0,
21939
+ low: 2,
21940
+ medium: 4,
21941
+ high: 6
21942
+ };
21943
+ BORDER_WIDTH_MAP$4 = {
21944
+ "border-0": "0px",
21945
+ "border": "1px",
21946
+ "border-2": "2px",
21947
+ "border-4": "4px",
21948
+ "border-8": "8px"
21949
+ };
21950
+ FONT_SIZE_MAP = {
21951
+ "text-xs": "0.75rem",
21952
+ "text-sm": "0.875rem",
21953
+ "text-base": "1rem",
21954
+ "text-lg": "1.125rem",
21955
+ "text-xl": "1.25rem",
21956
+ "text-2xl": "1.5rem"
21957
+ };
21958
+ DEFAULT_BUTTON_SIZES = {
21959
+ sm: {
21960
+ padding: "0.5rem 1rem",
21961
+ fontSize: "text-sm"
21962
+ },
21963
+ md: { padding: "0.75rem 1.5rem" },
21964
+ lg: {
21965
+ padding: "1rem 2rem",
21966
+ fontSize: "text-lg"
21967
+ },
21968
+ xl: {
21969
+ padding: "1.25rem 2.5rem",
21970
+ fontSize: "text-xl"
21971
+ }
21972
+ };
21973
+ }));
21974
+ //#endregion
21975
+ //#region ../theme-core/src/buttons/effectClassification.ts
21976
+ function validateButtonEffectOptions(effect) {
21977
+ const parsed = buttonEffectApplicationSchema.safeParse(effect);
21978
+ if (parsed.success) return { ok: true };
21979
+ const firstIssue = parsed.error.issues[0];
21980
+ const firstPathPart = firstIssue?.path[firstIssue.path.length - 1];
21981
+ return {
21982
+ ok: false,
21983
+ option: (firstIssue?.code === "unrecognized_keys" ? firstIssue.keys[0] : void 0) ?? (typeof firstPathPart === "string" ? firstPathPart : "options")
21984
+ };
21985
+ }
21986
+ function getButtonEffectPolicy(effectId) {
21987
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
21988
+ }
21989
+ var BUTTON_EFFECT_POLICIES;
21990
+ var init_effectClassification = __esmMin((() => {
21991
+ init_types$12();
21992
+ BUTTON_EFFECT_POLICIES = {
21993
+ "darken-background": {
21994
+ classification: "colour-transition",
21995
+ transition: {
21996
+ kind: "adjust-shade",
21997
+ direction: "darker"
21998
+ }
21999
+ },
22000
+ "lighten-background": {
22001
+ classification: "colour-transition",
22002
+ transition: {
22003
+ kind: "adjust-shade",
22004
+ direction: "lighter"
22005
+ }
22006
+ },
22007
+ "background-on-hover": {
22008
+ classification: "colour-transition",
22009
+ transition: { kind: "replace-background" }
22010
+ },
22011
+ "background-on-hover-alpha": {
22012
+ classification: "unsupported-colour",
22013
+ reason: "alpha_requires_surface"
22014
+ },
22015
+ "fade-background": {
22016
+ classification: "unsupported-colour",
22017
+ reason: "changes_element_opacity"
22018
+ },
22019
+ "opacity-reduce": {
22020
+ classification: "unsupported-colour",
22021
+ reason: "changes_element_opacity"
22022
+ },
22023
+ "gradient-text": {
22024
+ classification: "unsupported-colour",
22025
+ reason: "changes_foreground"
22026
+ },
22027
+ "text-color-change": {
22028
+ classification: "unsupported-colour",
22029
+ reason: "changes_foreground"
22030
+ },
22031
+ "border-color-change": {
22032
+ classification: "unsupported-colour",
22033
+ reason: "changes_border"
22034
+ },
22035
+ "aurora-glow": {
22036
+ classification: "unsupported-background-overlay",
22037
+ reason: "unresolved_background_overlay"
22038
+ },
22039
+ "cosmic-stardust": {
22040
+ classification: "unsupported-background-overlay",
22041
+ reason: "unresolved_background_overlay"
22042
+ },
22043
+ "gradient-border-fill": {
22044
+ classification: "unsupported-background-overlay",
22045
+ reason: "unresolved_background_overlay"
22046
+ },
22047
+ "animated-gradient-border-fill": {
22048
+ classification: "unsupported-background-overlay",
22049
+ reason: "unresolved_background_overlay"
22050
+ },
22051
+ "nav-underline": {
22052
+ classification: "not-button",
22053
+ reason: "not_button_effect"
22054
+ },
22055
+ "nav-frosted-base": {
22056
+ classification: "not-button",
22057
+ reason: "not_button_effect"
22058
+ },
22059
+ "nav-frosted-hover": {
22060
+ classification: "not-button",
22061
+ reason: "not_button_effect"
22062
+ },
22063
+ "nav-frosted-active": {
22064
+ classification: "not-button",
22065
+ reason: "not_button_effect"
22066
+ },
22067
+ "animated-gradient": { classification: "non-colour" },
22068
+ "border-glow": {
22069
+ classification: "unsupported-colour",
22070
+ reason: "changes_shadow_colour"
22071
+ },
22072
+ "drop-shadow": { classification: "decorative-colour" },
22073
+ "inner-shadow": { classification: "decorative-colour" },
22074
+ "neumorphic-shadow": { classification: "decorative-colour" },
22075
+ "outer-glow": {
22076
+ classification: "unsupported-colour",
22077
+ reason: "changes_shadow_colour"
22078
+ },
22079
+ "retro-3d-shadow": { classification: "decorative-colour" },
22080
+ "scale-up": { classification: "non-colour" },
22081
+ "scale-down": { classification: "non-colour" },
22082
+ lift: { classification: "non-colour" },
22083
+ "press-down": { classification: "non-colour" },
22084
+ pop: { classification: "non-colour" },
22085
+ "border-bottom-grow": { classification: "non-colour" },
22086
+ "sketchy-border": { classification: "decorative-colour" },
22087
+ "pulse-animation": {
22088
+ classification: "unsupported-colour",
22089
+ reason: "changes_element_opacity"
22090
+ }
22091
+ };
22092
+ }));
22093
+ //#endregion
22094
+ //#region ../theme-core/src/buttons/resolveButtonColourStates.ts
22095
+ function compileButtonColourStates(input) {
22096
+ const baseTransition = applyColourEffects({
22097
+ variantId: input.variant.id,
22098
+ state: "base",
22099
+ treatment: input.variant.background,
22100
+ effects: input.variant.effects?.base,
22101
+ palette: input.palette
22102
+ });
22103
+ if (!baseTransition.ok) return baseTransition;
22104
+ const stateTreatments = {
22105
+ base: baseTransition.treatment,
22106
+ hover: hoverTreatment(input.variant, input.global, baseTransition.treatment),
22107
+ focus: baseTransition.treatment,
22108
+ active: baseTransition.treatment,
22109
+ disabled: baseTransition.treatment
22110
+ };
22111
+ const nonColourEffects = { ...baseTransition.nonColourEffects.length > 0 ? { base: [...baseTransition.nonColourEffects] } : {} };
22112
+ for (const state of [
22113
+ "hover",
22114
+ "focus",
22115
+ "active"
22116
+ ]) {
22117
+ const transition = applyColourEffects({
22118
+ variantId: input.variant.id,
22119
+ state,
22120
+ treatment: stateTreatments[state],
22121
+ effects: input.variant.effects?.[state],
22122
+ palette: input.palette
22123
+ });
22124
+ if (!transition.ok) return transition;
22125
+ stateTreatments[state] = transition.treatment;
22126
+ if (transition.nonColourEffects.length > 0) nonColourEffects[state] = [...transition.nonColourEffects];
22127
+ }
22128
+ const resolved = {};
22129
+ for (const state of BUTTON_VISUAL_STATES) {
22130
+ const result = resolveTreatment$1({
22131
+ variantId: input.variant.id,
22132
+ state,
22133
+ treatment: stateTreatments[state],
22134
+ palette: input.palette
22135
+ });
22136
+ if (!result.ok) return result;
22137
+ resolved[state] = result.colour;
22138
+ }
22139
+ return {
22140
+ ok: true,
22141
+ states: resolved,
22142
+ focusIndicator: resolveFocusIndicator(resolved.focus),
22143
+ nonColourEffects
22144
+ };
22145
+ }
22146
+ function formatButtonColourContractError(error) {
22147
+ switch (error.tag) {
22148
+ case "unknown_palette_token": return `Button "${error.variantId}" ${error.state} state uses unknown palette token "${error.token}".`;
22149
+ case "missing_on_colour": return `Button "${error.variantId}" ${error.state} state cannot derive ${error.foregroundToken} from ${error.backgroundToken}.`;
22150
+ case "insufficient_contrast": return `Button "${error.variantId}" ${error.state} state has ${error.ratio.toFixed(2)}:1 contrast (${error.requiredRatio}:1 required).`;
22151
+ case "unsupported_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" is not contrast-safe (${error.reason}).`;
22152
+ case "invalid_colour_effect_options": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" has an invalid ${error.option} option.`;
22153
+ case "inapplicable_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" cannot apply to a ${error.treatment} treatment.`;
22154
+ case "unknown_button_effect": return `Button "${error.variantId}" ${error.state} uses unknown effect "${error.effectId}".`;
22155
+ }
22156
+ }
22157
+ function hoverTreatment(variant, global, fallback) {
22158
+ const token = variant.hoverBackgroundToken ?? (global.hoverColor === "token" ? global.hoverColorToken : void 0);
22159
+ return token === void 0 ? fallback : {
22160
+ type: "solid",
22161
+ colorToken: token
22162
+ };
22163
+ }
22164
+ function applyColourEffects(input) {
22165
+ let treatment = input.treatment;
22166
+ const nonColourEffects = [];
22167
+ for (const effect of input.effects ?? []) {
22168
+ const policy = getButtonEffectPolicy(effect.effectId);
22169
+ if (policy === null) return unknownEffect(input, effect);
22170
+ if (policy.classification === "unsupported-colour" || policy.classification === "unsupported-background-overlay" || policy.classification === "not-button") return unsupportedEffect(input, effect, policy.reason);
22171
+ const options = validateButtonEffectOptions(effect);
22172
+ if (!options.ok) return invalidEffectOption(input, effect, options.option);
22173
+ switch (policy.classification) {
22174
+ case "non-colour":
22175
+ case "decorative-colour":
22176
+ nonColourEffects.push(effect);
22177
+ break;
22178
+ case "colour-transition":
22179
+ if (policy.transition.kind === "adjust-shade") {
22180
+ if (effect.effectId !== "darken-background" && effect.effectId !== "lighten-background") return unknownEffect(input, effect);
22181
+ if (treatment.type !== "solid") return inapplicableEffect(input, effect, treatment);
22182
+ const amount = readShadeAmount(effect);
22183
+ if (amount === null) return invalidEffectOption(input, effect, "amount");
22184
+ const signedAmount = policy.transition.direction === "darker" ? amount : -amount;
22185
+ treatment = {
22186
+ type: "solid",
22187
+ colorToken: adjustShade(treatment.colorToken, signedAmount, input.palette)
22188
+ };
22189
+ break;
22190
+ }
22191
+ if (policy.transition.kind === "replace-background") {
22192
+ if (effect.effectId !== "background-on-hover") return unknownEffect(input, effect);
22193
+ const colorToken = readOpaqueToken(effect);
22194
+ if (colorToken === null) return invalidEffectOption(input, effect, "colorToken");
22195
+ treatment = {
22196
+ type: "solid",
22197
+ colorToken
22198
+ };
22199
+ break;
22200
+ }
22201
+ return unknownEffect(input, effect);
22202
+ }
22203
+ }
22204
+ return {
22205
+ ok: true,
22206
+ treatment,
22207
+ nonColourEffects
22208
+ };
22209
+ }
22210
+ function resolveTreatment$1(input) {
22211
+ const treatment = input.treatment;
22212
+ switch (treatment.type) {
22213
+ case "surface": return {
22214
+ ok: true,
22215
+ colour: {
22216
+ kind: "surface",
22217
+ role: treatment.role,
22218
+ backgroundCss: "transparent",
22219
+ foregroundCss: surfaceForegroundValue(treatment.role)
22220
+ }
22221
+ };
22222
+ case "solid": return resolveSolid(input, treatment.colorToken);
22223
+ case "gradient": return resolveGradient$2(input, treatment);
22224
+ }
22225
+ }
22226
+ function resolveFocusIndicator(colour) {
22227
+ switch (colour.kind) {
22228
+ case "solid": return {
22229
+ kind: "two-tone",
22230
+ innerCss: colour.foregroundCss,
22231
+ outerCss: colour.backgroundCss,
22232
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
22233
+ };
22234
+ case "gradient": return {
22235
+ kind: "two-tone",
22236
+ innerCss: colour.foregroundCss,
22237
+ outerCss: tokenCss(colour.backgroundTokens[0]),
22238
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
22239
+ };
22240
+ case "surface": return {
22241
+ kind: "surface-role",
22242
+ colorCss: colour.foregroundCss,
22243
+ minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
22244
+ };
22245
+ }
22246
+ }
22247
+ function resolveSolid(input, backgroundToken) {
22248
+ const backgroundHex = paletteHex(input, backgroundToken);
22249
+ if (!backgroundHex.ok) return backgroundHex;
22250
+ const foregroundToken = unsafeAsOpaqueButtonColourToken(onColorTokenName(backgroundToken));
22251
+ const foregroundHex = input.palette[foregroundToken];
22252
+ if (typeof foregroundHex !== "string") return {
22253
+ ok: false,
22254
+ error: {
22255
+ tag: "missing_on_colour",
22256
+ variantId: input.variantId,
22257
+ state: input.state,
22258
+ backgroundToken,
22259
+ foregroundToken
22260
+ }
22261
+ };
22262
+ const contrast = validateContrast({
22263
+ ...input,
22264
+ background: backgroundToken,
22265
+ backgroundHex: backgroundHex.hex,
22266
+ foreground: foregroundToken,
22267
+ foregroundHex
22268
+ });
22269
+ if (!contrast.ok) return contrast;
22270
+ return {
22271
+ ok: true,
22272
+ colour: {
22273
+ kind: "solid",
22274
+ backgroundToken,
22275
+ foregroundToken,
22276
+ backgroundCss: tokenCss(backgroundToken),
22277
+ foregroundCss: tokenCss(foregroundToken)
22278
+ }
22279
+ };
22280
+ }
22281
+ function resolveGradient$2(input, treatment) {
22282
+ const foregroundHex = paletteHex(input, treatment.foregroundToken);
22283
+ if (!foregroundHex.ok) return foregroundHex;
22284
+ const stopHexes = [];
22285
+ for (const token of treatment.stops) {
22286
+ const stop = paletteHex(input, token);
22287
+ if (!stop.ok) return stop;
22288
+ stopHexes.push(stop.hex);
22289
+ }
22290
+ for (let segment = 0; segment < stopHexes.length - 1; segment += 1) {
22291
+ const start = stopHexes[segment];
22292
+ const end = stopHexes[segment + 1];
22293
+ const startToken = treatment.stops[segment];
22294
+ const endToken = treatment.stops[segment + 1];
22295
+ if (start === void 0 || end === void 0 || startToken === void 0 || endToken === void 0) continue;
22296
+ for (let sample = 0; sample <= BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment; sample += 1) {
22297
+ const position = sample / BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment;
22298
+ const sampleHex = interpolateHex(start, end, position);
22299
+ const contrast = validateContrast({
22300
+ ...input,
22301
+ background: `${startToken}→${endToken}@${position.toFixed(2)}`,
22302
+ backgroundHex: sampleHex,
22303
+ foreground: treatment.foregroundToken,
22304
+ foregroundHex: foregroundHex.hex
22305
+ });
22306
+ if (!contrast.ok) return contrast;
22307
+ }
22308
+ }
22309
+ const direction = GRADIENT_DIRECTION_MAP$2[treatment.direction] ?? "to right";
22310
+ return {
22311
+ ok: true,
22312
+ colour: {
22313
+ kind: "gradient",
22314
+ backgroundTokens: treatment.stops,
22315
+ foregroundToken: treatment.foregroundToken,
22316
+ backgroundCss: `linear-gradient(${direction}, ${treatment.stops.map(tokenCss).join(", ")})`,
22317
+ foregroundCss: tokenCss(treatment.foregroundToken)
22318
+ }
22319
+ };
22320
+ }
22321
+ function paletteHex(input, token) {
22322
+ const hex = input.palette[token];
22323
+ return typeof hex === "string" ? {
22324
+ ok: true,
22325
+ hex
22326
+ } : {
22327
+ ok: false,
22328
+ error: {
22329
+ tag: "unknown_palette_token",
22330
+ variantId: input.variantId,
22331
+ state: input.state,
22332
+ token
22333
+ }
22334
+ };
22335
+ }
22336
+ function validateContrast(input) {
22337
+ const ratio = contrastRatio(input.backgroundHex, input.foregroundHex);
22338
+ return ratio >= BUTTON_CONTRAST_POLICY.textMinimumRatio ? { ok: true } : {
22339
+ ok: false,
22340
+ error: {
22341
+ tag: "insufficient_contrast",
22342
+ variantId: input.variantId,
22343
+ state: input.state,
22344
+ background: input.background,
22345
+ foreground: input.foreground,
22346
+ ratio,
22347
+ requiredRatio: BUTTON_CONTRAST_POLICY.textMinimumRatio
22348
+ }
22349
+ };
22350
+ }
22351
+ function tokenCss(token) {
22352
+ return `rgb(var(--tb-${token}))`;
22353
+ }
22354
+ function adjustShade(token, amount, palette) {
22355
+ const match = token.match(/^(.*)-(\d{2,3})$/);
22356
+ const base = match?.[1] ?? token;
22357
+ const currentShade = match?.[2] === void 0 ? 500 : Number(match[2]);
22358
+ const availableShades = [
22359
+ 50,
22360
+ 100,
22361
+ 200,
22362
+ 300,
22363
+ 400,
22364
+ 500,
22365
+ 600,
22366
+ 700,
22367
+ 800,
22368
+ 900,
22369
+ 950
22370
+ ].filter((shade) => typeof palette[`${base}-${shade}`] === "string");
22371
+ if (availableShades.length === 0) return token;
22372
+ const firstShade = availableShades[0];
22373
+ if (firstShade === void 0) return token;
22374
+ const exactIndex = availableShades.indexOf(currentShade);
22375
+ const startingIndex = exactIndex >= 0 ? exactIndex : availableShades.indexOf(availableShades.reduce((closestShade, shade) => Math.abs(shade - currentShade) < Math.abs(closestShade - currentShade) ? shade : closestShade, firstShade));
22376
+ const stepCount = Math.abs(amount) / 100;
22377
+ const direction = amount < 0 ? -1 : 1;
22378
+ const targetShade = availableShades[Math.max(0, Math.min(availableShades.length - 1, startingIndex + direction * stepCount))];
22379
+ return targetShade === void 0 ? token : unsafeAsOpaqueButtonColourToken(`${base}-${targetShade}`);
22380
+ }
22381
+ function readShadeAmount(effect) {
22382
+ const value = effect.options?.amount ?? 100;
22383
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 && value % 100 === 0 ? value : null;
22384
+ }
22385
+ function readOpaqueToken(effect) {
22386
+ return parseOpaqueButtonColourToken(effect.options?.colorToken ?? "neutral-800");
22387
+ }
22388
+ function unsupportedEffect(input, effect, reason) {
22389
+ return {
22390
+ ok: false,
22391
+ error: {
22392
+ tag: "unsupported_colour_effect",
22393
+ variantId: input.variantId,
22394
+ state: input.state,
22395
+ effectId: effect.effectId,
22396
+ reason
22397
+ }
22398
+ };
22399
+ }
22400
+ function invalidEffectOption(input, effect, option) {
22401
+ return {
22402
+ ok: false,
22403
+ error: {
22404
+ tag: "invalid_colour_effect_options",
22405
+ variantId: input.variantId,
22406
+ state: input.state,
22407
+ effectId: effect.effectId,
22408
+ option
22409
+ }
22410
+ };
22411
+ }
22412
+ function inapplicableEffect(input, effect, treatment) {
22413
+ return {
22414
+ ok: false,
22415
+ error: {
22416
+ tag: "inapplicable_colour_effect",
22417
+ variantId: input.variantId,
22418
+ state: input.state,
22419
+ effectId: effect.effectId,
22420
+ treatment: treatment.type
22421
+ }
22422
+ };
22423
+ }
22424
+ function unknownEffect(input, effect) {
22425
+ return {
22426
+ ok: false,
22427
+ error: {
22428
+ tag: "unknown_button_effect",
22429
+ variantId: input.variantId,
22430
+ state: input.state,
22431
+ effectId: effect.effectId
22432
+ }
22433
+ };
22434
+ }
22435
+ function interpolateHex(startHex, endHex, position) {
22436
+ const start = hexToRgb$1(startHex);
22437
+ const end = hexToRgb$1(endHex);
22438
+ const channel = (from, to) => Math.round(from + (to - from) * position).toString(16).padStart(2, "0");
22439
+ return `#${channel(start.r, end.r)}${channel(start.g, end.g)}${channel(start.b, end.b)}`;
22440
+ }
22441
+ var BUTTON_VISUAL_STATES, BUTTON_CONTRAST_POLICY;
22442
+ var init_resolveButtonColourStates = __esmMin((() => {
22443
+ init_contrast$1();
22444
+ init_colorConversion();
22445
+ init_onColor();
22446
+ init_foregroundContract();
22447
+ init_types$12();
22448
+ init_constants$2();
22449
+ init_effectClassification();
22450
+ BUTTON_VISUAL_STATES = [
22451
+ "base",
22452
+ "hover",
22453
+ "focus",
22454
+ "active",
22455
+ "disabled"
22456
+ ];
22457
+ BUTTON_CONTRAST_POLICY = {
22458
+ textMinimumRatio: 4.5,
22459
+ nonTextMinimumRatio: 3,
22460
+ gradientSamplesPerSegment: 20,
22461
+ alphaBackgrounds: "reject-without-known-surface",
22462
+ disabled: "retain-full-colour-contract"
22463
+ };
22464
+ }));
22465
+ //#endregion
22466
+ //#region ../theme-core/src/buttons/parseThemeForPersistence.ts
22467
+ /**
22468
+ * Proves that every persisted button variant compiles against the theme's
22469
+ * concrete palette. Public rendering may still recover from malformed
22470
+ * external/runtime input, but persistence boundaries must reject it.
22471
+ */
22472
+ function parseThemeForPersistence(value) {
22473
+ const parsed = themeSchema.safeParse(value);
22474
+ if (!parsed.success) return {
22475
+ ok: false,
22476
+ error: {
22477
+ kind: "invalid-theme-schema",
22478
+ issues: parsed.error.issues
22479
+ }
22480
+ };
22481
+ const theme = parsed.data;
22482
+ if (!theme.buttons) return {
22483
+ ok: true,
22484
+ value: theme
22485
+ };
22486
+ const palette = expandPalette(theme.palette);
22487
+ for (const variant of theme.buttons.variants) {
22488
+ const result = compileButtonColourStates({
22489
+ variant,
22490
+ global: theme.buttons.global,
22491
+ palette
22492
+ });
22493
+ if (!result.ok) return {
22494
+ ok: false,
22495
+ error: {
22496
+ kind: "invalid-button-colour-contract",
22497
+ variantId: variant.id,
22498
+ cause: result.error
22499
+ }
22500
+ };
22501
+ }
22502
+ return {
22503
+ ok: true,
22504
+ value: theme
22505
+ };
22506
+ }
22507
+ var init_parseThemeForPersistence = __esmMin((() => {
22508
+ init_schema();
22509
+ init_expandPalette();
22510
+ init_resolveButtonColourStates();
22511
+ }));
22512
+ //#endregion
21655
22513
  //#region ../theme-core/src/buttons/classNames.ts
21656
22514
  /**
21657
22515
  * Parse content/runtime variant identifiers into the closed theme-button class
@@ -21661,6 +22519,7 @@ var init_media$2 = __esmMin((() => {
21661
22519
  function parseThemeButtonVariantId(value) {
21662
22520
  const normalized = value?.trim() ?? "";
21663
22521
  if (normalized.length === 0) return null;
22522
+ if (!buttonVariantIdSchema.safeParse(normalized).success) return null;
21664
22523
  if (normalized === "default") return DEFAULT_VARIANT_ALIAS_ID;
21665
22524
  return isVariantRole(normalized) ? normalized : asSpecialVariantId(normalized);
21666
22525
  }
@@ -21684,7 +22543,7 @@ function themeButtonClassName(spec) {
21684
22543
  ].filter(Boolean).join(" ");
21685
22544
  }
21686
22545
  var init_classNames = __esmMin((() => {
21687
- init_types$13();
22546
+ init_types$12();
21688
22547
  }));
21689
22548
  //#endregion
21690
22549
  //#region ../theme-core/src/interactive/generateBaseCSS.ts
@@ -21755,9 +22614,21 @@ var init_background$2 = __esmMin((() => {
21755
22614
  applicableTo: ["button"],
21756
22615
  customizableOption: {
21757
22616
  name: "amount",
21758
- type: "number",
22617
+ type: "select",
21759
22618
  label: "Darken Amount (shade step)",
21760
- default: 100
22619
+ default: 100,
22620
+ options: [
22621
+ 0,
22622
+ 100,
22623
+ 200,
22624
+ 300,
22625
+ 400,
22626
+ 500,
22627
+ 600,
22628
+ 700,
22629
+ 800,
22630
+ 900
22631
+ ]
21761
22632
  },
21762
22633
  isApplicable: (buttonConfig) => {
21763
22634
  return buttonConfig.background.type === "solid";
@@ -21784,9 +22655,21 @@ var init_background$2 = __esmMin((() => {
21784
22655
  applicableTo: ["button"],
21785
22656
  customizableOption: {
21786
22657
  name: "amount",
21787
- type: "number",
22658
+ type: "select",
21788
22659
  label: "Lighten Amount (shade step)",
21789
- default: 100
22660
+ default: 100,
22661
+ options: [
22662
+ 0,
22663
+ 100,
22664
+ 200,
22665
+ 300,
22666
+ 400,
22667
+ 500,
22668
+ 600,
22669
+ 700,
22670
+ 800,
22671
+ 900
22672
+ ]
21790
22673
  },
21791
22674
  isApplicable: (buttonConfig) => {
21792
22675
  return buttonConfig.background.type === "solid";
@@ -21810,7 +22693,7 @@ var init_background$2 = __esmMin((() => {
21810
22693
  description: "Reduces background opacity on hover",
21811
22694
  category: "background",
21812
22695
  pseudoElement: "none",
21813
- applicableTo: ["button", "nav-link"],
22696
+ applicableTo: ["nav-link"],
21814
22697
  customizableOption: {
21815
22698
  name: "opacity",
21816
22699
  type: "percentage",
@@ -21829,10 +22712,10 @@ var init_background$2 = __esmMin((() => {
21829
22712
  opacityReduceEffect = {
21830
22713
  id: "opacity-reduce",
21831
22714
  name: "Reduce Opacity",
21832
- description: "Reduces button opacity on hover by a percentage",
22715
+ description: "Reduces navigation-link opacity on hover by a percentage",
21833
22716
  category: "background",
21834
22717
  pseudoElement: "none",
21835
- applicableTo: ["button", "nav-link"],
22718
+ applicableTo: ["nav-link"],
21836
22719
  customizableOption: {
21837
22720
  name: "reduction",
21838
22721
  type: "percentage",
@@ -21920,7 +22803,7 @@ var init_background$2 = __esmMin((() => {
21920
22803
  description: "Adds semi-transparent background on hover",
21921
22804
  category: "background",
21922
22805
  pseudoElement: "none",
21923
- applicableTo: ["button", "nav-link"],
22806
+ applicableTo: ["nav-link"],
21924
22807
  customizableOption: {
21925
22808
  name: "opacity",
21926
22809
  type: "percentage",
@@ -21994,7 +22877,7 @@ var init_shadow = __esmMin((() => {
21994
22877
  description: "Adds a glowing shadow on hover",
21995
22878
  category: "shadow",
21996
22879
  pseudoElement: "none",
21997
- applicableTo: ["button", "nav-link"],
22880
+ applicableTo: ["nav-link"],
21998
22881
  customizableOption: {
21999
22882
  name: "glowColorToken",
22000
22883
  type: "colorToken",
@@ -22093,10 +22976,10 @@ var init_shadow = __esmMin((() => {
22093
22976
  outerGlowEffect = {
22094
22977
  id: "outer-glow",
22095
22978
  name: "Outer Glow",
22096
- description: "Creates an outer glow around the button",
22979
+ description: "Creates an outer glow around a navigation link",
22097
22980
  category: "shadow",
22098
22981
  pseudoElement: "none",
22099
- applicableTo: ["button", "nav-link"],
22982
+ applicableTo: ["nav-link"],
22100
22983
  customizableOption: {
22101
22984
  name: "spread",
22102
22985
  type: "number",
@@ -22152,105 +23035,6 @@ var init_shadow = __esmMin((() => {
22152
23035
  };
22153
23036
  }));
22154
23037
  //#endregion
22155
- //#region ../theme-core/src/buttons/constants.ts
22156
- /**
22157
- * Generate shadow CSS value dynamically based on elevation, softness, and position
22158
- *
22159
- * This replaces the static shadow maps with a single dynamic function.
22160
- * Benefits: single source of truth, easy to adjust algorithm, no redundancy.
22161
- *
22162
- * @param elevation - Shadow elevation level
22163
- * @param softness - Shadow softness/blur style
22164
- * @param position - Shadow position (bottom or bottom-right diagonal)
22165
- * @returns CSS box-shadow value
22166
- */
22167
- function generateShadowValue$1(elevation, softness, position = "bottom", color) {
22168
- if (elevation === "none") return "none";
22169
- const config = {
22170
- low: {
22171
- blur: 4,
22172
- spread: 0
22173
- },
22174
- medium: {
22175
- blur: 8,
22176
- spread: -1
22177
- },
22178
- high: {
22179
- blur: 12,
22180
- spread: -2
22181
- }
22182
- }[elevation];
22183
- const baseOffset = ELEVATION_OFFSET[elevation];
22184
- const xOffset = position === "bottom-right" ? baseOffset : 0;
22185
- const yOffset = baseOffset;
22186
- switch (softness) {
22187
- case null:
22188
- case "soft": return `${xOffset}px ${yOffset}px ${config.blur}px ${config.spread}px ${color ?? "rgb(0 0 0 / 0.3)"}`;
22189
- case "hard": return `${xOffset}px ${yOffset}px 0 0 ${color ?? "rgb(0 0 0 / 1)"}`;
22190
- case "crisp": return `${xOffset}px ${yOffset}px ${baseOffset}px ${config.spread}px ${color ?? "rgb(0 0 0 / 0.4)"}`;
22191
- }
22192
- }
22193
- var GRADIENT_DIRECTION_MAP$2, BORDER_RADIUS_MAP, ELEVATION_OFFSET, BORDER_WIDTH_MAP$4, FONT_SIZE_MAP, DEFAULT_BUTTON_SIZES;
22194
- var init_constants$2 = __esmMin((() => {
22195
- GRADIENT_DIRECTION_MAP$2 = {
22196
- "to-r": "to right",
22197
- "to-l": "to left",
22198
- "to-t": "to top",
22199
- "to-b": "to bottom",
22200
- "to-br": "to bottom right",
22201
- "to-bl": "to bottom left",
22202
- "to-tr": "to top right",
22203
- "to-tl": "to top left"
22204
- };
22205
- BORDER_RADIUS_MAP = {
22206
- "rounded-none": "0",
22207
- "rounded-sm": "0.125rem",
22208
- "rounded": "0.25rem",
22209
- "rounded-md": "0.375rem",
22210
- "rounded-lg": "0.5rem",
22211
- "rounded-xl": "0.75rem",
22212
- "rounded-2xl": "1rem",
22213
- "rounded-3xl": "1.5rem",
22214
- "rounded-full": "9999px"
22215
- };
22216
- ELEVATION_OFFSET = {
22217
- none: 0,
22218
- low: 2,
22219
- medium: 4,
22220
- high: 6
22221
- };
22222
- BORDER_WIDTH_MAP$4 = {
22223
- "border-0": "0px",
22224
- "border": "1px",
22225
- "border-2": "2px",
22226
- "border-4": "4px",
22227
- "border-8": "8px"
22228
- };
22229
- FONT_SIZE_MAP = {
22230
- "text-xs": "0.75rem",
22231
- "text-sm": "0.875rem",
22232
- "text-base": "1rem",
22233
- "text-lg": "1.125rem",
22234
- "text-xl": "1.25rem",
22235
- "text-2xl": "1.5rem"
22236
- };
22237
- DEFAULT_BUTTON_SIZES = {
22238
- sm: {
22239
- padding: "0.5rem 1rem",
22240
- fontSize: "text-sm"
22241
- },
22242
- md: { padding: "0.75rem 1.5rem" },
22243
- lg: {
22244
- padding: "1rem 2rem",
22245
- fontSize: "text-lg"
22246
- },
22247
- xl: {
22248
- padding: "1.25rem 2.5rem",
22249
- fontSize: "text-xl"
22250
- }
22251
- };
22252
- }));
22253
- //#endregion
22254
23038
  //#region ../theme-core/src/buttons/effects/presets/transform.ts
22255
23039
  var scaleUpEffect, scaleDownEffect, liftEffect, pressDownEffect, popEffect;
22256
23040
  var init_transform = __esmMin((() => {
@@ -22270,6 +23054,7 @@ var init_transform = __esmMin((() => {
22270
23054
  default: "1.05",
22271
23055
  options: [
22272
23056
  "1.02",
23057
+ "1.03",
22273
23058
  "1.05",
22274
23059
  "1.10"
22275
23060
  ]
@@ -22394,7 +23179,7 @@ var init_overlay = __esmMin((() => {
22394
23179
  description: "Blurred gradient glow that appears on hover",
22395
23180
  category: "overlay",
22396
23181
  pseudoElement: "before",
22397
- applicableTo: ["button"],
23182
+ applicableTo: [],
22398
23183
  customizableOption: {
22399
23184
  name: "intensity",
22400
23185
  type: "percentage",
@@ -22452,7 +23237,7 @@ var init_overlay = __esmMin((() => {
22452
23237
  description: "Rotating rainbow gradient glow (always visible, intensifies on hover)",
22453
23238
  category: "overlay",
22454
23239
  pseudoElement: "before",
22455
- applicableTo: ["button"],
23240
+ applicableTo: [],
22456
23241
  customizableOption: {
22457
23242
  name: "speed",
22458
23243
  type: "select",
@@ -22519,7 +23304,7 @@ var init_overlay = __esmMin((() => {
22519
23304
  description: "Gradient border that fills on hover using ::before pseudo-element",
22520
23305
  category: "overlay",
22521
23306
  pseudoElement: "before",
22522
- applicableTo: ["button"],
23307
+ applicableTo: [],
22523
23308
  customizableOption: {
22524
23309
  name: "borderWidth",
22525
23310
  type: "number",
@@ -22568,7 +23353,7 @@ var init_overlay = __esmMin((() => {
22568
23353
  description: "Rotating gradient border that fills on hover",
22569
23354
  category: "overlay",
22570
23355
  pseudoElement: "before",
22571
- applicableTo: ["button"],
23356
+ applicableTo: [],
22572
23357
  customizableOption: {
22573
23358
  name: "speed",
22574
23359
  type: "select",
@@ -22642,15 +23427,13 @@ var init_overlay = __esmMin((() => {
22642
23427
  applicableTo: ["button", "nav-link"],
22643
23428
  customizableOption: {
22644
23429
  name: "height",
22645
- type: "number",
23430
+ type: "select",
22646
23431
  label: "Border Height (px)",
22647
- default: 1
23432
+ default: 1,
23433
+ options: [1, 2]
22648
23434
  },
22649
23435
  generateCSS: (ctx) => {
22650
- const { themeId, variantId, options, tokens } = ctx;
22651
- const height = options.height || 1;
22652
- const colorToken = options.colorToken || "neutral-400";
22653
- const origin = options.origin || "left";
23436
+ const { themeId, variantId, options } = ctx;
22654
23437
  return `
22655
23438
  /* Setup button for pseudo-element */
22656
23439
  :where([data-theme-scope="${themeId}"]) .${variantId} {
@@ -22664,10 +23447,10 @@ var init_overlay = __esmMin((() => {
22664
23447
  bottom: 0;
22665
23448
  left: 0;
22666
23449
  width: 100%;
22667
- height: ${height}px;
22668
- background: ${tokens.getColor(colorToken)};
23450
+ height: ${options.height || 1}px;
23451
+ background: currentColor;
22669
23452
  transform: scaleX(0);
22670
- transform-origin: ${origin};
23453
+ transform-origin: ${options.origin || "left"};
22671
23454
  transition: transform 300ms ease-in-out;
22672
23455
  }
22673
23456
 
@@ -22689,7 +23472,7 @@ var init_text = __esmMin((() => {
22689
23472
  description: "Gradient text using background-clip",
22690
23473
  category: "text",
22691
23474
  pseudoElement: "none",
22692
- applicableTo: ["button"],
23475
+ applicableTo: [],
22693
23476
  customizableOption: {
22694
23477
  name: "solidOnHover",
22695
23478
  type: "select",
@@ -22732,7 +23515,7 @@ var init_text = __esmMin((() => {
22732
23515
  description: "Changes text color on hover",
22733
23516
  category: "text",
22734
23517
  pseudoElement: "none",
22735
- applicableTo: ["button", "nav-link"],
23518
+ applicableTo: ["nav-link"],
22736
23519
  customizableOption: {
22737
23520
  name: "hoverColorToken",
22738
23521
  type: "select",
@@ -22768,7 +23551,7 @@ var init_border = __esmMin((() => {
22768
23551
  description: "Changes border color on hover",
22769
23552
  category: "border",
22770
23553
  pseudoElement: "none",
22771
- applicableTo: ["button", "nav-link"],
23554
+ applicableTo: ["nav-link"],
22772
23555
  customizableOption: {
22773
23556
  name: "hoverColorToken",
22774
23557
  type: "select",
@@ -22822,8 +23605,7 @@ var init_border = __esmMin((() => {
22822
23605
  medium: "rotate(-1deg)",
22823
23606
  strong: "rotate(-1.5deg)"
22824
23607
  }[intensity]};
22825
- filter: contrast(0.95) brightness(1.02);
22826
- transition: transform 0.2s ease, filter 0.2s ease;
23608
+ transition: transform 0.2s ease;
22827
23609
  }
22828
23610
 
22829
23611
  :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
@@ -22832,7 +23614,6 @@ var init_border = __esmMin((() => {
22832
23614
  medium: "rotate(1deg)",
22833
23615
  strong: "rotate(1.5deg)"
22834
23616
  }[intensity]} scale(1.02);
22835
- filter: contrast(1) brightness(1);
22836
23617
  }
22837
23618
 
22838
23619
  :where([data-theme-scope="${themeId}"]) .${variantId}:active {
@@ -22852,7 +23633,7 @@ var init_animation = __esmMin((() => {
22852
23633
  description: "Continuous pulse animation (opacity fade)",
22853
23634
  category: "animation",
22854
23635
  pseudoElement: "none",
22855
- applicableTo: ["button", "nav-link"],
23636
+ applicableTo: ["nav-link"],
22856
23637
  customizableOption: {
22857
23638
  name: "speed",
22858
23639
  type: "select",
@@ -23048,6 +23829,7 @@ var init_registry$1 = __esmMin((() => {
23048
23829
  init_border();
23049
23830
  init_animation();
23050
23831
  init_effects();
23832
+ init_effectClassification();
23051
23833
  EFFECT_PRESETS = [
23052
23834
  darkenBackgroundEffect,
23053
23835
  lightenBackgroundEffect,
@@ -23149,11 +23931,11 @@ function narrowCornerStyle(corners) {
23149
23931
  /**
23150
23932
  * Generate default button system from theme settings.
23151
23933
  *
23152
- * Creates 4 sized variants when theme.buttons is not defined:
23153
- * 1. Primary - primary color background with opacity-reduce hover effect
23154
- * 2. Secondary - neutral-700 background with opacity-reduce hover effect
23155
- * 3. Outline - transparent background with primary border and opacity-reduce hover effect
23156
- * 4. Ghost - transparent background, no border, with opacity-reduce hover effect
23934
+ * Creates 4 sized canonical variants when theme.buttons is not defined:
23935
+ * 1. Primary - solid primary treatment
23936
+ * 2. Secondary - solid neutral treatment
23937
+ * 3. Outline - surface treatment with a border
23938
+ * 4. Ghost - surface treatment without a border
23157
23939
  *
23158
23940
  * All four are sized variants — they inherit padding/fontSize from the theme's
23159
23941
  * `sizes` config (or the system defaults) so they're consistent at any size.
@@ -23230,7 +24012,6 @@ function generateDefaultButtonSystem(theme) {
23230
24012
  cornerStyle: narrowCornerStyle(theme.corners),
23231
24013
  textTransform: "none",
23232
24014
  fontWeight: 500,
23233
- borderWidth: theme.border.width === "none" ? 1 : theme.border.width === "thick" ? 3 : 2,
23234
24015
  hoverTransform: "none",
23235
24016
  hoverColor: "none"
23236
24017
  },
@@ -23239,7 +24020,7 @@ function generateDefaultButtonSystem(theme) {
23239
24020
  }
23240
24021
  var BORDER_WIDTH_TO_CLASS_MAP, VALID_CORNER_STYLES;
23241
24022
  var init_generateDefaultButtonSystem = __esmMin((() => {
23242
- init_types$13();
24023
+ init_types$12();
23243
24024
  BORDER_WIDTH_TO_CLASS_MAP = {
23244
24025
  none: "border-0",
23245
24026
  hairline: "border",
@@ -23275,445 +24056,6 @@ var init_affordanceIcons = __esmMin((() => {
23275
24056
  };
23276
24057
  }));
23277
24058
  //#endregion
23278
- //#region ../theme-core/src/surfaces/foregroundRoles.ts
23279
- var SURFACE_FOREGROUND_ROLES;
23280
- var init_foregroundRoles = __esmMin((() => {
23281
- SURFACE_FOREGROUND_ROLES = [
23282
- "text",
23283
- "heading",
23284
- "link",
23285
- "supporting"
23286
- ];
23287
- }));
23288
- //#endregion
23289
- //#region ../theme-core/src/surfaces/foregroundContract.ts
23290
- function requireSurfaceColorValue(role, value) {
23291
- const normalized = value.trim();
23292
- if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
23293
- return normalized;
23294
- }
23295
- function completeSurfaceForegrounds(input) {
23296
- const text = requireSurfaceColorValue("text", input.text);
23297
- return {
23298
- text,
23299
- heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
23300
- link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
23301
- supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
23302
- };
23303
- }
23304
- function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
23305
- const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
23306
- const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
23307
- if (role === "text") return `var(${roleVariable}, ${fallback})`;
23308
- return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
23309
- }
23310
- function surfaceForegroundValueWithOpacity(role, opacityPercent) {
23311
- if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
23312
- return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
23313
- }
23314
- function surfaceForegroundStyle(input) {
23315
- const foregrounds = completeSurfaceForegrounds(input);
23316
- return {
23317
- color: foregrounds.text,
23318
- [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
23319
- [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
23320
- [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
23321
- [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
23322
- };
23323
- }
23324
- function surfaceForegroundDeclarations(input) {
23325
- const foregrounds = completeSurfaceForegrounds(input);
23326
- return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
23327
- }
23328
- var SURFACE_FOREGROUND_CSS_VARS, DEFAULT_SURFACE_TEXT_COLOR, DEFAULT_SURFACE_LINK_COLOR, DEFAULT_SURFACE_SUPPORTING_COLOR, DEFAULT_ROLE_FALLBACKS;
23329
- var init_foregroundContract = __esmMin((() => {
23330
- init_foregroundRoles();
23331
- SURFACE_FOREGROUND_CSS_VARS = {
23332
- text: "--rb-surface-text-color",
23333
- heading: "--rb-surface-heading-color",
23334
- link: "--rb-surface-link-color",
23335
- supporting: "--rb-surface-supporting-color"
23336
- };
23337
- DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
23338
- DEFAULT_SURFACE_LINK_COLOR = "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))";
23339
- DEFAULT_SURFACE_SUPPORTING_COLOR = "rgb(var(--tb-mutedText, 100 116 139))";
23340
- DEFAULT_ROLE_FALLBACKS = {
23341
- text: DEFAULT_SURFACE_TEXT_COLOR,
23342
- heading: DEFAULT_SURFACE_TEXT_COLOR,
23343
- link: DEFAULT_SURFACE_LINK_COLOR,
23344
- supporting: DEFAULT_SURFACE_SUPPORTING_COLOR
23345
- };
23346
- }));
23347
- //#endregion
23348
- //#region ../theme-core/src/buttons/resolveButtonColourStates.ts
23349
- function compileButtonColourStates(input) {
23350
- const baseTransition = applyColourEffects({
23351
- variantId: input.variant.id,
23352
- state: "base",
23353
- treatment: input.variant.background,
23354
- effects: input.variant.effects?.base,
23355
- palette: input.palette
23356
- });
23357
- if (!baseTransition.ok) return baseTransition;
23358
- const stateTreatments = {
23359
- base: baseTransition.treatment,
23360
- hover: hoverTreatment(input.variant, input.global, baseTransition.treatment),
23361
- focus: baseTransition.treatment,
23362
- active: baseTransition.treatment,
23363
- disabled: baseTransition.treatment
23364
- };
23365
- const nonColourEffects = { ...baseTransition.nonColourEffects.length > 0 ? { base: [...baseTransition.nonColourEffects] } : {} };
23366
- for (const state of [
23367
- "hover",
23368
- "focus",
23369
- "active"
23370
- ]) {
23371
- const transition = applyColourEffects({
23372
- variantId: input.variant.id,
23373
- state,
23374
- treatment: stateTreatments[state],
23375
- effects: input.variant.effects?.[state],
23376
- palette: input.palette
23377
- });
23378
- if (!transition.ok) return transition;
23379
- stateTreatments[state] = transition.treatment;
23380
- if (transition.nonColourEffects.length > 0) nonColourEffects[state] = [...transition.nonColourEffects];
23381
- }
23382
- const resolved = {};
23383
- for (const state of BUTTON_VISUAL_STATES) {
23384
- const result = resolveTreatment$1({
23385
- variantId: input.variant.id,
23386
- state,
23387
- treatment: stateTreatments[state],
23388
- palette: input.palette
23389
- });
23390
- if (!result.ok) return result;
23391
- resolved[state] = result.colour;
23392
- }
23393
- return {
23394
- ok: true,
23395
- states: resolved,
23396
- focusIndicator: resolveFocusIndicator(resolved.focus),
23397
- nonColourEffects
23398
- };
23399
- }
23400
- function formatButtonColourContractError(error) {
23401
- switch (error.tag) {
23402
- case "unknown_palette_token": return `Button "${error.variantId}" ${error.state} state uses unknown palette token "${error.token}".`;
23403
- case "missing_on_colour": return `Button "${error.variantId}" ${error.state} state cannot derive ${error.foregroundToken} from ${error.backgroundToken}.`;
23404
- case "insufficient_contrast": return `Button "${error.variantId}" ${error.state} state has ${error.ratio.toFixed(2)}:1 contrast (${error.requiredRatio}:1 required).`;
23405
- case "unsupported_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" is not contrast-safe (${error.reason}).`;
23406
- case "invalid_colour_effect_options": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" has an invalid ${error.option} option.`;
23407
- case "inapplicable_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" cannot apply to a ${error.treatment} treatment.`;
23408
- case "unknown_button_effect": return `Button "${error.variantId}" ${error.state} uses unknown effect "${error.effectId}".`;
23409
- }
23410
- }
23411
- function hoverTreatment(variant, global, fallback) {
23412
- const token = variant.hoverBackgroundToken ?? (global.hoverColor === "token" ? global.hoverColorToken : void 0);
23413
- return token === void 0 ? fallback : {
23414
- type: "solid",
23415
- colorToken: token
23416
- };
23417
- }
23418
- function applyColourEffects(input) {
23419
- let treatment = input.treatment;
23420
- const nonColourEffects = [];
23421
- for (const effect of input.effects ?? []) {
23422
- const policy = getButtonEffectPolicy(effect.effectId);
23423
- if (policy === null) return unknownEffect(input, effect);
23424
- switch (policy.classification) {
23425
- case "non-colour":
23426
- nonColourEffects.push(effect);
23427
- break;
23428
- case "unsupported-colour":
23429
- case "unsupported-background-overlay":
23430
- case "not-button": return unsupportedEffect(input, effect, policy.reason);
23431
- case "colour-transition":
23432
- if (policy.transition.kind === "adjust-shade") {
23433
- if (treatment.type !== "solid") return inapplicableEffect(input, effect, treatment);
23434
- const amount = readShadeAmount(effect);
23435
- if (amount === null) return invalidEffectOption(input, effect, "amount");
23436
- const signedAmount = policy.transition.direction === "darker" ? amount : -amount;
23437
- treatment = {
23438
- type: "solid",
23439
- colorToken: adjustShade(treatment.colorToken, signedAmount, input.palette)
23440
- };
23441
- break;
23442
- }
23443
- if (policy.transition.kind === "replace-background") {
23444
- const colorToken = readOpaqueToken(effect, "colorToken", "neutral-800");
23445
- if (colorToken === null) return invalidEffectOption(input, effect, "colorToken");
23446
- treatment = {
23447
- type: "solid",
23448
- colorToken
23449
- };
23450
- break;
23451
- }
23452
- return unknownEffect(input, effect);
23453
- }
23454
- }
23455
- return {
23456
- ok: true,
23457
- treatment,
23458
- nonColourEffects
23459
- };
23460
- }
23461
- function resolveTreatment$1(input) {
23462
- const treatment = input.treatment;
23463
- switch (treatment.type) {
23464
- case "surface": return {
23465
- ok: true,
23466
- colour: {
23467
- kind: "surface",
23468
- role: treatment.role,
23469
- backgroundCss: "transparent",
23470
- foregroundCss: surfaceForegroundValue(treatment.role)
23471
- }
23472
- };
23473
- case "solid": return resolveSolid(input, treatment.colorToken);
23474
- case "gradient": return resolveGradient$2(input, treatment);
23475
- }
23476
- }
23477
- function resolveFocusIndicator(colour) {
23478
- switch (colour.kind) {
23479
- case "solid": return {
23480
- kind: "two-tone",
23481
- innerCss: colour.foregroundCss,
23482
- outerCss: colour.backgroundCss,
23483
- minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
23484
- };
23485
- case "gradient": return {
23486
- kind: "two-tone",
23487
- innerCss: colour.foregroundCss,
23488
- outerCss: tokenCss(colour.backgroundTokens[0]),
23489
- minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
23490
- };
23491
- case "surface": return {
23492
- kind: "surface-role",
23493
- colorCss: colour.foregroundCss,
23494
- minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
23495
- };
23496
- }
23497
- }
23498
- function resolveSolid(input, backgroundToken) {
23499
- const backgroundHex = paletteHex(input, backgroundToken);
23500
- if (!backgroundHex.ok) return backgroundHex;
23501
- const foregroundToken = unsafeAsOpaqueButtonColourToken(onColorTokenName(backgroundToken));
23502
- const foregroundHex = input.palette[foregroundToken];
23503
- if (typeof foregroundHex !== "string") return {
23504
- ok: false,
23505
- error: {
23506
- tag: "missing_on_colour",
23507
- variantId: input.variantId,
23508
- state: input.state,
23509
- backgroundToken,
23510
- foregroundToken
23511
- }
23512
- };
23513
- const contrast = validateContrast({
23514
- ...input,
23515
- background: backgroundToken,
23516
- backgroundHex: backgroundHex.hex,
23517
- foreground: foregroundToken,
23518
- foregroundHex
23519
- });
23520
- if (!contrast.ok) return contrast;
23521
- return {
23522
- ok: true,
23523
- colour: {
23524
- kind: "solid",
23525
- backgroundToken,
23526
- foregroundToken,
23527
- backgroundCss: tokenCss(backgroundToken),
23528
- foregroundCss: tokenCss(foregroundToken)
23529
- }
23530
- };
23531
- }
23532
- function resolveGradient$2(input, treatment) {
23533
- const foregroundHex = paletteHex(input, treatment.foregroundToken);
23534
- if (!foregroundHex.ok) return foregroundHex;
23535
- const stopHexes = [];
23536
- for (const token of treatment.stops) {
23537
- const stop = paletteHex(input, token);
23538
- if (!stop.ok) return stop;
23539
- stopHexes.push(stop.hex);
23540
- }
23541
- for (let segment = 0; segment < stopHexes.length - 1; segment += 1) {
23542
- const start = stopHexes[segment];
23543
- const end = stopHexes[segment + 1];
23544
- const startToken = treatment.stops[segment];
23545
- const endToken = treatment.stops[segment + 1];
23546
- if (start === void 0 || end === void 0 || startToken === void 0 || endToken === void 0) continue;
23547
- for (let sample = 0; sample <= BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment; sample += 1) {
23548
- const position = sample / BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment;
23549
- const sampleHex = interpolateHex(start, end, position);
23550
- const contrast = validateContrast({
23551
- ...input,
23552
- background: `${startToken}→${endToken}@${position.toFixed(2)}`,
23553
- backgroundHex: sampleHex,
23554
- foreground: treatment.foregroundToken,
23555
- foregroundHex: foregroundHex.hex
23556
- });
23557
- if (!contrast.ok) return contrast;
23558
- }
23559
- }
23560
- const direction = GRADIENT_DIRECTION_MAP$2[treatment.direction] ?? "to right";
23561
- return {
23562
- ok: true,
23563
- colour: {
23564
- kind: "gradient",
23565
- backgroundTokens: treatment.stops,
23566
- foregroundToken: treatment.foregroundToken,
23567
- backgroundCss: `linear-gradient(${direction}, ${treatment.stops.map(tokenCss).join(", ")})`,
23568
- foregroundCss: tokenCss(treatment.foregroundToken)
23569
- }
23570
- };
23571
- }
23572
- function paletteHex(input, token) {
23573
- const hex = input.palette[token];
23574
- return typeof hex === "string" ? {
23575
- ok: true,
23576
- hex
23577
- } : {
23578
- ok: false,
23579
- error: {
23580
- tag: "unknown_palette_token",
23581
- variantId: input.variantId,
23582
- state: input.state,
23583
- token
23584
- }
23585
- };
23586
- }
23587
- function validateContrast(input) {
23588
- const ratio = contrastRatio(input.backgroundHex, input.foregroundHex);
23589
- return ratio >= BUTTON_CONTRAST_POLICY.textMinimumRatio ? { ok: true } : {
23590
- ok: false,
23591
- error: {
23592
- tag: "insufficient_contrast",
23593
- variantId: input.variantId,
23594
- state: input.state,
23595
- background: input.background,
23596
- foreground: input.foreground,
23597
- ratio,
23598
- requiredRatio: BUTTON_CONTRAST_POLICY.textMinimumRatio
23599
- }
23600
- };
23601
- }
23602
- function tokenCss(token) {
23603
- return `rgb(var(--tb-${token}))`;
23604
- }
23605
- function adjustShade(token, amount, palette) {
23606
- const match = token.match(/^(.*)-(\d{2,3})$/);
23607
- const base = match?.[1] ?? token;
23608
- const currentShade = match?.[2] === void 0 ? 500 : Number(match[2]);
23609
- const availableShades = [
23610
- 50,
23611
- 100,
23612
- 200,
23613
- 300,
23614
- 400,
23615
- 500,
23616
- 600,
23617
- 700,
23618
- 800,
23619
- 900,
23620
- 950
23621
- ].filter((shade) => typeof palette[`${base}-${shade}`] === "string");
23622
- if (availableShades.length === 0) return token;
23623
- const firstShade = availableShades[0];
23624
- if (firstShade === void 0) return token;
23625
- const exactIndex = availableShades.indexOf(currentShade);
23626
- const startingIndex = exactIndex >= 0 ? exactIndex : availableShades.indexOf(availableShades.reduce((closestShade, shade) => Math.abs(shade - currentShade) < Math.abs(closestShade - currentShade) ? shade : closestShade, firstShade));
23627
- const stepCount = Math.abs(amount) / 100;
23628
- const direction = amount < 0 ? -1 : 1;
23629
- const targetShade = availableShades[Math.max(0, Math.min(availableShades.length - 1, startingIndex + direction * stepCount))];
23630
- return targetShade === void 0 ? token : unsafeAsOpaqueButtonColourToken(`${base}-${targetShade}`);
23631
- }
23632
- function readShadeAmount(effect) {
23633
- const value = effect.options?.amount ?? 100;
23634
- return typeof value === "number" && Number.isFinite(value) && value >= 0 && value % 100 === 0 ? value : null;
23635
- }
23636
- function readOpaqueToken(effect, key, fallback) {
23637
- return parseOpaqueButtonColourToken(effect.options?.[key] ?? fallback);
23638
- }
23639
- function unsupportedEffect(input, effect, reason) {
23640
- return {
23641
- ok: false,
23642
- error: {
23643
- tag: "unsupported_colour_effect",
23644
- variantId: input.variantId,
23645
- state: input.state,
23646
- effectId: effect.effectId,
23647
- reason
23648
- }
23649
- };
23650
- }
23651
- function invalidEffectOption(input, effect, option) {
23652
- return {
23653
- ok: false,
23654
- error: {
23655
- tag: "invalid_colour_effect_options",
23656
- variantId: input.variantId,
23657
- state: input.state,
23658
- effectId: effect.effectId,
23659
- option
23660
- }
23661
- };
23662
- }
23663
- function inapplicableEffect(input, effect, treatment) {
23664
- return {
23665
- ok: false,
23666
- error: {
23667
- tag: "inapplicable_colour_effect",
23668
- variantId: input.variantId,
23669
- state: input.state,
23670
- effectId: effect.effectId,
23671
- treatment: treatment.type
23672
- }
23673
- };
23674
- }
23675
- function unknownEffect(input, effect) {
23676
- return {
23677
- ok: false,
23678
- error: {
23679
- tag: "unknown_button_effect",
23680
- variantId: input.variantId,
23681
- state: input.state,
23682
- effectId: effect.effectId
23683
- }
23684
- };
23685
- }
23686
- function interpolateHex(startHex, endHex, position) {
23687
- const start = hexToRgb$1(startHex);
23688
- const end = hexToRgb$1(endHex);
23689
- const channel = (from, to) => Math.round(from + (to - from) * position).toString(16).padStart(2, "0");
23690
- return `#${channel(start.r, end.r)}${channel(start.g, end.g)}${channel(start.b, end.b)}`;
23691
- }
23692
- var BUTTON_VISUAL_STATES, BUTTON_CONTRAST_POLICY;
23693
- var init_resolveButtonColourStates = __esmMin((() => {
23694
- init_contrast$1();
23695
- init_colorConversion();
23696
- init_onColor();
23697
- init_foregroundContract();
23698
- init_types$13();
23699
- init_constants$2();
23700
- init_effectClassification();
23701
- BUTTON_VISUAL_STATES = [
23702
- "base",
23703
- "hover",
23704
- "focus",
23705
- "active",
23706
- "disabled"
23707
- ];
23708
- BUTTON_CONTRAST_POLICY = {
23709
- textMinimumRatio: 4.5,
23710
- nonTextMinimumRatio: 3,
23711
- gradientSamplesPerSegment: 20,
23712
- alphaBackgrounds: "reject-without-known-surface",
23713
- disabled: "retain-full-colour-contract"
23714
- };
23715
- }));
23716
- //#endregion
23717
24059
  //#region ../theme-core/src/buttons/resolvedButtonCss.ts
23718
24060
  /**
23719
24061
  * Canonical colour declaration mapping shared by full themes and ThemeBridge.
@@ -23922,8 +24264,8 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme, colo
23922
24264
  * Only variants that declare `affordance` with a known icon id produce a rule —
23923
24265
  * every other variant is byte-identical to before. The `:not(.rb-affordance-off)`
23924
24266
  * guard lets a `button` node that renders its own trailing icon suppress this
23925
- * one (node overrides personality). Colour comes from the affordance token, or
23926
- * `currentColor` (the button text colour) when no token is given.
24267
+ * one. The mask uses `currentColor`, so the icon always shares the canonical
24268
+ * button foreground.
23927
24269
  */
23928
24270
  function variantAffordanceRule(variant, selector) {
23929
24271
  const affordance = variant.affordance;
@@ -24083,7 +24425,7 @@ function resolveBoxShadow(variant, global, theme, tokens) {
24083
24425
  }
24084
24426
  var AFFORDANCE_SUPPRESS_CLASS, BUTTON_SIZE_NAMES, LETTER_SPACING_MAP, STRUCTURAL_DECLARATIONS;
24085
24427
  var init_generateButtonCss = __esmMin((() => {
24086
- init_types$13();
24428
+ init_types$12();
24087
24429
  init_classNames();
24088
24430
  init_resolver$1();
24089
24431
  init_generateBaseCSS();
@@ -24140,17 +24482,10 @@ var init_presets = __esmMin((() => {
24140
24482
  });
24141
24483
  }));
24142
24484
  //#endregion
24143
- //#region ../theme-core/src/buttons/effects/types.ts
24144
- var init_types$11 = __esmMin((() => {}));
24145
- var init_core$2 = __esmMin((() => {
24146
- init_resolveButtonColourStates();
24147
- init_resolvedButtonCss();
24148
- init_types$13();
24149
- }));
24150
- //#endregion
24151
24485
  //#region ../theme-core/src/buttons/index.ts
24152
24486
  var init_buttons = __esmMin((() => {
24153
- init_types$13();
24487
+ init_types$12();
24488
+ init_parseThemeForPersistence();
24154
24489
  init_classNames();
24155
24490
  init_generateButtonCss();
24156
24491
  init_resolveButtonColourStates();
@@ -24159,10 +24494,6 @@ var init_buttons = __esmMin((() => {
24159
24494
  init_constants$2();
24160
24495
  init_presets();
24161
24496
  init_styles();
24162
- init_types$11();
24163
- init_registry$1();
24164
- init_transform();
24165
- init_core$2();
24166
24497
  }));
24167
24498
  //#endregion
24168
24499
  //#region ../theme-core/src/cards/types.ts
@@ -24311,9 +24642,9 @@ function generateShadowValue(shadow) {
24311
24642
  case "high": return soft ? `${xOffset}px 25px 50px rgba(0,0,0,.18)` : `${xOffset}px 20px 30px rgba(0,0,0,.28)`;
24312
24643
  }
24313
24644
  }
24314
- var CORNER_RADIUS_MAP$2, GRADIENT_DIRECTION_MAP$1;
24645
+ var CORNER_RADIUS_MAP$3, GRADIENT_DIRECTION_MAP$1;
24315
24646
  var init_constants$1 = __esmMin((() => {
24316
- CORNER_RADIUS_MAP$2 = {
24647
+ CORNER_RADIUS_MAP$3 = {
24317
24648
  square: "0px",
24318
24649
  soft: "8px",
24319
24650
  rounded: "16px",
@@ -24403,7 +24734,7 @@ var init_surfaces = __esmMin((() => {
24403
24734
  //#endregion
24404
24735
  //#region ../theme-core/src/cards/generateCardCss.ts
24405
24736
  function resolveCornerRadiiCss$1(cornerRadii, fallback) {
24406
- const fallbackValue = CORNER_RADIUS_MAP$2[fallback];
24737
+ const fallbackValue = CORNER_RADIUS_MAP$3[fallback];
24407
24738
  const at = (value) => value ? PER_CORNER_RADIUS_MAP$1[value] : fallbackValue;
24408
24739
  return `${at(cornerRadii.topLeft)} ${at(cornerRadii.topRight)} ${at(cornerRadii.bottomRight)} ${at(cornerRadii.bottomLeft)}`;
24409
24740
  }
@@ -24461,7 +24792,7 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
24461
24792
  rules.push(`border: ${borderWidth} solid ${borderColor}`);
24462
24793
  }
24463
24794
  const corners = variant.corners ?? theme.corners;
24464
- const radius = variant.cornerRadii ? resolveCornerRadiiCss$1(variant.cornerRadii, corners) : CORNER_RADIUS_MAP$2[corners];
24795
+ const radius = variant.cornerRadii ? resolveCornerRadiiCss$1(variant.cornerRadii, corners) : CORNER_RADIUS_MAP$3[corners];
24465
24796
  rules.push(`border-radius: ${radius}`);
24466
24797
  const shadow = variant.shadow ?? theme.shadow;
24467
24798
  if (shadow.elevation !== "none") {
@@ -25485,12 +25816,12 @@ var init_schema = __esmMin((() => {
25485
25816
  init_cards();
25486
25817
  init_types$9();
25487
25818
  init_types$8();
25488
- init_types$12();
25819
+ init_types$11();
25489
25820
  init_types$7();
25490
25821
  init_validation$2();
25491
25822
  init_atRuleValidation();
25492
25823
  init_shared$5();
25493
- init_types$16();
25824
+ init_types$15();
25494
25825
  init_logoBranding();
25495
25826
  init_rawStyleFields();
25496
25827
  init_themeColorTokens();
@@ -26348,7 +26679,7 @@ function uniqueNonEmpty$1(values) {
26348
26679
  var designResolutionPolicySchema, runtimeStyleFieldNameSchema, nonEmptyRuntimeStyleFieldNamesSchema, heroLegibilityStrategySchema, heroCompositionIntentSchema, heroTypographyScaleIntentSchema, sectionHeightIntentSchema, imageSurfaceTreatmentIntensitySchema, imageSurfaceMotionSchema, imageSurfaceTreatmentSchema, testimonialCardTreatmentSchema, tileTreatmentSchema, eventListTreatmentSchema, eyebrowTreatmentSchema, userPanelTreatments, userFlushTreatments, userFlushBleeds, contentFrameIntentSchema, blockDesignPlanSchema, styleAuthoritySchema, blockRuntimeStyleAuthoritySchema;
26349
26680
  var init_designState = __esmMin((() => {
26350
26681
  init_sourceCatalogs();
26351
- init_types$16();
26682
+ init_types$15();
26352
26683
  init_schemaVersionedJson();
26353
26684
  init_rawStyleFields();
26354
26685
  designResolutionPolicySchema = z$1.enum([
@@ -26527,7 +26858,7 @@ var init_runtimeCompiler = __esmMin((() => {
26527
26858
  init_styles();
26528
26859
  init_colors();
26529
26860
  init_designState();
26530
- init_types$16();
26861
+ init_types$15();
26531
26862
  init_accessibleSurfaces();
26532
26863
  init_sectionTransitions();
26533
26864
  init_tokens();
@@ -26946,7 +27277,7 @@ var init_curatedSiteStyles = __esmMin((() => {
26946
27277
  init_footerLooks();
26947
27278
  init_curatedChoices();
26948
27279
  init_sourceCatalogs();
26949
- init_types$16();
27280
+ init_types$15();
26950
27281
  init_siteStyleTypography();
26951
27282
  init_runtimeCompiler();
26952
27283
  SOFT_EARTH_SITE_STYLE_ID_VALUE = "site-style:soft-earth";
@@ -28360,13 +28691,13 @@ var init_curatedSiteStyles = __esmMin((() => {
28360
28691
  curatedSiteStylesById = new Map(curatedSiteStyles.map((style) => [style.id, style]));
28361
28692
  })), init_lookResolution = __esmMin((() => {
28362
28693
  init_appearancePresets();
28363
- init_types$16();
28694
+ init_types$15();
28364
28695
  }));
28365
28696
  var init_siteStyleBlockPolicies = __esmMin((() => {
28366
28697
  init_lookResolution();
28367
28698
  init_appearancePresets();
28368
28699
  init_pageDesignIntent();
28369
- init_types$16();
28700
+ init_types$15();
28370
28701
  init_sectionTransitions();
28371
28702
  asPageFlowPresetId("generated-default");
28372
28703
  asSiteStyleId("site-style:south-west-twerk-school");
@@ -28379,12 +28710,12 @@ var init_siteStyleBlockPolicies = __esmMin((() => {
28379
28710
  init_lookResolution();
28380
28711
  init_siteStyleBlockPolicies();
28381
28712
  init_pageDesignIntent();
28382
- init_types$16();
28713
+ init_types$15();
28383
28714
  init_sectionTransitions();
28384
28715
  asPageFlowPresetId("flow:quiet"), noneBoundaryOption.id, asPageFlowPresetId("flow:balanced"), softBoundaryOption.id, asPageFlowPresetId("flow:expressive"), spaciousBoundaryOption.id;
28385
28716
  }));
28386
28717
  var init_resolver = __esmMin((() => {
28387
- init_types$16();
28718
+ init_types$15();
28388
28719
  }));
28389
28720
  var init_siteStyleThemeCompiler = __esmMin((() => {
28390
28721
  init_schema();
@@ -28394,7 +28725,7 @@ var init_siteStyleThemeCompiler = __esmMin((() => {
28394
28725
  init_resolveSelection();
28395
28726
  }));
28396
28727
  var init_previewCustomization = __esmMin((() => {
28397
- init_types$16();
28728
+ init_types$15();
28398
28729
  }));
28399
28730
  var init_previewCompiler = __esmMin((() => {
28400
28731
  init_schema();
@@ -28404,7 +28735,7 @@ var init_previewCompiler = __esmMin((() => {
28404
28735
  init_resolveSelection();
28405
28736
  init_curatedSiteStyles();
28406
28737
  init_resolver();
28407
- init_types$16();
28738
+ init_types$15();
28408
28739
  init_footerLooks();
28409
28740
  init_headerLooks();
28410
28741
  init_runtimeCompiler();
@@ -28443,7 +28774,7 @@ var generatedPanelTreatments, generatedFlushTreatments, generatedFlushBleeds, ge
28443
28774
  var init_generatedSchemas = __esmMin((() => {
28444
28775
  init_curatedSiteStyles();
28445
28776
  init_sourceCatalogs();
28446
- init_types$16();
28777
+ init_types$15();
28447
28778
  generatedPanelTreatments = uniqueNonEmpty(generatedDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "panel").map((frame) => frame.treatment));
28448
28779
  generatedFlushTreatments = uniqueNonEmpty(generatedDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "flush-panel").map((frame) => frame.treatment));
28449
28780
  generatedFlushBleeds = uniqueNonEmpty(generatedDesignOptionCatalog.contentFrames.filter((frame) => frame.kind === "flush-panel").map((frame) => frame.bleed));
@@ -28510,7 +28841,7 @@ var init_generatedDesignPipeline = __esmMin((() => {
28510
28841
  init_headerOpeningSection();
28511
28842
  init_resolver();
28512
28843
  init_runtimeCompiler();
28513
- init_types$16();
28844
+ init_types$15();
28514
28845
  }));
28515
28846
  function validateBlockSequence(snapshots, ctx) {
28516
28847
  for (const issue of collectBlockSequenceIssues(snapshots)) ctx.addIssue(issue);
@@ -28545,7 +28876,7 @@ function collectBlockSequenceIssues(snapshots) {
28545
28876
  }
28546
28877
  var nonEmptyStringSchema, blockContentVersionIdSchema, designBlockIdSchema, designPageIdSchema, designEntryIdSchema, blockOrderIndexSchema, publishedPageBlockSnapshotSchema, draftPageBlockSnapshotSchema, missingPageBlockSnapshotSchema, pageBlockSnapshotSchema, publishedPageBlockSequenceSchema, draftPageBlockSequenceSchema, publishedPageDesignVersionDataV1Schema, draftPageDesignVersionDataV1Schema;
28547
28878
  var init_pageDesignAuthority = __esmMin((() => {
28548
- init_types$16();
28879
+ init_types$15();
28549
28880
  init_pageDesignIntent();
28550
28881
  nonEmptyStringSchema = z$1.string().min(1);
28551
28882
  blockContentVersionIdSchema = nonEmptyStringSchema.transform(asBlockContentVersionId);
@@ -28841,7 +29172,7 @@ var init_site_styles = __esmMin((() => {
28841
29172
  init_tokenRecipes();
28842
29173
  init_siteStyleTypography();
28843
29174
  init_themeParity();
28844
- init_types$16();
29175
+ init_types$15();
28845
29176
  }));
28846
29177
  //#endregion
28847
29178
  //#region ../blocks/src/system/designCapabilities.ts
@@ -32562,45 +32893,6 @@ var init_formEmbed = __esmMin((() => {
32562
32893
  });
32563
32894
  }));
32564
32895
  //#endregion
32565
- //#region ../blocks/src/system/fragments/library/footerBottomText.ts
32566
- var footerBottomTextFragment;
32567
- var init_footerBottomText = __esmMin((() => {
32568
- init_types$5();
32569
- init_builder$1();
32570
- init_colorStyles();
32571
- footerBottomTextFragment = defineFragment({
32572
- id: "footerBottomText",
32573
- title: "Footer Text",
32574
- description: "Rich text content for the main footer body and optional bottom bar.",
32575
- fields: [{
32576
- id: "bodyText",
32577
- type: "richText",
32578
- label: "Body text",
32579
- description: "Appears in the main footer area.",
32580
- ui: { variant: "limited" }
32581
- }, {
32582
- id: "bottomText",
32583
- type: "richText",
32584
- label: "Bottom bar text",
32585
- description: "Appears in the optional footer bottom bar.",
32586
- ui: { variant: "limited" }
32587
- }],
32588
- layout: [richText({
32589
- className: "rb-prose rb-prose-sm rb-mx-auto rb-max-w-3xl rb-text-center",
32590
- style: textColorStyle("text/80")
32591
- }, when("bodyText"), bind("bodyText", { transforms: [{
32592
- id: "content.interpolateRichTextTokens",
32593
- options: { tokens: ["year", "site_name"] }
32594
- }] })), richText({
32595
- className: "rb-prose rb-prose-sm rb-mx-auto rb-max-w-3xl rb-text-center",
32596
- style: textColorStyle("text/80")
32597
- }, when("bottomText"), bind("bottomText", { transforms: [{
32598
- id: "content.interpolateRichTextTokens",
32599
- options: { tokens: ["year", "site_name"] }
32600
- }] }))]
32601
- });
32602
- }));
32603
- //#endregion
32604
32896
  //#region ../blocks/src/system/fragments/library/headerCta.ts
32605
32897
  var headerCtaFragment;
32606
32898
  var init_headerCta = __esmMin((() => {
@@ -33114,7 +33406,6 @@ var init_lazyInit = __esmMin((() => {
33114
33406
  init_testimonialsCarousel();
33115
33407
  init_formCopy();
33116
33408
  init_formEmbed();
33117
- init_footerBottomText();
33118
33409
  init_headerCta();
33119
33410
  init_singleButton();
33120
33411
  init_blogFeaturedPost();
@@ -33134,7 +33425,6 @@ var init_lazyInit = __esmMin((() => {
33134
33425
  testimonialsCarouselFragment,
33135
33426
  formCopyFragment,
33136
33427
  formEmbedFragment,
33137
- footerBottomTextFragment,
33138
33428
  headerCtaFragment,
33139
33429
  singleButtonFragment,
33140
33430
  blogFeaturedPostFragment,
@@ -33951,7 +34241,6 @@ function ensureFragmentsRegistered() {
33951
34241
  registerFragment(formCopyFragment);
33952
34242
  registerFragment(formEmbedFragment);
33953
34243
  registerFragment(bookingFormFragment);
33954
- registerFragment(footerBottomTextFragment);
33955
34244
  registerFragment(headerCtaFragment);
33956
34245
  registerFragment(singleButtonFragment);
33957
34246
  registerFragment(blogFeaturedPostFragment);
@@ -33981,7 +34270,6 @@ var init_init = __esmMin((() => {
33981
34270
  init_formCopy();
33982
34271
  init_formEmbed();
33983
34272
  init_bookingForm$1();
33984
- init_footerBottomText();
33985
34273
  init_headerCta();
33986
34274
  init_singleButton();
33987
34275
  init_blogFeaturedPost();
@@ -34274,7 +34562,6 @@ var init_fragments = __esmMin((() => {
34274
34562
  init_formCopy();
34275
34563
  init_formEmbed();
34276
34564
  init_bookingForm$1();
34277
- init_footerBottomText();
34278
34565
  init_headerCta();
34279
34566
  init_singleButton();
34280
34567
  init_blogFeaturedPost();
@@ -35514,14 +35801,14 @@ function defineClientOwnedBlockRuntime(runtime) {
35514
35801
  var init_runtime = __esmMin((() => {}));
35515
35802
  //#endregion
35516
35803
  //#region ../blocks/src/contracts/islands.ts
35517
- function isObjectRecord$1(value) {
35804
+ function isObjectRecord(value) {
35518
35805
  return typeof value === "object" && value !== null;
35519
35806
  }
35520
35807
  function pickRecordKeys(source, keys) {
35521
35808
  return Object.fromEntries(keys.map((key) => [key, source[key]]));
35522
35809
  }
35523
35810
  function expectEncodedRecord(value, label) {
35524
- if (isObjectRecord$1(value)) return value;
35811
+ if (isObjectRecord(value)) return value;
35525
35812
  throw new Error(`Expected ${label} codec to encode an object`);
35526
35813
  }
35527
35814
  function prefixIssues(prefix, issues) {
@@ -35562,7 +35849,7 @@ function createInteractiveIslandCodec(options) {
35562
35849
  };
35563
35850
  },
35564
35851
  decode: (input) => {
35565
- if (!isObjectRecord$1(input)) return decodeFailure([{
35852
+ if (!isObjectRecord(input)) return decodeFailure([{
35566
35853
  path: [],
35567
35854
  message: "Expected island props object"
35568
35855
  }]);
@@ -35573,7 +35860,7 @@ function createInteractiveIslandCodec(options) {
35573
35860
  message: `Expected renderKind "${options.runtime.kind}"`
35574
35861
  });
35575
35862
  const renderInput = input.render;
35576
- if (!isObjectRecord$1(renderInput)) renderIssues.push({
35863
+ if (!isObjectRecord(renderInput)) renderIssues.push({
35577
35864
  path: ["render"],
35578
35865
  message: "Expected render object"
35579
35866
  });
@@ -36802,7 +37089,7 @@ const uiTransforms = [
36802
37089
  ];
36803
37090
  //#endregion
36804
37091
  //#region ../theme-core/src/siteChromePlacement.ts
36805
- init_types$16();
37092
+ init_types$15();
36806
37093
  const SITE_CHROME_PLACEMENT_CLASSES = [
36807
37094
  "rb-sticky",
36808
37095
  "rb-fixed",
@@ -37444,25 +37731,6 @@ const mediaTransforms = [{
37444
37731
  }
37445
37732
  }];
37446
37733
  //#endregion
37447
- //#region ../blocks/src/lib/typeGuards.ts
37448
- /**
37449
- * Strict record guard: excludes null, primitives, and arrays.
37450
- */
37451
- function isRecord$24(value) {
37452
- return typeof value === "object" && value !== null && !Array.isArray(value);
37453
- }
37454
- /**
37455
- * Non-null object guard: includes arrays for behavior parity with legacy helpers.
37456
- *
37457
- * NOTE: This intentionally narrows to UnknownRecord for compatibility with existing
37458
- * callsites even though arrays pass at runtime. Follow-up cleanup should replace
37459
- * this API with a more precise predicate type and migrate consumers.
37460
- */
37461
- function isObjectRecord(value) {
37462
- return typeof value === "object" && value !== null;
37463
- }
37464
- var init_typeGuards = __esmMin((() => {}));
37465
- //#endregion
37466
37734
  //#region ../blocks/src/system/transforms/registry/content.ts
37467
37735
  init_typeGuards();
37468
37736
  const supportedRichTextTokenSchema = z$1.enum(["year", "site_name"]);
@@ -37470,16 +37738,16 @@ const interpolateRichTextTokensOptionsSchema = z$1.object({ tokens: z$1.array(su
37470
37738
  const richTextTokenPattern = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g;
37471
37739
  function getSiteName(context) {
37472
37740
  const viewModel = context.viewModel;
37473
- if (!isRecord$24(viewModel)) return null;
37741
+ if (!isRecord$25(viewModel)) return null;
37474
37742
  const site = viewModel.site;
37475
- if (isRecord$24(site) && typeof site.title === "string") {
37743
+ if (isRecord$25(site) && typeof site.title === "string") {
37476
37744
  const title = site.title.trim();
37477
37745
  return title.length > 0 ? title : null;
37478
37746
  }
37479
37747
  const root = viewModel.$root;
37480
- if (isRecord$24(root)) {
37748
+ if (isRecord$25(root)) {
37481
37749
  const rootSite = root.site;
37482
- if (isRecord$24(rootSite) && typeof rootSite.title === "string") {
37750
+ if (isRecord$25(rootSite) && typeof rootSite.title === "string") {
37483
37751
  const title = rootSite.title.trim();
37484
37752
  if (title.length > 0) return title;
37485
37753
  }
@@ -37501,7 +37769,7 @@ function replaceTokenText(input, allowedTokens, tokenValues) {
37501
37769
  });
37502
37770
  }
37503
37771
  function visitRichTextNode(node, allowedTokens, tokenValues) {
37504
- if (!isRecord$24(node)) return node;
37772
+ if (!isRecord$25(node)) return node;
37505
37773
  let changed = false;
37506
37774
  const nextNode = { ...node };
37507
37775
  if (nextNode.type === "text" && typeof nextNode.text === "string") {
@@ -37522,21 +37790,11 @@ function visitRichTextNode(node, allowedTokens, tokenValues) {
37522
37790
  return changed ? nextNode : node;
37523
37791
  }
37524
37792
  function interpolateRichTextTokens(value, options, context) {
37525
- if (!isRecord$24(value)) return value;
37526
- const allowedTokens = new Set(options.tokens);
37527
- const tokenValues = {
37793
+ if (!isRecord$25(value)) return value;
37794
+ return visitRichTextNode(value, new Set(options.tokens), {
37528
37795
  year: String((/* @__PURE__ */ new Date()).getFullYear()),
37529
37796
  site_name: getSiteName(context)
37530
- };
37531
- if (isRecord$24(value.doc)) {
37532
- const nextDoc = visitRichTextNode(value.doc, allowedTokens, tokenValues);
37533
- if (nextDoc === value.doc) return value;
37534
- return {
37535
- ...value,
37536
- doc: nextDoc
37537
- };
37538
- }
37539
- return visitRichTextNode(value, allowedTokens, tokenValues);
37797
+ });
37540
37798
  }
37541
37799
  const contentTransforms = [{
37542
37800
  id: "content.interpolateRichTextTokens",
@@ -40055,124 +40313,6 @@ var init_media$1 = __esmMin((() => {
40055
40313
  archiveMediaSchema
40056
40314
  ]);
40057
40315
  }));
40058
- /**
40059
- * Permissive unwrap for a value known to be the root of a rich-text field.
40060
- *
40061
- * Producers should emit the canonical unwrapped form `{ type: 'doc', content: [...] }`,
40062
- * but two legacy shapes still appear in older data and pre-Phase-1 fixtures:
40063
- *
40064
- * - `{ doc: <typed-doc> }` — pre-migration DB storage.
40065
- * - `{ doc: <typed-doc>, html, plain }` — pre-Phase-1 dummy-content output.
40066
- *
40067
- * This helper is the single right place to tolerate either shape at a known
40068
- * rich-text root (transforms, coercion, validators that operate on rich text).
40069
- * The strictness sits on the inner node's `type === 'doc'`, which prevents
40070
- * misidentifying random objects that happen to carry a field named `doc`.
40071
- *
40072
- * Returns the inner doc node when the input matches a legacy shape, otherwise
40073
- * returns the input unchanged.
40074
- *
40075
- * For deep structural traversal where any nested key might be named `doc`
40076
- * (and unwrapping would be incorrect), use the strict `isDocWrapper` private
40077
- * helper inside `@riverbankcms/blocks/bindings`.
40078
- */
40079
- function unwrapRichTextRoot(value) {
40080
- if (!isRecord$24(value)) return value;
40081
- if (!("doc" in value)) return value;
40082
- const inner = value.doc;
40083
- if (isRecord$24(inner) && inner.type === "doc") return inner;
40084
- return value;
40085
- }
40086
- function createHardBreakNode() {
40087
- return { type: "hardBreak" };
40088
- }
40089
- /**
40090
- * Parse a small markdown subset into TipTap inline nodes.
40091
- *
40092
- * This intentionally supports only bold (`**text**`) because the SDK/content
40093
- * import paths use it for lightweight default content, not full markdown.
40094
- */
40095
- function parseRichTextInlineMarkdown(text) {
40096
- const out = [];
40097
- const pushText = (value, marks) => {
40098
- if (!value) return;
40099
- out.push(marks && marks.length > 0 ? {
40100
- type: "text",
40101
- text: value,
40102
- marks
40103
- } : {
40104
- type: "text",
40105
- text: value
40106
- });
40107
- };
40108
- let rest = text;
40109
- while (rest.length > 0) {
40110
- const start = rest.indexOf("**");
40111
- if (start === -1) {
40112
- pushText(rest);
40113
- break;
40114
- }
40115
- const end = rest.indexOf("**", start + 2);
40116
- if (end === -1) {
40117
- pushText(rest);
40118
- break;
40119
- }
40120
- pushText(rest.slice(0, start));
40121
- pushText(rest.slice(start + 2, end), [{ type: "bold" }]);
40122
- rest = rest.slice(end + 2);
40123
- }
40124
- return out;
40125
- }
40126
- function parseRichTextParagraphInlineMarkdown(text) {
40127
- return text.split("\n").flatMap((line, index) => {
40128
- const lineNodes = parseRichTextInlineMarkdown(line.trim());
40129
- return index === 0 ? lineNodes : [createHardBreakNode(), ...lineNodes];
40130
- });
40131
- }
40132
- /**
40133
- * Convert a plain string with a tiny markdown subset to canonical TipTap JSON.
40134
- *
40135
- * Double newlines create semantic paragraphs. Single newlines remain inside the
40136
- * current paragraph as TipTap `hardBreak` nodes for line-oriented content such
40137
- * as addresses, opening hours, and contact details.
40138
- */
40139
- function createRichTextDocFromMarkdown(markdown) {
40140
- const normalized = markdown.replace(/\r\n/g, "\n").trim();
40141
- if (!normalized) return {
40142
- type: "doc",
40143
- content: []
40144
- };
40145
- return {
40146
- type: "doc",
40147
- content: normalized.split(/\n{2,}/).map((paragraph) => paragraph.trim()).filter(Boolean).map((paragraph) => {
40148
- const inline = parseRichTextParagraphInlineMarkdown(paragraph);
40149
- return inline.length > 0 ? {
40150
- type: "paragraph",
40151
- content: inline
40152
- } : { type: "paragraph" };
40153
- })
40154
- };
40155
- }
40156
- var TipTapMarkSchema, TipTapNodeSchema, RichTextDocSchema;
40157
- var init_richTextSchema = __esmMin((() => {
40158
- init_typeGuards();
40159
- TipTapMarkSchema = z$1.object({
40160
- type: z$1.string(),
40161
- attrs: z$1.record(z$1.string(), z$1.unknown()).optional()
40162
- });
40163
- TipTapNodeSchema = z$1.lazy(() => z$1.object({
40164
- type: z$1.string(),
40165
- content: z$1.array(TipTapNodeSchema).optional(),
40166
- text: z$1.string().optional(),
40167
- attrs: z$1.record(z$1.string(), z$1.unknown()).optional(),
40168
- marks: z$1.array(TipTapMarkSchema).optional()
40169
- }));
40170
- z$1.union([TipTapNodeSchema, z$1.object({ doc: TipTapNodeSchema })]);
40171
- RichTextDocSchema = z$1.object({
40172
- type: z$1.literal("doc"),
40173
- content: z$1.array(TipTapNodeSchema)
40174
- });
40175
- }));
40176
40316
  //#endregion
40177
40317
  //#region ../blocks/src/system/blocks/shared/bookingPaymentTerms.ts
40178
40318
  var bookingDepositRefundPolicySchema, bookingInstalmentPlanSchema, bookingFlexibleBalanceDueDateRuleSchema, bookingFlexibleBalanceConfigSchema, blockBookingPaymentCollectionOptionSchema, blockBookingPaymentTermsSchema;
@@ -55083,42 +55223,54 @@ function normalize(value) {
55083
55223
  return trimmed.length > 0 ? trimmed : null;
55084
55224
  }
55085
55225
  /**
55086
- * Resolve the trailing affordance a button should render. Node overrides
55087
- * personality; returns `null` when nothing is configured.
55226
+ * Resolve the node-authored trailing affordance, or `null` when no icon exists.
55088
55227
  */
55089
55228
  function resolveButtonAffordance(input) {
55090
55229
  const nodeIcon = normalize(input.trailingIcon);
55091
- if (nodeIcon) {
55092
- const colorToken = normalize(input.trailingIconColorToken);
55093
- return {
55094
- iconId: nodeIcon,
55095
- source: "node",
55096
- ...colorToken ? { colorToken } : {}
55097
- };
55098
- }
55099
- const personality = input.personalityAffordance;
55100
- const personalityIcon = normalize(personality?.iconId);
55101
- if (personality && personalityIcon) {
55102
- const colorToken = normalize(personality.colorToken);
55103
- return {
55104
- iconId: personalityIcon,
55105
- source: "personality",
55106
- ...colorToken ? { colorToken } : {}
55107
- };
55108
- }
55230
+ if (nodeIcon) return { iconId: nodeIcon };
55109
55231
  return null;
55110
55232
  }
55111
55233
  //#endregion
55234
+ //#region ../logger/src/noop.ts
55235
+ var noop, logger;
55236
+ var init_noop = __esmMin((() => {
55237
+ noop = () => {};
55238
+ logger = {
55239
+ debug: noop,
55240
+ info: noop,
55241
+ warn: noop,
55242
+ error: noop,
55243
+ withFields: (_) => logger
55244
+ };
55245
+ }));
55246
+ //#endregion
55112
55247
  //#region ../blocks/src/system/runtime/nodes/richText-coerce.ts
55113
- function coerceRichTextDoc(value) {
55114
- const raw = unwrapRichTextRoot(value);
55115
- if (typeof raw === "string") return createRichTextDocFromMarkdown(raw);
55116
- if (isRecord$24(raw) && typeof raw.type === "string") return raw;
55248
+ function parseRichTextDoc(value) {
55249
+ const parsed = RichTextDocSchema.safeParse(value);
55250
+ if (parsed.success) return {
55251
+ kind: "valid",
55252
+ doc: parsed.data
55253
+ };
55254
+ return {
55255
+ kind: "invalid",
55256
+ issues: parsed.error.issues.map((issue) => ({
55257
+ path: issue.path.map((segment) => String(segment)),
55258
+ message: issue.message
55259
+ }))
55260
+ };
55261
+ }
55262
+ function coerceRichTextDoc(value, source) {
55263
+ const parsed = parseRichTextDoc(value);
55264
+ if (parsed.kind === "valid") return parsed.doc;
55265
+ if (value !== null && value !== void 0) logger.warn("blocks:rich-text:invalid-document", {
55266
+ source,
55267
+ issues: parsed.issues.slice(0, 3)
55268
+ });
55117
55269
  return null;
55118
55270
  }
55119
55271
  var init_richText_coerce = __esmMin((() => {
55272
+ init_noop();
55120
55273
  init_richTextSchema();
55121
- init_typeGuards();
55122
55274
  }));
55123
55275
  //#endregion
55124
55276
  //#region ../blocks/src/system/runtime/nodes/renderInlineText.tsx
@@ -55170,13 +55322,12 @@ function readStringPath(source, path) {
55170
55322
  }
55171
55323
  const RichTextNode = ({ value, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, ...rest }) => {
55172
55324
  return /* @__PURE__ */ jsx(RichText$1, {
55173
- doc: coerceRichTextDoc(value) ?? void 0,
55325
+ doc: coerceRichTextDoc(value, `block-runtime:${_blockKind ?? "unknown"}:${rest.path ?? "richText"}`) ?? void 0,
55174
55326
  ...rest
55175
55327
  });
55176
55328
  };
55177
55329
  /**
55178
- * Render the resolved trailing affordance icon. Colour is applied via a theme
55179
- * CSS var so it recolours with the palette; the icon stroke uses `currentColor`.
55330
+ * Render the resolved trailing affordance icon using the button's foreground.
55180
55331
  */
55181
55332
  function renderTrailingAffordanceIcon(affordance) {
55182
55333
  if (!affordance) return null;
@@ -55184,21 +55335,16 @@ function renderTrailingAffordanceIcon(affordance) {
55184
55335
  if (!Icon) return null;
55185
55336
  return /* @__PURE__ */ jsx(Icon, {
55186
55337
  "aria-hidden": true,
55187
- className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block",
55188
- style: affordance.colorToken ? { color: `rgb(var(--tb-${affordance.colorToken}))` } : void 0
55338
+ className: "rb-ml-2 rb-h-4 rb-w-4 rb-inline-block"
55189
55339
  });
55190
55340
  }
55191
- 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 }) => {
55341
+ const ButtonNode = ({ value, children, href, variantId = "primary", size = "md", disabled, type = "button", target, rel, linkRequired = false, trailingIcon, blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, pathBase: _pathBase, className, ...rest }) => {
55192
55342
  const content = value ?? children;
55193
55343
  if (!content) {
55194
55344
  console.warn("[ButtonNode] No content to render - value and children are both empty");
55195
55345
  return null;
55196
55346
  }
55197
- const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({
55198
- trailingIcon,
55199
- trailingIconColorToken,
55200
- personalityAffordance
55201
- }));
55347
+ const affordanceIcon = renderTrailingAffordanceIcon(resolveButtonAffordance({ trailingIcon }));
55202
55348
  const resolvedHref = typeof href === "string" ? href.trim() : "";
55203
55349
  if (linkRequired && resolvedHref.length === 0) {
55204
55350
  console.warn("[ButtonNode] Missing href for link-required button");
@@ -55864,9 +56010,9 @@ const AccordionItemNodeSSR = ({ className, value, trigger, content, question, an
55864
56010
  };
55865
56011
  function resolveNode$1(value) {
55866
56012
  if (typeof value === "string" || typeof value === "number") return String(value);
55867
- const doc = coerceRichTextDoc(value);
56013
+ const doc = coerceRichTextDoc(value, "block-runtime:accordion:item-content");
55868
56014
  if (doc) return /* @__PURE__ */ jsx(RichText$1, { doc });
55869
- return value;
56015
+ return React.isValidElement(value) ? value : null;
55870
56016
  }
55871
56017
  //#endregion
55872
56018
  //#region ../blocks/src/system/runtime/nodes/header-section.server.tsx
@@ -56611,19 +56757,6 @@ var init_booking_form_state = __esmMin((() => {
56611
56757
  init_src$3();
56612
56758
  init_booking_form_reserved_fields();
56613
56759
  }));
56614
- //#endregion
56615
- //#region ../logger/src/noop.ts
56616
- var noop, logger;
56617
- var init_noop = __esmMin((() => {
56618
- noop = () => {};
56619
- logger = {
56620
- debug: noop,
56621
- info: noop,
56622
- warn: noop,
56623
- error: noop,
56624
- withFields: (_) => logger
56625
- };
56626
- }));
56627
56760
  var bookingFieldOptionSchema, bookingFieldSchema, bookingSettingsSchema, bookingSourceFormSchema;
56628
56761
  var init_booking_runtime_sources = __esmMin((() => {
56629
56762
  init_noop();
@@ -57608,7 +57741,7 @@ function CourseDetailsView(props) {
57608
57741
  const sortedSessions = [...course.sessions ?? []].sort((a, b) => Date.parse(a.startsAt) - Date.parse(b.startsAt));
57609
57742
  const visibleSessions = sessionLimit === "all" ? sortedSessions : sortedSessions.slice(0, sessionLimit);
57610
57743
  const hasMoreSessions = sessionLimit !== "all" && sortedSessions.length > sessionLimit;
57611
- const descriptionDoc = showDescription ? coerceRichTextDoc(course.description) : null;
57744
+ const descriptionDoc = showDescription ? coerceRichTextDoc(course.description, "block-runtime:course-details:description") : null;
57612
57745
  const teamMembers = course.teamMembers ?? [];
57613
57746
  return /* @__PURE__ */ jsxs("div", {
57614
57747
  className: "rb-flex rb-flex-col rb-gap-6",
@@ -59294,7 +59427,7 @@ function ProductDetailServerContent(props) {
59294
59427
  actions: props.render.display.state === "ready" ? renderServerPendingAction(props.render.display.actionLabel, props.render.display.soldOut) : null,
59295
59428
  body: props.render.display.state === "ready" && props.render.display.body ? /* @__PURE__ */ jsx("div", {
59296
59429
  className: "rb-prose rb-max-w-none",
59297
- children: /* @__PURE__ */ jsx(RichText$1, { doc: coerceRichTextDoc(props.render.display.body) })
59430
+ children: /* @__PURE__ */ jsx(RichText$1, { doc: coerceRichTextDoc(props.render.display.body, "block-runtime:product-detail:body") })
59298
59431
  }) : null
59299
59432
  });
59300
59433
  }
@@ -61003,8 +61136,8 @@ function extractAlignmentClassName(className) {
61003
61136
  //#region ../blocks/src/system/runtime/resolver.ts
61004
61137
  init_src$3();
61005
61138
  init_node();
61006
- init_richTextSchema();
61007
61139
  init_headingDecoration();
61140
+ init_richText_coerce();
61008
61141
  /**
61009
61142
  * Maps meta binding paths to their actual store keys.
61010
61143
  * The metadata store uses 'draft' prefixed keys (e.g., draftTitle, draftSlug)
@@ -61328,13 +61461,9 @@ function isTextConditionValueEmpty(value) {
61328
61461
  return !value;
61329
61462
  }
61330
61463
  function isRichTextConditionValueEmpty(value) {
61331
- const root = unwrapRichTextRoot(value);
61332
- if (typeof root === "string") return root.trim().length === 0;
61333
- if (!isTipTapNode(root)) return root === null || root === void 0 || !root;
61334
- return richTextStructuralPresence(root).kind === "empty";
61335
- }
61336
- function isTipTapNode(value) {
61337
- return isPlainObject$2(value) && typeof value.type === "string";
61464
+ const doc = coerceRichTextDoc(value, "block-runtime:condition:richText");
61465
+ if (!doc) return true;
61466
+ return richTextStructuralPresence(doc).kind === "empty";
61338
61467
  }
61339
61468
  function richTextStructuralPresence(node) {
61340
61469
  if (typeof node.text === "string" && node.text.trim().length > 0) return {
@@ -66088,7 +66217,7 @@ function hydrateValue(value, context) {
66088
66217
  const resolvedItems = value.map((item) => hydrateValue(item, context));
66089
66218
  return resolvedItems.every((item, index) => item === value[index]) ? value : resolvedItems;
66090
66219
  }
66091
- if (isRecord$24(value)) {
66220
+ if (isRecord$25(value)) {
66092
66221
  if (isInternalLink$1(value)) return hydrateInternalLink(value, context.routes);
66093
66222
  if (isPageLink$1(value)) return hydratePageLink(value, context);
66094
66223
  if (isEntryLink$1(value)) return hydrateEntryLink(value, context);
@@ -66428,8 +66557,8 @@ function boundaryReserveValueForTreatment(boundary) {
66428
66557
  return boundary.metrics.reserveCss;
66429
66558
  }
66430
66559
  function transitionCssVarsStyle(content) {
66431
- const transitionStyles = isObjectRecord(content._transitionStyles) ? content._transitionStyles : null;
66432
- const cssVars = isObjectRecord(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
66560
+ const transitionStyles = isObjectRecord$1(content._transitionStyles) ? content._transitionStyles : null;
66561
+ const cssVars = isObjectRecord$1(transitionStyles?.cssVars) ? transitionStyles.cssVars : null;
66433
66562
  const from = typeof cssVars?.from === "string" ? cssVars.from : null;
66434
66563
  const to = typeof cssVars?.to === "string" ? cssVars.to : null;
66435
66564
  if (!from && !to) return void 0;
@@ -66749,7 +66878,7 @@ function shouldDebugCustomBlocks() {
66749
66878
  function resolveBlockData({ block, definition, dataContext }) {
66750
66879
  const blockId = block.id ?? null;
66751
66880
  const raw = blockId ? dataContext?.resolvedData?.[blockId] : void 0;
66752
- if (isObjectRecord(raw)) return { ...raw };
66881
+ if (isObjectRecord$1(raw)) return { ...raw };
66753
66882
  return definition.dataLoaders && Object.keys(definition.dataLoaders).length > 0 ? {} : void 0;
66754
66883
  }
66755
66884
  /**
@@ -66760,7 +66889,7 @@ function resolveBlockData({ block, definition, dataContext }) {
66760
66889
  */
66761
66890
  function getRenderableContent(block, previewStage = "published") {
66762
66891
  const source = previewStage === "preview" && block.draftContent ? block.draftContent : block.content ?? {};
66763
- if (!isObjectRecord(source)) return {};
66892
+ if (!isObjectRecord$1(source)) return {};
66764
66893
  return source;
66765
66894
  }
66766
66895
  function summarizeValue(value) {
@@ -66775,11 +66904,8 @@ function summarizeValue(value) {
66775
66904
  const preview = {};
66776
66905
  for (const k of keys.slice(0, 8)) {
66777
66906
  const v = rec[k];
66778
- if (k === "body" || k === "content") {
66779
- const isDocWrapper = !!(v && typeof v === "object" && isObjectRecord(v) && "doc" in v);
66780
- const isDoc = !!(v && typeof v === "object" && isObjectRecord(v) && v.type === "doc");
66781
- preview[k] = isDocWrapper ? "{doc}" : isDoc ? "{type:doc}" : summarizeValue(v);
66782
- } else preview[k] = summarizeValue(v);
66907
+ if (k === "body" || k === "content") preview[k] = !!(v && typeof v === "object" && isObjectRecord$1(v) && v.type === "doc") ? "{type:doc}" : summarizeValue(v);
66908
+ else preview[k] = summarizeValue(v);
66783
66909
  }
66784
66910
  return {
66785
66911
  keys,
@@ -66796,16 +66922,6 @@ function summarizeValue(value) {
66796
66922
  //#region ../blocks/src/subroutes/fold.ts
66797
66923
  init_src$3();
66798
66924
  //#endregion
66799
- //#region ../theme-core/src/styles/gradients.ts
66800
- init_paletteAccess();
66801
- init_colorConversion();
66802
- //#endregion
66803
- //#region ../theme-core/src/styles/glow.ts
66804
- init_palette$1();
66805
- //#endregion
66806
- //#region ../theme-core/src/styles/buttons.ts
66807
- init_colorStyles();
66808
- //#endregion
66809
66925
  //#region ../blocks/src/structure/schema.ts
66810
66926
  const BlockKind = z.string();
66811
66927
  const blockSchema = z.object({
@@ -66824,8 +66940,9 @@ z.object({
66824
66940
  blocks: z.array(blockSchema).min(1)
66825
66941
  });
66826
66942
  //#endregion
66827
- //#region ../theme-core/src/recommend/generateThemes.ts
66828
- init_expandPalette();
66943
+ //#region ../theme-core/src/styles/gradients.ts
66944
+ init_paletteAccess();
66945
+ init_colorConversion();
66829
66946
  //#endregion
66830
66947
  //#region ../theme-core/src/generated/containerResponsiveThemeCss.ts
66831
66948
  /**
@@ -79881,6 +79998,11 @@ function ResponsiveScope({ children, responsiveMode = DEFAULT_THEME_RESPONSIVE_M
79881
79998
  });
79882
79999
  }
79883
80000
  //#endregion
80001
+ //#region ../theme-core/src/buttons/core.ts
80002
+ init_resolveButtonColourStates();
80003
+ init_resolvedButtonCss();
80004
+ init_types$12();
80005
+ //#endregion
79884
80006
  //#region ../theme-core/src/runtime/buildThemeRuntimeFromBridge.ts
79885
80007
  /**
79886
80008
  * Build Theme Runtime from ThemeBridge Config
@@ -79892,7 +80014,6 @@ function ResponsiveScope({ children, responsiveMode = DEFAULT_THEME_RESPONSIVE_M
79892
80014
  init_colorConversion();
79893
80015
  init_textColor();
79894
80016
  init_onColor();
79895
- init_core$2();
79896
80017
  init_core$1();
79897
80018
  z$1.object({
79898
80019
  tokens: z$1.record(z$1.string(), z$1.string()),
@@ -79937,7 +80058,7 @@ z$1.object({
79937
80058
  }).passthrough();
79938
80059
  //#endregion
79939
80060
  //#region ../theme-core/src/siteChrome.tsx
79940
- init_types$16();
80061
+ init_types$15();
79941
80062
  //#endregion
79942
80063
  //#region ../blocks/src/system/runtime/bindings.ts
79943
80064
  init_node();
@@ -80068,10 +80189,10 @@ function normalizeDataLoaders(def) {
80068
80189
  */
80069
80190
  function normalizeContent(block) {
80070
80191
  const source = block.draftContent ?? block.content ?? block.publishedContent ?? {};
80071
- if (!isObjectRecord(source)) return {};
80192
+ if (!isObjectRecord$1(source)) return {};
80072
80193
  if ("data" in source) {
80073
80194
  const data = source.data;
80074
- if (isObjectRecord(data)) return data;
80195
+ if (isObjectRecord$1(data)) return data;
80075
80196
  if (data === null || data === void 0) return {};
80076
80197
  }
80077
80198
  return source;
@@ -80264,7 +80385,7 @@ function stableNormalize(value) {
80264
80385
  //#region ../blocks/src/system/data/normalizeLoaderParams.ts
80265
80386
  init_typeGuards();
80266
80387
  function toStringParams(value) {
80267
- if (!isObjectRecord(value)) return {};
80388
+ if (!isObjectRecord$1(value)) return {};
80268
80389
  const out = {};
80269
80390
  for (const [k, v] of Object.entries(value)) if (typeof v === "string") out[k] = v;
80270
80391
  return out;
@@ -81098,6 +81219,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
81098
81219
  "idempotency_amount_mismatch",
81099
81220
  "idempotency_method_mismatch",
81100
81221
  "idempotency_receipt_mismatch",
81222
+ "idempotency_scope_mismatch",
81101
81223
  "refund_in_progress"
81102
81224
  ],
81103
81225
  "invalid_amount",
@@ -81477,6 +81599,7 @@ BOOKING_QUESTION_ANSWER_EXPORT_SCOPES.site, BOOKING_QUESTION_ANSWER_EXPORT_SCOPE
81477
81599
  init_src$3();
81478
81600
  //#endregion
81479
81601
  //#region ../api/src/siteBanner.ts
81602
+ init_richTextSchema();
81480
81603
  const SITE_BANNER_SCOPE_VALUES = ["homepage", "all-pages"];
81481
81604
  const SITE_BANNER_TONE_VALUES = [
81482
81605
  "announcement",
@@ -81486,7 +81609,7 @@ const SITE_BANNER_TONE_VALUES = [
81486
81609
  ];
81487
81610
  const siteBannerScopeSchema = z$1.enum(SITE_BANNER_SCOPE_VALUES);
81488
81611
  const siteBannerToneSchema = z$1.enum(SITE_BANNER_TONE_VALUES);
81489
- const siteBannerBodySchema = z$1.unknown().transform(unwrapRichTextValue);
81612
+ const siteBannerBodySchema = RichTextDocSchema;
81490
81613
  const siteBannerCtaSchema = z$1.object({
81491
81614
  label: z$1.string().trim().min(1),
81492
81615
  link: linkPayloadSchema
@@ -81514,7 +81637,8 @@ const EMPTY_SITE_BANNER_BODY = {
81514
81637
  }]
81515
81638
  };
81516
81639
  function analyzeSiteBannerBody(body) {
81517
- const sanitizedBody = sanitizeSiteBannerBodyInternal(body, { limitParagraphs: false });
81640
+ const parsed = RichTextDocSchema.safeParse(body);
81641
+ const sanitizedBody = parsed.success ? sanitizeSiteBannerBodyInternal(parsed.data, { limitParagraphs: false }) : EMPTY_SITE_BANNER_BODY;
81518
81642
  const paragraphs = collectParagraphs(sanitizedBody);
81519
81643
  const textLength = paragraphs.reduce((total, paragraph) => total + paragraphTextLength(paragraph), 0);
81520
81644
  const issues = [];
@@ -81536,7 +81660,7 @@ function siteBannerBodyIssueMessage(issue) {
81536
81660
  }
81537
81661
  }
81538
81662
  function sanitizeSiteBannerBodyInternal(input, options) {
81539
- const content = normalizeTopLevelNodes(unwrapRichTextValue(input).content ?? [], options);
81663
+ const content = normalizeTopLevelNodes(input.content, options);
81540
81664
  return {
81541
81665
  type: "doc",
81542
81666
  content: content.length > 0 ? content : EMPTY_SITE_BANNER_BODY.content
@@ -81617,28 +81741,6 @@ function sanitizeMarks(marks) {
81617
81741
  });
81618
81742
  return sanitized.length > 0 ? sanitized : void 0;
81619
81743
  }
81620
- function unwrapRichTextValue(value) {
81621
- if (isRecord$5(value) && isRecord$5(value.doc)) return unwrapRichTextValue(value.doc);
81622
- if (isRecord$5(value) && value.type === "doc") return {
81623
- type: "doc",
81624
- content: Array.isArray(value.content) ? value.content.filter(isTipTapNodeLike).map(coerceTipTapNode) : []
81625
- };
81626
- return EMPTY_SITE_BANNER_BODY;
81627
- }
81628
- function isTipTapNodeLike(value) {
81629
- return isRecord$5(value) && typeof value.type === "string";
81630
- }
81631
- function coerceTipTapNode(value) {
81632
- return {
81633
- type: value.type,
81634
- ...Array.isArray(value.content) ? { content: value.content.filter(isTipTapNodeLike).map(coerceTipTapNode) } : {},
81635
- ...typeof value.text === "string" ? { text: value.text } : {},
81636
- ...Array.isArray(value.marks) ? { marks: value.marks.filter((mark) => isRecord$5(mark) && typeof mark.type === "string").map((mark) => ({
81637
- type: mark.type,
81638
- ...isRecord$5(mark.attrs) ? { attrs: mark.attrs } : {}
81639
- })) } : {}
81640
- };
81641
- }
81642
81744
  function paragraphTextLength(paragraph) {
81643
81745
  return collectText(paragraph).length;
81644
81746
  }
@@ -152970,7 +153072,7 @@ var init_event_registration_client = __esmMin((() => {
152970
153072
  * Loads Leaflet CSS/JS from CDN to avoid bundling in the blocks package.
152971
153073
  */
152972
153074
  function isLeafletApi(value) {
152973
- if (!isRecord$24(value)) return false;
153075
+ if (!isRecord$25(value)) return false;
152974
153076
  return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
152975
153077
  }
152976
153078
  function loadLeaflet() {
@@ -158116,7 +158218,7 @@ function ProductDetailController(props) {
158116
158218
  selectedProduct,
158117
158219
  variantId
158118
158220
  ]);
158119
- const bodyDoc = display.state === "ready" && props.render.hydration.showBody ? coerceRichTextDoc(display.body) : null;
158221
+ const bodyDoc = display.state === "ready" && props.render.hydration.showBody ? coerceRichTextDoc(display.body, "block-runtime:product-detail:body") : null;
158120
158222
  return /* @__PURE__ */ jsx(ProductDetailView, {
158121
158223
  display,
158122
158224
  gallery: display.state === "ready" ? /* @__PURE__ */ jsx(ProductGalleryFrameView, {
@@ -159711,41 +159813,11 @@ init_classic_professional();
159711
159813
  init_vibrant_creative();
159712
159814
  //#endregion
159713
159815
  //#region src/rendering/blocks-theme-runtime.ts
159714
- const AXES_TONE_OPTIONS = [
159715
- "minimal",
159716
- "classic",
159717
- "bold"
159718
- ];
159719
- const DEFAULT_AXES_TONE = AXES_TONE_OPTIONS[0];
159720
- const AXES_TONE_SET = new Set(AXES_TONE_OPTIONS);
159721
- const THEME_NAME_MAX_LENGTH = 30;
159722
- function normalizeThemeForBlocks(theme) {
159723
- if (!theme || typeof theme !== "object") return theme;
159724
- const cloned = JSON.parse(JSON.stringify(theme));
159725
- if (typeof cloned.name === "string" && cloned.name.length > THEME_NAME_MAX_LENGTH) cloned.name = cloned.name.slice(0, THEME_NAME_MAX_LENGTH);
159726
- if (cloned.axes && typeof cloned.axes === "object") {
159727
- const axes = cloned.axes;
159728
- const tone = axes.tone;
159729
- if (typeof tone === "string" && !AXES_TONE_SET.has(tone)) axes.tone = DEFAULT_AXES_TONE;
159730
- }
159731
- return cloned;
159732
- }
159816
+ init_buttons();
159733
159817
  function parseBlocksTheme(theme) {
159734
- const schema = themeSchema;
159735
- if (typeof schema.safeParse !== "function") {
159736
- console.warn("[sdk/rendering] themeSchema.safeParse is unavailable; skipping theme validation and using normalized theme data directly.");
159737
- return normalizeThemeForBlocks(theme);
159738
- }
159739
- const parsed = schema.safeParse(theme);
159740
- if (parsed.success) return parsed.data;
159741
- const normalized = normalizeThemeForBlocks(theme);
159742
- const reparsed = schema.safeParse(normalized);
159743
- if (reparsed.success) {
159744
- console.warn("[sdk/rendering] Repaired invalid theme to satisfy blocks schema:", parsed.error.issues);
159745
- return reparsed.data;
159746
- }
159747
- console.warn("[sdk/rendering] Failed to parse theme; falling back to modernMinimalTheme:", reparsed.error.issues);
159748
- return modernMinimalTheme;
159818
+ const parsed = parseThemeForPersistence(theme);
159819
+ if (!parsed.ok) throw new Error(`Theme does not satisfy the canonical runtime contract: ${parsed.error.kind}`);
159820
+ return parsed.value;
159749
159821
  }
159750
159822
  function buildThemeRuntime(theme) {
159751
159823
  return { tokens: buildThemeRuntime$1(parseBlocksTheme(theme)).tokens };
@@ -160044,7 +160116,7 @@ var SimpleCache = class {
160044
160116
  * 1. This constant
160045
160117
  * 2. The "version" field in package.json
160046
160118
  */
160047
- const SDK_VERSION = "0.111.0";
160119
+ const SDK_VERSION = "0.118.0";
160048
160120
  //#endregion
160049
160121
  //#region src/client/error.ts
160050
160122
  let _Symbol$for;