@riverbankcms/sdk 0.111.0 → 0.119.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 (196) hide show
  1. package/dist/{PreviewEditorSidebar-CTR6LUhN.mjs → PreviewEditorSidebar-C7TXFitV.mjs} +4 -4
  2. package/dist/{PreviewEditorUI-DZg15Zip.mjs → PreviewEditorUI-_1JIHTXS.mjs} +3 -3
  3. package/dist/{PreviewQueryProvider-kkmjklLG.mjs → PreviewQueryProvider-nKUT4TL-.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-DeOTAFvR.mjs → SdkPreviewModeRuntime-CvJTVgWa.mjs} +2579 -34325
  5. package/dist/{SiteChromeCustomizeContext-DOSDLCiJ.mjs → SiteChromeCustomizeContext-66QfCbAS.mjs} +64625 -32791
  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/bookingConfig.d.ts +26 -1
  10. package/dist/_dts/api/src/bookingRecords.d.ts +6 -74
  11. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +3 -3
  12. package/dist/_dts/api/src/contentRuntime.d.ts +5 -1
  13. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +4 -4
  14. package/dist/_dts/api/src/endpoints.d.ts +35 -0
  15. package/dist/_dts/api/src/event-presentation.d.ts +4 -0
  16. package/dist/_dts/api/src/index.d.ts +4 -4
  17. package/dist/_dts/api/src/navigation/dashboardBookingsNav.d.ts +4 -1
  18. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +2 -2
  19. package/dist/_dts/api/src/sdk-event-upsert.d.ts +2 -2
  20. package/dist/_dts/api/src/sdkContracts.d.ts +85 -7
  21. package/dist/_dts/api/src/siteBanner.d.ts +8 -8
  22. package/dist/_dts/api/src/siteOperations.d.ts +1 -1
  23. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +32 -4
  24. package/dist/_dts/block-form/src/widgets/RichTextField/richTextFieldDefaults.d.ts +3 -12
  25. package/dist/_dts/block-form/src/widgets/RichTextField/richTextFieldSchema.d.ts +1 -5
  26. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -10
  27. package/dist/_dts/blocks/src/index.d.ts +3 -6
  28. package/dist/_dts/blocks/src/primitives/content/primitives.d.ts +2 -2
  29. package/dist/_dts/blocks/src/system/blocks/body-text.d.ts +2 -2
  30. package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +2 -2
  31. package/dist/_dts/blocks/src/system/blocks/events/shared/schemas.d.ts +2 -8
  32. package/dist/_dts/blocks/src/system/blocks/feature-card-icons.d.ts +2 -2
  33. package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +3 -3
  34. package/dist/_dts/blocks/src/system/blocks/form.d.ts +2 -15
  35. package/dist/_dts/blocks/src/system/blocks/intro.d.ts +2 -2
  36. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +66 -66
  37. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +2 -16
  38. package/dist/_dts/blocks/src/system/blocks/site-footer.d.ts +0 -3
  39. package/dist/_dts/blocks/src/system/fragments/index.d.ts +0 -1
  40. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +19 -2
  41. package/dist/_dts/blocks/src/system/manifest/richTextSchema.d.ts +8 -70
  42. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +1 -0
  43. package/dist/_dts/blocks/src/system/manifest/validation.d.ts +6 -0
  44. package/dist/_dts/blocks/src/system/node/schema.d.ts +4 -4
  45. package/dist/_dts/blocks/src/system/runtime/nodes/basic.d.ts +1 -10
  46. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +5 -21
  47. package/dist/_dts/blocks/src/system/runtime/nodes/richText-coerce.d.ts +14 -2
  48. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +1 -1
  49. package/dist/_dts/content-editor/src/controller/seedDraftBaselinesFromBlocks.d.ts +1 -1
  50. package/dist/_dts/content-editor/src/hooks/useBlockAutosave.d.ts +17 -1
  51. package/dist/_dts/content-editor/src/hooks/useDebouncedLatestSave.d.ts +1 -1
  52. package/dist/_dts/content-editor/src/hooks/useSimpleAutosave.d.ts +1 -1
  53. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +3 -2
  54. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +2 -2
  55. package/dist/_dts/content-editor/src/ui/stores/autosaveStore.d.ts +1 -1
  56. package/dist/_dts/content-editor/src/ui/stores/types.d.ts +1 -1
  57. package/dist/_dts/content-model/src/content-types/builtins.d.ts +3 -15
  58. package/dist/_dts/content-model/src/content-types/entryValidation.d.ts +2 -0
  59. package/dist/_dts/content-model/src/content-types/schema.d.ts +1 -1
  60. package/dist/_dts/content-model/src/templates/defaults.d.ts +1 -21
  61. package/dist/_dts/core/src/editor-state.d.ts +14 -1
  62. package/dist/_dts/core/src/footer-composition.d.ts +2 -1
  63. package/dist/_dts/core/src/index.d.ts +1 -0
  64. package/dist/_dts/core/src/rich-text.d.ts +16 -0
  65. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +189 -86
  66. package/dist/_dts/editor/src/index.d.ts +1 -1
  67. package/dist/_dts/editor/src/primitives/rich-text/utils.d.ts +3 -5
  68. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +1 -1
  69. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +2 -1
  70. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +2 -1
  71. package/dist/_dts/editor-blocks/src/block-editor/blockDraftBaselineSeed.d.ts +15 -0
  72. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockBaselineSync.d.ts +3 -7
  73. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +12 -0
  74. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +1 -0
  75. package/dist/_dts/editor-blocks/src/block-editor/utils.d.ts +1 -1
  76. package/dist/_dts/editor-blocks/src/index.d.ts +6 -5
  77. package/dist/_dts/editor-blocks/src/widgets/rich-text/RichTextField.d.ts +2 -2
  78. package/dist/_dts/media-core/src/contentMediaAudit.d.ts +104 -0
  79. package/dist/_dts/media-core/src/contentMediaAuditFieldAdapter.d.ts +8 -0
  80. package/dist/_dts/media-core/src/contentMediaSnapshotAudit.d.ts +22 -0
  81. package/dist/_dts/media-core/src/index.d.ts +3 -1
  82. package/dist/_dts/sdk/src/cli/commands/event.d.ts +18 -1
  83. package/dist/_dts/sdk/src/cli/commands/push/execute/theme.d.ts +2 -16
  84. package/dist/_dts/sdk/src/cli/content/reader.d.ts +8 -5
  85. package/dist/_dts/sdk/src/client/management/events.d.ts +2 -1
  86. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  87. package/dist/_dts/sdk/src/client/management/types.d.ts +36 -9
  88. package/dist/_dts/sdk/src/config/typed-entries.d.ts +7 -7
  89. package/dist/_dts/sdk/src/config/validation.d.ts +7 -7
  90. package/dist/_dts/sdk/src/contracts/content.d.ts +5 -15
  91. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  92. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -25
  93. package/dist/_dts/sdk/src/contracts/theme.d.ts +2 -18
  94. package/dist/_dts/sdk/src/manifest/passes/pass1-fields.d.ts +1 -1
  95. package/dist/_dts/sdk/src/manifest/three-pass-converter.d.ts +4 -4
  96. package/dist/_dts/sdk/src/rendering/helpers/bindings.d.ts +1 -2
  97. package/dist/_dts/sdk/src/rendering/helpers/index.d.ts +1 -1
  98. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +2 -13
  99. package/dist/_dts/sdk/src/theme/index.d.ts +0 -29
  100. package/dist/_dts/sdk/src/version.d.ts +1 -1
  101. package/dist/_dts/site-commands/src/commands.d.ts +31 -18
  102. package/dist/_dts/theme-core/src/buttons/affordanceIcons.d.ts +2 -2
  103. package/dist/_dts/theme-core/src/buttons/core.d.ts +0 -1
  104. package/dist/_dts/theme-core/src/buttons/effectClassification.d.ts +22 -9
  105. package/dist/_dts/theme-core/src/buttons/effects/presets/background.d.ts +1 -2
  106. package/dist/_dts/theme-core/src/buttons/effects/presets/border.d.ts +1 -2
  107. package/dist/_dts/theme-core/src/buttons/effects/presets/overlay.d.ts +3 -1
  108. package/dist/_dts/theme-core/src/buttons/effects/presets/shadow.d.ts +2 -2
  109. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +8 -18
  110. package/dist/_dts/theme-core/src/buttons/generateButtonCss.d.ts +2 -2
  111. package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +5 -5
  112. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -4
  113. package/dist/_dts/theme-core/src/buttons/parseThemeForPersistence.d.ts +36 -0
  114. package/dist/_dts/theme-core/src/buttons/types.d.ts +1638 -93
  115. package/dist/_dts/theme-core/src/cards/types.d.ts +13 -13
  116. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +969 -69
  117. package/dist/_dts/theme-core/src/navigation/types.d.ts +2 -2
  118. package/dist/_dts/theme-core/src/recommend/generateThemes.d.ts +0 -1
  119. package/dist/_dts/theme-core/src/schema.d.ts +1100 -116
  120. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  121. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +14 -14
  122. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +2 -2
  123. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +4 -4
  124. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +6 -0
  125. package/dist/cli/index.mjs +5706 -4852
  126. package/dist/cli/init-docs/content/cli-reference.md +40 -1
  127. package/dist/cli/init-docs/content/content-management.md +6 -0
  128. package/dist/client/{DiscountCodeDisclosure-C4xvTBux.mjs → DiscountCodeDisclosure-DIWj-P9v.mjs} +1 -1
  129. package/dist/client/{EventCombined.client-Cr7G131j.mjs → EventCombined.client-De8YWBSr.mjs} +2 -2
  130. package/dist/client/{EventListing.client-CAjbseNy.mjs → EventListing.client-seHTjimY.mjs} +2 -2
  131. package/dist/client/{LeafletStaticMap-BMlWfwz3.mjs → LeafletStaticMap-BmQxFcJW.mjs} +1 -1
  132. package/dist/client/{MagicLinkForm-ChdFz96y.mjs → MagicLinkForm-OoJAIUIj.mjs} +1 -1
  133. package/dist/client/{StepIndicator-7D3GaBeM.mjs → StepIndicator-CiZ8kdPk.mjs} +2 -2
  134. package/dist/client/{accordion-D8JTs2Si.mjs → accordion-6lnN__XJ.mjs} +1 -1
  135. package/dist/client/{bookingForm-H3DCRBHs.mjs → bookingForm-5uyqhONU.mjs} +6 -6
  136. package/dist/client/bookings.mjs +2219 -527
  137. package/dist/client/{carousel-DMr_QWlz.mjs → carousel-Dtnifil_.mjs} +1 -1
  138. package/dist/client/{cart-DWMbfBdR.mjs → cart-5Tc5S7NV.mjs} +3 -3
  139. package/dist/client/{checkout-zmfdkXLx.mjs → checkout-CYKKN5Hr.mjs} +3 -3
  140. package/dist/client/client.mjs +2498 -2384
  141. package/dist/client/{colorTokenParts-FSS3al6l.mjs → colorStyles-BWpj_h4C.mjs} +88 -1
  142. package/dist/client/{courseRegistration-Z_mn18jy.mjs → courseRegistration-CxCBybB4.mjs} +6 -6
  143. package/dist/client/{eventCalendar-CYp0YJGF.mjs → eventCalendar-Xj2jZS9X.mjs} +4 -4
  144. package/dist/client/{eventCombined-rKyYZUa9.mjs → eventCombined-CgcMoOgM.mjs} +2 -2
  145. package/dist/client/{eventDetails-X0ZaUuMj.mjs → eventDetails-CEAH8Edc.mjs} +3 -3
  146. package/dist/client/{eventListing-W1SuL7EP.mjs → eventListing-qyPVQ0wP.mjs} +2 -2
  147. package/dist/client/{eventRegistration-ClWricui.mjs → eventRegistration-DDu79CtL.mjs} +6 -6
  148. package/dist/client/{form--eKPwAAD.mjs → form-Bc7JKI7I.mjs} +1 -1
  149. package/dist/client/{headerSection-BSeGr-FS.mjs → headerSection-vTku_LEl.mjs} +2 -2
  150. package/dist/client/hooks.mjs +373 -555
  151. package/dist/client/{locationMap-BpOrtNYn.mjs → locationMap-Bg7X4Jna.mjs} +3 -3
  152. package/dist/client/{media-DoF0dcVx.mjs → media-CNE1Z-wb.mjs} +1 -2
  153. package/dist/client/{newsletterForm-Bt7it7Dy.mjs → newsletterForm-lpylVdp5.mjs} +1 -1
  154. package/dist/client/{pricing-BTjSDDr4.mjs → pricing-DE8fjJiT.mjs} +1 -1
  155. package/dist/client/{productDetail-ICnVTcCg.mjs → productDetail-D7Bo2RMH.mjs} +3 -3
  156. package/dist/client/{productList-ZHr6D604.mjs → productList-VjnZqiqN.mjs} +3 -3
  157. package/dist/client/{propsDecoder-wWN0tBDF.mjs → propsDecoder-DreFXjNP.mjs} +2212 -621
  158. package/dist/client/rendering/client.mjs +21612 -21646
  159. package/dist/client/rendering/islands.mjs +20 -20
  160. package/dist/client/rendering.mjs +1571 -1547
  161. package/dist/client/{shop-C1u_BUn0.mjs → shop-IRsHHbf7.mjs} +5 -5
  162. package/dist/client/{shop-commerce-CleZdRha.mjs → shop-commerce-gnI8PieZ.mjs} +27 -10
  163. package/dist/client/{shop-commerce-store-ycnoB2Ce.mjs → shop-commerce-store-BTbrhObn.mjs} +1 -1
  164. package/dist/client/{shopShared-CPhByt2a.mjs → shopShared-D6KS2_qk.mjs} +3 -3
  165. package/dist/client/{useDiscountCodeUi-cStSQI6C.mjs → useDiscountCodeUi-DCccGCxV.mjs} +1 -1
  166. package/dist/client/{useEventFilters-DKPN7hSY.mjs → useEventFilters-eGs3rPZQ.mjs} +3 -104
  167. package/dist/client/{usePolling-BKAd6pkZ.mjs → usePolling-CvSU2sur.mjs} +2 -2
  168. package/dist/preview-next/before-render.mjs +57 -0
  169. package/dist/preview-next/client/runtime.mjs +4 -4
  170. package/dist/preview-next/middleware.mjs +57 -0
  171. package/dist/{previewAuthStore-BkT1D06A.mjs → previewAuthStore-DN7vcRsv.mjs} +57 -0
  172. package/dist/{sdk-runtime-hu3wr3ng.mjs → sdk-runtime-DaOiA7ct.mjs} +2 -2
  173. package/dist/{separator-Bln8izQ9.mjs → separator-CqRhcCxD.mjs} +1 -1
  174. package/dist/server/components.mjs +4092 -4108
  175. package/dist/server/config-template-validation.mjs +4 -23
  176. package/dist/server/config-validation.mjs +373 -555
  177. package/dist/server/config.mjs +410 -558
  178. package/dist/server/data.mjs +373 -555
  179. package/dist/server/index.mjs +58 -1
  180. package/dist/server/next.mjs +32958 -32926
  181. package/dist/server/page-converter.mjs +369 -526
  182. package/dist/server/prebuild.mjs +1 -1
  183. package/dist/server/rendering/server.mjs +5371 -3174
  184. package/dist/server/rendering.mjs +4099 -4124
  185. package/dist/server/routing.mjs +758 -966
  186. package/dist/server/server.mjs +448 -632
  187. package/dist/server/theme-bridge.mjs +472 -525
  188. package/dist/server/theme.mjs +1074 -392
  189. package/package.json +1 -1
  190. package/dist/_dts/blocks/src/primitives/content/components/Button.d.ts +0 -40
  191. package/dist/_dts/blocks/src/system/fragments/library/footerBottomText.d.ts +0 -19
  192. package/dist/_dts/media-core/src/legacyMediaValue.d.ts +0 -11
  193. package/dist/_dts/theme-core/src/styles/buttons.d.ts +0 -27
  194. package/dist/_dts/theme-core/src/styles/buttonsLibrary.d.ts +0 -2
  195. package/dist/_dts/theme-core/src/styles/glow.d.ts +0 -3
  196. package/dist/client/colorStyles-gcTh5yZT.mjs +0 -89
@@ -7329,111 +7329,6 @@ function useAppointmentCheckoutVerificationWithDeps(config, deps) {
7329
7329
  };
7330
7330
  }
7331
7331
  //#endregion
7332
- //#region ../theme-core/src/buttons/effectClassification.ts
7333
- /**
7334
- * Exhaustive live policy for every registered effect id.
7335
- *
7336
- * The resolver consumes the transition payload directly, so adding an effect
7337
- * cannot update classification without also defining its runtime behavior.
7338
- */
7339
- const BUTTON_EFFECT_POLICIES = {
7340
- "darken-background": {
7341
- classification: "colour-transition",
7342
- transition: {
7343
- kind: "adjust-shade",
7344
- direction: "darker"
7345
- }
7346
- },
7347
- "lighten-background": {
7348
- classification: "colour-transition",
7349
- transition: {
7350
- kind: "adjust-shade",
7351
- direction: "lighter"
7352
- }
7353
- },
7354
- "background-on-hover": {
7355
- classification: "colour-transition",
7356
- transition: { kind: "replace-background" }
7357
- },
7358
- "background-on-hover-alpha": {
7359
- classification: "unsupported-colour",
7360
- reason: "alpha_requires_surface"
7361
- },
7362
- "fade-background": {
7363
- classification: "unsupported-colour",
7364
- reason: "changes_element_opacity"
7365
- },
7366
- "opacity-reduce": {
7367
- classification: "unsupported-colour",
7368
- reason: "changes_element_opacity"
7369
- },
7370
- "gradient-text": {
7371
- classification: "unsupported-colour",
7372
- reason: "changes_foreground"
7373
- },
7374
- "text-color-change": {
7375
- classification: "unsupported-colour",
7376
- reason: "changes_foreground"
7377
- },
7378
- "border-color-change": {
7379
- classification: "unsupported-colour",
7380
- reason: "changes_border"
7381
- },
7382
- "aurora-glow": {
7383
- classification: "unsupported-background-overlay",
7384
- reason: "unresolved_background_overlay"
7385
- },
7386
- "cosmic-stardust": {
7387
- classification: "unsupported-background-overlay",
7388
- reason: "unresolved_background_overlay"
7389
- },
7390
- "gradient-border-fill": {
7391
- classification: "unsupported-background-overlay",
7392
- reason: "unresolved_background_overlay"
7393
- },
7394
- "animated-gradient-border-fill": {
7395
- classification: "unsupported-background-overlay",
7396
- reason: "unresolved_background_overlay"
7397
- },
7398
- "nav-underline": {
7399
- classification: "not-button",
7400
- reason: "not_button_effect"
7401
- },
7402
- "nav-frosted-base": {
7403
- classification: "not-button",
7404
- reason: "not_button_effect"
7405
- },
7406
- "nav-frosted-hover": {
7407
- classification: "not-button",
7408
- reason: "not_button_effect"
7409
- },
7410
- "nav-frosted-active": {
7411
- classification: "not-button",
7412
- reason: "not_button_effect"
7413
- },
7414
- "animated-gradient": { classification: "non-colour" },
7415
- "border-glow": { classification: "non-colour" },
7416
- "drop-shadow": { classification: "non-colour" },
7417
- "inner-shadow": { classification: "non-colour" },
7418
- "neumorphic-shadow": { classification: "non-colour" },
7419
- "outer-glow": { classification: "non-colour" },
7420
- "retro-3d-shadow": { classification: "non-colour" },
7421
- "scale-up": { classification: "non-colour" },
7422
- "scale-down": { classification: "non-colour" },
7423
- lift: { classification: "non-colour" },
7424
- "press-down": { classification: "non-colour" },
7425
- pop: { classification: "non-colour" },
7426
- "border-bottom-grow": { classification: "non-colour" },
7427
- "sketchy-border": { classification: "non-colour" },
7428
- "pulse-animation": { classification: "non-colour" }
7429
- };
7430
- function getButtonEffectPolicy(effectId) {
7431
- return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
7432
- }
7433
- function classifyButtonEffectId(effectId) {
7434
- return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
7435
- }
7436
- //#endregion
7437
7332
  //#region ../theme-core/src/tokens/colorTokenParts.ts
7438
7333
  function parseOpacityPercent(source) {
7439
7334
  const trimmed = source.trim();
@@ -7587,6 +7482,13 @@ const VARIANT_ROLES = [
7587
7482
  "tertiary",
7588
7483
  "accent"
7589
7484
  ];
7485
+ /**
7486
+ * Canonical persisted/CSS-safe button variant identifier.
7487
+ *
7488
+ * IDs become class selectors, so keep the contract deliberately narrower than
7489
+ * an arbitrary string and shared with every authoring/runtime boundary.
7490
+ */
7491
+ const buttonVariantIdSchema = z$1.string().min(1).max(50).regex(/^[a-z0-9-]+$/, "Button variant IDs may contain lowercase letters, numbers, and hyphens only");
7590
7492
  function parseOpaqueButtonColourToken(value) {
7591
7493
  const token = parseThemeColorToken(value);
7592
7494
  if (token === null) return null;
@@ -7601,6 +7503,109 @@ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => pa
7601
7503
  if (token === null) throw new Error("Invariant: opaque button token passed its schema");
7602
7504
  return token;
7603
7505
  });
7506
+ const buttonShadeAmountSchema = z$1.number().finite().min(0).max(900).multipleOf(100);
7507
+ const buttonShadowIntensitySchema = z$1.enum([
7508
+ "subtle",
7509
+ "medium",
7510
+ "strong"
7511
+ ]);
7512
+ /**
7513
+ * The complete persisted button-effect contract.
7514
+ *
7515
+ * Navigation has its own generic interactive-effect model. Button variants use
7516
+ * this closed union so unsupported effect IDs, unknown option keys, and unsafe
7517
+ * CSS values cannot become representable after the schema boundary.
7518
+ */
7519
+ const buttonEffectApplicationSchema = z$1.discriminatedUnion("effectId", [
7520
+ z$1.strictObject({
7521
+ effectId: z$1.literal("darken-background"),
7522
+ options: z$1.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
7523
+ }),
7524
+ z$1.strictObject({
7525
+ effectId: z$1.literal("lighten-background"),
7526
+ options: z$1.strictObject({ amount: buttonShadeAmountSchema.optional() }).optional()
7527
+ }),
7528
+ z$1.strictObject({
7529
+ effectId: z$1.literal("background-on-hover"),
7530
+ options: z$1.strictObject({ colorToken: opaqueButtonColourTokenSchema.optional() }).optional()
7531
+ }),
7532
+ z$1.strictObject({
7533
+ effectId: z$1.literal("animated-gradient"),
7534
+ options: z$1.strictObject({ direction: z$1.enum(["horizontal", "vertical"]).optional() }).optional()
7535
+ }),
7536
+ z$1.strictObject({
7537
+ effectId: z$1.literal("drop-shadow"),
7538
+ options: z$1.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
7539
+ }),
7540
+ z$1.strictObject({
7541
+ effectId: z$1.literal("inner-shadow"),
7542
+ options: z$1.strictObject({}).optional()
7543
+ }),
7544
+ z$1.strictObject({
7545
+ effectId: z$1.literal("neumorphic-shadow"),
7546
+ options: z$1.strictObject({
7547
+ mode: z$1.enum(["raised", "pressed"]).optional(),
7548
+ intensity: buttonShadowIntensitySchema.optional()
7549
+ }).optional()
7550
+ }),
7551
+ z$1.strictObject({
7552
+ effectId: z$1.literal("retro-3d-shadow"),
7553
+ options: z$1.strictObject({}).optional()
7554
+ }),
7555
+ z$1.strictObject({
7556
+ effectId: z$1.literal("scale-up"),
7557
+ options: z$1.strictObject({ scale: z$1.enum([
7558
+ "1.02",
7559
+ "1.03",
7560
+ "1.05",
7561
+ "1.10"
7562
+ ]).optional() }).optional()
7563
+ }),
7564
+ z$1.strictObject({
7565
+ effectId: z$1.literal("scale-down"),
7566
+ options: z$1.strictObject({ scale: z$1.enum([
7567
+ "0.90",
7568
+ "0.95",
7569
+ "0.97",
7570
+ "0.98"
7571
+ ]).optional() }).optional()
7572
+ }),
7573
+ z$1.strictObject({
7574
+ effectId: z$1.literal("lift"),
7575
+ options: z$1.strictObject({ amount: z$1.enum([
7576
+ "0.25",
7577
+ "0.5",
7578
+ "1"
7579
+ ]).optional() }).optional()
7580
+ }),
7581
+ z$1.strictObject({
7582
+ effectId: z$1.literal("press-down"),
7583
+ options: z$1.strictObject({}).optional()
7584
+ }),
7585
+ z$1.strictObject({
7586
+ effectId: z$1.literal("pop"),
7587
+ options: z$1.strictObject({ intensity: z$1.enum([
7588
+ "subtle",
7589
+ "medium",
7590
+ "dramatic"
7591
+ ]).optional() }).optional()
7592
+ }),
7593
+ z$1.strictObject({
7594
+ effectId: z$1.literal("border-bottom-grow"),
7595
+ options: z$1.strictObject({
7596
+ height: z$1.union([z$1.literal(1), z$1.literal(2)]).optional(),
7597
+ origin: z$1.enum([
7598
+ "left",
7599
+ "center",
7600
+ "right"
7601
+ ]).optional()
7602
+ }).optional()
7603
+ }),
7604
+ z$1.strictObject({
7605
+ effectId: z$1.literal("sketchy-border"),
7606
+ options: z$1.strictObject({ intensity: buttonShadowIntensitySchema.optional() }).optional()
7607
+ })
7608
+ ]);
7604
7609
  const cornerStyleSchema = z$1.enum([
7605
7610
  "square",
7606
7611
  "rounded",
@@ -7618,372 +7623,2080 @@ const textTransformSchema = z$1.enum([
7618
7623
  "lowercase",
7619
7624
  "capitalize"
7620
7625
  ]);
7621
- const fontWeightSchema = z$1.union([
7622
- z$1.literal(500),
7623
- z$1.literal(600),
7624
- z$1.literal(700)
7626
+ const fontWeightSchema = z$1.union([
7627
+ z$1.literal(500),
7628
+ z$1.literal(600),
7629
+ z$1.literal(700)
7630
+ ]);
7631
+ const buttonTypographySchema = z$1.enum(["body", "heading"]);
7632
+ const letterSpacingSchema = z$1.enum([
7633
+ "tight",
7634
+ "normal",
7635
+ "loose"
7636
+ ]);
7637
+ const hoverTransformSchema = z$1.enum([
7638
+ "none",
7639
+ "lift",
7640
+ "scale",
7641
+ "press"
7642
+ ]);
7643
+ z$1.enum(["none", "token"]);
7644
+ const buttonPaddingPresetSchema = z$1.enum([
7645
+ "compact",
7646
+ "default",
7647
+ "spacious"
7648
+ ]);
7649
+ const gradientStyleSchema = z$1.enum([
7650
+ "linear",
7651
+ "radial",
7652
+ "conic"
7653
+ ]);
7654
+ const gradientSharpnessSchema = z$1.enum([
7655
+ "smooth",
7656
+ "medium",
7657
+ "hard"
7658
+ ]);
7659
+ const prioritySchema = z$1.union([
7660
+ z$1.literal(1),
7661
+ z$1.literal(2),
7662
+ z$1.literal(3)
7663
+ ]);
7664
+ z$1.enum(VARIANT_ROLES);
7665
+ const buttonSizeNameSchema = z$1.enum([
7666
+ "sm",
7667
+ "md",
7668
+ "lg",
7669
+ "xl"
7670
+ ]);
7671
+ /**
7672
+ * CSS padding string in `"<vertical> <horizontal>"` shorthand form.
7673
+ *
7674
+ * Exactly two space-separated CSS length tokens. Each token is either the
7675
+ * literal `0` or a number followed by `rem`/`em`/`px`/`%`. This lets the
7676
+ * generator trust the shape rather than defensively defaulting downstream.
7677
+ */
7678
+ const PADDING_TOKEN_PATTERN = /^(?:0|\d+(?:\.\d+)?(?:rem|em|px|%))$/;
7679
+ const paddingShorthandSchema = z$1.string().refine((value) => {
7680
+ const parts = value.split(/\s+/).filter(Boolean);
7681
+ return parts.length === 2 && parts.every((token) => PADDING_TOKEN_PATTERN.test(token));
7682
+ }, { message: "Padding must be two space-separated CSS length tokens (e.g. \"0.5rem 1rem\"). Use `0` for zero." });
7683
+ const buttonSizeConfigSchema = z$1.object({
7684
+ padding: paddingShorthandSchema,
7685
+ fontSize: z$1.string().optional()
7686
+ });
7687
+ /**
7688
+ * `xl` is optional on the wire so themes persisted before the `xl` size was
7689
+ * added (e.g. SWTS) continue to parse. When `xl` is missing the schema
7690
+ * backfills it from `lg`, keeping `ButtonSizes` a complete `sm/md/lg/xl` map
7691
+ * downstream — generators never need to deal with an undefined `xl`.
7692
+ */
7693
+ const buttonSizesSchema = z$1.object({
7694
+ sm: buttonSizeConfigSchema,
7695
+ md: buttonSizeConfigSchema,
7696
+ lg: buttonSizeConfigSchema,
7697
+ xl: buttonSizeConfigSchema.optional()
7698
+ }).transform(({ sm, md, lg, xl }) => ({
7699
+ sm,
7700
+ md,
7701
+ lg,
7702
+ xl: xl ?? lg
7703
+ }));
7704
+ const buttonGlobalSettingsBaseSchema = z$1.strictObject({
7705
+ cornerStyle: cornerStyleSchema,
7706
+ cornerRadius: z$1.number().min(0).max(24).optional(),
7707
+ /**
7708
+ * Family-level shadow inherited by variants that don't set their own.
7709
+ * Optional and flat-by-default: when omitted, buttons carry no drop shadow
7710
+ * (`elevation: 'none'`). A personality opts the whole family into a shadow by
7711
+ * setting this; individual variants still override. There is no system-level
7712
+ * shadow-by-default — shadows only appear when explicitly declared.
7713
+ */
7714
+ shadow: shadowSizeSchema.optional(),
7715
+ textTransform: textTransformSchema,
7716
+ fontWeight: fontWeightSchema,
7717
+ typography: buttonTypographySchema.optional(),
7718
+ fontSize: z$1.string().optional(),
7719
+ letterSpacing: letterSpacingSchema.optional(),
7720
+ italic: z$1.boolean().optional(),
7721
+ paddingPreset: buttonPaddingPresetSchema.optional(),
7722
+ hoverTransform: hoverTransformSchema,
7723
+ gradientStyle: gradientStyleSchema.optional(),
7724
+ gradientAngle: z$1.number().min(0).max(360).optional(),
7725
+ gradientSharpness: gradientSharpnessSchema.optional()
7726
+ });
7727
+ const buttonGlobalSettingsSchema = z$1.discriminatedUnion("hoverColor", [buttonGlobalSettingsBaseSchema.extend({
7728
+ hoverColor: z$1.literal("none"),
7729
+ hoverColorToken: z$1.never().optional()
7730
+ }), buttonGlobalSettingsBaseSchema.extend({
7731
+ hoverColor: z$1.literal("token"),
7732
+ hoverColorToken: opaqueButtonColourTokenSchema
7733
+ })]);
7734
+ const gradientDirectionSchema$1 = z$1.enum([
7735
+ "to-r",
7736
+ "to-l",
7737
+ "to-t",
7738
+ "to-b",
7739
+ "to-tr",
7740
+ "to-tl",
7741
+ "to-br",
7742
+ "to-bl"
7743
+ ]);
7744
+ const buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
7745
+ z$1.strictObject({
7746
+ type: z$1.literal("solid"),
7747
+ colorToken: opaqueButtonColourTokenSchema
7748
+ }),
7749
+ z$1.strictObject({
7750
+ type: z$1.literal("gradient"),
7751
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
7752
+ const [first, second, ...rest] = stops;
7753
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
7754
+ return [
7755
+ first,
7756
+ second,
7757
+ ...rest
7758
+ ];
7759
+ }),
7760
+ direction: gradientDirectionSchema$1,
7761
+ foregroundToken: opaqueButtonColourTokenSchema
7762
+ }),
7763
+ z$1.strictObject({
7764
+ type: z$1.literal("surface"),
7765
+ role: z$1.literal("link")
7766
+ })
7767
+ ]);
7768
+ const buttonBackgroundSchema = buttonColourTreatmentSchema;
7769
+ const buttonBorderSchema = z$1.strictObject({ widthClass: z$1.string() });
7770
+ const buttonVariantAffordanceSchema = z$1.strictObject({ iconId: z$1.string().min(1) });
7771
+ const variantShadowSchema = z$1.strictObject({
7772
+ elevation: z$1.enum([
7773
+ "none",
7774
+ "low",
7775
+ "medium",
7776
+ "high"
7777
+ ]),
7778
+ softness: z$1.enum([
7779
+ "crisp",
7780
+ "soft",
7781
+ "hard"
7782
+ ]).nullable(),
7783
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
7784
+ colorToken: opaqueButtonColourTokenSchema.optional()
7785
+ });
7786
+ const variantEffectsSchema = z$1.strictObject({
7787
+ base: z$1.array(buttonEffectApplicationSchema).optional(),
7788
+ hover: z$1.array(buttonEffectApplicationSchema).optional(),
7789
+ active: z$1.array(buttonEffectApplicationSchema).optional(),
7790
+ focus: z$1.array(buttonEffectApplicationSchema).optional()
7791
+ });
7792
+ /**
7793
+ * Per-variant size overrides schema — every entry is optional.
7794
+ *
7795
+ * For each size key present, the values override the theme's `sizes` config
7796
+ * for that size on this variant. Missing sizes fall through to theme.sizes,
7797
+ * then system defaults.
7798
+ */
7799
+ const variantSizeOverridesSchema = z$1.object({
7800
+ sm: buttonSizeConfigSchema.optional(),
7801
+ md: buttonSizeConfigSchema.optional(),
7802
+ lg: buttonSizeConfigSchema.optional(),
7803
+ xl: buttonSizeConfigSchema.optional()
7804
+ });
7805
+ /**
7806
+ * Unified variant schema. Every variant participates in the size system; the
7807
+ * optional `sizes` field lets a variant scale differently than the theme
7808
+ * default (e.g. link-style variants declaring zero horizontal padding at
7809
+ * every size).
7810
+ */
7811
+ const buttonVariantSchema = z$1.strictObject({
7812
+ id: buttonVariantIdSchema,
7813
+ name: z$1.string().min(1).max(20),
7814
+ enabled: z$1.boolean(),
7815
+ priority: prioritySchema,
7816
+ background: buttonBackgroundSchema,
7817
+ /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
7818
+ borderRadius: z$1.string().optional(),
7819
+ shadow: variantShadowSchema.optional(),
7820
+ border: buttonBorderSchema.optional(),
7821
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
7822
+ effects: variantEffectsSchema.optional(),
7823
+ sizes: variantSizeOverridesSchema.optional(),
7824
+ affordance: buttonVariantAffordanceSchema.optional()
7825
+ });
7826
+ const buttonSystemSchema = z$1.strictObject({
7827
+ global: buttonGlobalSettingsSchema,
7828
+ variants: z$1.array(buttonVariantSchema).min(1).max(6),
7829
+ sizes: buttonSizesSchema.optional()
7830
+ }).superRefine((system, ctx) => {
7831
+ const seen = /* @__PURE__ */ new Set();
7832
+ system.variants.forEach((variant, index) => {
7833
+ if (seen.has(variant.id)) ctx.addIssue({
7834
+ code: "custom",
7835
+ path: [
7836
+ "variants",
7837
+ index,
7838
+ "id"
7839
+ ],
7840
+ message: `Duplicate button variant ID: ${variant.id}`
7841
+ });
7842
+ seen.add(variant.id);
7843
+ });
7844
+ });
7845
+ //#endregion
7846
+ //#region ../theme-core/src/lib/media.ts
7847
+ const hotspotSchema$1 = z.object({
7848
+ x: z.number().min(0).max(1),
7849
+ y: z.number().min(0).max(1),
7850
+ radius: z.number().optional()
7851
+ });
7852
+ const rotationSchema$1 = z.union([
7853
+ z.literal(0),
7854
+ z.literal(90),
7855
+ z.literal(180),
7856
+ z.literal(270)
7857
+ ]);
7858
+ const rectSchema$1 = z.tuple([
7859
+ z.number(),
7860
+ z.number(),
7861
+ z.number(),
7862
+ z.number()
7863
+ ]);
7864
+ const aspectCropSchema$1 = z.object({
7865
+ aspect: z.preprocess((value) => value == null ? void 0 : value, z.string().optional()),
7866
+ rect: z.preprocess((value) => value == null ? void 0 : value, rectSchema$1.optional()),
7867
+ hotspot: z.preprocess((value) => value == null ? void 0 : value, hotspotSchema$1.optional()),
7868
+ rotation: z.preprocess((value) => value == null ? void 0 : value, rotationSchema$1.optional())
7869
+ });
7870
+ const transformSchema$1 = z.object({
7871
+ aspectCrops: z.preprocess((value) => {
7872
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
7873
+ return value;
7874
+ }, z.record(z.string(), aspectCropSchema$1.catch({}))).optional(),
7875
+ rect: rectSchema$1.optional(),
7876
+ hotspot: hotspotSchema$1.optional(),
7877
+ rotation: rotationSchema$1.optional()
7878
+ });
7879
+ const mediaSchema$1 = z.object({
7880
+ type: z.enum([
7881
+ "image",
7882
+ "video",
7883
+ "audio",
7884
+ "document",
7885
+ "spreadsheet",
7886
+ "archive"
7887
+ ]),
7888
+ purpose: z.string().optional(),
7889
+ placeholder: z.boolean().default(true).optional(),
7890
+ assetId: z.string().optional(),
7891
+ identifier: z.string().optional(),
7892
+ src: z.string().optional(),
7893
+ alt: z.string().optional(),
7894
+ filename: z.string().optional(),
7895
+ mimeType: z.string().optional(),
7896
+ width: z.number().optional(),
7897
+ height: z.number().optional(),
7898
+ storageBucket: z.string().optional(),
7899
+ storagePath: z.string().optional(),
7900
+ transform: transformSchema$1.optional()
7901
+ });
7902
+ //#endregion
7903
+ //#region ../theme-core/src/cards/types.ts
7904
+ const cardVariantRoleValues = ["default", "alternative"];
7905
+ const boxlessCardVariantValue = "none";
7906
+ const cardSpacingSchema = z$1.enum([
7907
+ "none",
7908
+ "compact",
7909
+ "cozy",
7910
+ "medium",
7911
+ "comfortable",
7912
+ "spacious"
7913
+ ]);
7914
+ const gradientDirectionSchema = z$1.enum([
7915
+ "to-r",
7916
+ "to-l",
7917
+ "to-t",
7918
+ "to-b",
7919
+ "to-tr",
7920
+ "to-tl",
7921
+ "to-br",
7922
+ "to-bl"
7923
+ ]);
7924
+ z$1.enum(cardVariantRoleValues);
7925
+ const boxStylesCardVariantSchema = z$1.enum([...cardVariantRoleValues, boxlessCardVariantValue]);
7926
+ const cardBackgroundSchema = z$1.discriminatedUnion("type", [
7927
+ z$1.object({
7928
+ type: z$1.literal("solid"),
7929
+ colorToken: themeColorTokenSchema
7930
+ }),
7931
+ z$1.object({
7932
+ type: z$1.literal("gradient"),
7933
+ fromToken: themeColorTokenSchema,
7934
+ toToken: themeColorTokenSchema,
7935
+ direction: gradientDirectionSchema
7936
+ }),
7937
+ z$1.object({ type: z$1.literal("transparent") })
7938
+ ]);
7939
+ const cardBorderSchema = z$1.object({
7940
+ widthClass: z$1.string(),
7941
+ colorToken: themeColorTokenSchema
7942
+ });
7943
+ /** Per-corner radius value. `expressive` is a large block-radius multiple. */
7944
+ const cardCornerValueSchema = z$1.enum([
7945
+ "square",
7946
+ "soft",
7947
+ "rounded",
7948
+ "pill",
7949
+ "expressive"
7950
+ ]);
7951
+ /**
7952
+ * A single accented card edge (e.g. a left accent bar). When set, it replaces
7953
+ * the full `border` so the card reads as edge-accented rather than outlined.
7954
+ */
7955
+ const cardAccentEdgeSchema = z$1.object({
7956
+ edge: z$1.enum([
7957
+ "left",
7958
+ "top",
7959
+ "right",
7960
+ "bottom"
7961
+ ]),
7962
+ colorToken: themeColorTokenSchema,
7963
+ width: z$1.enum([
7964
+ "thin",
7965
+ "medium",
7966
+ "thick",
7967
+ "heavy"
7968
+ ])
7969
+ });
7970
+ const cardCornerRadiiSchema = z$1.object({
7971
+ topLeft: cardCornerValueSchema.optional(),
7972
+ topRight: cardCornerValueSchema.optional(),
7973
+ bottomLeft: cardCornerValueSchema.optional(),
7974
+ bottomRight: cardCornerValueSchema.optional()
7975
+ });
7976
+ const cardVariantSchema = z$1.object({
7977
+ id: z$1.string(),
7978
+ name: z$1.string().min(1).max(20),
7979
+ enabled: z$1.boolean(),
7980
+ priority: z$1.union([
7981
+ z$1.literal(1),
7982
+ z$1.literal(2),
7983
+ z$1.literal(3)
7984
+ ]),
7985
+ background: cardBackgroundSchema,
7986
+ spacing: cardSpacingSchema,
7987
+ foregroundToken: themeColorTokenSchema.optional(),
7988
+ shadow: z$1.object({
7989
+ elevation: z$1.enum([
7990
+ "none",
7991
+ "low",
7992
+ "medium",
7993
+ "high"
7994
+ ]),
7995
+ softness: z$1.enum([
7996
+ "crisp",
7997
+ "soft",
7998
+ "hard"
7999
+ ]).nullable(),
8000
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom")
8001
+ }).optional(),
8002
+ corners: z$1.enum([
8003
+ "square",
8004
+ "soft",
8005
+ "rounded",
8006
+ "pill"
8007
+ ]).optional(),
8008
+ cornerRadii: cardCornerRadiiSchema.optional(),
8009
+ border: cardBorderSchema.optional(),
8010
+ accentEdge: cardAccentEdgeSchema.optional()
8011
+ });
8012
+ const cardSystemSchema = z$1.object({ variants: z$1.array(cardVariantSchema).min(1).max(3) });
8013
+ //#endregion
8014
+ //#region ../theme-core/src/accordions/types.ts
8015
+ /**
8016
+ * Accordion icon styles for expand/collapse indicators
8017
+ */
8018
+ const accordionIconSchema = z$1.enum([
8019
+ "plus-minus",
8020
+ "chevron",
8021
+ "caret",
8022
+ "arrow",
8023
+ "circle-plus-minus"
8024
+ ]);
8025
+ /**
8026
+ * Accordion configuration for a theme
8027
+ * Single style per theme (no variants needed)
8028
+ */
8029
+ const accordionSystemSchema = z$1.object({
8030
+ background: z$1.object({
8031
+ type: z$1.literal("solid"),
8032
+ colorToken: themeColorTokenSchema
8033
+ }).nullable(),
8034
+ spacing: z$1.enum([
8035
+ "none",
8036
+ "compact",
8037
+ "cozy",
8038
+ "medium",
8039
+ "comfortable",
8040
+ "spacious"
8041
+ ]),
8042
+ corners: z$1.enum([
8043
+ "square",
8044
+ "soft",
8045
+ "rounded",
8046
+ "pill"
8047
+ ]).nullable(),
8048
+ border: z$1.object({
8049
+ widthClass: z$1.string(),
8050
+ colorToken: themeColorTokenSchema
8051
+ }).nullable(),
8052
+ shadow: z$1.object({
8053
+ elevation: z$1.enum([
8054
+ "none",
8055
+ "low",
8056
+ "medium",
8057
+ "high"
8058
+ ]),
8059
+ softness: z$1.enum([
8060
+ "soft",
8061
+ "crisp",
8062
+ "hard"
8063
+ ]).nullable(),
8064
+ position: z$1.enum(["bottom", "bottom-right"])
8065
+ }).nullable(),
8066
+ icon: z$1.object({
8067
+ style: accordionIconSchema,
8068
+ position: z$1.enum(["left", "right"]),
8069
+ size: z$1.enum([
8070
+ "sm",
8071
+ "md",
8072
+ "lg"
8073
+ ]),
8074
+ colorToken: themeColorTokenSchema.optional()
8075
+ }),
8076
+ trigger: z$1.object({
8077
+ textColorToken: themeColorTokenSchema,
8078
+ fontWeight: z$1.enum([
8079
+ "regular",
8080
+ "medium",
8081
+ "semibold",
8082
+ "bold"
8083
+ ]).nullable(),
8084
+ fontFamily: z$1.enum(["body", "heading"]).optional(),
8085
+ fontScale: z$1.enum([
8086
+ "body",
8087
+ "md",
8088
+ "lg"
8089
+ ]).optional(),
8090
+ letterSpacing: z$1.enum([
8091
+ "normal",
8092
+ "tight",
8093
+ "wide"
8094
+ ]).optional(),
8095
+ textTransform: z$1.enum(["none", "uppercase"]).optional()
8096
+ }),
8097
+ hover: z$1.object({
8098
+ backgroundColorToken: themeColorTokenSchema.optional(),
8099
+ textColorToken: themeColorTokenSchema.optional(),
8100
+ borderColorToken: themeColorTokenSchema.optional()
8101
+ }),
8102
+ openState: z$1.object({
8103
+ backgroundColorToken: themeColorTokenSchema.optional(),
8104
+ triggerColorToken: themeColorTokenSchema.optional(),
8105
+ accent: z$1.object({
8106
+ edge: z$1.enum([
8107
+ "left",
8108
+ "top",
8109
+ "bottom"
8110
+ ]),
8111
+ colorToken: themeColorTokenSchema,
8112
+ thickness: z$1.enum([
8113
+ "thin",
8114
+ "medium",
8115
+ "thick"
8116
+ ])
8117
+ }).optional()
8118
+ }).optional(),
8119
+ content: z$1.object({ textColorToken: themeColorTokenSchema })
8120
+ });
8121
+ //#endregion
8122
+ //#region ../theme-core/src/inputs/types.ts
8123
+ /**
8124
+ * Input styling configuration for a theme
8125
+ *
8126
+ * Provides comprehensive control over form input appearance including:
8127
+ * - Base styling (background, borders, spacing)
8128
+ * - Label styling
8129
+ * - Focus, error, and disabled states
8130
+ *
8131
+ * Single configuration per theme (no variants needed for inputs)
8132
+ */
8133
+ const inputSystemSchema = z$1.object({
8134
+ base: z$1.object({
8135
+ background: z$1.union([z$1.object({
8136
+ type: z$1.literal("solid"),
8137
+ colorToken: themeColorTokenSchema
8138
+ }), z$1.object({ type: z$1.literal("transparent") })]),
8139
+ textColorToken: themeColorTokenSchema,
8140
+ border: z$1.object({
8141
+ widthClass: z$1.string(),
8142
+ colorToken: themeColorTokenSchema,
8143
+ style: z$1.enum(["all", "underline"]).optional()
8144
+ }),
8145
+ corners: z$1.enum([
8146
+ "square",
8147
+ "soft",
8148
+ "rounded",
8149
+ "pill"
8150
+ ]).nullable(),
8151
+ shadow: z$1.object({
8152
+ elevation: z$1.enum([
8153
+ "none",
8154
+ "low",
8155
+ "medium"
8156
+ ]),
8157
+ softness: z$1.enum([
8158
+ "soft",
8159
+ "crisp",
8160
+ "hard"
8161
+ ]).nullable()
8162
+ }).nullable(),
8163
+ spacing: z$1.enum([
8164
+ "compact",
8165
+ "cozy",
8166
+ "medium",
8167
+ "comfortable"
8168
+ ]),
8169
+ fontSize: z$1.enum([
8170
+ "sm",
8171
+ "base",
8172
+ "lg"
8173
+ ])
8174
+ }),
8175
+ label: z$1.object({
8176
+ textColorToken: themeColorTokenSchema,
8177
+ fontWeight: z$1.enum([
8178
+ "regular",
8179
+ "medium",
8180
+ "semibold",
8181
+ "bold",
8182
+ "black"
8183
+ ]),
8184
+ fontSize: z$1.enum([
8185
+ "2xs",
8186
+ "xs",
8187
+ "sm",
8188
+ "base"
8189
+ ]),
8190
+ textTransform: z$1.enum([
8191
+ "none",
8192
+ "uppercase",
8193
+ "lowercase",
8194
+ "capitalize"
8195
+ ]).optional(),
8196
+ letterSpacing: z$1.enum([
8197
+ "normal",
8198
+ "wide",
8199
+ "wider",
8200
+ "widest"
8201
+ ]).optional(),
8202
+ opacity: z$1.number().min(.2).max(1).optional()
8203
+ }),
8204
+ focus: z$1.object({
8205
+ ringColorToken: themeColorTokenSchema,
8206
+ ringWidth: z$1.enum([
8207
+ "0",
8208
+ "1",
8209
+ "2",
8210
+ "3"
8211
+ ]),
8212
+ borderColorToken: themeColorTokenSchema.optional()
8213
+ }),
8214
+ error: z$1.object({
8215
+ borderColorToken: themeColorTokenSchema,
8216
+ textColorToken: themeColorTokenSchema
8217
+ }),
8218
+ disabled: z$1.object({
8219
+ backgroundColorToken: themeColorTokenSchema,
8220
+ textColorToken: themeColorTokenSchema,
8221
+ opacity: z$1.number().min(.3).max(.7)
8222
+ })
8223
+ });
8224
+ //#endregion
8225
+ //#region ../theme-core/src/gradients/types.ts
8226
+ /**
8227
+ * Gradient configuration types and schemas
8228
+ */
8229
+ /**
8230
+ * Gradient color stop
8231
+ */
8232
+ const gradientStopSchema = z$1.object({
8233
+ color: themeColorTokenSchema,
8234
+ position: z$1.number().min(0).max(100)
8235
+ });
8236
+ /**
8237
+ * Radial gradient shape. Optional; defaults to `circle` (the historical shape)
8238
+ * so existing radial gradients are byte-identical.
8239
+ *
8240
+ * Named `RadialGradientShape` to avoid clashing with `styles/gradients.ts`'s
8241
+ * `GradientShape` (which names the gradient *kind*: linear/radial/conic).
8242
+ */
8243
+ const radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
8244
+ /**
8245
+ * Gradient configuration.
8246
+ *
8247
+ * `type` is optional and defaults to `'linear'` so gradients persisted without a
8248
+ * type (or with an explicit `'linear'`) render exactly as before. `'radial'` and
8249
+ * `'conic'` are additive kinds:
8250
+ * - linear: `angle` (degrees)
8251
+ * - radial: optional `shape` (circle/ellipse) + `position`
8252
+ * - conic: optional `angle` (from-angle, degrees) + `position`
8253
+ */
8254
+ const gradientConfigSchema = z$1.object({
8255
+ type: z$1.enum([
8256
+ "linear",
8257
+ "radial",
8258
+ "conic"
8259
+ ]).default("linear"),
8260
+ angle: z$1.number().min(0).max(360).optional(),
8261
+ shape: radialGradientShapeSchema.optional(),
8262
+ position: z$1.string().optional(),
8263
+ stops: z$1.array(gradientStopSchema).min(2)
8264
+ });
8265
+ //#endregion
8266
+ //#region ../theme-core/src/interactive/baseSchema.ts
8267
+ /**
8268
+ * Shared Base Schemas for Interactive Elements
8269
+ *
8270
+ * These Zod schemas are shared by buttons and nav links for DRY architecture.
8271
+ */
8272
+ /**
8273
+ * Typography settings shared by buttons and nav links
8274
+ */
8275
+ const interactiveTypographySchema = z$1.object({
8276
+ /** Font family source */
8277
+ typography: z$1.enum(["body", "heading"]).default("body"),
8278
+ /** Font weight */
8279
+ fontWeight: z$1.enum([
8280
+ "regular",
8281
+ "medium",
8282
+ "semibold",
8283
+ "bold"
8284
+ ]).default("medium"),
8285
+ /** Text transform */
8286
+ textTransform: z$1.enum([
8287
+ "none",
8288
+ "uppercase",
8289
+ "capitalize"
8290
+ ]).default("none"),
8291
+ /** Italic style */
8292
+ italic: z$1.boolean().default(false)
8293
+ });
8294
+ /**
8295
+ * Effect application reference (shared between buttons and nav)
8296
+ */
8297
+ const effectApplicationSchema = z$1.object({
8298
+ /** Effect preset ID */
8299
+ effectId: z$1.string(),
8300
+ /** User-provided customization options */
8301
+ options: z$1.record(z$1.string(), z$1.any()).optional()
8302
+ });
8303
+ /**
8304
+ * Effect composition by state (shared pattern)
8305
+ */
8306
+ const effectCompositionSchema = z$1.object({
8307
+ /** Effects always applied */
8308
+ base: z$1.array(effectApplicationSchema).optional(),
8309
+ /** Effects applied on hover */
8310
+ hover: z$1.array(effectApplicationSchema).optional(),
8311
+ /** Effects applied on active/pressed */
8312
+ active: z$1.array(effectApplicationSchema).optional(),
8313
+ /** Effects applied on focus */
8314
+ focus: z$1.array(effectApplicationSchema).optional()
8315
+ });
8316
+ //#endregion
8317
+ //#region ../theme-core/src/navigation/types.ts
8318
+ /**
8319
+ * Navigation Link Style Types
8320
+ *
8321
+ * Schema and types for composable nav link styling used by header and footer.
8322
+ */
8323
+ /**
8324
+ * Padding preset options for nav links
8325
+ */
8326
+ const navLinkPaddingSchema = z$1.enum([
8327
+ "none",
8328
+ "compact",
8329
+ "default"
8330
+ ]);
8331
+ /**
8332
+ * Horizontal padding override for nav links.
8333
+ * When set, overrides only the horizontal component of the `padding` preset.
8334
+ */
8335
+ const navLinkPaddingXSchema = z$1.enum([
8336
+ "none",
8337
+ "tight",
8338
+ "compact",
8339
+ "default",
8340
+ "relaxed",
8341
+ "spacious"
8342
+ ]);
8343
+ /**
8344
+ * Border radius options for nav links
8345
+ */
8346
+ const navLinkBorderRadiusSchema = z$1.enum([
8347
+ "none",
8348
+ "sm",
8349
+ "md",
8350
+ "full"
8351
+ ]);
8352
+ /**
8353
+ * Typography size options for nav links.
8354
+ */
8355
+ const navLinkTextSizeSchema = z$1.enum([
8356
+ "xs",
8357
+ "sm",
8358
+ "base",
8359
+ "lg",
8360
+ "xl"
8361
+ ]);
8362
+ /**
8363
+ * Letter spacing options for nav links.
8364
+ */
8365
+ const navLinkLetterSpacingSchema = z$1.enum([
8366
+ "normal",
8367
+ "wide",
8368
+ "wider",
8369
+ "widest"
8370
+ ]);
8371
+ /**
8372
+ * Optional legibility aid for nav text that floats over uncertain imagery or color.
8373
+ */
8374
+ const navLinkContrastTreatmentSchema = z$1.enum(["none", "soft-glow"]);
8375
+ /**
8376
+ * Nav link style schema
8377
+ *
8378
+ * Extends interactive typography base with nav-specific settings.
8379
+ */
8380
+ const navLinkStyleSchema = z$1.object({
8381
+ /** Display name for the style */
8382
+ name: z$1.string().min(1).max(30).optional(),
8383
+ /** Typography settings (inherited from interactive base) */
8384
+ ...interactiveTypographySchema.shape,
8385
+ /** Text color token */
8386
+ colorToken: themeColorTokenSchema.default("text"),
8387
+ /** Optional text size override */
8388
+ textSize: navLinkTextSizeSchema.optional(),
8389
+ /** Optional letter spacing override */
8390
+ letterSpacing: navLinkLetterSpacingSchema.optional(),
8391
+ /** Optional text-only contrast treatment for transparent/overlay navigation */
8392
+ contrastTreatment: navLinkContrastTreatmentSchema.optional(),
8393
+ /** Hover/active color token (for color-change effects) */
8394
+ hoverColorToken: themeColorTokenSchema.nullable().optional(),
8395
+ /** Padding preset */
8396
+ padding: navLinkPaddingSchema.default("compact"),
8397
+ /** Horizontal padding override (overrides horizontal component of padding preset) */
8398
+ paddingX: navLinkPaddingXSchema.optional(),
8399
+ /** Border radius (for capsule/pill styles) */
8400
+ borderRadius: navLinkBorderRadiusSchema.default("none"),
8401
+ /** Composable effects */
8402
+ effects: effectCompositionSchema.optional()
8403
+ });
8404
+ //#endregion
8405
+ //#region ../theme-core/src/customCss/validation.ts
8406
+ /**
8407
+ * Custom CSS Validation Schemas
8408
+ *
8409
+ * Zod schemas for validating custom CSS rules.
8410
+ * Enforces security constraints by construction.
8411
+ */
8412
+ /** Global selectors that could affect elements outside theme scope */
8413
+ const FORBIDDEN_SELECTORS = [
8414
+ ":root",
8415
+ "html",
8416
+ "body"
8417
+ ];
8418
+ /** Universal selector - forbidden because it affects everything */
8419
+ const UNIVERSAL_SELECTOR = "*";
8420
+ /** Pattern to detect remote URL references (http://, https://, //) */
8421
+ const REMOTE_URL_PATTERN = /url\s*\(\s*['"]?(https?:|\/\/)/i;
8422
+ /** Pattern to detect javascript: URLs */
8423
+ const JAVASCRIPT_URL_PATTERN = /javascript\s*:/i;
8424
+ /**
8425
+ * Check if a single selector part (no commas) is forbidden.
8426
+ */
8427
+ function isForbiddenSelectorPart(part) {
8428
+ const normalized = part.toLowerCase().trim();
8429
+ if (!normalized) return true;
8430
+ if (normalized === UNIVERSAL_SELECTOR || normalized.startsWith("* ") || normalized.endsWith(" *") || normalized.includes(" * ")) return true;
8431
+ for (const forbidden of FORBIDDEN_SELECTORS) {
8432
+ if (normalized === forbidden) return true;
8433
+ if (normalized.startsWith(forbidden + " ")) return true;
8434
+ if (normalized.startsWith(forbidden + ">")) return true;
8435
+ if (normalized.startsWith(forbidden + "+")) return true;
8436
+ if (normalized.startsWith(forbidden + "~")) return true;
8437
+ if (normalized.startsWith(forbidden + ".")) return true;
8438
+ if (normalized.startsWith(forbidden + "#")) return true;
8439
+ if (normalized.startsWith(forbidden + "[")) return true;
8440
+ if (normalized.startsWith(forbidden + ":") && !normalized.startsWith(forbidden + "::")) return true;
8441
+ }
8442
+ return false;
8443
+ }
8444
+ /**
8445
+ * Check if a selector uses sibling combinators with & that could escape scope.
8446
+ * Patterns like "& ~ .outside" or "& + .sibling" can select elements outside the scope.
8447
+ */
8448
+ function hasScopeEscapingSiblingCombinator(selector) {
8449
+ const normalized = selector.trim();
8450
+ return /&\s*[+~]/.test(normalized);
8451
+ }
8452
+ /**
8453
+ * Check if a selector contains forbidden global selectors.
8454
+ * Handles selectors like ":root", "html body", "body.class", "body, .x", etc.
8455
+ */
8456
+ function containsForbiddenSelector(selector) {
8457
+ const normalized = selector.toLowerCase().trim();
8458
+ if (!normalized) return true;
8459
+ if (hasScopeEscapingSiblingCombinator(selector)) return true;
8460
+ const parts = normalized.split(",");
8461
+ for (const part of parts) if (isForbiddenSelectorPart(part)) return true;
8462
+ return false;
8463
+ }
8464
+ /**
8465
+ * Validates a CSS selector for safety.
8466
+ */
8467
+ const selectorSchema = z$1.string().min(1, "Selector cannot be empty").max(200, "Selector too long (max 200 characters)").refine((s) => !containsForbiddenSelector(s), { message: "Global selectors (:root, html, body, *) are not allowed" });
8468
+ /**
8469
+ * Check if a CSS value contains a remote URL.
8470
+ */
8471
+ function containsRemoteUrl(value) {
8472
+ return REMOTE_URL_PATTERN.test(value);
8473
+ }
8474
+ /**
8475
+ * Check if a CSS value contains a javascript: URL.
8476
+ */
8477
+ function containsJavascriptUrl(value) {
8478
+ return JAVASCRIPT_URL_PATTERN.test(value);
8479
+ }
8480
+ /**
8481
+ * Validates a CSS declaration value for safety.
8482
+ * Allows: url(#id), url(data:...), url(/path), var(--)
8483
+ * Forbids: url(http...), url(//...), javascript:
8484
+ */
8485
+ const declarationValueSchema = z$1.string().max(500, "Declaration value too long (max 500 characters)").refine((v) => !containsRemoteUrl(v), { message: "Remote url() references are not allowed. Use local paths, data URIs, or fragment IDs." }).refine((v) => !containsJavascriptUrl(v), { message: "javascript: URLs are not allowed" });
8486
+ /**
8487
+ * Schema for CSS declarations object (property -> value map).
8488
+ */
8489
+ const declarationsSchema = z$1.record(z$1.string().min(1).max(100), declarationValueSchema);
8490
+ /**
8491
+ * Schema for a single custom CSS rule.
8492
+ */
8493
+ const customCssRuleSchema = z$1.object({
8494
+ id: z$1.string().min(1, "Rule ID is required").max(50, "Rule ID too long"),
8495
+ selector: selectorSchema,
8496
+ declarations: declarationsSchema
8497
+ });
8498
+ /**
8499
+ * Schema for block-specific CSS rule.
8500
+ */
8501
+ const blockCustomCssRuleSchema = customCssRuleSchema.extend({ blockKind: z$1.string().min(1, "Block kind is required").max(50, "Block kind too long") });
8502
+ /**
8503
+ * Array of custom CSS rules for theme-level styling.
8504
+ */
8505
+ const customCssRulesSchema = z$1.array(customCssRuleSchema).optional();
8506
+ /**
8507
+ * Array of block-specific CSS rules.
8508
+ */
8509
+ const blockCustomCssRulesSchema = z$1.array(blockCustomCssRuleSchema).optional();
8510
+ //#endregion
8511
+ //#region ../theme-core/src/customCss/atRuleValidation.ts
8512
+ /**
8513
+ * CSS At-Rule Validation Schemas
8514
+ *
8515
+ * Zod schemas for validating CSS at-rules.
8516
+ * Blocks @import for security.
8517
+ */
8518
+ /** Valid keyframe offset values - requires % for numeric values */
8519
+ const KEYFRAME_OFFSET_PATTERN = /^(from|to|\d{1,3}%)$/i;
8520
+ /** Valid animation name (CSS identifier) */
8521
+ const ANIMATION_NAME_PATTERN = /^[a-zA-Z_-][a-zA-Z0-9_-]*$/;
8522
+ /** Blocked at-rules in raw CSS */
8523
+ const BLOCKED_AT_RULES = ["@import", "@charset"];
8524
+ /** Pattern to detect blocked at-rules */
8525
+ const BLOCKED_AT_RULE_PATTERN = /@(?:import|charset)\b/i;
8526
+ /** Rule ID schema - reused from main validation */
8527
+ const ruleIdSchema = z$1.string().min(1, "Rule ID is required").max(50, "Rule ID too long");
8528
+ /** Nested rule schema for @media and @supports */
8529
+ const nestedRuleSchema = z$1.object({
8530
+ selector: selectorSchema,
8531
+ declarations: declarationsSchema
8532
+ });
8533
+ /**
8534
+ * Validate keyframe offset is in valid range (0-100%).
8535
+ * Returns true for 'from', 'to', or numeric values 0-100.
8536
+ */
8537
+ function isValidKeyframeOffset(offset) {
8538
+ const trimmed = offset.trim().toLowerCase();
8539
+ if (trimmed === "from" || trimmed === "to") return true;
8540
+ const match = trimmed.match(/^(\d{1,3})%$/);
8541
+ if (!match || match[1] === void 0) return false;
8542
+ const value = parseInt(match[1], 10);
8543
+ return value >= 0 && value <= 100;
8544
+ }
8545
+ /** Keyframe offset validation (0%, 50%, 100%, from, to) */
8546
+ const keyframeOffsetSchema = z$1.string().transform((offset) => offset.trim()).refine((offset) => KEYFRAME_OFFSET_PATTERN.test(offset), { message: "Invalid keyframe offset. Use percentages (0%, 50%, 100%) or \"from\"/\"to\"" }).refine(isValidKeyframeOffset, { message: "Keyframe offset must be between 0% and 100%" });
8547
+ /** Animation name validation (CSS identifier) */
8548
+ const animationNameSchema = z$1.string().min(1, "Animation name is required").max(50, "Animation name too long").refine((name) => ANIMATION_NAME_PATTERN.test(name), { message: "Invalid animation name. Use letters, numbers, dashes, underscores (start with letter, dash, or underscore)" });
8549
+ /** Single keyframe (offset + declarations) */
8550
+ const keyframeSchema = z$1.object({
8551
+ offset: keyframeOffsetSchema,
8552
+ declarations: declarationsSchema
8553
+ });
8554
+ /** @keyframes rule schema */
8555
+ const keyframesAtRuleSchema = z$1.object({
8556
+ id: ruleIdSchema,
8557
+ type: z$1.literal("keyframes"),
8558
+ name: animationNameSchema,
8559
+ frames: z$1.array(keyframeSchema).min(1, "At least one keyframe is required")
8560
+ });
8561
+ /** Font-face declarations - uses standard declarations but with font-specific validation */
8562
+ const fontFaceDeclarationsSchema = z$1.record(z$1.string().min(1).max(100), declarationValueSchema).refine((decls) => "fontFamily" in decls || "font-family" in decls, { message: "font-family is required in @font-face" });
8563
+ /** @font-face rule schema */
8564
+ const fontFaceAtRuleSchema = z$1.object({
8565
+ id: ruleIdSchema,
8566
+ type: z$1.literal("font-face"),
8567
+ declarations: fontFaceDeclarationsSchema
8568
+ });
8569
+ /** Media query string validation */
8570
+ const mediaQuerySchema = z$1.string().min(1, "Media query is required").max(200, "Media query too long");
8571
+ /** @media rule schema */
8572
+ const mediaAtRuleSchema = z$1.object({
8573
+ id: ruleIdSchema,
8574
+ type: z$1.literal("media"),
8575
+ query: mediaQuerySchema,
8576
+ rules: z$1.array(nestedRuleSchema).min(1, "At least one rule is required")
8577
+ });
8578
+ /** Supports condition string validation */
8579
+ const supportsConditionSchema = z$1.string().min(1, "Supports condition is required").max(200, "Supports condition too long");
8580
+ /** @supports rule schema */
8581
+ const supportsAtRuleSchema = z$1.object({
8582
+ id: ruleIdSchema,
8583
+ type: z$1.literal("supports"),
8584
+ condition: supportsConditionSchema,
8585
+ rules: z$1.array(nestedRuleSchema).min(1, "At least one rule is required")
8586
+ });
8587
+ /**
8588
+ * Check if raw CSS contains blocked at-rules.
8589
+ */
8590
+ function containsBlockedAtRule(css) {
8591
+ return BLOCKED_AT_RULE_PATTERN.test(css);
8592
+ }
8593
+ /** Raw CSS validation - blocks @import, @charset, must start with @ */
8594
+ const rawCssSchema = z$1.string().min(1, "CSS is required").max(5e3, "Raw CSS too long (max 5000 characters)").refine((css) => css.trim().startsWith("@"), { message: "Raw at-rule must start with @" }).refine((css) => !containsBlockedAtRule(css), { message: `Blocked at-rules: ${BLOCKED_AT_RULES.join(", ")}. Use typed at-rules or local assets instead.` });
8595
+ /** Raw at-rule schema */
8596
+ const rawAtRuleSchema = z$1.object({
8597
+ id: ruleIdSchema,
8598
+ type: z$1.literal("raw"),
8599
+ css: rawCssSchema
8600
+ });
8601
+ /**
8602
+ * Discriminated union schema for all at-rule types.
8603
+ */
8604
+ const customCssAtRuleSchema = z$1.discriminatedUnion("type", [
8605
+ keyframesAtRuleSchema,
8606
+ fontFaceAtRuleSchema,
8607
+ mediaAtRuleSchema,
8608
+ supportsAtRuleSchema,
8609
+ rawAtRuleSchema
8610
+ ]);
8611
+ /**
8612
+ * Array of at-rules for theme-level styling.
8613
+ */
8614
+ const customCssAtRulesSchema = z$1.array(customCssAtRuleSchema).optional();
8615
+ //#endregion
8616
+ //#region ../theme-core/src/shared/componentStyles.ts
8617
+ /**
8618
+ * Shared Component Style Schemas
8619
+ *
8620
+ * Reusable schemas for border and shadow styling that can be shared across
8621
+ * themed components (header, buttons, cards, accordions, inputs).
8622
+ *
8623
+ * Design decisions:
8624
+ * - Shadow elevation uses CSS-aligned names (none/sm/md/lg/xl/2xl)
8625
+ * - Shadow softness is controlled globally, not per-component
8626
+ * - Border position is component-specific, not in shared schema
8627
+ */
8628
+ /**
8629
+ * Shared border schema for themed components.
8630
+ * Position is excluded - each component determines its own border position.
8631
+ */
8632
+ const componentBorderSchema = z$1.object({
8633
+ width: z$1.enum([
8634
+ "none",
8635
+ "hairline",
8636
+ "thin",
8637
+ "medium",
8638
+ "thick"
8639
+ ]).default("none"),
8640
+ style: z$1.enum(["solid", "dashed"]).default("solid"),
8641
+ colorToken: themeColorTokenSchema.optional()
8642
+ });
8643
+ /**
8644
+ * Shared shadow schema for themed components.
8645
+ * Softness is inherited from global theme, not configurable per-component.
8646
+ */
8647
+ const componentShadowSchema = z$1.object({ elevation: z$1.enum([
8648
+ "none",
8649
+ "sm",
8650
+ "md",
8651
+ "lg",
8652
+ "xl",
8653
+ "2xl"
8654
+ ]).default("sm") });
8655
+ //#endregion
8656
+ //#region ../theme-core/src/site-styles/types.ts
8657
+ function asSiteStyleId(value) {
8658
+ const siteStyleId = brandNonEmptyString(value, "SiteStyleId");
8659
+ if (!siteStyleId.startsWith("site-style:")) throw new Error(`SiteStyleId must start with "site-style:". Received: ${value}`);
8660
+ return siteStyleId;
8661
+ }
8662
+ function brandNonEmptyString(value, label) {
8663
+ if (value.length === 0) throw new Error(`${label} must be a non-empty string.`);
8664
+ return value;
8665
+ }
8666
+ const tileTreatmentValues = [
8667
+ "default",
8668
+ "quiet",
8669
+ "brand-depth"
8670
+ ];
8671
+ const eventListTreatmentValues = [
8672
+ "plain",
8673
+ "lined-panel",
8674
+ "ruled-register",
8675
+ "editorial-register",
8676
+ "dense-index"
8677
+ ];
8678
+ const eyebrowTreatmentValues = [
8679
+ "plain",
8680
+ "accent",
8681
+ "pill",
8682
+ "accent-pill",
8683
+ "pill-bounce",
8684
+ "accent-pill-bounce"
8685
+ ];
8686
+ const visibleHeadingDecorationFamilyValues = ["organic-squiggle", "short-center-rule"];
8687
+ const headingDecorationOverrideValues = ["site-default", "off"];
8688
+ const headingDecorationColorTokenValues = [
8689
+ "text",
8690
+ "primary",
8691
+ "secondary",
8692
+ "accent",
8693
+ "border",
8694
+ "muted"
8695
+ ];
8696
+ const accordionIconSetValues = [
8697
+ "plus",
8698
+ "chevron",
8699
+ "caret",
8700
+ "minimal-cross"
8701
+ ];
8702
+ const accordionIconColorTokenValues = [
8703
+ "text",
8704
+ "muted",
8705
+ "primary",
8706
+ "secondary",
8707
+ "accent",
8708
+ "current"
8709
+ ];
8710
+ const accordionIconMotionValues = [
8711
+ "none",
8712
+ "rotate",
8713
+ "swap"
8714
+ ];
8715
+ //#endregion
8716
+ //#region ../theme-core/src/site-styles/logoBranding.ts
8717
+ const logoTextConfidenceValues = [
8718
+ "low",
8719
+ "medium",
8720
+ "high"
8721
+ ];
8722
+ const logoAssetShapeValues = [
8723
+ "none",
8724
+ "horizontal",
8725
+ "square",
8726
+ "portrait",
8727
+ "tall"
8728
+ ];
8729
+ const logoKindValues = [
8730
+ "mark",
8731
+ "wordmark",
8732
+ "lockup",
8733
+ "badge",
8734
+ "stacked-wordmark",
8735
+ "unknown"
8736
+ ];
8737
+ const logoDensityValues = [
8738
+ "simple",
8739
+ "detailed",
8740
+ "unknown"
8741
+ ];
8742
+ const logoContainsTextSchema = z$1.discriminatedUnion("kind", [
8743
+ z$1.object({
8744
+ kind: z$1.literal("contains-text"),
8745
+ confidence: z$1.enum(logoTextConfidenceValues),
8746
+ text: z$1.string().trim().min(1).max(200).optional()
8747
+ }),
8748
+ z$1.object({
8749
+ kind: z$1.literal("no-text"),
8750
+ confidence: z$1.enum(logoTextConfidenceValues)
8751
+ }),
8752
+ z$1.object({
8753
+ kind: z$1.literal("unknown"),
8754
+ reason: z$1.enum([
8755
+ "analysis-unavailable",
8756
+ "unsupported-file",
8757
+ "low-confidence"
8758
+ ])
8759
+ })
8760
+ ]);
8761
+ const logoAnalysisSourceSchema = z$1.discriminatedUnion("kind", [
8762
+ z$1.object({ kind: z$1.literal("none") }),
8763
+ z$1.object({
8764
+ kind: z$1.literal("deterministic"),
8765
+ reason: z$1.enum(["dimensions", "fallback"])
8766
+ }),
8767
+ z$1.object({
8768
+ kind: z$1.literal("llm"),
8769
+ model: z$1.literal("gpt-5.4-mini"),
8770
+ analyzedAt: z$1.string().trim().min(1).max(80).optional()
8771
+ }),
8772
+ z$1.object({ kind: z$1.literal("manual-override") })
8773
+ ]);
8774
+ z$1.object({
8775
+ shape: z$1.enum(logoAssetShapeValues),
8776
+ containsText: logoContainsTextSchema,
8777
+ kind: z$1.enum(logoKindValues),
8778
+ density: z$1.enum(logoDensityValues),
8779
+ source: logoAnalysisSourceSchema
8780
+ });
8781
+ const brandDisplayModeValues = [
8782
+ "auto",
8783
+ "logo-only",
8784
+ "logo-plus-title",
8785
+ "title-only"
8786
+ ];
8787
+ const logoAccommodationPatternValues = [
8788
+ "title-only",
8789
+ "inline-logo-only",
8790
+ "inline-wordmark",
8791
+ "inline-mark-with-title",
8792
+ "logo-plate",
8793
+ "centered-badge",
8794
+ "popout-badge",
8795
+ "centered-masthead",
8796
+ "hero-badge"
8797
+ ];
8798
+ const logoSizePolicyValues = [
8799
+ "auto",
8800
+ "compact",
8801
+ "standard",
8802
+ "generous",
8803
+ "display"
8804
+ ];
8805
+ //#endregion
8806
+ //#region ../theme-core/src/site-styles/rawStyleFields.ts
8807
+ const themeV2RuntimeStyleFieldNames = [
8808
+ "_frameStyles",
8809
+ "_sectionStyles",
8810
+ "_containerStyles",
8811
+ "_cardStyles",
8812
+ "_transitionStyles",
8813
+ "styleGroup"
8814
+ ];
8815
+ const themeV2BlockSpecificRawStyleFieldNames = [
8816
+ "_contentCardStyles",
8817
+ "_heroLayoutStyles",
8818
+ "_textCardStyles"
8819
+ ];
8820
+ const themeV2NormalEditorRawStyleFieldNames = [...themeV2RuntimeStyleFieldNames, ...themeV2BlockSpecificRawStyleFieldNames];
8821
+ new Set(themeV2NormalEditorRawStyleFieldNames);
8822
+ [...themeV2RuntimeStyleFieldNames, ...themeV2BlockSpecificRawStyleFieldNames];
8823
+ const pageDesignEditorBackgroundOverrideOwner = "page-design-editor";
8824
+ const siteChromeBackgroundOverrideOwner = "site-chrome-editor";
8825
+ //#endregion
8826
+ //#region ../theme-core/src/utils/tokenOrColor.ts
8827
+ /**
8828
+ * Runtime color-reference fields intentionally accept any string, including
8829
+ * the legacy empty-string "no color" sentinel. Semantic validation needs
8830
+ * palette context and happens in `parseThemeColorReference`.
8831
+ */
8832
+ const tokenOrCssColorValueSchema = z$1.string();
8833
+ //#endregion
8834
+ //#region ../theme-core/src/schema.ts
8835
+ const axesSchema = z$1.object({
8836
+ tone: z$1.enum([
8837
+ "minimal",
8838
+ "classic",
8839
+ "bold"
8840
+ ]),
8841
+ energy: z$1.enum(["calm", "vibrant"]),
8842
+ density: z$1.enum([
8843
+ "airy",
8844
+ "regular",
8845
+ "compact"
8846
+ ]),
8847
+ mediaBias: z$1.enum([
8848
+ "text",
8849
+ "media",
8850
+ "mixed"
8851
+ ]),
8852
+ conversionBias: z$1.enum([
8853
+ "low",
8854
+ "med",
8855
+ "high"
8856
+ ]),
8857
+ motion: z$1.enum([
8858
+ "subtle",
8859
+ "standard",
8860
+ "expressive"
8861
+ ])
8862
+ });
8863
+ const colourHexString = z$1.string().regex(/^#([0-9A-Fa-f]{3}){1,2}$/);
8864
+ const paletteColorSchema = z$1.object({
8865
+ name: z$1.string().min(1),
8866
+ hex: colourHexString
8867
+ });
8868
+ const paletteMetaSchema = z$1.object({ mode: z$1.enum(["light", "dark"]) });
8869
+ const paletteSchema = z$1.object({
8870
+ colors: z$1.array(paletteColorSchema),
8871
+ meta: paletteMetaSchema
8872
+ });
8873
+ const typographyStyleSchema = z$1.object({
8874
+ family: z$1.string().min(1),
8875
+ weight: z$1.enum([
8876
+ "light",
8877
+ "regular",
8878
+ "medium",
8879
+ "semibold",
8880
+ "bold"
8881
+ ]),
8882
+ letterSpacing: z$1.enum([
8883
+ "tight",
8884
+ "normal",
8885
+ "loose"
8886
+ ]),
8887
+ lineHeight: z$1.enum([
8888
+ "normal",
8889
+ "relaxed",
8890
+ "loose"
8891
+ ])
8892
+ });
8893
+ const bodyTypographyStyleSchema = typographyStyleSchema.extend({ size: z$1.enum([
8894
+ "md",
8895
+ "lg",
8896
+ "xl"
8897
+ ]) });
8898
+ const headingSizeSchema = z$1.enum([
8899
+ "xs",
8900
+ "sm",
8901
+ "md",
8902
+ "lg",
8903
+ "xl",
8904
+ "2xl"
8905
+ ]);
8906
+ const headingTypographyOverridesSchema = z$1.object({
8907
+ weight: z$1.enum([
8908
+ "light",
8909
+ "regular",
8910
+ "medium",
8911
+ "semibold",
8912
+ "bold"
8913
+ ]).nullable().optional(),
8914
+ letterSpacing: z$1.enum([
8915
+ "tight",
8916
+ "normal",
8917
+ "loose"
8918
+ ]).nullable().optional(),
8919
+ size: headingSizeSchema.nullable().optional(),
8920
+ lineHeight: z$1.enum([
8921
+ "tight",
8922
+ "snug",
8923
+ "normal",
8924
+ "relaxed",
8925
+ "loose"
8926
+ ]).nullable().optional(),
8927
+ italic: z$1.boolean().nullable().optional(),
8928
+ colorToken: themeColorTokenSchema.nullable().optional()
8929
+ });
8930
+ const headingTypographyStyleSchema = typographyStyleSchema.extend({
8931
+ case: z$1.enum([
8932
+ "uppercase",
8933
+ "normal",
8934
+ "smallCaps"
8935
+ ]).nullable(),
8936
+ italic: z$1.boolean().nullable(),
8937
+ colorToken: themeColorTokenSchema.nullable().optional()
8938
+ });
8939
+ const proseLinkUnderlineStyleSchema = z$1.enum([
8940
+ "solid",
8941
+ "dotted",
8942
+ "dashed"
8943
+ ]);
8944
+ const proseLinkUnderlineThicknessSchema = z$1.enum([
8945
+ "auto",
8946
+ "fromFont",
8947
+ "thin",
8948
+ "medium",
8949
+ "thick"
8950
+ ]);
8951
+ const proseLinkUnderlineOffsetSchema = z$1.enum([
8952
+ "auto",
8953
+ "tight",
8954
+ "normal",
8955
+ "loose"
8956
+ ]);
8957
+ const proseLinkStyleSchema = z$1.object({
8958
+ colorToken: themeColorTokenSchema.optional(),
8959
+ hoverColorToken: themeColorTokenSchema.optional(),
8960
+ underline: z$1.boolean().optional(),
8961
+ decorationColorToken: themeColorTokenSchema.optional(),
8962
+ hoverDecorationColorToken: themeColorTokenSchema.optional(),
8963
+ underlineStyle: proseLinkUnderlineStyleSchema.optional(),
8964
+ underlineThickness: proseLinkUnderlineThicknessSchema.optional(),
8965
+ underlineOffset: proseLinkUnderlineOffsetSchema.optional()
8966
+ });
8967
+ const semanticSpacingSchema = z$1.enum([
8968
+ "none",
8969
+ "compact",
8970
+ "cozy",
8971
+ "medium",
8972
+ "comfortable",
8973
+ "spacious"
8974
+ ]);
8975
+ const boxRoundedSchema = z$1.enum([
8976
+ "none",
8977
+ "sm",
8978
+ "md",
8979
+ "lg",
8980
+ "xl",
8981
+ "2xl",
8982
+ "full"
8983
+ ]);
8984
+ const boxBackgroundOverlaySchema = z$1.object({
8985
+ type: z$1.enum([
8986
+ "none",
8987
+ "color",
8988
+ "gradient"
8989
+ ]).nullable().optional(),
8990
+ color: tokenOrCssColorValueSchema.nullable().optional(),
8991
+ gradient: z$1.string().nullable().optional(),
8992
+ opacity: z$1.number().min(0).max(1).nullable().optional()
8993
+ });
8994
+ const boxBackgroundSchema = z$1.object({
8995
+ type: z$1.enum([
8996
+ "color",
8997
+ "gradient",
8998
+ "image"
8999
+ ]).optional(),
9000
+ contentOwner: z$1.literal(pageDesignEditorBackgroundOverrideOwner).optional(),
9001
+ color: tokenOrCssColorValueSchema.nullable().optional(),
9002
+ gradient: z$1.string().nullable().optional(),
9003
+ gradientPresetId: z$1.string().min(1).nullable().optional(),
9004
+ image: mediaSchema$1.nullable().optional(),
9005
+ objectFit: z$1.enum([
9006
+ "fill",
9007
+ "fit",
9008
+ "original",
9009
+ "custom"
9010
+ ]).nullable().optional(),
9011
+ scale: z$1.string().nullable().optional(),
9012
+ position: z$1.string().nullable().optional(),
9013
+ opacity: z$1.number().min(0).max(1).nullable().optional(),
9014
+ motion: z$1.enum(["static", "fixed-frame"]).nullable().optional(),
9015
+ overlay: boxBackgroundOverlaySchema.nullable().optional(),
9016
+ textColor: tokenOrCssColorValueSchema.nullable().optional(),
9017
+ headingColor: tokenOrCssColorValueSchema.nullable().optional(),
9018
+ linkColor: tokenOrCssColorValueSchema.nullable().optional(),
9019
+ supportingColor: tokenOrCssColorValueSchema.nullable().optional()
9020
+ });
9021
+ const noHeadingDecorationSchema = z$1.object({ family: z$1.literal("none") });
9022
+ const visibleHeadingDecorationSchema = z$1.object({
9023
+ family: z$1.enum(visibleHeadingDecorationFamilyValues),
9024
+ colorToken: z$1.enum(headingDecorationColorTokenValues).optional()
9025
+ });
9026
+ const headingDecorationSchema = z$1.union([noHeadingDecorationSchema, visibleHeadingDecorationSchema]);
9027
+ const headingDecorationOverrideSchema = z$1.union([z$1.enum(headingDecorationOverrideValues), z$1.literal("on").transform(() => "site-default")]);
9028
+ const accordionIconTreatmentSchema = z$1.object({
9029
+ iconSet: z$1.enum(accordionIconSetValues),
9030
+ colorToken: z$1.enum(accordionIconColorTokenValues),
9031
+ openColorToken: z$1.enum(accordionIconColorTokenValues).optional(),
9032
+ motion: z$1.enum(accordionIconMotionValues)
9033
+ });
9034
+ const sectionStylesOverrideSchema = z$1.object({
9035
+ background: boxBackgroundSchema.nullable().optional(),
9036
+ spacing: semanticSpacingSchema.nullable().optional(),
9037
+ minHeight: z$1.enum([
9038
+ "none",
9039
+ "banner",
9040
+ "hero",
9041
+ "immersive"
9042
+ ]).nullable().optional(),
9043
+ tileTreatment: z$1.enum(tileTreatmentValues).nullable().optional(),
9044
+ eventListTreatment: z$1.enum(eventListTreatmentValues).nullable().optional(),
9045
+ eyebrowTreatment: z$1.enum(eyebrowTreatmentValues).nullable().optional(),
9046
+ headingDecoration: headingDecorationSchema.nullable().optional(),
9047
+ headingDecorationOverride: headingDecorationOverrideSchema.nullable().optional(),
9048
+ accordionIconTreatment: accordionIconTreatmentSchema.nullable().optional()
9049
+ });
9050
+ const containerStylesOverrideSchema = z$1.object({
9051
+ background: boxBackgroundSchema.nullable().optional(),
9052
+ spacing: semanticSpacingSchema.nullable().optional(),
9053
+ raised: z$1.boolean().nullable().optional(),
9054
+ rounded: boxRoundedSchema.nullable().optional(),
9055
+ fullWidth: z$1.boolean().nullable().optional()
9056
+ });
9057
+ const cardBorderOverrideSchema = z$1.object({
9058
+ enabled: z$1.boolean().nullable().optional(),
9059
+ width: z$1.enum([
9060
+ "none",
9061
+ "1",
9062
+ "2",
9063
+ "3"
9064
+ ]).nullable().optional(),
9065
+ colorToken: themeColorTokenSchema.nullable().optional()
9066
+ });
9067
+ const cardStylesOverrideSchema = z$1.object({
9068
+ background: boxBackgroundSchema.nullable().optional(),
9069
+ border: cardBorderOverrideSchema.nullable().optional(),
9070
+ spacing: semanticSpacingSchema.nullable().optional(),
9071
+ raised: z$1.boolean().nullable().optional(),
9072
+ rounded: boxRoundedSchema.nullable().optional(),
9073
+ treatment: z$1.enum([
9074
+ "accent-quote",
9075
+ "editorial-rule",
9076
+ "soft-panel",
9077
+ "editorial-serif-quote",
9078
+ "editorial-open",
9079
+ "color-blocked"
9080
+ ]).nullable().optional(),
9081
+ cardVariant: boxStylesCardVariantSchema.nullable().optional()
9082
+ });
9083
+ const blockStyleOverridesSchema = z$1.object({
9084
+ sectionStyles: sectionStylesOverrideSchema.nullable().optional(),
9085
+ containerStyles: containerStylesOverrideSchema.nullable().optional(),
9086
+ cardStyles: cardStylesOverrideSchema.nullable().optional()
9087
+ });
9088
+ const blockThemeOverrideSchema = z$1.object({
9089
+ typography: z$1.object({ proseLinkStyle: proseLinkStyleSchema.optional() }).optional(),
9090
+ styles: blockStyleOverridesSchema.optional()
9091
+ });
9092
+ const typographyScaleSchema = z$1.enum([
9093
+ "compact",
9094
+ "balanced",
9095
+ "spacious",
9096
+ "minorThird",
9097
+ "majorThird",
9098
+ "perfectFourth"
9099
+ ]);
9100
+ const eyebrowTypographyStyleSchema = z$1.object({
9101
+ family: z$1.string().min(1),
9102
+ size: z$1.enum([
9103
+ "sm",
9104
+ "md",
9105
+ "lg"
9106
+ ]).optional(),
9107
+ weight: z$1.enum([
9108
+ "light",
9109
+ "regular",
9110
+ "medium",
9111
+ "semibold",
9112
+ "bold"
9113
+ ]).optional(),
9114
+ letterSpacing: z$1.enum([
9115
+ "tight",
9116
+ "normal",
9117
+ "loose",
9118
+ "wide"
9119
+ ]).optional(),
9120
+ case: z$1.enum(["uppercase", "normal"]).optional()
9121
+ });
9122
+ const typographySchema = z$1.object({
9123
+ body: bodyTypographyStyleSchema,
9124
+ headings: z$1.object({
9125
+ default: headingTypographyStyleSchema,
9126
+ h1: headingTypographyOverridesSchema,
9127
+ h2: headingTypographyOverridesSchema,
9128
+ h3: headingTypographyOverridesSchema,
9129
+ h4: headingTypographyOverridesSchema.optional(),
9130
+ h5: headingTypographyOverridesSchema.optional(),
9131
+ h6: headingTypographyOverridesSchema.optional()
9132
+ }),
9133
+ scale: typographyScaleSchema,
9134
+ proseLinkStyle: proseLinkStyleSchema.optional(),
9135
+ eyebrow: eyebrowTypographyStyleSchema.optional()
9136
+ });
9137
+ const spaceSchema = z$1.enum([
9138
+ "comfortable",
9139
+ "standard",
9140
+ "dense"
9141
+ ]);
9142
+ const corners = z$1.enum([
9143
+ "square",
9144
+ "soft",
9145
+ "rounded",
9146
+ "pill"
9147
+ ]);
9148
+ const shadow = z$1.object({
9149
+ elevation: z$1.enum([
9150
+ "none",
9151
+ "low",
9152
+ "medium",
9153
+ "high"
9154
+ ]),
9155
+ softness: z$1.enum([
9156
+ "crisp",
9157
+ "soft",
9158
+ "hard"
9159
+ ]).nullable(),
9160
+ position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
9161
+ colorToken: themeColorTokenSchema.optional()
9162
+ });
9163
+ const border = z$1.object({
9164
+ width: z$1.enum([
9165
+ "none",
9166
+ "hairline",
9167
+ "thin",
9168
+ "thick"
9169
+ ]),
9170
+ style: z$1.enum(["solid", "dashed"])
9171
+ });
9172
+ const motion = z$1.object({
9173
+ level: z$1.enum([
9174
+ "off",
9175
+ "low",
9176
+ "medium",
9177
+ "high"
9178
+ ]),
9179
+ easing: z$1.enum([
9180
+ "standard",
9181
+ "snappy",
9182
+ "gentle"
9183
+ ]).nullable()
9184
+ });
9185
+ z$1.object({ shape: corners });
9186
+ z$1.object({
9187
+ elevation: z$1.enum([
9188
+ "none",
9189
+ "low",
9190
+ "medium",
9191
+ "high"
9192
+ ]),
9193
+ border: z$1.enum([
9194
+ "none",
9195
+ "subtle",
9196
+ "defined"
9197
+ ]),
9198
+ shape: corners,
9199
+ headerStyle: z$1.enum([
9200
+ "plain",
9201
+ "accentBar",
9202
+ "subtleBg"
9203
+ ]).nullable(),
9204
+ mediaTreatment: z$1.enum([
9205
+ "square",
9206
+ "rounded",
9207
+ "bleed"
9208
+ ]).nullable()
9209
+ });
9210
+ const inputStyle = z$1.object({
9211
+ shape: corners,
9212
+ border: z$1.enum([
9213
+ "subtle",
9214
+ "defined",
9215
+ "underline"
9216
+ ]),
9217
+ focus: z$1.enum([
9218
+ "glow",
9219
+ "ring",
9220
+ "underline"
9221
+ ]),
9222
+ label: z$1.enum(["inside", "above"])
9223
+ });
9224
+ const headerVariant = z$1.enum([
9225
+ "classic",
9226
+ "centered",
9227
+ "transparent",
9228
+ "floating"
9229
+ ]);
9230
+ const headerPositioning = z$1.enum([
9231
+ "static",
9232
+ "sticky",
9233
+ "fixed"
9234
+ ]);
9235
+ const headerNavStyle = z$1.enum([
9236
+ "minimal",
9237
+ "underline",
9238
+ "underline-grow",
9239
+ "capsule",
9240
+ "scale",
9241
+ "frosted",
9242
+ "solid"
9243
+ ]);
9244
+ const navFontWeight = z$1.enum([
9245
+ "regular",
9246
+ "medium",
9247
+ "semibold",
9248
+ "bold"
9249
+ ]);
9250
+ const headerMaxWidth = z$1.enum(["container", "full"]);
9251
+ const headerBarFrame = z$1.enum(["full-bleed", "inset-shell"]);
9252
+ const headerContainerSchema = z$1.object({
9253
+ rounded: z$1.enum([
9254
+ "none",
9255
+ "sm",
9256
+ "md",
9257
+ "lg",
9258
+ "xl",
9259
+ "2xl"
9260
+ ]).default("xl"),
9261
+ border: z$1.boolean().default(true),
9262
+ shadow: z$1.boolean().default(true),
9263
+ padding: z$1.enum([
9264
+ "sm",
9265
+ "md",
9266
+ "lg"
9267
+ ]).default("md"),
9268
+ tint: z$1.string().nullable().optional(),
9269
+ opacity: z$1.number().min(0).max(1).default(.12)
9270
+ }).optional();
9271
+ const headerBorderSchema = componentBorderSchema.extend({ position: z$1.enum([
9272
+ "bottom",
9273
+ "top",
9274
+ "both",
9275
+ "none"
9276
+ ]).default("bottom") }).optional();
9277
+ const logoStyleSchema = z$1.object({
9278
+ fontFamily: z$1.enum(["heading", "body"]).default("heading"),
9279
+ letterSpacing: z$1.enum([
9280
+ "normal",
9281
+ "wide",
9282
+ "wider",
9283
+ "widest"
9284
+ ]).default("normal"),
9285
+ gradient: z$1.boolean().default(false),
9286
+ brandDisplay: z$1.enum(brandDisplayModeValues).optional(),
9287
+ size: z$1.enum(logoSizePolicyValues).optional(),
9288
+ accommodation: z$1.enum(logoAccommodationPatternValues).optional()
9289
+ }).optional();
9290
+ const headerLogoTextSchema = z$1.object({
9291
+ mobileWrapLines: z$1.union([z$1.literal(1), z$1.literal(2)]).optional(),
9292
+ mobileMaxWidth: z$1.enum([
9293
+ "xs",
9294
+ "sm",
9295
+ "md"
9296
+ ]).optional(),
9297
+ hideOnShrink: z$1.boolean().optional()
9298
+ }).optional();
9299
+ const navEffectsSchema = z$1.object({
9300
+ underlineGradient: z$1.boolean().default(false),
9301
+ glow: z$1.boolean().default(false),
9302
+ glowColor: z$1.string().optional(),
9303
+ neumorphic: z$1.boolean().default(false)
9304
+ }).optional();
9305
+ const dropdownStyleSchema = z$1.object({
9306
+ background: themeColorTokenSchema.default("surface"),
9307
+ textColor: themeColorTokenSchema.default("text"),
9308
+ borderColor: themeColorTokenSchema.nullable().default("border"),
9309
+ shadow: z$1.enum([
9310
+ "none",
9311
+ "sm",
9312
+ "md",
9313
+ "lg"
9314
+ ]).default("md"),
9315
+ borderRadius: z$1.enum([
9316
+ "none",
9317
+ "sm",
9318
+ "md",
9319
+ "lg"
9320
+ ]).default("md"),
9321
+ hoverBackground: themeColorTokenSchema.nullable().optional(),
9322
+ hoverTextColor: themeColorTokenSchema.nullable().optional(),
9323
+ textTransform: z$1.enum([
9324
+ "none",
9325
+ "uppercase",
9326
+ "capitalize"
9327
+ ]).default("none"),
9328
+ letterSpacing: z$1.enum([
9329
+ "normal",
9330
+ "wide",
9331
+ "wider"
9332
+ ]).default("normal"),
9333
+ fontWeight: z$1.enum([
9334
+ "regular",
9335
+ "medium",
9336
+ "semibold",
9337
+ "bold"
9338
+ ]).optional(),
9339
+ textSize: z$1.enum([
9340
+ "xs",
9341
+ "sm",
9342
+ "base",
9343
+ "lg"
9344
+ ]).optional()
9345
+ }).optional();
9346
+ /**
9347
+ * CTA button gap (left margin) for desktop header.
9348
+ * Controls the spacing between nav links and the CTA button.
9349
+ */
9350
+ const headerCtaGapSchema = z$1.enum([
9351
+ "none",
9352
+ "tight",
9353
+ "compact",
9354
+ "default",
9355
+ "relaxed",
9356
+ "spacious"
9357
+ ]);
9358
+ const headerCtaTreatmentSchema = z$1.enum([
9359
+ "default",
9360
+ "primary",
9361
+ "secondary",
9362
+ "inverted",
9363
+ "outline",
9364
+ "ghost"
9365
+ ]);
9366
+ const navContainerSchema = z$1.object({
9367
+ type: z$1.enum([
9368
+ "none",
9369
+ "pill",
9370
+ "glass"
9371
+ ]).default("none"),
9372
+ tint: z$1.string().nullable().optional(),
9373
+ opacity: z$1.number().min(0).max(1).default(.15)
9374
+ }).default({
9375
+ type: "none",
9376
+ tint: null,
9377
+ opacity: .15
9378
+ });
9379
+ const headerBackgroundSchema = z$1.object({
9380
+ type: z$1.enum([
9381
+ "color",
9382
+ "gradient",
9383
+ "image"
9384
+ ]),
9385
+ contentOwner: z$1.literal(siteChromeBackgroundOverrideOwner).optional(),
9386
+ color: tokenOrCssColorValueSchema.nullable().optional(),
9387
+ gradient: gradientConfigSchema.nullable().optional(),
9388
+ image: mediaSchema$1.nullable().optional(),
9389
+ textColor: tokenOrCssColorValueSchema.nullable().optional()
9390
+ });
9391
+ const headerSchema = z$1.object({
9392
+ variant: headerVariant,
9393
+ positioning: headerPositioning,
9394
+ shrinkOnScroll: z$1.boolean(),
9395
+ maxWidth: headerMaxWidth,
9396
+ barFrame: headerBarFrame.optional(),
9397
+ logoOverride: mediaSchema$1.nullable().optional(),
9398
+ background: headerBackgroundSchema.default({
9399
+ type: "color",
9400
+ color: "surface"
9401
+ }),
9402
+ textColor: themeColorTokenSchema.nullable().optional(),
9403
+ navStyle: headerNavStyle,
9404
+ navColor: themeColorTokenSchema.nullable().optional(),
9405
+ navWeight: navFontWeight.default("medium"),
9406
+ navFontRole: z$1.enum(["body", "heading"]).optional(),
9407
+ navTypography: z$1.enum(["body", "heading"]).optional(),
9408
+ navTextSize: navLinkStyleSchema.shape.textSize,
9409
+ navPlacement: z$1.enum(["end", "center"]).optional(),
9410
+ container: headerContainerSchema,
9411
+ border: headerBorderSchema,
9412
+ shadow: componentShadowSchema.optional(),
9413
+ logo: logoStyleSchema,
9414
+ logoText: headerLogoTextSchema,
9415
+ navEffects: navEffectsSchema,
9416
+ navContainer: navContainerSchema,
9417
+ navLinkStyle: navLinkStyleSchema.optional(),
9418
+ ctaGap: headerCtaGapSchema.optional(),
9419
+ ctaTreatment: headerCtaTreatmentSchema.optional(),
9420
+ ctaVariant: z$1.string().min(1).optional(),
9421
+ dropdownStyle: dropdownStyleSchema
9422
+ }).transform(normaliseHeaderNavFontRole);
9423
+ /**
9424
+ * Normalises the legacy `navTypography` font-role alias into the canonical
9425
+ * `navFontRole` field so persisted themes migrate at the parse boundary without
9426
+ * a data migration. `navFontRole` always wins when both are present; the legacy
9427
+ * field is dropped so we never carry a dual write forward.
9428
+ */
9429
+ function normaliseHeaderNavFontRole(header) {
9430
+ if (header.navTypography === void 0) return header;
9431
+ const { navTypography, ...rest } = header;
9432
+ return header.navFontRole === void 0 ? {
9433
+ ...rest,
9434
+ navFontRole: navTypography
9435
+ } : rest;
9436
+ }
9437
+ const footerVariant = z$1.enum([
9438
+ "simple",
9439
+ "columns",
9440
+ "split"
7625
9441
  ]);
7626
- const buttonTypographySchema = z$1.enum(["body", "heading"]);
7627
- const letterSpacingSchema = z$1.enum([
7628
- "tight",
7629
- "normal",
7630
- "loose"
9442
+ const footerMaxWidth = z$1.enum(["container", "full"]);
9443
+ const footerMode = z$1.enum([
9444
+ "default",
9445
+ "blocks",
9446
+ "default+blocks",
9447
+ "none"
7631
9448
  ]);
7632
- const hoverTransformSchema = z$1.enum([
7633
- "none",
7634
- "lift",
7635
- "scale",
7636
- "press"
9449
+ const footerNavLayoutMode = z$1.enum([
9450
+ "stack",
9451
+ "inline",
9452
+ "inline-wrap"
7637
9453
  ]);
7638
- const hoverColorSchema = z$1.enum([
7639
- "none",
7640
- "brighten",
7641
- "darken",
7642
- "saturate",
7643
- "token"
9454
+ const footerNavLayoutAlign = z$1.enum([
9455
+ "start",
9456
+ "center",
9457
+ "end",
9458
+ "space-between"
7644
9459
  ]);
7645
- const buttonPaddingPresetSchema = z$1.enum([
9460
+ const footerSpacing = z$1.enum([
9461
+ "none",
9462
+ "tight",
7646
9463
  "compact",
7647
9464
  "default",
9465
+ "relaxed",
7648
9466
  "spacious"
7649
9467
  ]);
7650
- const gradientStyleSchema = z$1.enum([
7651
- "linear",
7652
- "radial",
7653
- "conic"
7654
- ]);
7655
- const gradientSharpnessSchema = z$1.enum([
7656
- "smooth",
7657
- "medium",
7658
- "hard"
9468
+ const footerLogoPlacement = z$1.enum([
9469
+ "left",
9470
+ "right",
9471
+ "above",
9472
+ "below"
7659
9473
  ]);
7660
- const prioritySchema = z$1.union([
7661
- z$1.literal(1),
7662
- z$1.literal(2),
7663
- z$1.literal(3)
9474
+ const footerLogoSize = z$1.enum([
9475
+ "sm",
9476
+ "md",
9477
+ "lg",
9478
+ "xl"
7664
9479
  ]);
7665
- z$1.enum(VARIANT_ROLES);
7666
- const buttonSizeNameSchema = z$1.enum([
9480
+ const footerLogoMaxHeight = z$1.enum([
7667
9481
  "sm",
7668
9482
  "md",
7669
9483
  "lg",
7670
9484
  "xl"
7671
9485
  ]);
7672
- /**
7673
- * CSS padding string in `"<vertical> <horizontal>"` shorthand form.
7674
- *
7675
- * Exactly two space-separated CSS length tokens. Each token is either the
7676
- * literal `0` or a number followed by `rem`/`em`/`px`/`%`. This lets the
7677
- * generator trust the shape rather than defensively defaulting downstream.
7678
- */
7679
- const PADDING_TOKEN_PATTERN = /^(?:0|\d+(?:\.\d+)?(?:rem|em|px|%))$/;
7680
- const paddingShorthandSchema = z$1.string().refine((value) => {
7681
- const parts = value.split(/\s+/).filter(Boolean);
7682
- return parts.length === 2 && parts.every((token) => PADDING_TOKEN_PATTERN.test(token));
7683
- }, { message: "Padding must be two space-separated CSS length tokens (e.g. \"0.5rem 1rem\"). Use `0` for zero." });
7684
- const buttonSizeConfigSchema = z$1.object({
7685
- padding: paddingShorthandSchema,
7686
- fontSize: z$1.string().optional()
9486
+ const footerBottomTextLinkStyleSchema = z$1.object({
9487
+ colorToken: themeColorTokenSchema.optional(),
9488
+ hoverColorToken: themeColorTokenSchema.nullable().optional(),
9489
+ decorationColorToken: themeColorTokenSchema.nullable().optional(),
9490
+ underline: z$1.boolean().optional()
7687
9491
  });
7688
- /**
7689
- * `xl` is optional on the wire so themes persisted before the `xl` size was
7690
- * added (e.g. SWTS) continue to parse. When `xl` is missing the schema
7691
- * backfills it from `lg`, keeping `ButtonSizes` a complete `sm/md/lg/xl` map
7692
- * downstream — generators never need to deal with an undefined `xl`.
7693
- */
7694
- const buttonSizesSchema = z$1.object({
7695
- sm: buttonSizeConfigSchema,
7696
- md: buttonSizeConfigSchema,
7697
- lg: buttonSizeConfigSchema,
7698
- xl: buttonSizeConfigSchema.optional()
7699
- }).transform(({ sm, md, lg, xl }) => ({
7700
- sm,
7701
- md,
7702
- lg,
7703
- xl: xl ?? lg
7704
- }));
7705
- const canonicalButtonGlobalSettingsSchema = z$1.object({
7706
- cornerStyle: cornerStyleSchema,
7707
- cornerRadius: z$1.number().min(0).max(24).optional(),
7708
- /**
7709
- * Family-level shadow inherited by variants that don't set their own.
7710
- * Optional and flat-by-default: when omitted, buttons carry no drop shadow
7711
- * (`elevation: 'none'`). A personality opts the whole family into a shadow by
7712
- * setting this; individual variants still override. There is no system-level
7713
- * shadow-by-default — shadows only appear when explicitly declared.
7714
- */
7715
- shadow: shadowSizeSchema.optional(),
7716
- textTransform: textTransformSchema,
7717
- fontWeight: fontWeightSchema,
9492
+ const footerBottomBarSchema = z$1.object({
9493
+ enabled: z$1.boolean().optional(),
9494
+ fullBleed: z$1.boolean().optional(),
9495
+ background: headerBackgroundSchema.optional(),
9496
+ textColor: themeColorTokenSchema.nullable().optional(),
9497
+ textAlign: z$1.enum([
9498
+ "left",
9499
+ "center",
9500
+ "right"
9501
+ ]).optional(),
9502
+ paddingY: footerSpacing.optional(),
9503
+ paddingX: footerSpacing.optional(),
9504
+ borderTop: z$1.object({
9505
+ colorToken: themeColorTokenSchema.nullable().optional(),
9506
+ width: z$1.enum([
9507
+ "none",
9508
+ "thin",
9509
+ "medium",
9510
+ "thick"
9511
+ ]).optional()
9512
+ }).optional()
9513
+ });
9514
+ const footerNavLayoutSchema = z$1.object({
9515
+ layout: footerNavLayoutMode.optional(),
9516
+ align: footerNavLayoutAlign.optional(),
9517
+ gapX: footerSpacing.optional(),
9518
+ gapY: footerSpacing.optional(),
9519
+ columns: z$1.number().int().min(1).max(6).optional()
9520
+ });
9521
+ const footerLogoSchema = z$1.object({
9522
+ showLogo: z$1.boolean().default(true),
9523
+ showLogoText: z$1.boolean().optional(),
9524
+ placement: footerLogoPlacement.optional(),
9525
+ size: footerLogoSize.optional(),
9526
+ maxHeight: footerLogoMaxHeight.optional(),
9527
+ align: z$1.enum([
9528
+ "start",
9529
+ "center",
9530
+ "end"
9531
+ ]).optional()
9532
+ });
9533
+ const footerSchema = z$1.object({
7718
9534
  /**
7719
- * @deprecated Set per-variant via `variant.border.widthClass` instead.
7720
- * Schema field is preserved so existing presets parse; the value is unread
7721
- * by the current generator and will be removed once the legacy
7722
- * `primitives/content/components/Button.tsx` slot exports are deleted.
9535
+ * SDK-only footer rendering mode.
9536
+ *
9537
+ * Backwards compatible: missing/undefined behaves as 'default'.
7723
9538
  */
7724
- borderWidth: z$1.union([
7725
- z$1.literal(1),
7726
- z$1.literal(2),
7727
- z$1.literal(3)
7728
- ]),
7729
- typography: buttonTypographySchema.optional(),
7730
- fontSize: z$1.string().optional(),
7731
- letterSpacing: letterSpacingSchema.optional(),
7732
- italic: z$1.boolean().optional(),
7733
- paddingPreset: buttonPaddingPresetSchema.optional(),
7734
- hoverTransform: hoverTransformSchema,
7735
- hoverColor: hoverColorSchema,
7736
- hoverColorToken: opaqueButtonColourTokenSchema.optional(),
7737
- gradientStyle: gradientStyleSchema.optional(),
7738
- gradientAngle: z$1.number().min(0).max(360).optional(),
7739
- gradientSharpness: gradientSharpnessSchema.optional()
9539
+ mode: footerMode.optional(),
9540
+ variant: footerVariant,
9541
+ maxWidth: footerMaxWidth,
9542
+ showLogoText: z$1.boolean().optional(),
9543
+ background: headerBackgroundSchema.default({
9544
+ type: "color",
9545
+ color: "surface"
9546
+ }),
9547
+ navStyle: headerNavStyle.default("minimal"),
9548
+ navColor: themeColorTokenSchema.nullable().optional(),
9549
+ navWeight: navFontWeight.default("medium"),
9550
+ navLinkStyle: navLinkStyleSchema.optional(),
9551
+ bottomTextLinkStyle: footerBottomTextLinkStyleSchema.optional(),
9552
+ navLayout: footerNavLayoutSchema.optional(),
9553
+ logo: footerLogoSchema.optional(),
9554
+ bottomBar: footerBottomBarSchema.optional()
7740
9555
  });
7741
- const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
7742
- const gradientDirectionSchema = z$1.enum([
7743
- "to-r",
7744
- "to-l",
7745
- "to-t",
7746
- "to-b",
7747
- "to-tr",
7748
- "to-tl",
7749
- "to-br",
7750
- "to-bl"
9556
+ const containerPaddingPresetSchema = z$1.enum([
9557
+ "tight",
9558
+ "compact",
9559
+ "default",
9560
+ "relaxed"
7751
9561
  ]);
7752
- const buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
7753
- z$1.object({
7754
- type: z$1.literal("solid"),
7755
- colorToken: opaqueButtonColourTokenSchema
7756
- }),
7757
- z$1.object({
7758
- type: z$1.literal("gradient"),
7759
- stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
7760
- const [first, second, ...rest] = stops;
7761
- if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
7762
- return [
7763
- first,
7764
- second,
7765
- ...rest
7766
- ];
7767
- }),
7768
- direction: gradientDirectionSchema,
7769
- foregroundToken: opaqueButtonColourTokenSchema
7770
- }),
7771
- z$1.object({
7772
- type: z$1.literal("surface"),
7773
- role: z$1.literal("link")
7774
- })
9562
+ const layoutSchema = z$1.object({ containerPadding: z$1.object({
9563
+ mobile: containerPaddingPresetSchema.optional(),
9564
+ tablet: containerPaddingPresetSchema.optional(),
9565
+ desktop: containerPaddingPresetSchema.optional()
9566
+ }).optional() }).optional();
9567
+ const heroTypographySizeSchema = z$1.enum([
9568
+ "sm",
9569
+ "base",
9570
+ "lg",
9571
+ "xl",
9572
+ "2xl",
9573
+ "3xl",
9574
+ "4xl",
9575
+ "5xl",
9576
+ "6xl",
9577
+ "editorial"
7775
9578
  ]);
7776
- const buttonBackgroundSchema = buttonColourTreatmentSchema;
7777
- const effectApplicationSchema = z$1.object({
7778
- effectId: z$1.string(),
7779
- options: z$1.record(z$1.string(), z$1.json()).optional()
9579
+ const heroTypographyLineHeightSchema = z$1.enum([
9580
+ "tight",
9581
+ "snug",
9582
+ "normal",
9583
+ "relaxed"
9584
+ ]);
9585
+ const heroResponsiveTypographySchema = z$1.object({
9586
+ headlineSize: heroTypographySizeSchema.optional(),
9587
+ headlineLineHeight: heroTypographyLineHeightSchema.optional(),
9588
+ subheadlineSize: heroTypographySizeSchema.optional(),
9589
+ subheadlineLineHeight: heroTypographyLineHeightSchema.optional()
7780
9590
  });
7781
- const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
7782
- const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
7783
- const variantShadowSchema = z$1.object({
7784
- elevation: z$1.enum([
7785
- "none",
7786
- "low",
7787
- "medium",
7788
- "high"
7789
- ]),
7790
- softness: z$1.enum([
7791
- "crisp",
7792
- "soft",
7793
- "hard"
7794
- ]).nullable(),
7795
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
7796
- colorToken: themeColorTokenSchema.optional()
9591
+ const heroTypographySchema = z$1.object({
9592
+ headlineSize: heroTypographySizeSchema.optional(),
9593
+ headlineLineHeight: heroTypographyLineHeightSchema.optional(),
9594
+ subheadlineSize: heroTypographySizeSchema.optional(),
9595
+ subheadlineLineHeight: heroTypographyLineHeightSchema.optional(),
9596
+ microHeadlineSize: heroTypographySizeSchema.optional(),
9597
+ microHeadlineLineHeight: heroTypographyLineHeightSchema.optional(),
9598
+ microSubheadlineSize: heroTypographySizeSchema.optional(),
9599
+ microSubheadlineLineHeight: heroTypographyLineHeightSchema.optional(),
9600
+ responsive: z$1.object({
9601
+ tablet: heroResponsiveTypographySchema.optional(),
9602
+ mobile: heroResponsiveTypographySchema.optional()
9603
+ }).optional()
7797
9604
  });
7798
- const variantEffectsSchema = z$1.object({
7799
- base: z$1.array(effectApplicationSchema).optional(),
7800
- hover: z$1.array(effectApplicationSchema).optional(),
7801
- active: z$1.array(effectApplicationSchema).optional(),
7802
- focus: z$1.array(effectApplicationSchema).optional()
9605
+ const heroSchema = z$1.object({ typography: heroTypographySchema.optional() }).optional();
9606
+ const bodyTextIntroTypographySizeSchema = z$1.enum(["default", "editorial"]);
9607
+ const bodyTextSchema = z$1.object({ intro: z$1.object({
9608
+ paragraphSize: bodyTextIntroTypographySizeSchema.optional(),
9609
+ headingSize: bodyTextIntroTypographySizeSchema.optional()
9610
+ }).optional() }).optional();
9611
+ const gradientsSchema = z$1.object({
9612
+ button: z$1.string().min(1).nullable().optional(),
9613
+ hero: z$1.string().min(1).nullable().optional(),
9614
+ background: z$1.string().min(1).nullable().optional()
7803
9615
  });
7804
9616
  /**
7805
- * Per-variant size overrides schema — every entry is optional.
7806
- *
7807
- * For each size key present, the values override the theme's `sizes` config
7808
- * for that size on this variant. Missing sizes fall through to theme.sizes,
7809
- * then system defaults.
9617
+ * Testimonial quote-mark treatment, owned by the site style (analogous to the
9618
+ * accordion icon). `style` is the coarse selector; the optional fields fine-tune
9619
+ * it. `none` hides the mark. The block renders the mark; the site style decides
9620
+ * its character; a look may still hide it.
7810
9621
  */
7811
- const variantSizeOverridesSchema = z$1.object({
7812
- sm: buttonSizeConfigSchema.optional(),
7813
- md: buttonSizeConfigSchema.optional(),
7814
- lg: buttonSizeConfigSchema.optional(),
7815
- xl: buttonSizeConfigSchema.optional()
9622
+ const testimonialQuoteTreatmentSchema = z$1.object({
9623
+ style: z$1.enum([
9624
+ "serif-display",
9625
+ "accent-glyph",
9626
+ "none"
9627
+ ]),
9628
+ fontFamily: z$1.enum(["heading", "body"]).optional(),
9629
+ scale: z$1.enum([
9630
+ "sm",
9631
+ "md",
9632
+ "lg",
9633
+ "xl"
9634
+ ]).optional(),
9635
+ colorToken: themeColorTokenSchema.optional(),
9636
+ opacity: z$1.number().min(0).max(1).optional()
7816
9637
  });
7817
- /**
7818
- * Unified variant schema. Every variant participates in the size system; the
7819
- * optional `sizes` field lets a variant scale differently than the theme
7820
- * default (e.g. link-style variants declaring zero horizontal padding at
7821
- * every size).
7822
- */
7823
- const canonicalButtonVariantSchema = z$1.object({
7824
- id: z$1.string(),
7825
- name: z$1.string().min(1).max(20),
7826
- enabled: z$1.boolean(),
7827
- priority: prioritySchema,
7828
- background: buttonBackgroundSchema,
7829
- /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
7830
- borderRadius: z$1.string().optional(),
7831
- shadow: variantShadowSchema.optional(),
7832
- border: buttonBorderSchema.optional(),
7833
- hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
7834
- effects: variantEffectsSchema.optional(),
7835
- sizes: variantSizeOverridesSchema.optional(),
7836
- affordance: buttonVariantAffordanceSchema.optional()
9638
+ const themeSchema = z$1.object({
9639
+ name: z$1.string().min(1).max(30),
9640
+ description: z$1.string().min(1).max(400),
9641
+ rationale: z$1.string().min(1).max(400),
9642
+ siteStyleId: z$1.string().min(1).transform((value) => asSiteStyleId(value)).optional(),
9643
+ axes: axesSchema,
9644
+ palette: paletteSchema,
9645
+ typography: typographySchema,
9646
+ space: spaceSchema,
9647
+ border,
9648
+ shadow,
9649
+ motion,
9650
+ corners,
9651
+ gradients: gradientsSchema.optional(),
9652
+ layout: layoutSchema,
9653
+ hero: heroSchema,
9654
+ bodyText: bodyTextSchema,
9655
+ header: headerSchema,
9656
+ footer: footerSchema,
9657
+ buttons: buttonSystemSchema.optional(),
9658
+ cards: cardSystemSchema.optional(),
9659
+ accordions: accordionSystemSchema.optional(),
9660
+ testimonialQuote: testimonialQuoteTreatmentSchema.optional(),
9661
+ inputs: inputSystemSchema.optional(),
9662
+ inputStyle: inputStyle.optional(),
9663
+ blockCustomVars: z$1.record(z$1.string(), z$1.record(z$1.string(), z$1.string())).optional(),
9664
+ blockOverrides: z$1.record(z$1.string(), blockThemeOverrideSchema).optional(),
9665
+ headingDecoration: headingDecorationSchema.optional(),
9666
+ customCssRules: customCssRulesSchema,
9667
+ blockCustomCssRules: blockCustomCssRulesSchema,
9668
+ customCssAtRules: customCssAtRulesSchema,
9669
+ /**
9670
+ * Style groups define named visual presets that content authors can apply to blocks.
9671
+ *
9672
+ * Unlike variants (which change block structure/layout), style groups only affect
9673
+ * CSS styling. The selected style group is rendered as a `data-style-group` attribute
9674
+ * on the block wrapper, which can be targeted in `blockCustomCssRules`.
9675
+ *
9676
+ * @example
9677
+ * ```typescript
9678
+ * {
9679
+ * styleGroups: {
9680
+ * hero: ['bold', 'minimal', 'featured'],
9681
+ * 'body-text': ['intro', 'compact'],
9682
+ * },
9683
+ * blockCustomCssRules: [
9684
+ * {
9685
+ * id: 'hero-bold-headline',
9686
+ * blockKind: 'hero',
9687
+ * selector: '&[data-style-group="bold"] .hero-headline',
9688
+ * declarations: { fontWeight: '800', fontSize: '3rem' }
9689
+ * }
9690
+ * ]
9691
+ * }
9692
+ * ```
9693
+ */
9694
+ styleGroups: z$1.record(z$1.string(), z$1.array(z$1.string())).optional()
7837
9695
  });
7838
- /**
7839
- * Temporary persisted-theme admission boundary for issue #1206.
7840
- *
7841
- * Production inventory on 2026-07-22 found 22 rows using the old independent
7842
- * `textColorToken`/border colour shape. New source and all downstream code use
7843
- * only the canonical relationship. Delete this preprocessor after the reviewed
7844
- * production rewrite reports zero legacy rows.
7845
- */
7846
- const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
7847
- const buttonSystemSchema = z$1.object({
7848
- global: buttonGlobalSettingsSchema,
7849
- variants: z$1.array(buttonVariantSchema).min(1).max(6),
7850
- sizes: buttonSizesSchema.optional()
9696
+ z$1.object({
9697
+ message: z$1.string().min(1),
9698
+ themes: z$1.array(themeSchema).length(3)
7851
9699
  });
7852
- function normalizeLegacyButtonVariantInput(input) {
7853
- if (!isUnknownRecord(input)) return input;
7854
- const background = input.background;
7855
- if (!isUnknownRecord(background)) return input;
7856
- 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;
7857
- const { textColorToken, ...withoutLegacyText } = input;
7858
- const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
7859
- const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
7860
- const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
7861
- const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
7862
- if (background.type === "transparent") return {
7863
- ...withoutLegacyText,
7864
- background: {
7865
- type: "surface",
7866
- role: "link"
7867
- },
7868
- border: normalizedBorder,
7869
- affordance: normalizedAffordance,
7870
- effects: normalizedEffects,
7871
- hoverBackgroundToken
7872
- };
7873
- if (background.type === "gradient") {
7874
- const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
7875
- return {
7876
- ...withoutLegacyText,
7877
- background: {
7878
- ...background,
7879
- stops,
7880
- foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
7881
- },
7882
- border: normalizedBorder,
7883
- affordance: normalizedAffordance,
7884
- effects: normalizedEffects,
7885
- hoverBackgroundToken
7886
- };
7887
- }
7888
- return {
7889
- ...withoutLegacyText,
7890
- background: background.type === "solid" ? {
7891
- ...background,
7892
- colorToken: stripLegacyTokenAlpha(background.colorToken)
7893
- } : background,
7894
- border: normalizedBorder,
7895
- affordance: normalizedAffordance,
7896
- effects: normalizedEffects,
7897
- hoverBackgroundToken
7898
- };
7899
- }
7900
- function normalizeLegacyButtonGlobalInput(input) {
7901
- if (!isUnknownRecord(input)) return input;
7902
- const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
7903
- return hoverColorToken === input.hoverColorToken ? input : {
7904
- ...input,
7905
- hoverColorToken
7906
- };
7907
- }
7908
- function hasLegacyAlphaToken(input, background) {
7909
- const stops = isUnknownArray(background.stops) ? background.stops : [];
7910
- return [
7911
- input.hoverBackgroundToken,
7912
- background.colorToken,
7913
- background.foregroundToken,
7914
- ...stops
7915
- ].some((token) => stripLegacyTokenAlpha(token) !== token);
7916
- }
7917
- function stripLegacyTokenAlpha(value) {
7918
- if (typeof value !== "string") return value;
7919
- const slashIndex = value.indexOf("/");
7920
- return slashIndex < 0 ? value : value.slice(0, slashIndex);
7921
- }
7922
- function hasLegacyButtonEffects(input) {
7923
- if (!isUnknownRecord(input)) return false;
7924
- return [
7925
- "base",
7926
- "hover",
7927
- "active",
7928
- "focus"
7929
- ].some((state) => {
7930
- const effects = input[state];
7931
- return Array.isArray(effects) && effects.some((effect) => {
7932
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
7933
- const classification = classifyButtonEffectId(effect.effectId);
7934
- if (classification !== "colour-transition" && classification !== "non-colour") return true;
7935
- return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
7936
- });
7937
- });
7938
- }
7939
- function normalizeLegacyButtonEffects(input, backgroundType) {
7940
- if (!isUnknownRecord(input)) return input;
7941
- const normalized = {};
7942
- for (const state of [
7943
- "base",
7944
- "hover",
7945
- "active",
7946
- "focus"
7947
- ]) {
7948
- const effects = input[state];
7949
- if (!Array.isArray(effects)) continue;
7950
- const safeEffects = effects.flatMap((effect) => {
7951
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
7952
- const classification = classifyButtonEffectId(effect.effectId);
7953
- if (classification === "non-colour") return [effect];
7954
- if (classification !== "colour-transition") return [];
7955
- if (effect.effectId === "background-on-hover") {
7956
- const options = isUnknownRecord(effect.options) ? effect.options : null;
7957
- const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
7958
- return colorToken === null ? [] : [{
7959
- ...effect,
7960
- options: {
7961
- ...options,
7962
- colorToken
7963
- }
7964
- }];
7965
- }
7966
- if (backgroundType !== "solid") return [];
7967
- const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
7968
- const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
7969
- return [{
7970
- ...effect,
7971
- options: {
7972
- ...isUnknownRecord(effect.options) ? effect.options : {},
7973
- amount
7974
- }
7975
- }];
7976
- });
7977
- if (safeEffects.length > 0) normalized[state] = safeEffects;
7978
- }
7979
- return Object.keys(normalized).length === 0 ? void 0 : normalized;
7980
- }
7981
- function isUnknownRecord(value) {
7982
- return typeof value === "object" && value !== null && !Array.isArray(value);
7983
- }
7984
- function isUnknownArray(value) {
7985
- return Array.isArray(value);
7986
- }
7987
9700
  //#endregion
7988
9701
  //#region ../theme-core/src/buttons/classNames.ts
7989
9702
  function themeButtonVariantClassNames(variant) {
@@ -8155,7 +9868,6 @@ const quietArrowRecipe = defineButtonStyleRecipe({
8155
9868
  cornerStyle: "rounded",
8156
9869
  textTransform: "uppercase",
8157
9870
  fontWeight: 500,
8158
- borderWidth: 1,
8159
9871
  typography: "body",
8160
9872
  fontSize: "text-sm",
8161
9873
  letterSpacing: "loose",
@@ -8219,7 +9931,7 @@ const quietArrowRecipe = defineButtonStyleRecipe({
8219
9931
  affordance: { iconId: "ArrowRight" },
8220
9932
  effects: { hover: [{
8221
9933
  effectId: "background-on-hover",
8222
- options: { colorToken: "surfaceAlt" }
9934
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
8223
9935
  }] }
8224
9936
  }
8225
9937
  },
@@ -8330,7 +10042,6 @@ const softPillRecipe = defineStaticButtonStyleRecipe({
8330
10042
  shadow: "low",
8331
10043
  textTransform: "none",
8332
10044
  fontWeight: 500,
8333
- borderWidth: 2,
8334
10045
  hoverTransform: "lift",
8335
10046
  hoverColor: "none"
8336
10047
  },
@@ -8349,10 +10060,7 @@ const softPillRecipe = defineStaticButtonStyleRecipe({
8349
10060
  position: "bottom"
8350
10061
  },
8351
10062
  effects: {
8352
- hover: [{
8353
- effectId: "lift",
8354
- options: { translateY: "-1px" }
8355
- }],
10063
+ hover: [{ effectId: "lift" }],
8356
10064
  active: [{
8357
10065
  effectId: "scale-down",
8358
10066
  options: { scale: "0.98" }
@@ -8371,7 +10079,7 @@ const softPillRecipe = defineStaticButtonStyleRecipe({
8371
10079
  border: { widthClass: "border-2" },
8372
10080
  effects: { hover: [{
8373
10081
  effectId: "background-on-hover",
8374
- options: { colorToken: "surface" }
10082
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8375
10083
  }] }
8376
10084
  }
8377
10085
  },
@@ -8386,7 +10094,7 @@ const softPillRecipe = defineStaticButtonStyleRecipe({
8386
10094
  border: { widthClass: "border" },
8387
10095
  effects: { hover: [{
8388
10096
  effectId: "background-on-hover",
8389
- options: { colorToken: "surface" }
10097
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8390
10098
  }] }
8391
10099
  }
8392
10100
  },
@@ -8400,7 +10108,7 @@ const softPillRecipe = defineStaticButtonStyleRecipe({
8400
10108
  borderRadius: "rounded-full",
8401
10109
  effects: { hover: [{
8402
10110
  effectId: "background-on-hover",
8403
- options: { colorToken: "surface" }
10111
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8404
10112
  }] }
8405
10113
  }
8406
10114
  },
@@ -8430,7 +10138,6 @@ const earthPillRecipe = defineStaticButtonStyleRecipe({
8430
10138
  shadow: "low",
8431
10139
  textTransform: "none",
8432
10140
  fontWeight: 500,
8433
- borderWidth: 1,
8434
10141
  hoverTransform: "lift",
8435
10142
  hoverColor: "none",
8436
10143
  typography: "body",
@@ -8466,12 +10173,9 @@ const earthPillRecipe = defineStaticButtonStyleRecipe({
8466
10173
  position: "bottom"
8467
10174
  },
8468
10175
  effects: {
8469
- hover: [{
8470
- effectId: "lift",
8471
- options: { translateY: "-1px" }
8472
- }, {
10176
+ hover: [{ effectId: "lift" }, {
8473
10177
  effectId: "background-on-hover",
8474
- options: { colorToken: "accent" }
10178
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("accent") }
8475
10179
  }],
8476
10180
  active: [{
8477
10181
  effectId: "scale-down",
@@ -8491,7 +10195,7 @@ const earthPillRecipe = defineStaticButtonStyleRecipe({
8491
10195
  border: { widthClass: "border" },
8492
10196
  effects: { hover: [{
8493
10197
  effectId: "background-on-hover",
8494
- options: { colorToken: "muted" }
10198
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("muted") }
8495
10199
  }] }
8496
10200
  }
8497
10201
  },
@@ -8506,7 +10210,7 @@ const earthPillRecipe = defineStaticButtonStyleRecipe({
8506
10210
  border: { widthClass: "border" },
8507
10211
  effects: { hover: [{
8508
10212
  effectId: "background-on-hover",
8509
- options: { colorToken: "surfaceAlt" }
10213
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
8510
10214
  }] }
8511
10215
  }
8512
10216
  },
@@ -8566,7 +10270,6 @@ const confidentChipRecipe = defineStaticButtonStyleRecipe({
8566
10270
  shadow: "medium",
8567
10271
  textTransform: "none",
8568
10272
  fontWeight: 600,
8569
- borderWidth: 1,
8570
10273
  hoverTransform: "none",
8571
10274
  hoverColor: "none"
8572
10275
  },
@@ -8607,7 +10310,7 @@ const confidentChipRecipe = defineStaticButtonStyleRecipe({
8607
10310
  border: { widthClass: "border" },
8608
10311
  effects: { hover: [{
8609
10312
  effectId: "background-on-hover",
8610
- options: { colorToken: "background" }
10313
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("background") }
8611
10314
  }] }
8612
10315
  }
8613
10316
  },
@@ -8622,7 +10325,7 @@ const confidentChipRecipe = defineStaticButtonStyleRecipe({
8622
10325
  border: { widthClass: "border" },
8623
10326
  effects: { hover: [{
8624
10327
  effectId: "background-on-hover",
8625
- options: { colorToken: "surface" }
10328
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8626
10329
  }] }
8627
10330
  }
8628
10331
  },
@@ -8636,7 +10339,7 @@ const confidentChipRecipe = defineStaticButtonStyleRecipe({
8636
10339
  borderRadius: "rounded-md",
8637
10340
  effects: { hover: [{
8638
10341
  effectId: "background-on-hover",
8639
- options: { colorToken: "surface" }
10342
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8640
10343
  }] }
8641
10344
  }
8642
10345
  },
@@ -8671,7 +10374,6 @@ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
8671
10374
  cornerStyle: "square",
8672
10375
  textTransform: "none",
8673
10376
  fontWeight: 500,
8674
- borderWidth: 1,
8675
10377
  hoverTransform: "none",
8676
10378
  hoverColor: "none"
8677
10379
  },
@@ -8689,7 +10391,6 @@ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
8689
10391
  effectId: "border-bottom-grow",
8690
10392
  options: {
8691
10393
  height: 2,
8692
- colorToken: "text",
8693
10394
  origin: "left"
8694
10395
  }
8695
10396
  }] }
@@ -8708,7 +10409,6 @@ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
8708
10409
  effectId: "border-bottom-grow",
8709
10410
  options: {
8710
10411
  height: 1,
8711
- colorToken: "mutedText",
8712
10412
  origin: "left"
8713
10413
  }
8714
10414
  }] }
@@ -8727,7 +10427,6 @@ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
8727
10427
  effectId: "border-bottom-grow",
8728
10428
  options: {
8729
10429
  height: 1,
8730
- colorToken: "accent",
8731
10430
  origin: "left"
8732
10431
  }
8733
10432
  }] }
@@ -8751,7 +10450,6 @@ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
8751
10450
  effectId: "border-bottom-grow",
8752
10451
  options: {
8753
10452
  height: 2,
8754
- colorToken: "accent",
8755
10453
  origin: "left"
8756
10454
  }
8757
10455
  }] } }
@@ -8773,7 +10471,6 @@ const pebbleRecipe = defineStaticButtonStyleRecipe({
8773
10471
  cornerStyle: "pill",
8774
10472
  textTransform: "none",
8775
10473
  fontWeight: 500,
8776
- borderWidth: 2,
8777
10474
  hoverTransform: "none",
8778
10475
  hoverColor: "none"
8779
10476
  },
@@ -8818,7 +10515,7 @@ const pebbleRecipe = defineStaticButtonStyleRecipe({
8818
10515
  border: { widthClass: "border-2" },
8819
10516
  effects: { hover: [{
8820
10517
  effectId: "background-on-hover",
8821
- options: { colorToken: "accent" }
10518
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("accent") }
8822
10519
  }] }
8823
10520
  }
8824
10521
  },
@@ -8833,7 +10530,7 @@ const pebbleRecipe = defineStaticButtonStyleRecipe({
8833
10530
  border: { widthClass: "border" },
8834
10531
  effects: { hover: [{
8835
10532
  effectId: "background-on-hover",
8836
- options: { colorToken: "surface" }
10533
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8837
10534
  }] }
8838
10535
  }
8839
10536
  },
@@ -8888,7 +10585,6 @@ const brushedWashRecipe = defineStaticButtonStyleRecipe({
8888
10585
  shadow: "low",
8889
10586
  textTransform: "none",
8890
10587
  fontWeight: 500,
8891
- borderWidth: 1,
8892
10588
  hoverTransform: "none",
8893
10589
  hoverColor: "none"
8894
10590
  },
@@ -8953,7 +10649,7 @@ const brushedWashRecipe = defineStaticButtonStyleRecipe({
8953
10649
  border: { widthClass: "border" },
8954
10650
  effects: { hover: [{
8955
10651
  effectId: "background-on-hover",
8956
- options: { colorToken: "surface" }
10652
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8957
10653
  }] }
8958
10654
  }
8959
10655
  },
@@ -8967,7 +10663,7 @@ const brushedWashRecipe = defineStaticButtonStyleRecipe({
8967
10663
  borderRadius: "rounded-lg",
8968
10664
  effects: { hover: [{
8969
10665
  effectId: "background-on-hover",
8970
- options: { colorToken: "surface" }
10666
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
8971
10667
  }] }
8972
10668
  }
8973
10669
  },
@@ -8996,7 +10692,6 @@ const inkStampRecipe = defineStaticButtonStyleRecipe({
8996
10692
  cornerStyle: "rounded",
8997
10693
  textTransform: "uppercase",
8998
10694
  fontWeight: 600,
8999
- borderWidth: 1,
9000
10695
  hoverTransform: "none",
9001
10696
  hoverColor: "none",
9002
10697
  letterSpacing: "loose"
@@ -9054,7 +10749,7 @@ const inkStampRecipe = defineStaticButtonStyleRecipe({
9054
10749
  border: { widthClass: "border-2" },
9055
10750
  effects: { hover: [{
9056
10751
  effectId: "background-on-hover",
9057
- options: { colorToken: "surface" }
10752
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
9058
10753
  }] }
9059
10754
  }
9060
10755
  },
@@ -9069,7 +10764,7 @@ const inkStampRecipe = defineStaticButtonStyleRecipe({
9069
10764
  border: { widthClass: "border-2" },
9070
10765
  effects: { hover: [{
9071
10766
  effectId: "background-on-hover",
9072
- options: { colorToken: "surface" }
10767
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
9073
10768
  }] }
9074
10769
  }
9075
10770
  },
@@ -9103,7 +10798,6 @@ const inkStampRecipe = defineStaticButtonStyleRecipe({
9103
10798
  effectId: "border-bottom-grow",
9104
10799
  options: {
9105
10800
  height: 1,
9106
- colorToken: "accent",
9107
10801
  origin: "left"
9108
10802
  }
9109
10803
  }] }
@@ -9134,7 +10828,6 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9134
10828
  cornerStyle: "rounded",
9135
10829
  textTransform: "none",
9136
10830
  fontWeight: 600,
9137
- borderWidth: 1,
9138
10831
  typography: "body",
9139
10832
  letterSpacing: "tight",
9140
10833
  paddingPreset: "default",
@@ -9166,12 +10859,9 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9166
10859
  },
9167
10860
  borderRadius: "rounded-lg",
9168
10861
  affordance: { iconId: "ArrowRight" },
9169
- effects: { hover: [{
9170
- effectId: "lift",
9171
- options: { translateY: "-2px" }
9172
- }, {
10862
+ effects: { hover: [{ effectId: "lift" }, {
9173
10863
  effectId: "background-on-hover",
9174
- options: { colorToken: "secondary" }
10864
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("secondary") }
9175
10865
  }] }
9176
10866
  }
9177
10867
  },
@@ -9184,12 +10874,9 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9184
10874
  },
9185
10875
  borderRadius: "rounded-lg",
9186
10876
  border: { widthClass: "border" },
9187
- effects: { hover: [{
9188
- effectId: "lift",
9189
- options: { translateY: "-2px" }
9190
- }, {
10877
+ effects: { hover: [{ effectId: "lift" }, {
9191
10878
  effectId: "background-on-hover",
9192
- options: { colorToken: "surfaceAlt" }
10879
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
9193
10880
  }] }
9194
10881
  }
9195
10882
  },
@@ -9202,12 +10889,9 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9202
10889
  },
9203
10890
  borderRadius: "rounded-lg",
9204
10891
  border: { widthClass: "border" },
9205
- effects: { hover: [{
9206
- effectId: "lift",
9207
- options: { translateY: "-2px" }
9208
- }, {
10892
+ effects: { hover: [{ effectId: "lift" }, {
9209
10893
  effectId: "background-on-hover",
9210
- options: { colorToken: "surfaceAlt" }
10894
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surfaceAlt") }
9211
10895
  }] }
9212
10896
  }
9213
10897
  },
@@ -9219,10 +10903,7 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9219
10903
  role: "link"
9220
10904
  },
9221
10905
  borderRadius: "rounded-lg",
9222
- effects: { hover: [{
9223
- effectId: "lift",
9224
- options: { translateY: "-2px" }
9225
- }] }
10906
+ effects: { hover: [{ effectId: "lift" }] }
9226
10907
  }
9227
10908
  },
9228
10909
  accent: {
@@ -9234,10 +10915,7 @@ const flatInkRecipe = defineStaticButtonStyleRecipe({
9234
10915
  },
9235
10916
  borderRadius: "rounded-lg",
9236
10917
  affordance: { iconId: "ArrowRight" },
9237
- effects: { hover: [{
9238
- effectId: "lift",
9239
- options: { translateY: "-2px" }
9240
- }] }
10918
+ effects: { hover: [{ effectId: "lift" }] }
9241
10919
  }
9242
10920
  }
9243
10921
  }
@@ -9258,9 +10936,8 @@ const showtimePillRecipe = defineStaticButtonStyleRecipe({
9258
10936
  shadow: "low",
9259
10937
  textTransform: "uppercase",
9260
10938
  fontWeight: 700,
9261
- borderWidth: 2,
9262
10939
  hoverTransform: "lift",
9263
- hoverColor: "darken",
10940
+ hoverColor: "none",
9264
10941
  typography: "body",
9265
10942
  paddingPreset: "spacious",
9266
10943
  italic: false
@@ -9318,7 +10995,7 @@ const showtimePillRecipe = defineStaticButtonStyleRecipe({
9318
10995
  border: { widthClass: "border-2" },
9319
10996
  effects: { hover: [{
9320
10997
  effectId: "background-on-hover",
9321
- options: { colorToken: "background" }
10998
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("background") }
9322
10999
  }] }
9323
11000
  }
9324
11001
  },
@@ -9332,7 +11009,7 @@ const showtimePillRecipe = defineStaticButtonStyleRecipe({
9332
11009
  borderRadius: "rounded-full",
9333
11010
  effects: { hover: [{
9334
11011
  effectId: "background-on-hover",
9335
- options: { colorToken: "surface" }
11012
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
9336
11013
  }] }
9337
11014
  }
9338
11015
  },
@@ -9367,7 +11044,6 @@ const joyStampRecipe = defineStaticButtonStyleRecipe({
9367
11044
  typography: "heading",
9368
11045
  fontWeight: 700,
9369
11046
  fontSize: "text-lg",
9370
- borderWidth: 2,
9371
11047
  hoverTransform: "none",
9372
11048
  hoverColor: "none"
9373
11049
  },
@@ -9402,7 +11078,7 @@ const joyStampRecipe = defineStaticButtonStyleRecipe({
9402
11078
  elevation: "high",
9403
11079
  softness: "hard",
9404
11080
  position: "bottom-right",
9405
- colorToken: "text"
11081
+ colorToken: unsafeAsOpaqueButtonColourToken("text")
9406
11082
  },
9407
11083
  effects: { hover: [{ effectId: "press-down" }] }
9408
11084
  }
@@ -9420,7 +11096,7 @@ const joyStampRecipe = defineStaticButtonStyleRecipe({
9420
11096
  elevation: "high",
9421
11097
  softness: "hard",
9422
11098
  position: "bottom-right",
9423
- colorToken: "secondary"
11099
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
9424
11100
  },
9425
11101
  effects: { hover: [{ effectId: "press-down" }] }
9426
11102
  }
@@ -9465,7 +11141,6 @@ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
9465
11141
  cornerStyle: "rounded",
9466
11142
  textTransform: "uppercase",
9467
11143
  fontWeight: 600,
9468
- borderWidth: 1,
9469
11144
  hoverTransform: "none",
9470
11145
  hoverColor: "none",
9471
11146
  letterSpacing: "loose"
@@ -9501,7 +11176,7 @@ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
9501
11176
  effects: {
9502
11177
  hover: [{
9503
11178
  effectId: "background-on-hover",
9504
- options: { colorToken: "primary-100" }
11179
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("primary-100") }
9505
11180
  }],
9506
11181
  active: [{
9507
11182
  effectId: "scale-down",
@@ -9521,7 +11196,7 @@ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
9521
11196
  border: { widthClass: "border" },
9522
11197
  effects: { hover: [{
9523
11198
  effectId: "background-on-hover",
9524
- options: { colorToken: "surface" }
11199
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("surface") }
9525
11200
  }] }
9526
11201
  }
9527
11202
  },
@@ -9536,7 +11211,7 @@ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
9536
11211
  border: { widthClass: "border" },
9537
11212
  effects: { hover: [{
9538
11213
  effectId: "background-on-hover",
9539
- options: { colorToken: "muted" }
11214
+ options: { colorToken: unsafeAsOpaqueButtonColourToken("muted") }
9540
11215
  }] }
9541
11216
  }
9542
11217
  },
@@ -9570,7 +11245,6 @@ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
9570
11245
  effectId: "border-bottom-grow",
9571
11246
  options: {
9572
11247
  height: 1,
9573
- colorToken: "accent",
9574
11248
  origin: "left"
9575
11249
  }
9576
11250
  }] }
@@ -12561,11 +14235,8 @@ const mediaSchema = z.discriminatedUnion("type", [
12561
14235
  * This module provides a single source of truth for TipTap rich text validation
12562
14236
  * across both the block-form editor and the block rendering system.
12563
14237
  *
12564
- * Format compatibility:
12565
- * - Unwrapped format (new): { type: 'doc', content: [...] }
12566
- * - Wrapped format (legacy): { doc: { type: 'doc', content: [...] } }
12567
- *
12568
- * Both formats are supported for backward compatibility during migration.
14238
+ * Rich-text fields use one canonical root shape:
14239
+ * `{ type: 'doc', content: [...] }`.
12569
14240
  */
12570
14241
  /**
12571
14242
  * TipTap document node schema (recursive structure)
@@ -12578,17 +14249,40 @@ const mediaSchema = z.discriminatedUnion("type", [
12578
14249
  * - marks: Text formatting marks (e.g., bold, italic)
12579
14250
  */
12580
14251
  const TipTapMarkSchema = z$1.object({
12581
- type: z$1.string(),
14252
+ type: z$1.string().min(1),
12582
14253
  attrs: z$1.record(z$1.string(), z$1.unknown()).optional()
12583
- });
14254
+ }).strict();
12584
14255
  const TipTapNodeSchema = z$1.lazy(() => z$1.object({
12585
- type: z$1.string(),
14256
+ type: z$1.string().min(1),
12586
14257
  content: z$1.array(TipTapNodeSchema).optional(),
12587
14258
  text: z$1.string().optional(),
12588
14259
  attrs: z$1.record(z$1.string(), z$1.unknown()).optional(),
12589
14260
  marks: z$1.array(TipTapMarkSchema).optional()
14261
+ }).strict().superRefine((node, ctx) => {
14262
+ if (node.type === "doc") ctx.addIssue({
14263
+ code: "custom",
14264
+ path: ["type"],
14265
+ message: "Document nodes are only valid at the rich-text root"
14266
+ });
14267
+ if (node.type === "text") {
14268
+ if (node.text === void 0 || node.text.length === 0) ctx.addIssue({
14269
+ code: "custom",
14270
+ path: ["text"],
14271
+ message: "Text nodes require a non-empty text value"
14272
+ });
14273
+ if (node.content !== void 0) ctx.addIssue({
14274
+ code: "custom",
14275
+ path: ["content"],
14276
+ message: "Text nodes cannot contain child nodes"
14277
+ });
14278
+ return;
14279
+ }
14280
+ if (node.text !== void 0) ctx.addIssue({
14281
+ code: "custom",
14282
+ path: ["text"],
14283
+ message: "Only text nodes can contain a text value"
14284
+ });
12590
14285
  }));
12591
- z$1.union([TipTapNodeSchema, z$1.object({ doc: TipTapNodeSchema })]);
12592
14286
  /**
12593
14287
  * Canonical schema for a TipTap rich-text document root.
12594
14288
  *
@@ -12597,13 +14291,11 @@ z$1.union([TipTapNodeSchema, z$1.object({ doc: TipTapNodeSchema })]);
12597
14291
  * (dummy content, editor output, migrations) must emit, and the shape every
12598
14292
  * non-legacy consumer can rely on.
12599
14293
  *
12600
- * Legacy envelopes are read-tolerated by {@link RichTextValueSchema} but
12601
- * normalised before reaching anywhere typed as `RichTextDoc`.
12602
14294
  */
12603
14295
  const RichTextDocSchema = z$1.object({
12604
14296
  type: z$1.literal("doc"),
12605
14297
  content: z$1.array(TipTapNodeSchema)
12606
- });
14298
+ }).strict();
12607
14299
  //#endregion
12608
14300
  //#region ../blocks/src/system/blocks/courses/shared/schemas.ts
12609
14301
  /**