@riverbankcms/sdk 0.107.0 → 0.109.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 (256) hide show
  1. package/README.md +21 -1
  2. package/dist/{PreviewEditorSidebar-DpAbAl08.mjs → PreviewEditorSidebar-DWqwfy3_.mjs} +48 -28
  3. package/dist/{PreviewEditorUI-O7cn6Xxv.mjs → PreviewEditorUI-B7OL4sfR.mjs} +10 -9
  4. package/dist/{PreviewQueryProvider-D0tnKl0t.mjs → PreviewQueryProvider-D0y2l8JN.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CVB7urtl.mjs → SdkPreviewModeRuntime-D8Gt9Gbe.mjs} +633 -220
  6. package/dist/{SiteChromeCustomizeContext-C_sizso-.mjs → SiteChromeCustomizeContext-DUpalEdL.mjs} +5764 -1556
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +15383 -11388
  8. package/dist/_dts/api/src/blocks.d.ts +41 -7
  9. package/dist/_dts/api/src/bookingAdjustments.d.ts +5 -0
  10. package/dist/_dts/api/src/bookingOperations.d.ts +4 -0
  11. package/dist/_dts/api/src/bookingRecords.d.ts +177 -127
  12. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  13. package/dist/_dts/api/src/cache-tags.d.ts +3 -0
  14. package/dist/_dts/api/src/common/envelope.d.ts +7 -0
  15. package/dist/_dts/api/src/contentRuntime.d.ts +19 -1
  16. package/dist/_dts/api/src/courses.d.ts +1 -0
  17. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +5 -5
  18. package/dist/_dts/api/src/endpoints.d.ts +134 -0
  19. package/dist/_dts/api/src/footer-settings.d.ts +1 -0
  20. package/dist/_dts/api/src/footerSettings.d.ts +8 -0
  21. package/dist/_dts/api/src/index.d.ts +7 -4
  22. package/dist/_dts/api/src/navigation/contracts.d.ts +3 -3
  23. package/dist/_dts/api/src/participantMessaging.d.ts +18 -12
  24. package/dist/_dts/api/src/previewContentContract.d.ts +4 -0
  25. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +1 -0
  26. package/dist/_dts/api/src/sdkContracts.d.ts +309 -1
  27. package/dist/_dts/api/src/siteBanner.d.ts +2 -2
  28. package/dist/_dts/api/src/siteInfrastructure.d.ts +13 -0
  29. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +144 -60
  30. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +35 -1
  31. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +74 -28
  32. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientField.d.ts +9 -0
  33. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientWidget.d.ts +3 -4
  34. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  35. package/dist/_dts/blocks/src/index.d.ts +1 -1
  36. package/dist/_dts/blocks/src/primitives/layout/Section.d.ts +0 -1
  37. package/dist/_dts/blocks/src/rendering/server.d.ts +1 -0
  38. package/dist/_dts/blocks/src/system/blocks/audio-player.d.ts +3 -0
  39. package/dist/_dts/blocks/src/system/blocks/body-text.d.ts +3 -0
  40. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +3 -0
  41. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +1 -22
  42. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +3 -0
  43. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +1 -22
  44. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +3 -0
  45. package/dist/_dts/blocks/src/system/blocks/form.d.ts +3 -0
  46. package/dist/_dts/blocks/src/system/blocks/image-gallery.d.ts +3 -0
  47. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +3 -0
  48. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +3 -0
  49. package/dist/_dts/blocks/src/system/blocks/site-footer-runtime.d.ts +50 -0
  50. package/dist/_dts/blocks/src/system/blocks/site-footer.d.ts +9 -48
  51. package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +3 -0
  52. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  53. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +3 -0
  54. package/dist/_dts/blocks/src/system/blocks/video-grid.d.ts +3 -0
  55. package/dist/_dts/blocks/src/system/constants/background.d.ts +1 -1
  56. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +16 -6
  57. package/dist/_dts/blocks/src/system/defineBlock.d.ts +9 -1
  58. package/dist/_dts/blocks/src/system/fields/ctas.d.ts +8 -0
  59. package/dist/_dts/blocks/src/system/icons/registry.d.ts +2 -1
  60. package/dist/_dts/blocks/src/system/icons/social.d.ts +5 -0
  61. package/dist/_dts/blocks/src/system/icons/svg.d.ts +1 -0
  62. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +33 -2
  63. package/dist/_dts/blocks/src/system/node/fragments/backgroundLayer.d.ts +13 -0
  64. package/dist/_dts/blocks/src/system/node/fragments/footerNav.d.ts +2 -0
  65. package/dist/_dts/blocks/src/system/node/fragments/styledContainer.d.ts +4 -4
  66. package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +3 -12
  67. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  68. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +6 -6
  69. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  70. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +2 -2
  71. package/dist/_dts/blocks/src/system/types/link.d.ts +3 -3
  72. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +14 -0
  73. package/dist/_dts/content-editor/src/controller/EntryControllerProvider.d.ts +27 -8
  74. package/dist/_dts/content-editor/src/footerComposer.d.ts +56 -0
  75. package/dist/_dts/content-editor/src/hooks/useEntryActions.d.ts +1 -1
  76. package/dist/_dts/content-editor/src/hooks/useEntryMutations.d.ts +5 -5
  77. package/dist/_dts/content-editor/src/index.d.ts +2 -0
  78. package/dist/_dts/content-editor/src/primitives/PreviewRichTextEditor.d.ts +3 -1
  79. package/dist/_dts/content-editor/src/services/contentEntryServices.d.ts +20 -36
  80. package/dist/_dts/content-editor/src/ui/editorSnapshot.d.ts +5 -1
  81. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +11 -0
  82. package/dist/_dts/content-model/src/content-types/entryValidation.d.ts +31 -0
  83. package/dist/_dts/content-model/src/content-types/scaffold.d.ts +58 -0
  84. package/dist/_dts/content-model/src/content-types/schema.d.ts +1 -1
  85. package/dist/_dts/content-model/src/content-types/sentinels.d.ts +36 -0
  86. package/dist/_dts/content-model/src/definitions/shared.d.ts +3 -0
  87. package/dist/_dts/content-model/src/index.d.ts +3 -0
  88. package/dist/_dts/core/src/booking-date-time.d.ts +8 -0
  89. package/dist/_dts/core/src/branded.d.ts +3 -0
  90. package/dist/_dts/core/src/editor-state.d.ts +4 -0
  91. package/dist/_dts/core/src/footer-composition.d.ts +143 -0
  92. package/dist/_dts/core/src/index.d.ts +2 -0
  93. package/dist/_dts/core/src/public-profile.d.ts +73 -0
  94. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +221 -205
  95. package/dist/_dts/db/src/schemas/forms.d.ts +10 -10
  96. package/dist/_dts/editor/src/primitives/rich-text/RichTextEditorSurface.d.ts +5 -0
  97. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +1 -0
  98. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockCreation.d.ts +2 -1
  99. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockDuplication.d.ts +2 -1
  100. package/dist/_dts/editor-blocks/src/block-editor/hooks/useBlockReorder.d.ts +2 -1
  101. package/dist/_dts/editor-blocks/src/block-editor/owner.d.ts +10 -0
  102. package/dist/_dts/editor-blocks/src/block-editor/types.d.ts +1 -0
  103. package/dist/_dts/media-core/src/fileMimeDetection.d.ts +16 -0
  104. package/dist/_dts/media-core/src/fileStorage.d.ts +8 -0
  105. package/dist/_dts/media-core/src/storagePathDomain.d.ts +2 -0
  106. package/dist/_dts/media-core/src/uploadVerificationContract.d.ts +3 -0
  107. package/dist/_dts/path-utils/src/index.d.ts +5 -0
  108. package/dist/_dts/preview-next/src/client/blocks/BlockToolbar.d.ts +2 -0
  109. package/dist/_dts/preview-next/src/client/preview/PreviewChromeLayer.d.ts +5 -0
  110. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +2 -1
  111. package/dist/_dts/preview-next/src/client/preview/PreviewEntryControllerProvider.d.ts +1 -0
  112. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +2 -1
  113. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +2 -1
  114. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +1 -0
  115. package/dist/_dts/preview-next/src/client/preview/previewErrorMessages.d.ts +4 -0
  116. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -1
  117. package/dist/_dts/sdk/src/cli/commands/audit.d.ts +1 -1
  118. package/dist/_dts/sdk/src/cli/commands/compare.d.ts +1 -1
  119. package/dist/_dts/sdk/src/cli/commands/deploy.d.ts +1 -1
  120. package/dist/_dts/sdk/src/cli/commands/drafts.d.ts +18 -0
  121. package/dist/_dts/sdk/src/cli/commands/entry.d.ts +15 -0
  122. package/dist/_dts/sdk/src/cli/commands/init-docs.d.ts +2 -2
  123. package/dist/_dts/sdk/src/cli/commands/publish-all.d.ts +1 -1
  124. package/dist/_dts/sdk/src/cli/commands/pull.d.ts +1 -0
  125. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +1 -1
  126. package/dist/_dts/sdk/src/cli/commands/push/options.d.ts +3 -0
  127. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +12 -1
  128. package/dist/_dts/sdk/src/cli/commands/setup.d.ts +1 -0
  129. package/dist/_dts/sdk/src/cli/commands/verify.d.ts +1 -0
  130. package/dist/_dts/sdk/src/cli/content/reader.d.ts +1 -0
  131. package/dist/_dts/sdk/src/cli/helpers.d.ts +22 -1
  132. package/dist/_dts/sdk/src/cli/index.d.ts +4 -0
  133. package/dist/_dts/sdk/src/cli/output.d.ts +88 -0
  134. package/dist/_dts/sdk/src/cli/program.d.ts +29 -0
  135. package/dist/_dts/sdk/src/cli/push-config.d.ts +1 -1
  136. package/dist/_dts/sdk/src/client/management/blocks.d.ts +14 -1
  137. package/dist/_dts/sdk/src/client/management/catalog.d.ts +10 -0
  138. package/dist/_dts/sdk/src/client/management/http.d.ts +7 -1
  139. package/dist/_dts/sdk/src/client/management/index.d.ts +2 -1
  140. package/dist/_dts/sdk/src/client/management/types.d.ts +58 -20
  141. package/dist/_dts/sdk/src/config/content-types.d.ts +2 -0
  142. package/dist/_dts/sdk/src/config/content-validation.d.ts +4 -0
  143. package/dist/_dts/sdk/src/date-time/index.d.ts +68 -0
  144. package/dist/_dts/sdk/src/navigation/index.d.ts +2 -0
  145. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -2
  146. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -1
  147. package/dist/_dts/sdk/src/rendering/helpers/loadContent.d.ts +1 -1
  148. package/dist/_dts/sdk/src/version.d.ts +1 -1
  149. package/dist/_dts/site-commands/src/commands.d.ts +900 -827
  150. package/dist/_dts/theme-core/src/accordions/types.d.ts +2 -2
  151. package/dist/_dts/theme-core/src/buttons/core.d.ts +15 -46
  152. package/dist/_dts/theme-core/src/buttons/effectClassification.d.ts +147 -0
  153. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +2 -3
  154. package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +1 -1
  155. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  156. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +11 -0
  157. package/dist/_dts/theme-core/src/buttons/personalities/two-tone-pill.d.ts +17 -0
  158. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +45 -33
  159. package/dist/_dts/theme-core/src/buttons/presets.d.ts +4 -25
  160. package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +100 -0
  161. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +16 -0
  162. package/dist/_dts/theme-core/src/buttons/types.d.ts +104 -86
  163. package/dist/_dts/theme-core/src/cards/types.d.ts +16 -16
  164. package/dist/_dts/theme-core/src/footer/mode.d.ts +15 -0
  165. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  166. package/dist/_dts/theme-core/src/gradients/presets.d.ts +200 -8
  167. package/dist/_dts/theme-core/src/gradients/utils.d.ts +6 -2
  168. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
  169. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +117 -150
  170. package/dist/_dts/theme-core/src/mock-themes/modern-minimal.d.ts +1 -1
  171. package/dist/_dts/theme-core/src/navigation/types.d.ts +3 -3
  172. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +2 -2
  173. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +5 -8
  174. package/dist/_dts/theme-core/src/palette/index.d.ts +0 -1
  175. package/dist/_dts/theme-core/src/schema.d.ts +1264 -138
  176. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  177. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +10 -10
  178. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +12 -1
  179. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +3 -2
  180. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +13 -6
  181. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +29 -8
  182. package/dist/_dts/theme-core/src/site-styles/siteChromeNavPreferences.d.ts +15 -0
  183. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +2 -2
  184. package/dist/cli/index.mjs +68552 -66955
  185. package/dist/cli/init-docs/content/cli-reference.md +50 -7
  186. package/dist/cli/init-docs/content/content-management.md +7 -4
  187. package/dist/cli/init-docs/content/workflow-publish.md +5 -1
  188. package/dist/client/{DiscountCodeDisclosure-BwGkvmVH.mjs → DiscountCodeDisclosure-DU1ygxU2.mjs} +1 -1
  189. package/dist/client/{EventCombined.client-JnWE6Hzc.mjs → EventCombined.client-DB5zagCo.mjs} +3 -3
  190. package/dist/client/{EventListing.client-DQewc_kg.mjs → EventListing.client-CTX9JHBL.mjs} +2 -2
  191. package/dist/client/{LeafletStaticMap-DPAU3SFt.mjs → LeafletStaticMap-BYImhgiB.mjs} +1 -1
  192. package/dist/client/{MagicLinkForm-D4kpWCbW.mjs → MagicLinkForm-CRkw_M3l.mjs} +2 -2
  193. package/dist/client/{StepIndicator-CBlkb4rA.mjs → StepIndicator-BnmVBJJh.mjs} +2 -2
  194. package/dist/client/{accordion-DAIBVpTS.mjs → accordion-CeGreumd.mjs} +1 -1
  195. package/dist/client/{bookingForm-DZ-4l5_1.mjs → bookingForm-CSzFNrpN.mjs} +6 -6
  196. package/dist/client/bookings.mjs +637 -328
  197. package/dist/client/{buttons-DJgynGHQ.mjs → buttons-DoFV7KDL.mjs} +618 -306
  198. package/dist/client/{carousel-D-SLfX8r.mjs → carousel-B2jDtogf.mjs} +1 -1
  199. package/dist/client/{cart-CEgbgJhX.mjs → cart-D-jZ-vaY.mjs} +3 -3
  200. package/dist/client/{checkout-CXWrCRAA.mjs → checkout-Dza-LA7N.mjs} +3 -3
  201. package/dist/client/client.mjs +2497 -1216
  202. package/dist/client/{colorStyles-jZS6KfkP.mjs → colorStyles-CrgzoXsm.mjs} +1 -30
  203. package/dist/client/{courseRegistration-DVmLrRVz.mjs → courseRegistration-TYkNychb.mjs} +7 -7
  204. package/dist/client/{eventCalendar-DCuyPY_c.mjs → eventCalendar-BI_90SsT.mjs} +5 -5
  205. package/dist/client/{eventCombined-kP2CA2D4.mjs → eventCombined-mNrpryE9.mjs} +2 -2
  206. package/dist/client/{eventDetails-DU0LeF5e.mjs → eventDetails-D4GVlCIY.mjs} +3 -3
  207. package/dist/client/{eventListing-CcHF87BI.mjs → eventListing-YhKN018y.mjs} +2 -2
  208. package/dist/client/{eventRegistration-DJnR0yFH.mjs → eventRegistration-CdHGtilr.mjs} +7 -7
  209. package/dist/client/foregroundContract-xICPq59x.mjs +31 -0
  210. package/dist/client/{form-CH1lCusH.mjs → form-AcAL45rA.mjs} +2 -2
  211. package/dist/client/{headerSection-CBPFZoku.mjs → headerSection-uEC52ueD.mjs} +3 -3
  212. package/dist/client/hooks.mjs +1249 -841
  213. package/dist/client/{locationMap-Cx1hBg5n.mjs → locationMap-_wJDSUYe.mjs} +3 -3
  214. package/dist/client/{media-DHtSxS5V.mjs → media-BK0O3b-U.mjs} +3 -2
  215. package/dist/client/{newsletterForm-1ZL_ti9u.mjs → newsletterForm-DrArsb2B.mjs} +2 -2
  216. package/dist/client/{pricing-BIbzmV0G.mjs → pricing-BSYVghwo.mjs} +1 -1
  217. package/dist/client/{productDetail-BTh5gHBV.mjs → productDetail-Dyk90sMs.mjs} +3 -3
  218. package/dist/client/{productList-Cc7OMrqN.mjs → productList-BCKThwAI.mjs} +3 -3
  219. package/dist/client/{propsDecoder-oR-M-ISN.mjs → propsDecoder-CkXxkdSR.mjs} +96 -33
  220. package/dist/client/rendering/client.mjs +1278 -523
  221. package/dist/client/rendering/islands.mjs +19 -19
  222. package/dist/client/rendering.mjs +2308 -1028
  223. package/dist/client/{shop-CQ_YbCnn.mjs → shop-DeltVH10.mjs} +6 -6
  224. package/dist/client/{shop-commerce-BM-AoD3M.mjs → shop-commerce-BD9Jsm2Z.mjs} +6 -6
  225. package/dist/client/{shop-commerce-store-DFMQhU5p.mjs → shop-commerce-store-CmXD6FDS.mjs} +1 -1
  226. package/dist/client/{shopShared-D0SKO2Cu.mjs → shopShared-B8v-lH_F.mjs} +2 -2
  227. package/dist/client/{useDiscountCodeUi-CrG4_ARt.mjs → useDiscountCodeUi-DbWJN8ld.mjs} +1 -1
  228. package/dist/client/{useEventFilters-CxK8Fekl.mjs → useEventFilters-EJIMUnqT.mjs} +46 -69
  229. package/dist/client/{usePolling-jcVryNgZ.mjs → usePolling-Cmh14fc7.mjs} +2 -2
  230. package/dist/preview-next/before-render.mjs +213 -0
  231. package/dist/preview-next/client/runtime.mjs +4 -4
  232. package/dist/preview-next/middleware.mjs +213 -0
  233. package/dist/{previewAuthStore-BPcJPzdz.mjs → previewAuthStore-CTO7CRPk.mjs} +213 -0
  234. package/dist/{sdk-runtime-C39Rsk-x.mjs → sdk-runtime-Dou0GAav.mjs} +2 -2
  235. package/dist/{separator-BoMSQnsP.mjs → separator-CI5wZNXT.mjs} +1 -1
  236. package/dist/server/components.mjs +2370 -1132
  237. package/dist/server/config-validation.mjs +1256 -842
  238. package/dist/server/config.mjs +1256 -843
  239. package/dist/server/data.mjs +1249 -841
  240. package/dist/server/date-time.mjs +386 -0
  241. package/dist/server/index.mjs +214 -1
  242. package/dist/server/navigation.mjs +9 -3
  243. package/dist/server/next.mjs +3421 -1949
  244. package/dist/server/page-converter.mjs +1236 -659
  245. package/dist/server/prebuild.mjs +1 -1
  246. package/dist/server/rendering/server.mjs +2074 -1060
  247. package/dist/server/rendering.mjs +2370 -1132
  248. package/dist/server/routing.mjs +1543 -1062
  249. package/dist/server/server.mjs +1464 -843
  250. package/dist/server/theme-bridge.mjs +1581 -474
  251. package/dist/server/theme.mjs +614 -305
  252. package/dist/styles/index.css +12 -1
  253. package/package.json +7 -1
  254. package/dist/_dts/theme-core/src/buttons/presets/types.d.ts +0 -88
  255. package/dist/_dts/theme-core/src/buttons/utils/contrast.d.ts +0 -38
  256. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +0 -57
@@ -272,19 +272,29 @@ function isRecord$16(value) {
272
272
  //#region ../core/src/booking-date-time.ts
273
273
  const DEFAULT_LOCALE = "en-US";
274
274
  const FALLBACK_TIMEZONE = "UTC";
275
+ const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
276
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
277
+ const timeZoneValidityCache = /* @__PURE__ */ new Map();
275
278
  function isValidTimeZone$1(timeZone) {
279
+ const cached = timeZoneValidityCache.get(timeZone);
280
+ if (cached !== void 0) return cached;
281
+ let isValid;
276
282
  try {
277
283
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
278
- return true;
284
+ isValid = true;
279
285
  } catch {
280
- return false;
286
+ isValid = false;
281
287
  }
288
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
289
+ timeZoneValidityCache.set(timeZone, isValid);
290
+ return isValid;
282
291
  }
283
292
  function getSafeTimeZone(timeZone) {
284
293
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
285
294
  return normalized.length > 0 && isValidTimeZone$1(normalized) ? normalized : FALLBACK_TIMEZONE;
286
295
  }
287
296
  function parseStrictBookingTimeZone(timeZone) {
297
+ if (typeof timeZone !== "string") return null;
288
298
  const normalized = timeZone.trim();
289
299
  if (normalized.length === 0 || !isValidTimeZone$1(normalized)) return null;
290
300
  return normalized;
@@ -297,10 +307,19 @@ function formatParseError(error) {
297
307
  }
298
308
  }
299
309
  function formatToPartsLookup(date, locale, timeZone, format) {
300
- return new Map(new Intl.DateTimeFormat(locale, {
310
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
311
+ }
312
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
313
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
314
+ const cached = dateTimeFormatterCache.get(key);
315
+ if (cached !== void 0) return cached;
316
+ const formatter = new Intl.DateTimeFormat(locale, {
301
317
  ...format,
302
318
  timeZone
303
- }).formatToParts(date).map((part) => [part.type, part.value]));
319
+ });
320
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
321
+ dateTimeFormatterCache.set(key, formatter);
322
+ return formatter;
304
323
  }
305
324
  function getZonedDateTimeParts(date, timeZone) {
306
325
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -346,23 +365,9 @@ function toUtcIsoDateTimeString(value) {
346
365
  return parsed.value;
347
366
  }
348
367
  function parseScheduledBookingDateTime(input) {
368
+ let startsAt;
349
369
  try {
350
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
351
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
352
- if (timeZone === null) return {
353
- ok: false,
354
- field: "timeZone",
355
- reason: "invalid_time_zone",
356
- value: input.timeZone
357
- };
358
- return {
359
- ok: true,
360
- value: {
361
- startsAt,
362
- timeZone,
363
- locale: input.locale
364
- }
365
- };
370
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
366
371
  } catch {
367
372
  return {
368
373
  ok: false,
@@ -371,6 +376,21 @@ function parseScheduledBookingDateTime(input) {
371
376
  value: input.startsAt
372
377
  };
373
378
  }
379
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
380
+ if (timeZone === null) return {
381
+ ok: false,
382
+ field: "timeZone",
383
+ reason: "invalid_time_zone",
384
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
385
+ };
386
+ return {
387
+ ok: true,
388
+ value: {
389
+ startsAt,
390
+ timeZone,
391
+ locale: input.locale
392
+ }
393
+ };
374
394
  }
375
395
  function parseScheduledBookingDateRange(input) {
376
396
  const start = parseScheduledBookingDateTime(input);
@@ -409,10 +429,7 @@ function toScheduledBookingDateRange(input) {
409
429
  function formatBookingInstant(isoString, options) {
410
430
  const date = new Date(isoString);
411
431
  if (Number.isNaN(date.getTime())) return isoString;
412
- return new Intl.DateTimeFormat(options.locale ?? DEFAULT_LOCALE, {
413
- ...options.format,
414
- timeZone: getSafeTimeZone(options.timeZone)
415
- }).format(date);
432
+ return getCachedDateTimeFormatter(options.locale ?? DEFAULT_LOCALE, getSafeTimeZone(options.timeZone), options.format).format(date);
416
433
  }
417
434
  function formatBookingDate(input, format = {
418
435
  weekday: "long",
@@ -551,7 +568,8 @@ function validateRelativeStoragePath(value) {
551
568
  if (value.startsWith("sites/")) return fail({ tag: "SITE_SCOPED_PATH" });
552
569
  if (value.startsWith("/")) return fail({ tag: "LEADING_SLASH" });
553
570
  if (value.includes("//")) return fail({ tag: "DOUBLE_SLASH" });
554
- if (value.split("/").some((segment) => segment === "..")) return fail({ tag: "TRAVERSAL" });
571
+ if (value.includes("%")) return fail({ tag: "PERCENT_ENCODING" });
572
+ if (value.split("/").some((segment) => segment === "." || segment === "..")) return fail({ tag: "TRAVERSAL" });
555
573
  return ok(value);
556
574
  }
557
575
  function brandRelativeStoragePath(value) {
@@ -987,7 +1005,7 @@ function mqBetween(minPx, maxPx) {
987
1005
  return `${mqUp(minPx)} and ${mqDown(maxPx)}`;
988
1006
  }
989
1007
  const MQ_SM_UP = mqUp(640);
990
- mqUp(768);
1008
+ const MQ_MD_UP = mqUp(768);
991
1009
  const MQ_LG_UP = mqUp(BREAKPOINT_LG);
992
1010
  mqUp(BREAKPOINT_XL);
993
1011
  const MQ_SM_DOWN = mqDown(639);
@@ -1642,6 +1660,20 @@ const blockCategoryEnum = z$1.enum([
1642
1660
  "layout",
1643
1661
  "interactive"
1644
1662
  ]);
1663
+ const blockContentSourceSchema = z$1.object({
1664
+ kind: z$1.enum([
1665
+ "inline",
1666
+ "entries",
1667
+ "mixed"
1668
+ ]),
1669
+ contentType: z$1.string().min(1).optional()
1670
+ }).superRefine((value, ctx) => {
1671
+ if (value.kind === "inline" && value.contentType) ctx.addIssue({
1672
+ code: z$1.ZodIssueCode.custom,
1673
+ path: ["contentType"],
1674
+ message: "contentType is not allowed when contentSource.kind is \"inline\""
1675
+ });
1676
+ });
1645
1677
  z$1.object({
1646
1678
  name: z$1.string().min(1),
1647
1679
  version: z$1.string().min(1),
@@ -1672,6 +1704,12 @@ z$1.object({
1672
1704
  }).optional()).optional(),
1673
1705
  category: blockCategoryEnum.optional(),
1674
1706
  contentTypes: z$1.array(z$1.string()).optional(),
1707
+ /**
1708
+ * Explicit content-source classification (inline / entries / mixed). Optional at the
1709
+ * schema level for backward compatibility with SDK-defined custom blocks, but every
1710
+ * registered SYSTEM block must declare it (enforced by a registry-wide test).
1711
+ */
1712
+ contentSource: blockContentSourceSchema.optional(),
1675
1713
  tags: z$1.array(z$1.string()).optional(),
1676
1714
  icon: z$1.string().optional()
1677
1715
  });
@@ -3211,7 +3249,7 @@ function normalizeStoredObjectChildren(children, value, ctx) {
3211
3249
  return normalized;
3212
3250
  }
3213
3251
  function normalizeStoredRepeaterItems(plan, value, ctx) {
3214
- if (!isUnknownArray$1(value)) return value;
3252
+ if (!isUnknownArray$2(value)) return value;
3215
3253
  return value.map((item) => {
3216
3254
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
3217
3255
  const itemRecord = item;
@@ -3266,7 +3304,7 @@ function getAtFieldPath(source, path) {
3266
3304
  }, source);
3267
3305
  }
3268
3306
  function normalizeRepeaterItems(plan, value, ctx) {
3269
- if (!isUnknownArray$1(value)) return value;
3307
+ if (!isUnknownArray$2(value)) return value;
3270
3308
  return value.map((item) => {
3271
3309
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
3272
3310
  const itemRecord = item;
@@ -3641,7 +3679,7 @@ function isEmptyValue(value) {
3641
3679
  function isPlainObject$4(value) {
3642
3680
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
3643
3681
  }
3644
- function isUnknownArray$1(value) {
3682
+ function isUnknownArray$2(value) {
3645
3683
  return Array.isArray(value);
3646
3684
  }
3647
3685
  function isValidRichTextDoc(value) {
@@ -3863,6 +3901,14 @@ function relativeLuminance(r, g, b) {
3863
3901
  const R = srgbToLinear(r), G = srgbToLinear(g), B = srgbToLinear(b);
3864
3902
  return .2126 * R + .7152 * G + .0722 * B;
3865
3903
  }
3904
+ function contrastRatio(hex1, hex2) {
3905
+ const { r: r1, g: g1, b: b1 } = hexToRgb(hex1);
3906
+ const { r: r2, g: g2, b: b2 } = hexToRgb(hex2);
3907
+ const L1 = relativeLuminance(r1, g1, b1);
3908
+ const L2 = relativeLuminance(r2, g2, b2);
3909
+ const [hi, lo] = L1 >= L2 ? [L1, L2] : [L2, L1];
3910
+ return (hi + .05) / (lo + .05);
3911
+ }
3866
3912
  //#endregion
3867
3913
  //#region ../theme-core/src/palette/utils/onColor.ts
3868
3914
  const BACKGROUND_ROLE_NAMES = /* @__PURE__ */ new Set([
@@ -4854,6 +4900,10 @@ const modernMinimalTheme = {
4854
4900
  name: "primary",
4855
4901
  hex: "#1f2937"
4856
4902
  },
4903
+ {
4904
+ name: "primaryForeground",
4905
+ hex: "#ffffff"
4906
+ },
4857
4907
  {
4858
4908
  name: "secondary",
4859
4909
  hex: "#6b7280"
@@ -4882,6 +4932,14 @@ const modernMinimalTheme = {
4882
4932
  name: "surface",
4883
4933
  hex: "#ffffff"
4884
4934
  },
4935
+ {
4936
+ name: "surfaceAlt",
4937
+ hex: "#f9fafb"
4938
+ },
4939
+ {
4940
+ name: "muted",
4941
+ hex: "#f3f4f6"
4942
+ },
4885
4943
  {
4886
4944
  name: "text",
4887
4945
  hex: "#1f2937"
@@ -8295,6 +8353,111 @@ function boundaryKey$1(previousBlockId, nextBlockId) {
8295
8353
  return makeBoundaryId(previousBlockId, nextBlockId);
8296
8354
  }
8297
8355
  //#endregion
8356
+ //#region ../theme-core/src/buttons/effectClassification.ts
8357
+ /**
8358
+ * Exhaustive live policy for every registered effect id.
8359
+ *
8360
+ * The resolver consumes the transition payload directly, so adding an effect
8361
+ * cannot update classification without also defining its runtime behavior.
8362
+ */
8363
+ const BUTTON_EFFECT_POLICIES = {
8364
+ "darken-background": {
8365
+ classification: "colour-transition",
8366
+ transition: {
8367
+ kind: "adjust-shade",
8368
+ direction: "darker"
8369
+ }
8370
+ },
8371
+ "lighten-background": {
8372
+ classification: "colour-transition",
8373
+ transition: {
8374
+ kind: "adjust-shade",
8375
+ direction: "lighter"
8376
+ }
8377
+ },
8378
+ "background-on-hover": {
8379
+ classification: "colour-transition",
8380
+ transition: { kind: "replace-background" }
8381
+ },
8382
+ "background-on-hover-alpha": {
8383
+ classification: "unsupported-colour",
8384
+ reason: "alpha_requires_surface"
8385
+ },
8386
+ "fade-background": {
8387
+ classification: "unsupported-colour",
8388
+ reason: "changes_element_opacity"
8389
+ },
8390
+ "opacity-reduce": {
8391
+ classification: "unsupported-colour",
8392
+ reason: "changes_element_opacity"
8393
+ },
8394
+ "gradient-text": {
8395
+ classification: "unsupported-colour",
8396
+ reason: "changes_foreground"
8397
+ },
8398
+ "text-color-change": {
8399
+ classification: "unsupported-colour",
8400
+ reason: "changes_foreground"
8401
+ },
8402
+ "border-color-change": {
8403
+ classification: "unsupported-colour",
8404
+ reason: "changes_border"
8405
+ },
8406
+ "aurora-glow": {
8407
+ classification: "unsupported-background-overlay",
8408
+ reason: "unresolved_background_overlay"
8409
+ },
8410
+ "cosmic-stardust": {
8411
+ classification: "unsupported-background-overlay",
8412
+ reason: "unresolved_background_overlay"
8413
+ },
8414
+ "gradient-border-fill": {
8415
+ classification: "unsupported-background-overlay",
8416
+ reason: "unresolved_background_overlay"
8417
+ },
8418
+ "animated-gradient-border-fill": {
8419
+ classification: "unsupported-background-overlay",
8420
+ reason: "unresolved_background_overlay"
8421
+ },
8422
+ "nav-underline": {
8423
+ classification: "not-button",
8424
+ reason: "not_button_effect"
8425
+ },
8426
+ "nav-frosted-base": {
8427
+ classification: "not-button",
8428
+ reason: "not_button_effect"
8429
+ },
8430
+ "nav-frosted-hover": {
8431
+ classification: "not-button",
8432
+ reason: "not_button_effect"
8433
+ },
8434
+ "nav-frosted-active": {
8435
+ classification: "not-button",
8436
+ reason: "not_button_effect"
8437
+ },
8438
+ "animated-gradient": { classification: "non-colour" },
8439
+ "border-glow": { classification: "non-colour" },
8440
+ "drop-shadow": { classification: "non-colour" },
8441
+ "inner-shadow": { classification: "non-colour" },
8442
+ "neumorphic-shadow": { classification: "non-colour" },
8443
+ "outer-glow": { classification: "non-colour" },
8444
+ "retro-3d-shadow": { classification: "non-colour" },
8445
+ "scale-up": { classification: "non-colour" },
8446
+ "scale-down": { classification: "non-colour" },
8447
+ lift: { classification: "non-colour" },
8448
+ "press-down": { classification: "non-colour" },
8449
+ pop: { classification: "non-colour" },
8450
+ "border-bottom-grow": { classification: "non-colour" },
8451
+ "sketchy-border": { classification: "non-colour" },
8452
+ "pulse-animation": { classification: "non-colour" }
8453
+ };
8454
+ function getButtonEffectPolicy(effectId) {
8455
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
8456
+ }
8457
+ function classifyButtonEffectId(effectId) {
8458
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
8459
+ }
8460
+ //#endregion
8298
8461
  //#region ../theme-core/src/buttons/types.ts
8299
8462
  /**
8300
8463
  * Standard semantic variant roles a theme exposes.
@@ -8324,6 +8487,20 @@ function asSpecialVariantId(value) {
8324
8487
  * Shared between generator and renderer so neither side hard-codes the string.
8325
8488
  */
8326
8489
  const DEFAULT_VARIANT_ALIAS_ID = "default";
8490
+ function parseOpaqueButtonColourToken(value) {
8491
+ const token = parseThemeColorToken(value);
8492
+ if (token === null) return null;
8493
+ const parts = parseColorTokenParts(token);
8494
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
8495
+ }
8496
+ function unsafeAsOpaqueButtonColourToken(value) {
8497
+ return value;
8498
+ }
8499
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
8500
+ const token = parseOpaqueButtonColourToken(value);
8501
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
8502
+ return token;
8503
+ });
8327
8504
  const cornerStyleSchema = z$1.enum([
8328
8505
  "square",
8329
8506
  "rounded",
@@ -8425,7 +8602,7 @@ const buttonSizesSchema = z$1.object({
8425
8602
  lg,
8426
8603
  xl: xl ?? lg
8427
8604
  }));
8428
- const buttonGlobalSettingsSchema = z$1.object({
8605
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
8429
8606
  cornerStyle: cornerStyleSchema,
8430
8607
  cornerRadius: z$1.number().min(0).max(24).optional(),
8431
8608
  /**
@@ -8456,11 +8633,12 @@ const buttonGlobalSettingsSchema = z$1.object({
8456
8633
  paddingPreset: buttonPaddingPresetSchema.optional(),
8457
8634
  hoverTransform: hoverTransformSchema,
8458
8635
  hoverColor: hoverColorSchema,
8459
- hoverColorToken: themeColorTokenSchema.optional(),
8636
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
8460
8637
  gradientStyle: gradientStyleSchema.optional(),
8461
8638
  gradientAngle: z$1.number().min(0).max(360).optional(),
8462
8639
  gradientSharpness: gradientSharpnessSchema.optional()
8463
8640
  });
8641
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
8464
8642
  const gradientDirectionSchema$1 = z$1.enum([
8465
8643
  "to-r",
8466
8644
  "to-l",
@@ -8474,27 +8652,33 @@ const gradientDirectionSchema$1 = z$1.enum([
8474
8652
  const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
8475
8653
  z$1.object({
8476
8654
  type: z$1.literal("solid"),
8477
- colorToken: themeColorTokenSchema
8655
+ colorToken: opaqueButtonColourTokenSchema
8478
8656
  }),
8479
8657
  z$1.object({
8480
8658
  type: z$1.literal("gradient"),
8481
- stops: z$1.array(themeColorTokenSchema).min(2),
8482
- direction: gradientDirectionSchema$1
8659
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
8660
+ const [first, second, ...rest] = stops;
8661
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
8662
+ return [
8663
+ first,
8664
+ second,
8665
+ ...rest
8666
+ ];
8667
+ }),
8668
+ direction: gradientDirectionSchema$1,
8669
+ foregroundToken: opaqueButtonColourTokenSchema
8483
8670
  }),
8484
- z$1.object({ type: z$1.literal("transparent") })
8671
+ z$1.object({
8672
+ type: z$1.literal("surface"),
8673
+ role: z$1.literal("link")
8674
+ })
8485
8675
  ]);
8486
8676
  const effectApplicationSchema$1 = z$1.object({
8487
8677
  effectId: z$1.string(),
8488
- options: z$1.record(z$1.string(), z$1.any()).optional()
8489
- });
8490
- const buttonBorderSchema = z$1.object({
8491
- widthClass: z$1.string(),
8492
- colorToken: themeColorTokenSchema
8493
- });
8494
- const buttonVariantAffordanceSchema = z$1.object({
8495
- iconId: z$1.string().min(1),
8496
- colorToken: themeColorTokenSchema.optional()
8678
+ options: z$1.record(z$1.string(), z$1.json()).optional()
8497
8679
  });
8680
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
8681
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
8498
8682
  const variantShadowSchema = z$1.object({
8499
8683
  elevation: z$1.enum([
8500
8684
  "none",
@@ -8535,27 +8719,170 @@ const variantSizeOverridesSchema = z$1.object({
8535
8719
  * default (e.g. link-style variants declaring zero horizontal padding at
8536
8720
  * every size).
8537
8721
  */
8538
- const buttonVariantSchema = z$1.object({
8722
+ const canonicalButtonVariantSchema = z$1.object({
8539
8723
  id: z$1.string(),
8540
8724
  name: z$1.string().min(1).max(20),
8541
8725
  enabled: z$1.boolean(),
8542
8726
  priority: prioritySchema,
8543
8727
  background: buttonBackgroundSchema,
8544
- textColorToken: themeColorTokenSchema,
8545
8728
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
8546
8729
  borderRadius: z$1.string().optional(),
8547
8730
  shadow: variantShadowSchema.optional(),
8548
8731
  border: buttonBorderSchema.optional(),
8549
- hoverBackgroundToken: z$1.string().optional(),
8732
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
8550
8733
  effects: variantEffectsSchema.optional(),
8551
8734
  sizes: variantSizeOverridesSchema.optional(),
8552
8735
  affordance: buttonVariantAffordanceSchema.optional()
8553
8736
  });
8737
+ /**
8738
+ * Temporary persisted-theme admission boundary for issue #1206.
8739
+ *
8740
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
8741
+ * `textColorToken`/border colour shape. New source and all downstream code use
8742
+ * only the canonical relationship. Delete this preprocessor after the reviewed
8743
+ * production rewrite reports zero legacy rows.
8744
+ */
8745
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
8554
8746
  const buttonSystemSchema = z$1.object({
8555
8747
  global: buttonGlobalSettingsSchema,
8556
8748
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
8557
8749
  sizes: buttonSizesSchema.optional()
8558
8750
  });
8751
+ function normalizeLegacyButtonVariantInput(input) {
8752
+ if (!isUnknownRecord(input)) return input;
8753
+ const background = input.background;
8754
+ if (!isUnknownRecord(background)) return input;
8755
+ 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;
8756
+ const { textColorToken, ...withoutLegacyText } = input;
8757
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
8758
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
8759
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
8760
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
8761
+ if (background.type === "transparent") return {
8762
+ ...withoutLegacyText,
8763
+ background: {
8764
+ type: "surface",
8765
+ role: "link"
8766
+ },
8767
+ border: normalizedBorder,
8768
+ affordance: normalizedAffordance,
8769
+ effects: normalizedEffects,
8770
+ hoverBackgroundToken
8771
+ };
8772
+ if (background.type === "gradient") {
8773
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
8774
+ return {
8775
+ ...withoutLegacyText,
8776
+ background: {
8777
+ ...background,
8778
+ stops,
8779
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
8780
+ },
8781
+ border: normalizedBorder,
8782
+ affordance: normalizedAffordance,
8783
+ effects: normalizedEffects,
8784
+ hoverBackgroundToken
8785
+ };
8786
+ }
8787
+ return {
8788
+ ...withoutLegacyText,
8789
+ background: background.type === "solid" ? {
8790
+ ...background,
8791
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
8792
+ } : background,
8793
+ border: normalizedBorder,
8794
+ affordance: normalizedAffordance,
8795
+ effects: normalizedEffects,
8796
+ hoverBackgroundToken
8797
+ };
8798
+ }
8799
+ function normalizeLegacyButtonGlobalInput(input) {
8800
+ if (!isUnknownRecord(input)) return input;
8801
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
8802
+ return hoverColorToken === input.hoverColorToken ? input : {
8803
+ ...input,
8804
+ hoverColorToken
8805
+ };
8806
+ }
8807
+ function hasLegacyAlphaToken(input, background) {
8808
+ const stops = isUnknownArray$1(background.stops) ? background.stops : [];
8809
+ return [
8810
+ input.hoverBackgroundToken,
8811
+ background.colorToken,
8812
+ background.foregroundToken,
8813
+ ...stops
8814
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
8815
+ }
8816
+ function stripLegacyTokenAlpha(value) {
8817
+ if (typeof value !== "string") return value;
8818
+ const slashIndex = value.indexOf("/");
8819
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
8820
+ }
8821
+ function hasLegacyButtonEffects(input) {
8822
+ if (!isUnknownRecord(input)) return false;
8823
+ return [
8824
+ "base",
8825
+ "hover",
8826
+ "active",
8827
+ "focus"
8828
+ ].some((state) => {
8829
+ const effects = input[state];
8830
+ return Array.isArray(effects) && effects.some((effect) => {
8831
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
8832
+ const classification = classifyButtonEffectId(effect.effectId);
8833
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
8834
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
8835
+ });
8836
+ });
8837
+ }
8838
+ function normalizeLegacyButtonEffects(input, backgroundType) {
8839
+ if (!isUnknownRecord(input)) return input;
8840
+ const normalized = {};
8841
+ for (const state of [
8842
+ "base",
8843
+ "hover",
8844
+ "active",
8845
+ "focus"
8846
+ ]) {
8847
+ const effects = input[state];
8848
+ if (!Array.isArray(effects)) continue;
8849
+ const safeEffects = effects.flatMap((effect) => {
8850
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
8851
+ const classification = classifyButtonEffectId(effect.effectId);
8852
+ if (classification === "non-colour") return [effect];
8853
+ if (classification !== "colour-transition") return [];
8854
+ if (effect.effectId === "background-on-hover") {
8855
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
8856
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
8857
+ return colorToken === null ? [] : [{
8858
+ ...effect,
8859
+ options: {
8860
+ ...options,
8861
+ colorToken
8862
+ }
8863
+ }];
8864
+ }
8865
+ if (backgroundType !== "solid") return [];
8866
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
8867
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
8868
+ return [{
8869
+ ...effect,
8870
+ options: {
8871
+ ...isUnknownRecord(effect.options) ? effect.options : {},
8872
+ amount
8873
+ }
8874
+ }];
8875
+ });
8876
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
8877
+ }
8878
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
8879
+ }
8880
+ function isUnknownRecord(value) {
8881
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8882
+ }
8883
+ function isUnknownArray$1(value) {
8884
+ return Array.isArray(value);
8885
+ }
8559
8886
  //#endregion
8560
8887
  //#region ../theme-core/src/buttons/personalities/types.ts
8561
8888
  function asButtonPersonalityId(value) {
@@ -8581,7 +8908,7 @@ function defineButtonPersonality(input) {
8581
8908
  name: input.name,
8582
8909
  description: input.description,
8583
8910
  tags: input.tags,
8584
- buttonSystem: input.buttonSystem
8911
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
8585
8912
  };
8586
8913
  }
8587
8914
  //#endregion
@@ -8634,19 +8961,15 @@ const brushedWash = defineButtonPersonality({
8634
8961
  background: {
8635
8962
  type: "gradient",
8636
8963
  stops: ["primary", "accent"],
8637
- direction: "to-r"
8964
+ direction: "to-r",
8965
+ foregroundToken: "primaryForeground"
8638
8966
  },
8639
- textColorToken: "primaryForeground",
8640
8967
  borderRadius: "rounded-lg",
8641
8968
  shadow: {
8642
8969
  elevation: "low",
8643
8970
  softness: "soft",
8644
8971
  position: "bottom"
8645
- },
8646
- effects: { hover: [{
8647
- effectId: "opacity-reduce",
8648
- options: { reduction: -15 }
8649
- }] }
8972
+ }
8650
8973
  },
8651
8974
  {
8652
8975
  id: "secondary",
@@ -8656,32 +8979,27 @@ const brushedWash = defineButtonPersonality({
8656
8979
  background: {
8657
8980
  type: "gradient",
8658
8981
  stops: ["secondary", "accent"],
8659
- direction: "to-br"
8982
+ direction: "to-br",
8983
+ foregroundToken: "primaryForeground"
8660
8984
  },
8661
- textColorToken: "primaryForeground",
8662
8985
  borderRadius: "rounded-lg",
8663
8986
  shadow: {
8664
8987
  elevation: "low",
8665
8988
  softness: "soft",
8666
8989
  position: "bottom"
8667
- },
8668
- effects: { hover: [{
8669
- effectId: "opacity-reduce",
8670
- options: { reduction: -15 }
8671
- }] }
8990
+ }
8672
8991
  },
8673
8992
  {
8674
8993
  id: "outline",
8675
8994
  name: "Outline",
8676
8995
  enabled: true,
8677
8996
  priority: 3,
8678
- background: { type: "transparent" },
8679
- textColorToken: "primary",
8680
- borderRadius: "rounded-lg",
8681
- border: {
8682
- widthClass: "border",
8683
- colorToken: "primary"
8997
+ background: {
8998
+ type: "surface",
8999
+ role: "link"
8684
9000
  },
9001
+ borderRadius: "rounded-lg",
9002
+ border: { widthClass: "border" },
8685
9003
  effects: { hover: [{
8686
9004
  effectId: "background-on-hover",
8687
9005
  options: { colorToken: "surface" }
@@ -8692,8 +9010,10 @@ const brushedWash = defineButtonPersonality({
8692
9010
  name: "Ghost",
8693
9011
  enabled: true,
8694
9012
  priority: 3,
8695
- background: { type: "transparent" },
8696
- textColorToken: "text",
9013
+ background: {
9014
+ type: "surface",
9015
+ role: "link"
9016
+ },
8697
9017
  borderRadius: "rounded-lg",
8698
9018
  effects: { hover: [{
8699
9019
  effectId: "background-on-hover",
@@ -8739,7 +9059,6 @@ const confidentChip = defineButtonPersonality({
8739
9059
  type: "solid",
8740
9060
  colorToken: "primary"
8741
9061
  },
8742
- textColorToken: "primaryForeground",
8743
9062
  borderRadius: "rounded-md",
8744
9063
  shadow: {
8745
9064
  elevation: "medium",
@@ -8749,7 +9068,7 @@ const confidentChip = defineButtonPersonality({
8749
9068
  effects: {
8750
9069
  hover: [{
8751
9070
  effectId: "darken-background",
8752
- options: { amount: 60 }
9071
+ options: { amount: 100 }
8753
9072
  }],
8754
9073
  active: [{
8755
9074
  effectId: "scale-down",
@@ -8766,12 +9085,8 @@ const confidentChip = defineButtonPersonality({
8766
9085
  type: "solid",
8767
9086
  colorToken: "surface"
8768
9087
  },
8769
- textColorToken: "text",
8770
9088
  borderRadius: "rounded-md",
8771
- border: {
8772
- widthClass: "border",
8773
- colorToken: "border"
8774
- },
9089
+ border: { widthClass: "border" },
8775
9090
  effects: { hover: [{
8776
9091
  effectId: "background-on-hover",
8777
9092
  options: { colorToken: "background" }
@@ -8782,13 +9097,12 @@ const confidentChip = defineButtonPersonality({
8782
9097
  name: "Outline",
8783
9098
  enabled: true,
8784
9099
  priority: 3,
8785
- background: { type: "transparent" },
8786
- textColorToken: "primary",
8787
- borderRadius: "rounded-md",
8788
- border: {
8789
- widthClass: "border",
8790
- colorToken: "primary"
9100
+ background: {
9101
+ type: "surface",
9102
+ role: "link"
8791
9103
  },
9104
+ borderRadius: "rounded-md",
9105
+ border: { widthClass: "border" },
8792
9106
  effects: { hover: [{
8793
9107
  effectId: "background-on-hover",
8794
9108
  options: { colorToken: "surface" }
@@ -8799,8 +9113,10 @@ const confidentChip = defineButtonPersonality({
8799
9113
  name: "Ghost",
8800
9114
  enabled: true,
8801
9115
  priority: 3,
8802
- background: { type: "transparent" },
8803
- textColorToken: "primary",
9116
+ background: {
9117
+ type: "surface",
9118
+ role: "link"
9119
+ },
8804
9120
  borderRadius: "rounded-md",
8805
9121
  effects: { hover: [{
8806
9122
  effectId: "background-on-hover",
@@ -8863,7 +9179,6 @@ const earthPill = defineButtonPersonality({
8863
9179
  type: "solid",
8864
9180
  colorToken: "primary"
8865
9181
  },
8866
- textColorToken: "primaryForeground",
8867
9182
  borderRadius: "rounded-full",
8868
9183
  shadow: {
8869
9184
  elevation: "low",
@@ -8889,13 +9204,12 @@ const earthPill = defineButtonPersonality({
8889
9204
  name: "Secondary",
8890
9205
  enabled: true,
8891
9206
  priority: 2,
8892
- background: { type: "transparent" },
8893
- textColorToken: "primary",
8894
- borderRadius: "rounded-full",
8895
- border: {
8896
- widthClass: "border",
8897
- colorToken: "primary"
9207
+ background: {
9208
+ type: "surface",
9209
+ role: "link"
8898
9210
  },
9211
+ borderRadius: "rounded-full",
9212
+ border: { widthClass: "border" },
8899
9213
  effects: { hover: [{
8900
9214
  effectId: "background-on-hover",
8901
9215
  options: { colorToken: "muted" }
@@ -8906,13 +9220,12 @@ const earthPill = defineButtonPersonality({
8906
9220
  name: "Outline",
8907
9221
  enabled: true,
8908
9222
  priority: 3,
8909
- background: { type: "transparent" },
8910
- textColorToken: "text",
8911
- borderRadius: "rounded-full",
8912
- border: {
8913
- widthClass: "border",
8914
- colorToken: "border"
9223
+ background: {
9224
+ type: "surface",
9225
+ role: "link"
8915
9226
  },
9227
+ borderRadius: "rounded-full",
9228
+ border: { widthClass: "border" },
8916
9229
  effects: { hover: [{
8917
9230
  effectId: "background-on-hover",
8918
9231
  options: { colorToken: "surfaceAlt" }
@@ -8923,8 +9236,10 @@ const earthPill = defineButtonPersonality({
8923
9236
  name: "Ghost",
8924
9237
  enabled: true,
8925
9238
  priority: 3,
8926
- background: { type: "transparent" },
8927
- textColorToken: "primary",
9239
+ background: {
9240
+ type: "surface",
9241
+ role: "link"
9242
+ },
8928
9243
  borderRadius: "rounded-full",
8929
9244
  shadow: {
8930
9245
  elevation: "none",
@@ -8945,11 +9260,7 @@ const earthPill = defineButtonPersonality({
8945
9260
  padding: "0.625rem 0",
8946
9261
  fontSize: "text-xl"
8947
9262
  }
8948
- },
8949
- effects: { hover: [{
8950
- effectId: "opacity-reduce",
8951
- options: { reduction: 25 }
8952
- }] }
9263
+ }
8953
9264
  }
8954
9265
  ]
8955
9266
  }
@@ -8985,8 +9296,10 @@ const editorialLink = defineButtonPersonality({
8985
9296
  name: "Primary",
8986
9297
  enabled: true,
8987
9298
  priority: 1,
8988
- background: { type: "transparent" },
8989
- textColorToken: "text",
9299
+ background: {
9300
+ type: "surface",
9301
+ role: "link"
9302
+ },
8990
9303
  borderRadius: "rounded-none",
8991
9304
  sizes: {
8992
9305
  sm: { padding: "0.25rem 0" },
@@ -9008,8 +9321,10 @@ const editorialLink = defineButtonPersonality({
9008
9321
  name: "Secondary",
9009
9322
  enabled: true,
9010
9323
  priority: 2,
9011
- background: { type: "transparent" },
9012
- textColorToken: "mutedText",
9324
+ background: {
9325
+ type: "surface",
9326
+ role: "link"
9327
+ },
9013
9328
  borderRadius: "rounded-none",
9014
9329
  sizes: {
9015
9330
  sm: { padding: "0.25rem 0" },
@@ -9031,8 +9346,10 @@ const editorialLink = defineButtonPersonality({
9031
9346
  name: "Outline",
9032
9347
  enabled: true,
9033
9348
  priority: 3,
9034
- background: { type: "transparent" },
9035
- textColorToken: "accent",
9349
+ background: {
9350
+ type: "surface",
9351
+ role: "link"
9352
+ },
9036
9353
  borderRadius: "rounded-none",
9037
9354
  sizes: {
9038
9355
  sm: { padding: "0.25rem 0" },
@@ -9054,19 +9371,17 @@ const editorialLink = defineButtonPersonality({
9054
9371
  name: "Ghost",
9055
9372
  enabled: true,
9056
9373
  priority: 3,
9057
- background: { type: "transparent" },
9058
- textColorToken: "mutedText",
9374
+ background: {
9375
+ type: "surface",
9376
+ role: "link"
9377
+ },
9059
9378
  borderRadius: "rounded-none",
9060
9379
  sizes: {
9061
9380
  sm: { padding: "0.25rem 0" },
9062
9381
  md: { padding: "0.5rem 0" },
9063
9382
  lg: { padding: "0.625rem 0" },
9064
9383
  xl: { padding: "0.75rem 0" }
9065
- },
9066
- effects: { hover: [{
9067
- effectId: "opacity-reduce",
9068
- options: { reduction: -20 }
9069
- }] }
9384
+ }
9070
9385
  }
9071
9386
  ]
9072
9387
  }
@@ -9128,12 +9443,8 @@ const flatInk = defineButtonPersonality({
9128
9443
  type: "solid",
9129
9444
  colorToken: "primary"
9130
9445
  },
9131
- textColorToken: "primaryForeground",
9132
9446
  borderRadius: "rounded-lg",
9133
- affordance: {
9134
- iconId: "ArrowRight",
9135
- colorToken: "accent"
9136
- },
9447
+ affordance: { iconId: "ArrowRight" },
9137
9448
  effects: { hover: [{
9138
9449
  effectId: "lift",
9139
9450
  options: { translateY: "-2px" }
@@ -9147,13 +9458,12 @@ const flatInk = defineButtonPersonality({
9147
9458
  name: "Secondary",
9148
9459
  enabled: true,
9149
9460
  priority: 2,
9150
- background: { type: "transparent" },
9151
- textColorToken: "primary",
9152
- borderRadius: "rounded-lg",
9153
- border: {
9154
- widthClass: "border",
9155
- colorToken: "border"
9461
+ background: {
9462
+ type: "surface",
9463
+ role: "link"
9156
9464
  },
9465
+ borderRadius: "rounded-lg",
9466
+ border: { widthClass: "border" },
9157
9467
  effects: { hover: [{
9158
9468
  effectId: "lift",
9159
9469
  options: { translateY: "-2px" }
@@ -9171,12 +9481,8 @@ const flatInk = defineButtonPersonality({
9171
9481
  type: "solid",
9172
9482
  colorToken: "accent"
9173
9483
  },
9174
- textColorToken: "accentForeground",
9175
9484
  borderRadius: "rounded-lg",
9176
- affordance: {
9177
- iconId: "ArrowRight",
9178
- colorToken: "accentForeground"
9179
- },
9485
+ affordance: { iconId: "ArrowRight" },
9180
9486
  effects: { hover: [{
9181
9487
  effectId: "lift",
9182
9488
  options: { translateY: "-2px" }
@@ -9239,7 +9545,6 @@ const inkStamp = defineButtonPersonality({
9239
9545
  type: "solid",
9240
9546
  colorToken: "primary"
9241
9547
  },
9242
- textColorToken: "primaryForeground",
9243
9548
  borderRadius: "rounded-md",
9244
9549
  effects: {
9245
9550
  hover: [{
@@ -9260,13 +9565,12 @@ const inkStamp = defineButtonPersonality({
9260
9565
  name: "Secondary",
9261
9566
  enabled: true,
9262
9567
  priority: 2,
9263
- background: { type: "transparent" },
9264
- textColorToken: "primary",
9265
- borderRadius: "rounded-md",
9266
- border: {
9267
- widthClass: "border-2",
9268
- colorToken: "primary"
9568
+ background: {
9569
+ type: "surface",
9570
+ role: "link"
9269
9571
  },
9572
+ borderRadius: "rounded-md",
9573
+ border: { widthClass: "border-2" },
9270
9574
  effects: { hover: [{
9271
9575
  effectId: "background-on-hover",
9272
9576
  options: { colorToken: "surface" }
@@ -9277,13 +9581,12 @@ const inkStamp = defineButtonPersonality({
9277
9581
  name: "Outline",
9278
9582
  enabled: true,
9279
9583
  priority: 3,
9280
- background: { type: "transparent" },
9281
- textColorToken: "text",
9282
- borderRadius: "rounded-md",
9283
- border: {
9284
- widthClass: "border-2",
9285
- colorToken: "border"
9584
+ background: {
9585
+ type: "surface",
9586
+ role: "link"
9286
9587
  },
9588
+ borderRadius: "rounded-md",
9589
+ border: { widthClass: "border-2" },
9287
9590
  effects: { hover: [{
9288
9591
  effectId: "background-on-hover",
9289
9592
  options: { colorToken: "surface" }
@@ -9294,8 +9597,10 @@ const inkStamp = defineButtonPersonality({
9294
9597
  name: "Ghost",
9295
9598
  enabled: true,
9296
9599
  priority: 3,
9297
- background: { type: "transparent" },
9298
- textColorToken: "accent",
9600
+ background: {
9601
+ type: "surface",
9602
+ role: "link"
9603
+ },
9299
9604
  borderRadius: "rounded-none",
9300
9605
  sizes: {
9301
9606
  sm: {
@@ -9388,7 +9693,6 @@ const joyStamp = defineButtonPersonality({
9388
9693
  type: "solid",
9389
9694
  colorToken: "primary"
9390
9695
  },
9391
- textColorToken: "primaryForeground",
9392
9696
  borderRadius: "rounded-full",
9393
9697
  shadow: {
9394
9698
  elevation: "high",
@@ -9402,13 +9706,12 @@ const joyStamp = defineButtonPersonality({
9402
9706
  name: "Secondary",
9403
9707
  enabled: true,
9404
9708
  priority: 2,
9405
- background: { type: "transparent" },
9406
- textColorToken: "text",
9407
- borderRadius: "rounded-full",
9408
- border: {
9409
- widthClass: "border-2",
9410
- colorToken: "text"
9709
+ background: {
9710
+ type: "surface",
9711
+ role: "link"
9411
9712
  },
9713
+ borderRadius: "rounded-full",
9714
+ border: { widthClass: "border-2" },
9412
9715
  shadow: {
9413
9716
  elevation: "high",
9414
9717
  softness: "hard",
@@ -9473,12 +9776,8 @@ const ornateRitual = defineButtonPersonality({
9473
9776
  type: "solid",
9474
9777
  colorToken: "primary"
9475
9778
  },
9476
- textColorToken: "primaryForeground",
9477
9779
  borderRadius: "rounded-md",
9478
- border: {
9479
- widthClass: "border",
9480
- colorToken: "primary"
9481
- },
9780
+ border: { widthClass: "border" },
9482
9781
  effects: {
9483
9782
  hover: [{
9484
9783
  effectId: "background-on-hover",
@@ -9499,12 +9798,8 @@ const ornateRitual = defineButtonPersonality({
9499
9798
  type: "solid",
9500
9799
  colorToken: "secondary"
9501
9800
  },
9502
- textColorToken: "primaryForeground",
9503
9801
  borderRadius: "rounded-md",
9504
- border: {
9505
- widthClass: "border",
9506
- colorToken: "primary"
9507
- },
9802
+ border: { widthClass: "border" },
9508
9803
  effects: { hover: [{
9509
9804
  effectId: "background-on-hover",
9510
9805
  options: { colorToken: "surface" }
@@ -9515,13 +9810,12 @@ const ornateRitual = defineButtonPersonality({
9515
9810
  name: "Outline",
9516
9811
  enabled: true,
9517
9812
  priority: 3,
9518
- background: { type: "transparent" },
9519
- textColorToken: "primary",
9520
- borderRadius: "rounded-md",
9521
- border: {
9522
- widthClass: "border",
9523
- colorToken: "primary"
9813
+ background: {
9814
+ type: "surface",
9815
+ role: "link"
9524
9816
  },
9817
+ borderRadius: "rounded-md",
9818
+ border: { widthClass: "border" },
9525
9819
  effects: { hover: [{
9526
9820
  effectId: "background-on-hover",
9527
9821
  options: { colorToken: "muted" }
@@ -9532,8 +9826,10 @@ const ornateRitual = defineButtonPersonality({
9532
9826
  name: "Ghost",
9533
9827
  enabled: true,
9534
9828
  priority: 3,
9535
- background: { type: "transparent" },
9536
- textColorToken: "accent",
9829
+ background: {
9830
+ type: "surface",
9831
+ role: "link"
9832
+ },
9537
9833
  borderRadius: "rounded-none",
9538
9834
  sizes: {
9539
9835
  sm: {
@@ -9615,14 +9911,10 @@ const pebble = defineButtonPersonality({
9615
9911
  type: "solid",
9616
9912
  colorToken: "primary"
9617
9913
  },
9618
- textColorToken: "primaryForeground",
9619
9914
  borderRadius: "rounded-full",
9620
9915
  effects: { hover: [{
9621
- effectId: "background-on-hover-alpha",
9622
- options: {
9623
- colorToken: "primary",
9624
- opacity: 88
9625
- }
9916
+ effectId: "darken-background",
9917
+ options: { amount: 100 }
9626
9918
  }] }
9627
9919
  },
9628
9920
  {
@@ -9630,13 +9922,12 @@ const pebble = defineButtonPersonality({
9630
9922
  name: "Secondary",
9631
9923
  enabled: true,
9632
9924
  priority: 2,
9633
- background: { type: "transparent" },
9634
- textColorToken: "primary",
9635
- borderRadius: "rounded-full",
9636
- border: {
9637
- widthClass: "border-2",
9638
- colorToken: "accent"
9925
+ background: {
9926
+ type: "surface",
9927
+ role: "link"
9639
9928
  },
9929
+ borderRadius: "rounded-full",
9930
+ border: { widthClass: "border-2" },
9640
9931
  effects: { hover: [{
9641
9932
  effectId: "background-on-hover",
9642
9933
  options: { colorToken: "accent" }
@@ -9647,13 +9938,12 @@ const pebble = defineButtonPersonality({
9647
9938
  name: "Outline",
9648
9939
  enabled: true,
9649
9940
  priority: 3,
9650
- background: { type: "transparent" },
9651
- textColorToken: "text",
9652
- borderRadius: "rounded-full",
9653
- border: {
9654
- widthClass: "border",
9655
- colorToken: "border"
9941
+ background: {
9942
+ type: "surface",
9943
+ role: "link"
9656
9944
  },
9945
+ borderRadius: "rounded-full",
9946
+ border: { widthClass: "border" },
9657
9947
  effects: { hover: [{
9658
9948
  effectId: "background-on-hover",
9659
9949
  options: { colorToken: "surface" }
@@ -9664,8 +9954,10 @@ const pebble = defineButtonPersonality({
9664
9954
  name: "Ghost",
9665
9955
  enabled: true,
9666
9956
  priority: 3,
9667
- background: { type: "transparent" },
9668
- textColorToken: "primary",
9957
+ background: {
9958
+ type: "surface",
9959
+ role: "link"
9960
+ },
9669
9961
  borderRadius: "rounded-full",
9670
9962
  sizes: {
9671
9963
  sm: {
@@ -9681,11 +9973,7 @@ const pebble = defineButtonPersonality({
9681
9973
  padding: "0.75rem 1.5rem",
9682
9974
  fontSize: "text-xl"
9683
9975
  }
9684
- },
9685
- effects: { hover: [{
9686
- effectId: "opacity-reduce",
9687
- options: { reduction: 30 }
9688
- }] }
9976
+ }
9689
9977
  }
9690
9978
  ]
9691
9979
  }
@@ -9747,15 +10035,11 @@ const quietArrow = defineButtonPersonality({
9747
10035
  type: "solid",
9748
10036
  colorToken: "primary"
9749
10037
  },
9750
- textColorToken: "primaryForeground",
9751
10038
  borderRadius: "rounded-xl",
9752
10039
  affordance: { iconId: "ArrowRight" },
9753
10040
  effects: { hover: [{
9754
- effectId: "background-on-hover-alpha",
9755
- options: {
9756
- colorToken: "primary",
9757
- opacity: 90
9758
- }
10041
+ effectId: "darken-background",
10042
+ options: { amount: 100 }
9759
10043
  }] }
9760
10044
  },
9761
10045
  {
@@ -9763,13 +10047,12 @@ const quietArrow = defineButtonPersonality({
9763
10047
  name: "Secondary",
9764
10048
  enabled: true,
9765
10049
  priority: 2,
9766
- background: { type: "transparent" },
9767
- textColorToken: "primary",
9768
- borderRadius: "rounded-xl",
9769
- border: {
9770
- widthClass: "border",
9771
- colorToken: "primary"
10050
+ background: {
10051
+ type: "surface",
10052
+ role: "link"
9772
10053
  },
10054
+ borderRadius: "rounded-xl",
10055
+ border: { widthClass: "border" },
9773
10056
  affordance: { iconId: "ArrowRight" },
9774
10057
  effects: { hover: [{
9775
10058
  effectId: "background-on-hover",
@@ -9781,21 +10064,22 @@ const quietArrow = defineButtonPersonality({
9781
10064
  name: "Outline",
9782
10065
  enabled: true,
9783
10066
  priority: 3,
9784
- background: { type: "transparent" },
9785
- textColorToken: "primary",
10067
+ background: {
10068
+ type: "surface",
10069
+ role: "link"
10070
+ },
9786
10071
  borderRadius: "rounded-xl",
9787
- border: {
9788
- widthClass: "border",
9789
- colorToken: "primary"
9790
- }
10072
+ border: { widthClass: "border" }
9791
10073
  },
9792
10074
  {
9793
10075
  id: "ghost",
9794
10076
  name: "Ghost",
9795
10077
  enabled: true,
9796
10078
  priority: 3,
9797
- background: { type: "transparent" },
9798
- textColorToken: "primary",
10079
+ background: {
10080
+ type: "surface",
10081
+ role: "link"
10082
+ },
9799
10083
  borderRadius: "rounded-xl"
9800
10084
  }
9801
10085
  ]
@@ -9859,7 +10143,6 @@ const showtimePill = defineButtonPersonality({
9859
10143
  type: "solid",
9860
10144
  colorToken: "primary"
9861
10145
  },
9862
- textColorToken: "background",
9863
10146
  borderRadius: "rounded-full",
9864
10147
  effects: { hover: [{ effectId: "pop" }] }
9865
10148
  },
@@ -9868,13 +10151,12 @@ const showtimePill = defineButtonPersonality({
9868
10151
  name: "Secondary",
9869
10152
  enabled: true,
9870
10153
  priority: 2,
9871
- background: { type: "transparent" },
9872
- textColorToken: "primary",
9873
- borderRadius: "rounded-full",
9874
- border: {
9875
- widthClass: "border-2",
9876
- colorToken: "primary"
10154
+ background: {
10155
+ type: "surface",
10156
+ role: "link"
9877
10157
  },
10158
+ borderRadius: "rounded-full",
10159
+ border: { widthClass: "border-2" },
9878
10160
  effects: { hover: [{ effectId: "pop" }] }
9879
10161
  },
9880
10162
  {
@@ -9886,7 +10168,6 @@ const showtimePill = defineButtonPersonality({
9886
10168
  type: "solid",
9887
10169
  colorToken: "secondary"
9888
10170
  },
9889
- textColorToken: "primary",
9890
10171
  borderRadius: "rounded-full",
9891
10172
  effects: { hover: [{ effectId: "pop" }] }
9892
10173
  },
@@ -9899,12 +10180,8 @@ const showtimePill = defineButtonPersonality({
9899
10180
  type: "solid",
9900
10181
  colorToken: "background"
9901
10182
  },
9902
- textColorToken: "primary",
9903
10183
  borderRadius: "rounded-full",
9904
- border: {
9905
- widthClass: "border-2",
9906
- colorToken: "primary"
9907
- },
10184
+ border: { widthClass: "border-2" },
9908
10185
  effects: { hover: [{
9909
10186
  effectId: "background-on-hover",
9910
10187
  options: { colorToken: "surface" }
@@ -9915,13 +10192,12 @@ const showtimePill = defineButtonPersonality({
9915
10192
  name: "Outline",
9916
10193
  enabled: true,
9917
10194
  priority: 3,
9918
- background: { type: "transparent" },
9919
- textColorToken: "primary",
9920
- borderRadius: "rounded-full",
9921
- border: {
9922
- widthClass: "border-2",
9923
- colorToken: "primary"
10195
+ background: {
10196
+ type: "surface",
10197
+ role: "link"
9924
10198
  },
10199
+ borderRadius: "rounded-full",
10200
+ border: { widthClass: "border-2" },
9925
10201
  effects: { hover: [{
9926
10202
  effectId: "background-on-hover",
9927
10203
  options: { colorToken: "background" }
@@ -9932,8 +10208,10 @@ const showtimePill = defineButtonPersonality({
9932
10208
  name: "Ghost",
9933
10209
  enabled: true,
9934
10210
  priority: 3,
9935
- background: { type: "transparent" },
9936
- textColorToken: "primary",
10211
+ background: {
10212
+ type: "surface",
10213
+ role: "link"
10214
+ },
9937
10215
  borderRadius: "rounded-full",
9938
10216
  effects: { hover: [{
9939
10217
  effectId: "background-on-hover",
@@ -9944,104 +10222,151 @@ const showtimePill = defineButtonPersonality({
9944
10222
  }
9945
10223
  });
9946
10224
  //#endregion
9947
- //#region ../theme-core/src/buttons/personalities/index.ts
9948
- const buttonPersonalities = [
9949
- defineButtonPersonality({
9950
- id: "soft-pill",
9951
- name: "Soft Pill",
9952
- description: "Rounded pills with a gentle lift on hover. Quietly modern.",
9953
- tags: {
9954
- tone: "classic",
9955
- energy: "calm",
9956
- motion: "subtle",
9957
- era: "organic"
10225
+ //#region ../theme-core/src/buttons/personalities/soft-pill.ts
10226
+ /**
10227
+ * Soft Pill — rounded-full pill buttons with a hover lift. The default for
10228
+ * Calm Studio and Modern Wellness; reads as quietly modern and welcoming.
10229
+ */
10230
+ const softPill = defineButtonPersonality({
10231
+ id: "soft-pill",
10232
+ name: "Soft Pill",
10233
+ description: "Rounded pills with a gentle lift on hover. Quietly modern.",
10234
+ tags: {
10235
+ tone: "classic",
10236
+ energy: "calm",
10237
+ motion: "subtle",
10238
+ era: "organic"
10239
+ },
10240
+ buttonSystem: {
10241
+ global: {
10242
+ cornerStyle: "pill",
10243
+ shadow: "low",
10244
+ textTransform: "none",
10245
+ fontWeight: 500,
10246
+ borderWidth: 2,
10247
+ hoverTransform: "lift",
10248
+ hoverColor: "none"
9958
10249
  },
9959
- buttonSystem: {
9960
- global: {
9961
- cornerStyle: "pill",
9962
- shadow: "low",
9963
- textTransform: "none",
9964
- fontWeight: 500,
9965
- borderWidth: 2,
9966
- hoverTransform: "lift",
9967
- hoverColor: "none"
10250
+ variants: [
10251
+ {
10252
+ id: "primary",
10253
+ name: "Primary",
10254
+ enabled: true,
10255
+ priority: 1,
10256
+ background: {
10257
+ type: "solid",
10258
+ colorToken: "primary"
10259
+ },
10260
+ borderRadius: "rounded-full",
10261
+ shadow: {
10262
+ elevation: "low",
10263
+ softness: "soft",
10264
+ position: "bottom"
10265
+ },
10266
+ effects: {
10267
+ hover: [{
10268
+ effectId: "lift",
10269
+ options: { translateY: "-1px" }
10270
+ }],
10271
+ active: [{
10272
+ effectId: "scale-down",
10273
+ options: { scale: "0.98" }
10274
+ }]
10275
+ }
9968
10276
  },
9969
- variants: [
9970
- {
9971
- id: "primary",
9972
- name: "Primary",
9973
- enabled: true,
9974
- priority: 1,
9975
- background: {
9976
- type: "solid",
9977
- colorToken: "primary"
9978
- },
9979
- textColorToken: "primaryForeground",
9980
- borderRadius: "rounded-full",
9981
- shadow: {
9982
- elevation: "low",
9983
- softness: "soft",
9984
- position: "bottom"
9985
- },
9986
- effects: {
9987
- hover: [{
9988
- effectId: "lift",
9989
- options: { translateY: "-1px" }
9990
- }],
9991
- active: [{
9992
- effectId: "scale-down",
9993
- options: { scale: "0.98" }
9994
- }]
9995
- }
10277
+ {
10278
+ id: "secondary",
10279
+ name: "Secondary",
10280
+ enabled: true,
10281
+ priority: 2,
10282
+ background: {
10283
+ type: "surface",
10284
+ role: "link"
9996
10285
  },
9997
- {
9998
- id: "secondary",
9999
- name: "Secondary",
10000
- enabled: true,
10001
- priority: 2,
10002
- background: { type: "transparent" },
10003
- textColorToken: "primary",
10004
- borderRadius: "rounded-full",
10005
- border: {
10006
- widthClass: "border-2",
10007
- colorToken: "primary"
10008
- },
10009
- effects: { hover: [{
10010
- effectId: "background-on-hover",
10011
- options: { colorToken: "surface" }
10012
- }] }
10286
+ borderRadius: "rounded-full",
10287
+ border: { widthClass: "border-2" },
10288
+ effects: { hover: [{
10289
+ effectId: "background-on-hover",
10290
+ options: { colorToken: "surface" }
10291
+ }] }
10292
+ },
10293
+ {
10294
+ id: "outline",
10295
+ name: "Outline",
10296
+ enabled: true,
10297
+ priority: 3,
10298
+ background: {
10299
+ type: "surface",
10300
+ role: "link"
10013
10301
  },
10014
- {
10015
- id: "outline",
10016
- name: "Outline",
10017
- enabled: true,
10018
- priority: 3,
10019
- background: { type: "transparent" },
10020
- textColorToken: "text",
10021
- borderRadius: "rounded-full",
10022
- border: {
10023
- widthClass: "border",
10024
- colorToken: "border"
10025
- },
10026
- effects: { hover: [{
10027
- effectId: "background-on-hover",
10028
- options: { colorToken: "surface" }
10029
- }] }
10302
+ borderRadius: "rounded-full",
10303
+ border: { widthClass: "border" },
10304
+ effects: { hover: [{
10305
+ effectId: "background-on-hover",
10306
+ options: { colorToken: "surface" }
10307
+ }] }
10308
+ },
10309
+ {
10310
+ id: "ghost",
10311
+ name: "Ghost",
10312
+ enabled: true,
10313
+ priority: 3,
10314
+ background: {
10315
+ type: "surface",
10316
+ role: "link"
10030
10317
  },
10031
- {
10032
- id: "ghost",
10033
- name: "Ghost",
10034
- enabled: true,
10035
- priority: 3,
10036
- background: { type: "transparent" },
10037
- textColorToken: "text",
10038
- borderRadius: "rounded-full",
10039
- effects: { hover: [{
10040
- effectId: "background-on-hover",
10041
- options: { colorToken: "surface" }
10042
- }] }
10043
- }
10044
- ]
10318
+ borderRadius: "rounded-full",
10319
+ effects: { hover: [{
10320
+ effectId: "background-on-hover",
10321
+ options: { colorToken: "surface" }
10322
+ }] }
10323
+ }
10324
+ ]
10325
+ }
10326
+ });
10327
+ //#endregion
10328
+ //#region ../theme-core/src/buttons/personalities/two-tone-pill.ts
10329
+ const solidSecondary = {
10330
+ id: "secondary",
10331
+ name: "Secondary",
10332
+ enabled: true,
10333
+ priority: 2,
10334
+ background: {
10335
+ type: "solid",
10336
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
10337
+ },
10338
+ borderRadius: "rounded-full",
10339
+ shadow: {
10340
+ elevation: "none",
10341
+ softness: null,
10342
+ position: "bottom"
10343
+ },
10344
+ effects: {
10345
+ hover: [{
10346
+ effectId: "background-on-hover-alpha",
10347
+ options: {
10348
+ colorToken: "secondary",
10349
+ opacity: 88
10350
+ }
10351
+ }],
10352
+ active: [{
10353
+ effectId: "scale-down",
10354
+ options: { scale: "0.98" }
10355
+ }]
10356
+ }
10357
+ };
10358
+ //#endregion
10359
+ //#region ../theme-core/src/buttons/personalities/index.ts
10360
+ const buttonPersonalities = [
10361
+ softPill,
10362
+ defineButtonPersonality({
10363
+ id: "two-tone-pill",
10364
+ name: "Two-tone Pill",
10365
+ description: "Rounded pills with distinct solid primary and secondary brand colours.",
10366
+ tags: softPill.tags,
10367
+ buttonSystem: {
10368
+ ...softPill.buttonSystem,
10369
+ variants: softPill.buttonSystem.variants.map((variant) => variant.id === "secondary" ? solidSecondary : variant)
10045
10370
  }
10046
10371
  }),
10047
10372
  earthPill,
@@ -10442,6 +10767,282 @@ const serifDisplayQuote = { style: "serif-display" };
10442
10767
  /** Punchy quotation mark in the secondary accent colour. Bold / accent styles. */
10443
10768
  const accentGlyphQuote = { style: "accent-glyph" };
10444
10769
  //#endregion
10770
+ //#region ../theme-core/src/gradients/types.ts
10771
+ /**
10772
+ * Gradient configuration types and schemas
10773
+ */
10774
+ /**
10775
+ * Gradient color stop
10776
+ */
10777
+ const gradientStopSchema = z$1.object({
10778
+ color: themeColorTokenSchema,
10779
+ position: z$1.number().min(0).max(100)
10780
+ });
10781
+ /**
10782
+ * Radial gradient shape. Optional; defaults to `circle` (the historical shape)
10783
+ * so existing radial gradients are byte-identical.
10784
+ *
10785
+ * Named `RadialGradientShape` to avoid clashing with `styles/gradients.ts`'s
10786
+ * `GradientShape` (which names the gradient *kind*: linear/radial/conic).
10787
+ */
10788
+ const radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
10789
+ /**
10790
+ * Gradient configuration.
10791
+ *
10792
+ * `type` is optional and defaults to `'linear'` so gradients persisted without a
10793
+ * type (or with an explicit `'linear'`) render exactly as before. `'radial'` and
10794
+ * `'conic'` are additive kinds:
10795
+ * - linear: `angle` (degrees)
10796
+ * - radial: optional `shape` (circle/ellipse) + `position`
10797
+ * - conic: optional `angle` (from-angle, degrees) + `position`
10798
+ */
10799
+ const gradientConfigSchema = z$1.object({
10800
+ type: z$1.enum([
10801
+ "linear",
10802
+ "radial",
10803
+ "conic"
10804
+ ]).default("linear"),
10805
+ angle: z$1.number().min(0).max(360).optional(),
10806
+ shape: radialGradientShapeSchema.optional(),
10807
+ position: z$1.string().optional(),
10808
+ stops: z$1.array(gradientStopSchema).min(2)
10809
+ });
10810
+ /**
10811
+ * Curated library of gradient presets.
10812
+ * All gradients use theme color tokens, so they adapt to the site's palette.
10813
+ */
10814
+ const GRADIENT_PRESETS = [
10815
+ {
10816
+ id: "primary-secondary",
10817
+ name: "Primary to Secondary",
10818
+ description: "Blend your primary and secondary brand colors",
10819
+ type: "linear",
10820
+ angle: 135,
10821
+ stops: [{
10822
+ color: "primary-500",
10823
+ position: 0
10824
+ }, {
10825
+ color: "secondary-500",
10826
+ position: 100
10827
+ }]
10828
+ },
10829
+ {
10830
+ id: "primary-accent",
10831
+ name: "Primary to Accent",
10832
+ description: "Energetic gradient from primary to accent",
10833
+ type: "linear",
10834
+ angle: 135,
10835
+ stops: [{
10836
+ color: "primary-500",
10837
+ position: 0
10838
+ }, {
10839
+ color: "accent-500",
10840
+ position: 100
10841
+ }]
10842
+ },
10843
+ {
10844
+ id: "secondary-accent",
10845
+ name: "Secondary to Accent",
10846
+ description: "Vibrant secondary to accent blend",
10847
+ type: "linear",
10848
+ angle: 135,
10849
+ stops: [{
10850
+ color: "secondary-500",
10851
+ position: 0
10852
+ }, {
10853
+ color: "accent-500",
10854
+ position: 100
10855
+ }]
10856
+ },
10857
+ {
10858
+ id: "primary-light-dark",
10859
+ name: "Primary Light to Dark",
10860
+ description: "Subtle primary color fade",
10861
+ type: "linear",
10862
+ angle: 180,
10863
+ stops: [{
10864
+ color: "primary-500",
10865
+ position: 0
10866
+ }, {
10867
+ color: "primary-900",
10868
+ position: 100
10869
+ }]
10870
+ },
10871
+ {
10872
+ id: "primary-dark-light",
10873
+ name: "Primary Dark to Light",
10874
+ description: "Reverse primary fade",
10875
+ type: "linear",
10876
+ angle: 180,
10877
+ stops: [{
10878
+ color: "primary-900",
10879
+ position: 0
10880
+ }, {
10881
+ color: "primary-50",
10882
+ position: 100
10883
+ }]
10884
+ },
10885
+ {
10886
+ id: "secondary-light-dark",
10887
+ name: "Secondary Light to Dark",
10888
+ description: "Subtle secondary color fade",
10889
+ type: "linear",
10890
+ angle: 180,
10891
+ stops: [{
10892
+ color: "secondary-500",
10893
+ position: 0
10894
+ }, {
10895
+ color: "secondary-900",
10896
+ position: 100
10897
+ }]
10898
+ },
10899
+ {
10900
+ id: "accent-light-dark",
10901
+ name: "Accent Light to Dark",
10902
+ description: "Accent color depth fade",
10903
+ type: "linear",
10904
+ angle: 180,
10905
+ stops: [{
10906
+ color: "accent-500",
10907
+ position: 0
10908
+ }, {
10909
+ color: "accent-900",
10910
+ position: 100
10911
+ }]
10912
+ },
10913
+ {
10914
+ id: "background-surface",
10915
+ name: "Background to Surface",
10916
+ description: "Subtle depth using base colors",
10917
+ type: "linear",
10918
+ angle: 180,
10919
+ stops: [{
10920
+ color: "background",
10921
+ position: 0
10922
+ }, {
10923
+ color: "surface",
10924
+ position: 100
10925
+ }]
10926
+ },
10927
+ {
10928
+ id: "neutral-fade",
10929
+ name: "Neutral Gradient",
10930
+ description: "Elegant neutral color fade",
10931
+ type: "linear",
10932
+ angle: 180,
10933
+ stops: [{
10934
+ color: "neutral-900",
10935
+ position: 0
10936
+ }, {
10937
+ color: "neutral-50",
10938
+ position: 100
10939
+ }]
10940
+ },
10941
+ {
10942
+ id: "primary-glow",
10943
+ name: "Primary glow",
10944
+ description: "A soft top-centred glow using your primary palette",
10945
+ type: "radial",
10946
+ shape: "ellipse",
10947
+ position: "top center",
10948
+ stops: [{
10949
+ color: "primary-900",
10950
+ position: 0
10951
+ }, {
10952
+ color: "primary-950",
10953
+ position: 100
10954
+ }],
10955
+ foreground: {
10956
+ textColor: "onPrimary900",
10957
+ headingColor: "onPrimary900",
10958
+ linkColor: "onPrimary900",
10959
+ supportingColor: "onPrimary900"
10960
+ }
10961
+ },
10962
+ {
10963
+ id: "accent-glow",
10964
+ name: "Accent glow",
10965
+ description: "A soft top-centred glow using your accent palette",
10966
+ type: "radial",
10967
+ shape: "ellipse",
10968
+ position: "top center",
10969
+ stops: [{
10970
+ color: "accent-900",
10971
+ position: 0
10972
+ }, {
10973
+ color: "accent-950",
10974
+ position: 100
10975
+ }],
10976
+ foreground: {
10977
+ textColor: "onAccent900",
10978
+ headingColor: "onAccent900",
10979
+ linkColor: "onAccent900",
10980
+ supportingColor: "onAccent900"
10981
+ }
10982
+ },
10983
+ {
10984
+ id: "primary-secondary-accent",
10985
+ name: "Brand Trio",
10986
+ description: "All three brand colors in harmony",
10987
+ type: "linear",
10988
+ angle: 135,
10989
+ stops: [
10990
+ {
10991
+ color: "primary-500",
10992
+ position: 0
10993
+ },
10994
+ {
10995
+ color: "secondary-500",
10996
+ position: 50
10997
+ },
10998
+ {
10999
+ color: "accent-500",
11000
+ position: 100
11001
+ }
11002
+ ]
11003
+ }
11004
+ ].map((preset) => ({
11005
+ ...preset,
11006
+ id: preset.id,
11007
+ stops: preset.stops
11008
+ }));
11009
+ const GRADIENT_PRESET_IDS = GRADIENT_PRESETS.map((preset) => preset.id);
11010
+ const gradientPresetIdSet = new Set(GRADIENT_PRESET_IDS);
11011
+ const gradientPresetById = Object.fromEntries(GRADIENT_PRESETS.map((preset) => [preset.id, preset]));
11012
+ function parseGradientPresetId(value) {
11013
+ if (typeof value !== "string") return null;
11014
+ const normalized = value.trim();
11015
+ if (!gradientPresetIdSet.has(normalized)) return null;
11016
+ return normalized;
11017
+ }
11018
+ function getGradientPreset(id) {
11019
+ return gradientPresetById[id];
11020
+ }
11021
+ //#endregion
11022
+ //#region ../theme-core/src/gradients/utils.ts
11023
+ /**
11024
+ * Convert a GradientConfig to a CSS gradient string
11025
+ *
11026
+ * @param config - The gradient configuration using theme tokens
11027
+ * @param tokens - Map of theme color tokens to hex values
11028
+ * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
11029
+ */
11030
+ function gradientToCss(config, tokens) {
11031
+ const stops = config.stops.map((stop) => {
11032
+ return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
11033
+ }).join(", ");
11034
+ const type = config.type ?? "linear";
11035
+ if (type === "radial") {
11036
+ const position = config.position ?? "center";
11037
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
11038
+ }
11039
+ if (type === "conic") {
11040
+ const position = config.position ?? "center";
11041
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
11042
+ }
11043
+ return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
11044
+ }
11045
+ //#endregion
10445
11046
  //#region ../theme-core/src/site-styles/logoBranding.ts
10446
11047
  const logoTextConfidenceValues = [
10447
11048
  "low",
@@ -10665,7 +11266,7 @@ const overlayLogoAccommodations = [
10665
11266
  * optional nested styling fields that would otherwise leak from another Look.
10666
11267
  */
10667
11268
  function baseHeader(theme) {
10668
- const { navLinkStyle: _navLinkStyle, navTypography: _navTypography, navTextSize: _navTextSize, dropdownStyle: _dropdownStyle, ctaVariant: _ctaVariant, navContainer: _navContainer, container: _container, shadow: _shadow, logo: _logo, logoText: _logoText, border: _border, ...header } = theme.header;
11269
+ const { navLinkStyle: _navLinkStyle, navFontRole: _navFontRole, navTypography: _navTypography, navTextSize: _navTextSize, dropdownStyle: _dropdownStyle, ctaVariant: _ctaVariant, navContainer: _navContainer, container: _container, shadow: _shadow, logo: _logo, logoText: _logoText, border: _border, ...header } = theme.header;
10669
11270
  return {
10670
11271
  ...header,
10671
11272
  navContainer: {
@@ -10814,6 +11415,17 @@ const headerStyleCatalog = defineExactCatalog()([
10814
11415
  navTypography: "brand-caps",
10815
11416
  moods: ["expressive"]
10816
11417
  },
11418
+ {
11419
+ id: asHeaderStyleId("brand-capsule"),
11420
+ label: "Brand Capsule",
11421
+ description: "Solid brand chrome designed as a floating capsule, with quiet-caps nav, a soft pill active state, and an inverted CTA pill.",
11422
+ supportedLayoutIds: supportedLayouts(["classic"]),
11423
+ navInteraction: "pill-background",
11424
+ surface: "brand-solid",
11425
+ defaultDepth: "shadow",
11426
+ navTypography: "quiet-caps",
11427
+ moods: ["expressive", "professional"]
11428
+ },
10817
11429
  {
10818
11430
  id: asHeaderStyleId("serif-line"),
10819
11431
  label: "Serif Line",
@@ -10907,6 +11519,7 @@ const headerStyleCompatibilityOrder = /* @__PURE__ */ new Map([
10907
11519
  "brand-bar",
10908
11520
  "brand-underline",
10909
11521
  "brand-pill",
11522
+ "brand-capsule",
10910
11523
  "serif-line",
10911
11524
  "flat-tabs"
10912
11525
  ])],
@@ -10944,6 +11557,11 @@ headerStyleRepairChain([
10944
11557
  "brand-pill",
10945
11558
  "brand-bar",
10946
11559
  "minimal"
11560
+ ]), headerStyleRepairChain([
11561
+ "brand-capsule",
11562
+ "brand-pill",
11563
+ "brand-bar",
11564
+ "minimal"
10947
11565
  ]), headerStyleRepairChain([
10948
11566
  "pill-nav",
10949
11567
  "soft-bar",
@@ -12750,14 +13368,12 @@ const backgroundOnHoverEffect = {
12750
13368
  ]
12751
13369
  },
12752
13370
  generateCSS: (ctx) => {
12753
- const { themeId, variantId, options, tokens } = ctx;
13371
+ const { themeId, variantId, options, tokens, buttonConfig } = ctx;
12754
13372
  const colorToken = options.colorToken || "neutral-800";
12755
- const color = tokens.getColor(colorToken);
12756
- const textColorToken = typeof options.textColorToken === "string" ? options.textColorToken : null;
12757
13373
  return `
12758
13374
  /* Add background on hover */
12759
13375
  :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
12760
- background-color: ${color};${textColorToken ? `\n color: ${tokens.getColor(textColorToken)};` : ""}
13376
+ background-color: ${tokens.getColor(colorToken)};${"textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : ""}
12761
13377
  }
12762
13378
  `;
12763
13379
  }
@@ -12781,10 +13397,10 @@ const backgroundOnHoverAlphaEffect = {
12781
13397
  default: 50
12782
13398
  },
12783
13399
  generateCSS: (ctx) => {
12784
- const { themeId, variantId, stateGroup, options, buttonConfig } = ctx;
13400
+ const { themeId, variantId, stateGroup, options } = ctx;
12785
13401
  const rawOpacity = options.opacity;
12786
13402
  const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
12787
- const cssVar = `var(--tb-${options.colorToken || buttonConfig.textColorToken || "neutral-800"})`;
13403
+ const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
12788
13404
  return `
12789
13405
  /* Add semi-transparent background (${stateGroup}) */
12790
13406
  :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
@@ -12997,7 +13613,7 @@ const outerGlowEffect = {
12997
13613
  const spread = options.spread || 10;
12998
13614
  let glowColor;
12999
13615
  if (options.glowColorToken && typeof options.glowColorToken === "string") glowColor = tokens.getColor(options.glowColorToken);
13000
- else if (buttonConfig.border?.colorToken) glowColor = tokens.getColor(buttonConfig.border.colorToken);
13616
+ else if (buttonConfig.border) glowColor = "colorToken" in buttonConfig.border ? tokens.getColor(buttonConfig.border.colorToken) : "currentColor";
13001
13617
  else if (buttonConfig.background.type === "solid") glowColor = tokens.getColor(buttonConfig.background.colorToken ?? "primary-400");
13002
13618
  else glowColor = tokens.getColor("primary-400");
13003
13619
  return `
@@ -13987,31 +14603,6 @@ function generateSingleEffectCSS(themeId, variantId, stateGroup, effectApp, elem
13987
14603
  return effectPreset.generateCSS(ctx);
13988
14604
  }
13989
14605
  //#endregion
13990
- //#region ../theme-core/src/buttons/utils/contrast.ts
13991
- /**
13992
- * Get contrasting text color for a button background
13993
- *
13994
- * This function returns theme-aware text colors using the neutral scale,
13995
- * which is guaranteed to exist in every theme and harmonizes with the design.
13996
- *
13997
- * Uses neutral-50 (lightest) for dark backgrounds and neutral-950 (darkest)
13998
- * for light backgrounds. This ensures excellent contrast while respecting
13999
- * the theme's neutral palette (warm/cool tinting).
14000
- *
14001
- * For solid backgrounds with primary/secondary/neutral colors:
14002
- * - Dark backgrounds (shade >= 500): neutral-50 (very light)
14003
- * - Light backgrounds (shade < 500): neutral-950 (very dark)
14004
- */
14005
- function getContrastingTextColorToken(backgroundToken, theme) {
14006
- const isLightTheme = theme.palette.meta.mode === "light";
14007
- if (backgroundToken.startsWith("primary-") || backgroundToken.startsWith("secondary-")) return "neutral-50";
14008
- if (backgroundToken.startsWith("neutral-")) {
14009
- const match = backgroundToken.match(/neutral-(\d+)/);
14010
- if (match?.[1]) return parseInt(match[1], 10) >= 500 ? "neutral-50" : "neutral-950";
14011
- }
14012
- return isLightTheme ? "neutral-50" : "neutral-950";
14013
- }
14014
- //#endregion
14015
14606
  //#region ../theme-core/src/buttons/generateDefaultButtonSystem.ts
14016
14607
  /**
14017
14608
  * Map border width to border width class
@@ -14068,13 +14659,8 @@ function generateDefaultButtonSystem(theme) {
14068
14659
  priority: 1,
14069
14660
  background: {
14070
14661
  type: "solid",
14071
- colorToken: "primary"
14072
- },
14073
- textColorToken: getContrastingTextColorToken("primary", theme),
14074
- effects: { hover: [{
14075
- effectId: "opacity-reduce",
14076
- options: { reduction: 15 }
14077
- }] }
14662
+ colorToken: unsafeAsOpaqueButtonColourToken("primary")
14663
+ }
14078
14664
  },
14079
14665
  {
14080
14666
  id: "secondary",
@@ -14083,51 +14669,39 @@ function generateDefaultButtonSystem(theme) {
14083
14669
  priority: 2,
14084
14670
  background: {
14085
14671
  type: "solid",
14086
- colorToken: "neutral-700"
14087
- },
14088
- textColorToken: getContrastingTextColorToken("neutral-700", theme),
14089
- effects: { hover: [{
14090
- effectId: "opacity-reduce",
14091
- options: { reduction: 15 }
14092
- }] }
14672
+ colorToken: unsafeAsOpaqueButtonColourToken("neutral-700")
14673
+ }
14093
14674
  },
14094
14675
  {
14095
14676
  id: "outline",
14096
14677
  name: "Outline",
14097
14678
  enabled: true,
14098
14679
  priority: 3,
14099
- background: { type: "transparent" },
14100
- textColorToken: "primary",
14680
+ background: {
14681
+ type: "surface",
14682
+ role: "link"
14683
+ },
14101
14684
  shadow: {
14102
14685
  elevation: "none",
14103
14686
  softness: null,
14104
14687
  position: "bottom"
14105
14688
  },
14106
- border: {
14107
- colorToken: "primary",
14108
- widthClass: borderWidthClass
14109
- },
14110
- effects: { hover: [{
14111
- effectId: "opacity-reduce",
14112
- options: { reduction: 15 }
14113
- }] }
14689
+ border: { widthClass: borderWidthClass }
14114
14690
  },
14115
14691
  {
14116
14692
  id: "ghost",
14117
14693
  name: "Ghost",
14118
14694
  enabled: true,
14119
14695
  priority: 3,
14120
- background: { type: "transparent" },
14121
- textColorToken: "primary",
14696
+ background: {
14697
+ type: "surface",
14698
+ role: "link"
14699
+ },
14122
14700
  shadow: {
14123
14701
  elevation: "none",
14124
14702
  softness: null,
14125
14703
  position: "bottom"
14126
- },
14127
- effects: { hover: [{
14128
- effectId: "opacity-reduce",
14129
- options: { reduction: 15 }
14130
- }] }
14704
+ }
14131
14705
  }
14132
14706
  ];
14133
14707
  return {
@@ -14183,6 +14757,472 @@ function affordanceIconMaskUrl(iconId) {
14183
14757
  return `data:image/svg+xml,${`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>${paths.map((d) => `<path d='${d}'/>`).join("")}</svg>`.replace(/"/g, "'").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ")}`;
14184
14758
  }
14185
14759
  //#endregion
14760
+ //#region ../theme-core/src/surfaces/foregroundRoles.ts
14761
+ const SURFACE_FOREGROUND_ROLES = [
14762
+ "text",
14763
+ "heading",
14764
+ "link",
14765
+ "supporting"
14766
+ ];
14767
+ //#endregion
14768
+ //#region ../theme-core/src/surfaces/foregroundContract.ts
14769
+ const SURFACE_FOREGROUND_CSS_VARS = {
14770
+ text: "--rb-surface-text-color",
14771
+ heading: "--rb-surface-heading-color",
14772
+ link: "--rb-surface-link-color",
14773
+ supporting: "--rb-surface-supporting-color"
14774
+ };
14775
+ const DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
14776
+ const DEFAULT_ROLE_FALLBACKS = {
14777
+ text: DEFAULT_SURFACE_TEXT_COLOR,
14778
+ heading: DEFAULT_SURFACE_TEXT_COLOR,
14779
+ link: "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))",
14780
+ supporting: "rgb(var(--tb-mutedText, 100 116 139))"
14781
+ };
14782
+ function requireSurfaceColorValue(role, value) {
14783
+ const normalized = value.trim();
14784
+ if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
14785
+ return normalized;
14786
+ }
14787
+ function completeSurfaceForegrounds(input) {
14788
+ const text = requireSurfaceColorValue("text", input.text);
14789
+ return {
14790
+ text,
14791
+ heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
14792
+ link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
14793
+ supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
14794
+ };
14795
+ }
14796
+ function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
14797
+ const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
14798
+ const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
14799
+ if (role === "text") return `var(${roleVariable}, ${fallback})`;
14800
+ return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
14801
+ }
14802
+ function surfaceForegroundValueWithOpacity(role, opacityPercent) {
14803
+ if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
14804
+ return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
14805
+ }
14806
+ function surfaceForegroundStyle(input) {
14807
+ const foregrounds = completeSurfaceForegrounds(input);
14808
+ return {
14809
+ color: foregrounds.text,
14810
+ [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
14811
+ [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
14812
+ [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
14813
+ [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
14814
+ };
14815
+ }
14816
+ function surfaceForegroundDeclarations(input) {
14817
+ const foregrounds = completeSurfaceForegrounds(input);
14818
+ return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
14819
+ }
14820
+ //#endregion
14821
+ //#region ../theme-core/src/buttons/resolveButtonColourStates.ts
14822
+ const BUTTON_VISUAL_STATES = [
14823
+ "base",
14824
+ "hover",
14825
+ "focus",
14826
+ "active",
14827
+ "disabled"
14828
+ ];
14829
+ const BUTTON_CONTRAST_POLICY = {
14830
+ textMinimumRatio: 4.5,
14831
+ nonTextMinimumRatio: 3,
14832
+ gradientSamplesPerSegment: 20,
14833
+ alphaBackgrounds: "reject-without-known-surface",
14834
+ disabled: "retain-full-colour-contract"
14835
+ };
14836
+ function compileButtonColourStates(input) {
14837
+ const baseTransition = applyColourEffects({
14838
+ variantId: input.variant.id,
14839
+ state: "base",
14840
+ treatment: input.variant.background,
14841
+ effects: input.variant.effects?.base,
14842
+ palette: input.palette
14843
+ });
14844
+ if (!baseTransition.ok) return baseTransition;
14845
+ const stateTreatments = {
14846
+ base: baseTransition.treatment,
14847
+ hover: hoverTreatment(input.variant, input.global, baseTransition.treatment),
14848
+ focus: baseTransition.treatment,
14849
+ active: baseTransition.treatment,
14850
+ disabled: baseTransition.treatment
14851
+ };
14852
+ const nonColourEffects = { ...baseTransition.nonColourEffects.length > 0 ? { base: [...baseTransition.nonColourEffects] } : {} };
14853
+ for (const state of [
14854
+ "hover",
14855
+ "focus",
14856
+ "active"
14857
+ ]) {
14858
+ const transition = applyColourEffects({
14859
+ variantId: input.variant.id,
14860
+ state,
14861
+ treatment: stateTreatments[state],
14862
+ effects: input.variant.effects?.[state],
14863
+ palette: input.palette
14864
+ });
14865
+ if (!transition.ok) return transition;
14866
+ stateTreatments[state] = transition.treatment;
14867
+ if (transition.nonColourEffects.length > 0) nonColourEffects[state] = [...transition.nonColourEffects];
14868
+ }
14869
+ const resolved = {};
14870
+ for (const state of BUTTON_VISUAL_STATES) {
14871
+ const result = resolveTreatment$1({
14872
+ variantId: input.variant.id,
14873
+ state,
14874
+ treatment: stateTreatments[state],
14875
+ palette: input.palette
14876
+ });
14877
+ if (!result.ok) return result;
14878
+ resolved[state] = result.colour;
14879
+ }
14880
+ return {
14881
+ ok: true,
14882
+ states: resolved,
14883
+ focusIndicator: resolveFocusIndicator(resolved.focus),
14884
+ nonColourEffects
14885
+ };
14886
+ }
14887
+ function formatButtonColourContractError(error) {
14888
+ switch (error.tag) {
14889
+ case "unknown_palette_token": return `Button "${error.variantId}" ${error.state} state uses unknown palette token "${error.token}".`;
14890
+ case "missing_on_colour": return `Button "${error.variantId}" ${error.state} state cannot derive ${error.foregroundToken} from ${error.backgroundToken}.`;
14891
+ case "insufficient_contrast": return `Button "${error.variantId}" ${error.state} state has ${error.ratio.toFixed(2)}:1 contrast (${error.requiredRatio}:1 required).`;
14892
+ case "unsupported_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" is not contrast-safe (${error.reason}).`;
14893
+ case "invalid_colour_effect_options": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" has an invalid ${error.option} option.`;
14894
+ case "inapplicable_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" cannot apply to a ${error.treatment} treatment.`;
14895
+ case "unknown_button_effect": return `Button "${error.variantId}" ${error.state} uses unknown effect "${error.effectId}".`;
14896
+ }
14897
+ }
14898
+ function hoverTreatment(variant, global, fallback) {
14899
+ const token = variant.hoverBackgroundToken ?? (global.hoverColor === "token" ? global.hoverColorToken : void 0);
14900
+ return token === void 0 ? fallback : {
14901
+ type: "solid",
14902
+ colorToken: token
14903
+ };
14904
+ }
14905
+ function applyColourEffects(input) {
14906
+ let treatment = input.treatment;
14907
+ const nonColourEffects = [];
14908
+ for (const effect of input.effects ?? []) {
14909
+ const policy = getButtonEffectPolicy(effect.effectId);
14910
+ if (policy === null) return unknownEffect(input, effect);
14911
+ switch (policy.classification) {
14912
+ case "non-colour":
14913
+ nonColourEffects.push(effect);
14914
+ break;
14915
+ case "unsupported-colour":
14916
+ case "unsupported-background-overlay":
14917
+ case "not-button": return unsupportedEffect(input, effect, policy.reason);
14918
+ case "colour-transition":
14919
+ if (policy.transition.kind === "adjust-shade") {
14920
+ if (treatment.type !== "solid") return inapplicableEffect(input, effect, treatment);
14921
+ const amount = readShadeAmount(effect);
14922
+ if (amount === null) return invalidEffectOption(input, effect, "amount");
14923
+ const signedAmount = policy.transition.direction === "darker" ? amount : -amount;
14924
+ treatment = {
14925
+ type: "solid",
14926
+ colorToken: adjustShade(treatment.colorToken, signedAmount, input.palette)
14927
+ };
14928
+ break;
14929
+ }
14930
+ if (policy.transition.kind === "replace-background") {
14931
+ const colorToken = readOpaqueToken(effect, "colorToken", "neutral-800");
14932
+ if (colorToken === null) return invalidEffectOption(input, effect, "colorToken");
14933
+ treatment = {
14934
+ type: "solid",
14935
+ colorToken
14936
+ };
14937
+ break;
14938
+ }
14939
+ return unknownEffect(input, effect);
14940
+ }
14941
+ }
14942
+ return {
14943
+ ok: true,
14944
+ treatment,
14945
+ nonColourEffects
14946
+ };
14947
+ }
14948
+ function resolveTreatment$1(input) {
14949
+ const treatment = input.treatment;
14950
+ switch (treatment.type) {
14951
+ case "surface": return {
14952
+ ok: true,
14953
+ colour: {
14954
+ kind: "surface",
14955
+ role: treatment.role,
14956
+ backgroundCss: "transparent",
14957
+ foregroundCss: surfaceForegroundValue(treatment.role)
14958
+ }
14959
+ };
14960
+ case "solid": return resolveSolid(input, treatment.colorToken);
14961
+ case "gradient": return resolveGradient(input, treatment);
14962
+ }
14963
+ }
14964
+ function resolveFocusIndicator(colour) {
14965
+ switch (colour.kind) {
14966
+ case "solid": return {
14967
+ kind: "two-tone",
14968
+ innerCss: colour.foregroundCss,
14969
+ outerCss: colour.backgroundCss,
14970
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
14971
+ };
14972
+ case "gradient": return {
14973
+ kind: "two-tone",
14974
+ innerCss: colour.foregroundCss,
14975
+ outerCss: tokenCss(colour.backgroundTokens[0]),
14976
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
14977
+ };
14978
+ case "surface": return {
14979
+ kind: "surface-role",
14980
+ colorCss: colour.foregroundCss,
14981
+ minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
14982
+ };
14983
+ }
14984
+ }
14985
+ function resolveSolid(input, backgroundToken) {
14986
+ const backgroundHex = paletteHex(input, backgroundToken);
14987
+ if (!backgroundHex.ok) return backgroundHex;
14988
+ const foregroundToken = unsafeAsOpaqueButtonColourToken(onColorTokenName(backgroundToken));
14989
+ const foregroundHex = input.palette[foregroundToken];
14990
+ if (typeof foregroundHex !== "string") return {
14991
+ ok: false,
14992
+ error: {
14993
+ tag: "missing_on_colour",
14994
+ variantId: input.variantId,
14995
+ state: input.state,
14996
+ backgroundToken,
14997
+ foregroundToken
14998
+ }
14999
+ };
15000
+ const contrast = validateContrast({
15001
+ ...input,
15002
+ background: backgroundToken,
15003
+ backgroundHex: backgroundHex.hex,
15004
+ foreground: foregroundToken,
15005
+ foregroundHex
15006
+ });
15007
+ if (!contrast.ok) return contrast;
15008
+ return {
15009
+ ok: true,
15010
+ colour: {
15011
+ kind: "solid",
15012
+ backgroundToken,
15013
+ foregroundToken,
15014
+ backgroundCss: tokenCss(backgroundToken),
15015
+ foregroundCss: tokenCss(foregroundToken)
15016
+ }
15017
+ };
15018
+ }
15019
+ function resolveGradient(input, treatment) {
15020
+ const foregroundHex = paletteHex(input, treatment.foregroundToken);
15021
+ if (!foregroundHex.ok) return foregroundHex;
15022
+ const stopHexes = [];
15023
+ for (const token of treatment.stops) {
15024
+ const stop = paletteHex(input, token);
15025
+ if (!stop.ok) return stop;
15026
+ stopHexes.push(stop.hex);
15027
+ }
15028
+ for (let segment = 0; segment < stopHexes.length - 1; segment += 1) {
15029
+ const start = stopHexes[segment];
15030
+ const end = stopHexes[segment + 1];
15031
+ const startToken = treatment.stops[segment];
15032
+ const endToken = treatment.stops[segment + 1];
15033
+ if (start === void 0 || end === void 0 || startToken === void 0 || endToken === void 0) continue;
15034
+ for (let sample = 0; sample <= BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment; sample += 1) {
15035
+ const position = sample / BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment;
15036
+ const sampleHex = interpolateHex(start, end, position);
15037
+ const contrast = validateContrast({
15038
+ ...input,
15039
+ background: `${startToken}→${endToken}@${position.toFixed(2)}`,
15040
+ backgroundHex: sampleHex,
15041
+ foreground: treatment.foregroundToken,
15042
+ foregroundHex: foregroundHex.hex
15043
+ });
15044
+ if (!contrast.ok) return contrast;
15045
+ }
15046
+ }
15047
+ const direction = GRADIENT_DIRECTION_MAP$1[treatment.direction] ?? "to right";
15048
+ return {
15049
+ ok: true,
15050
+ colour: {
15051
+ kind: "gradient",
15052
+ backgroundTokens: treatment.stops,
15053
+ foregroundToken: treatment.foregroundToken,
15054
+ backgroundCss: `linear-gradient(${direction}, ${treatment.stops.map(tokenCss).join(", ")})`,
15055
+ foregroundCss: tokenCss(treatment.foregroundToken)
15056
+ }
15057
+ };
15058
+ }
15059
+ function paletteHex(input, token) {
15060
+ const hex = input.palette[token];
15061
+ return typeof hex === "string" ? {
15062
+ ok: true,
15063
+ hex
15064
+ } : {
15065
+ ok: false,
15066
+ error: {
15067
+ tag: "unknown_palette_token",
15068
+ variantId: input.variantId,
15069
+ state: input.state,
15070
+ token
15071
+ }
15072
+ };
15073
+ }
15074
+ function validateContrast(input) {
15075
+ const ratio = contrastRatio(input.backgroundHex, input.foregroundHex);
15076
+ return ratio >= BUTTON_CONTRAST_POLICY.textMinimumRatio ? { ok: true } : {
15077
+ ok: false,
15078
+ error: {
15079
+ tag: "insufficient_contrast",
15080
+ variantId: input.variantId,
15081
+ state: input.state,
15082
+ background: input.background,
15083
+ foreground: input.foreground,
15084
+ ratio,
15085
+ requiredRatio: BUTTON_CONTRAST_POLICY.textMinimumRatio
15086
+ }
15087
+ };
15088
+ }
15089
+ function tokenCss(token) {
15090
+ return `rgb(var(--tb-${token}))`;
15091
+ }
15092
+ function adjustShade(token, amount, palette) {
15093
+ const match = token.match(/^(.*)-(\d{2,3})$/);
15094
+ const base = match?.[1] ?? token;
15095
+ const currentShade = match?.[2] === void 0 ? 500 : Number(match[2]);
15096
+ const availableShades = [
15097
+ 50,
15098
+ 100,
15099
+ 200,
15100
+ 300,
15101
+ 400,
15102
+ 500,
15103
+ 600,
15104
+ 700,
15105
+ 800,
15106
+ 900,
15107
+ 950
15108
+ ].filter((shade) => typeof palette[`${base}-${shade}`] === "string");
15109
+ if (availableShades.length === 0) return token;
15110
+ const firstShade = availableShades[0];
15111
+ if (firstShade === void 0) return token;
15112
+ const exactIndex = availableShades.indexOf(currentShade);
15113
+ const startingIndex = exactIndex >= 0 ? exactIndex : availableShades.indexOf(availableShades.reduce((closestShade, shade) => Math.abs(shade - currentShade) < Math.abs(closestShade - currentShade) ? shade : closestShade, firstShade));
15114
+ const stepCount = Math.abs(amount) / 100;
15115
+ const direction = amount < 0 ? -1 : 1;
15116
+ const targetShade = availableShades[Math.max(0, Math.min(availableShades.length - 1, startingIndex + direction * stepCount))];
15117
+ return targetShade === void 0 ? token : unsafeAsOpaqueButtonColourToken(`${base}-${targetShade}`);
15118
+ }
15119
+ function readShadeAmount(effect) {
15120
+ const value = effect.options?.amount ?? 100;
15121
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 && value % 100 === 0 ? value : null;
15122
+ }
15123
+ function readOpaqueToken(effect, key, fallback) {
15124
+ return parseOpaqueButtonColourToken(effect.options?.[key] ?? fallback);
15125
+ }
15126
+ function unsupportedEffect(input, effect, reason) {
15127
+ return {
15128
+ ok: false,
15129
+ error: {
15130
+ tag: "unsupported_colour_effect",
15131
+ variantId: input.variantId,
15132
+ state: input.state,
15133
+ effectId: effect.effectId,
15134
+ reason
15135
+ }
15136
+ };
15137
+ }
15138
+ function invalidEffectOption(input, effect, option) {
15139
+ return {
15140
+ ok: false,
15141
+ error: {
15142
+ tag: "invalid_colour_effect_options",
15143
+ variantId: input.variantId,
15144
+ state: input.state,
15145
+ effectId: effect.effectId,
15146
+ option
15147
+ }
15148
+ };
15149
+ }
15150
+ function inapplicableEffect(input, effect, treatment) {
15151
+ return {
15152
+ ok: false,
15153
+ error: {
15154
+ tag: "inapplicable_colour_effect",
15155
+ variantId: input.variantId,
15156
+ state: input.state,
15157
+ effectId: effect.effectId,
15158
+ treatment: treatment.type
15159
+ }
15160
+ };
15161
+ }
15162
+ function unknownEffect(input, effect) {
15163
+ return {
15164
+ ok: false,
15165
+ error: {
15166
+ tag: "unknown_button_effect",
15167
+ variantId: input.variantId,
15168
+ state: input.state,
15169
+ effectId: effect.effectId
15170
+ }
15171
+ };
15172
+ }
15173
+ function interpolateHex(startHex, endHex, position) {
15174
+ const start = hexToRgb(startHex);
15175
+ const end = hexToRgb(endHex);
15176
+ const channel = (from, to) => Math.round(from + (to - from) * position).toString(16).padStart(2, "0");
15177
+ return `#${channel(start.r, end.r)}${channel(start.g, end.g)}${channel(start.b, end.b)}`;
15178
+ }
15179
+ //#endregion
15180
+ //#region ../theme-core/src/buttons/resolvedButtonCss.ts
15181
+ /**
15182
+ * Canonical colour declaration mapping shared by full themes and ThemeBridge.
15183
+ * Both background properties are always emitted so transitions cannot retain
15184
+ * a stale gradient or solid layer.
15185
+ */
15186
+ function resolvedButtonColourDeclarations(colour) {
15187
+ switch (colour.kind) {
15188
+ case "solid": return [
15189
+ ["background-color", colour.backgroundCss],
15190
+ ["background-image", "none"],
15191
+ ["color", colour.foregroundCss]
15192
+ ];
15193
+ case "gradient": return [
15194
+ ["background-color", "transparent"],
15195
+ ["background-image", colour.backgroundCss],
15196
+ ["color", colour.foregroundCss]
15197
+ ];
15198
+ case "surface": return [
15199
+ ["background-color", colour.backgroundCss],
15200
+ ["background-image", "none"],
15201
+ ["color", colour.foregroundCss]
15202
+ ];
15203
+ }
15204
+ }
15205
+ function resolvedButtonFocusDeclarations(indicator) {
15206
+ return indicator.kind === "two-tone" ? [
15207
+ ["outline", `2px solid ${indicator.innerCss}`],
15208
+ ["outline-offset", "2px"],
15209
+ ["box-shadow", `0 0 0 4px ${indicator.outerCss}`]
15210
+ ] : [["outline", `3px solid ${indicator.colorCss}`], ["outline-offset", "3px"]];
15211
+ }
15212
+ /**
15213
+ * Disabled buttons retain their validated colour pair and add a non-layout
15214
+ * visual affordance. `currentColor` keeps the cue inside the same contrast
15215
+ * relationship, while retaining pointer events lets the not-allowed cursor
15216
+ * remain observable.
15217
+ */
15218
+ const RESOLVED_BUTTON_DISABLED_DECLARATIONS = [
15219
+ ["cursor", "not-allowed"],
15220
+ ["transform", "none"],
15221
+ ["box-shadow", "none"],
15222
+ ["outline", "2px dashed currentColor"],
15223
+ ["outline-offset", "-4px"]
15224
+ ];
15225
+ //#endregion
14186
15226
  //#region ../theme-core/src/buttons/generateButtonCss.ts
14187
15227
  /**
14188
15228
  * Class the `button` runtime node adds when it renders its own trailing icon,
@@ -14249,6 +15289,7 @@ const STRUCTURAL_DECLARATIONS = [
14249
15289
  function generateButtonCss(options) {
14250
15290
  const { themeId, theme, buttonSystem: providedButtonSystem } = options;
14251
15291
  const tokens = new TokenResolver(theme);
15292
+ const palette = expandPalette(theme.palette);
14252
15293
  const buttonSystem = providedButtonSystem ?? generateDefaultButtonSystem(theme);
14253
15294
  const themeSizes = {
14254
15295
  ...DEFAULT_BUTTON_SIZES,
@@ -14257,34 +15298,109 @@ function generateButtonCss(options) {
14257
15298
  const enabledVariants = buttonSystem.variants.filter((v) => v.enabled);
14258
15299
  const aliasSource = resolveAliasSource(enabledVariants);
14259
15300
  const chunks = [];
14260
- for (const variant of enabledVariants) chunks.push(...variantChunks(variant, buttonSystem.global, themeSizes, themeId, tokens, theme));
15301
+ for (const variant of enabledVariants) {
15302
+ const compiled = compileRuntimeVariant(variant, buttonSystem.global, palette);
15303
+ if (compiled.fallbackError) chunks.push({ raw: `/* ${formatButtonColourContractError(compiled.fallbackError)} Using contrast-safe surface fallback. */` });
15304
+ chunks.push(...variantChunks(compiled.variant, compiled.global, themeSizes, themeId, tokens, theme, compiled.colours, compiled.focusIndicator, compiled.nonColourEffects));
15305
+ }
14261
15306
  if (aliasSource) {
14262
- const alias = {
15307
+ const compiled = compileRuntimeVariant({
14263
15308
  ...aliasSource,
14264
15309
  id: DEFAULT_VARIANT_ALIAS_ID,
14265
15310
  name: "Default"
14266
- };
14267
- chunks.push(...variantChunks(alias, buttonSystem.global, themeSizes, themeId, tokens, theme));
15311
+ }, buttonSystem.global, palette);
15312
+ if (compiled.fallbackError) chunks.push({ raw: `/* ${formatButtonColourContractError(compiled.fallbackError)} Using contrast-safe surface fallback. */` });
15313
+ chunks.push(...variantChunks(compiled.variant, compiled.global, themeSizes, themeId, tokens, theme, compiled.colours, compiled.focusIndicator, compiled.nonColourEffects));
14268
15314
  }
14269
15315
  return chunks.map(renderChunk).join("\n\n");
14270
15316
  }
15317
+ function compileRuntimeVariant(variant, global, palette) {
15318
+ const result = compileButtonColourStates({
15319
+ variant,
15320
+ global,
15321
+ palette
15322
+ });
15323
+ if (result.ok) return {
15324
+ variant,
15325
+ global,
15326
+ colours: result.states,
15327
+ focusIndicator: result.focusIndicator,
15328
+ nonColourEffects: result.nonColourEffects
15329
+ };
15330
+ const fallbackVariant = {
15331
+ ...variant,
15332
+ background: {
15333
+ type: "surface",
15334
+ role: "link"
15335
+ },
15336
+ hoverBackgroundToken: void 0,
15337
+ effects: void 0
15338
+ };
15339
+ const fallbackGlobal = {
15340
+ ...global,
15341
+ hoverColor: "none",
15342
+ hoverColorToken: void 0
15343
+ };
15344
+ const fallback = compileButtonColourStates({
15345
+ variant: fallbackVariant,
15346
+ global: fallbackGlobal,
15347
+ palette
15348
+ });
15349
+ if (!fallback.ok) {
15350
+ const colour = {
15351
+ kind: "surface",
15352
+ role: "link",
15353
+ backgroundCss: "transparent",
15354
+ foregroundCss: surfaceForegroundValue("link")
15355
+ };
15356
+ return {
15357
+ variant: fallbackVariant,
15358
+ global: fallbackGlobal,
15359
+ colours: {
15360
+ base: colour,
15361
+ hover: colour,
15362
+ focus: colour,
15363
+ active: colour,
15364
+ disabled: colour
15365
+ },
15366
+ focusIndicator: {
15367
+ kind: "surface-role",
15368
+ colorCss: colour.foregroundCss,
15369
+ minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
15370
+ },
15371
+ nonColourEffects: {},
15372
+ fallbackError: result.error
15373
+ };
15374
+ }
15375
+ return {
15376
+ variant: fallbackVariant,
15377
+ global: fallbackGlobal,
15378
+ colours: fallback.states,
15379
+ focusIndicator: fallback.focusIndicator,
15380
+ nonColourEffects: fallback.nonColourEffects,
15381
+ fallbackError: result.error
15382
+ };
15383
+ }
14271
15384
  /** Pick the highest-priority variant whose role we'll alias to `.default`. */
14272
15385
  function resolveAliasSource(enabled) {
14273
15386
  if (enabled.some((v) => v.id === "default")) return null;
14274
15387
  return enabled.slice().sort((a, b) => a.priority - b.priority)[0] ?? null;
14275
15388
  }
14276
- function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
15389
+ function variantChunks(variant, global, themeSizes, themeId, tokens, theme, colours, focusIndicator, nonColourEffects) {
14277
15390
  const out = [];
14278
15391
  const variantId = parseButtonVariantIdForCss(variant.id);
14279
15392
  const selector = `:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}`;
14280
- out.push(variantBaseRule(variant, selector, global, tokens, theme));
15393
+ out.push(variantBaseRule(variant, selector, global, tokens, theme, colours.base));
14281
15394
  out.push({ raw: generateInteractiveChildInheritanceCSS(selector) });
14282
- const hoverBg = variantHoverBackgroundRule(variant, variantId, global, themeId, tokens);
14283
- if (hoverBg) out.push(hoverBg);
14284
- out.push(variantFocusVisibleRule(variantId, themeId));
14285
- const effects = variantEffectsCss(variant, themeId, tokens, theme);
15395
+ for (const state of [
15396
+ "hover",
15397
+ "focus",
15398
+ "active"
15399
+ ]) if (!resolvedColoursEqual(colours.base, colours[state])) out.push(variantStateColourRule(variantId, themeId, state, colours[state]));
15400
+ const effects = variantEffectsCss(variant, nonColourEffects, themeId, tokens, theme);
14286
15401
  if (effects) out.push({ raw: effects });
14287
- const affordance = variantAffordanceRule(variant, selector, tokens);
15402
+ out.push(variantFocusVisibleRule(variantId, themeId, focusIndicator));
15403
+ const affordance = variantAffordanceRule(variant, selector);
14288
15404
  if (affordance) out.push(affordance);
14289
15405
  out.push(...variantDisabledRules(variantId, themeId));
14290
15406
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
@@ -14299,12 +15415,11 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
14299
15415
  * one (node overrides personality). Colour comes from the affordance token, or
14300
15416
  * `currentColor` (the button text colour) when no token is given.
14301
15417
  */
14302
- function variantAffordanceRule(variant, selector, tokens) {
15418
+ function variantAffordanceRule(variant, selector) {
14303
15419
  const affordance = variant.affordance;
14304
15420
  if (!affordance) return null;
14305
15421
  const maskUrl = affordanceIconMaskUrl(affordance.iconId);
14306
15422
  if (!maskUrl) return null;
14307
- const color = affordance.colorToken ? variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(affordance.colorToken)) : tokens.getColor(affordance.colorToken) : "currentColor";
14308
15423
  const mask = `url("${maskUrl}") no-repeat center / contain`;
14309
15424
  return rule(`${selector}:not(.${AFFORDANCE_SUPPRESS_CLASS})::after`, [
14310
15425
  ["content", "\"\""],
@@ -14313,7 +15428,7 @@ function variantAffordanceRule(variant, selector, tokens) {
14313
15428
  ["height", "1em"],
14314
15429
  ["margin-inline-start", "0.5em"],
14315
15430
  ["flex", "0 0 auto"],
14316
- ["background-color", color],
15431
+ ["background-color", "currentColor"],
14317
15432
  ["-webkit-mask", mask],
14318
15433
  ["mask", mask]
14319
15434
  ]);
@@ -14323,7 +15438,7 @@ function parseButtonVariantIdForCss(value) {
14323
15438
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
14324
15439
  return variantId;
14325
15440
  }
14326
- function variantBaseRule(variant, selector, global, tokens, theme) {
15441
+ function variantBaseRule(variant, selector, global, tokens, theme, colour) {
14327
15442
  const decls = [];
14328
15443
  decls.push(["font-weight", String(global.fontWeight)]);
14329
15444
  decls.push(["font-family", resolveFontFamily(global)]);
@@ -14335,18 +15450,10 @@ function variantBaseRule(variant, selector, global, tokens, theme) {
14335
15450
  for (const decl of STRUCTURAL_DECLARATIONS) decls.push(decl);
14336
15451
  decls.push(["border-radius", resolveBorderRadius(variant, global)]);
14337
15452
  decls.push(["box-shadow", resolveBoxShadow(variant, global, theme, tokens)]);
14338
- if (variant.background.type === "solid") decls.push(["background-color", tokens.getColor(variant.background.colorToken)]);
14339
- else if (variant.background.type === "gradient") {
14340
- const colors = variant.background.stops.map((stop) => tokens.getColor(stop)).join(", ");
14341
- const direction = GRADIENT_DIRECTION_MAP$1[variant.background.direction] || "to right";
14342
- decls.push(["background-image", `linear-gradient(${direction}, ${colors})`]);
14343
- } else decls.push(["background-color", "transparent"]);
14344
- const foregroundColor = variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(variant.textColorToken)) : tokens.getColor(variant.textColorToken);
14345
- decls.push(["color", foregroundColor]);
15453
+ decls.push(...resolvedButtonColourDeclarations(colour));
14346
15454
  if (variant.border) {
14347
15455
  const borderWidth = BORDER_WIDTH_MAP[variant.border.widthClass] || "1px";
14348
- const borderColor = variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(variant.border.colorToken)) : tokens.getColor(variant.border.colorToken);
14349
- decls.push(["border", `${borderWidth} solid ${borderColor}`]);
15456
+ decls.push(["border", `${borderWidth} solid currentColor`]);
14350
15457
  }
14351
15458
  return rule(selector, decls);
14352
15459
  }
@@ -14357,30 +15464,22 @@ function variantBaseRule(variant, selector, global, tokens, theme) {
14357
15464
  * token fallback keeps buttons usable in contexts that do not provide that
14358
15465
  * contract (and preserves the existing theme behaviour there).
14359
15466
  */
14360
- function surfaceLinkColor(fallbackColor) {
14361
- return `var(--rb-surface-link-color, ${fallbackColor})`;
15467
+ function variantStateColourRule(variantId, themeId, state, colour) {
15468
+ return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:${state}`, resolvedButtonColourDeclarations(colour));
14362
15469
  }
14363
- function variantHoverBackgroundRule(variant, variantId, global, themeId, tokens) {
14364
- let hoverToken = variant.hoverBackgroundToken;
14365
- if (!hoverToken && global.hoverColor === "token" && global.hoverColorToken) hoverToken = global.hoverColorToken;
14366
- if (!hoverToken) return null;
14367
- return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:hover`, [["background-color", tokens.getColor(hoverToken)]]);
15470
+ function variantFocusVisibleRule(variantId, themeId, focusIndicator) {
15471
+ return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:focus-visible`, resolvedButtonFocusDeclarations(focusIndicator));
14368
15472
  }
14369
- function variantFocusVisibleRule(variantId, themeId) {
14370
- return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:focus-visible`, [["outline", "2px solid currentColor"], ["outline-offset", "3px"]]);
14371
- }
14372
- function variantEffectsCss(variant, themeId, tokens, theme) {
14373
- if (!variant.effects) return "";
15473
+ function variantEffectsCss(variant, effects, themeId, tokens, theme) {
15474
+ if (!effects) return "";
14374
15475
  const elementConfig = {
14375
- background: variant.background,
14376
- textColorToken: variant.textColorToken,
14377
- border: variant.border ? { colorToken: variant.border.colorToken } : void 0,
15476
+ background: variant.background.type === "surface" ? { type: "transparent" } : variant.background,
14378
15477
  shadow: variant.shadow
14379
15478
  };
14380
15479
  return generateEffectsCSS({
14381
15480
  themeId,
14382
15481
  variantId: variant.id,
14383
- effects: variant.effects,
15482
+ effects,
14384
15483
  elementConfig,
14385
15484
  tokens,
14386
15485
  theme
@@ -14395,18 +15494,15 @@ function variantDisabledRules(variantId, themeId) {
14395
15494
  `${base}:focus`
14396
15495
  ];
14397
15496
  const pseudoSelectors = [`${base}::before`, `${base}::after`];
14398
- return [rule(disabledSelectors, [
14399
- ["opacity", "0.5"],
14400
- ["cursor", "not-allowed"],
14401
- ["pointer-events", "none"],
14402
- ["transform", "none"],
14403
- ["box-shadow", "none"]
14404
- ]), rule(pseudoSelectors, [
15497
+ return [rule(disabledSelectors, [...RESOLVED_BUTTON_DISABLED_DECLARATIONS]), rule(pseudoSelectors, [
14405
15498
  ["opacity", "0"],
14406
15499
  ["animation", "none"],
14407
15500
  ["pointer-events", "none"]
14408
15501
  ])];
14409
15502
  }
15503
+ function resolvedColoursEqual(left, right) {
15504
+ return JSON.stringify(left) === JSON.stringify(right);
15505
+ }
14410
15506
  function variantSizeRules(variant, variantId, themeSizes, themeId) {
14411
15507
  const borderWidth = variant.border ? BORDER_WIDTH_MAP[variant.border.widthClass] || "1px" : "0px";
14412
15508
  const rules = [];
@@ -14474,6 +15570,27 @@ function resolveBoxShadow(variant, global, theme, tokens) {
14474
15570
  const color = shadowConfig.colorToken ? tokens.getColor(shadowConfig.colorToken) : void 0;
14475
15571
  return generateShadowValue$1(shadowConfig.elevation, shadowConfig.softness, shadowConfig.position ?? "bottom", color);
14476
15572
  }
15573
+ buttonPersonalities.map((personality) => ({
15574
+ id: personality.id,
15575
+ name: personality.name,
15576
+ description: personality.description,
15577
+ category: presetCategory(personality),
15578
+ buttonSystem: personality.buttonSystem,
15579
+ compatibility: {
15580
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
15581
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
15582
+ }
15583
+ }));
15584
+ function presetCategory(personality) {
15585
+ switch (personality.tags.era) {
15586
+ case "retro": return "retro";
15587
+ case "editorial": return "minimal";
15588
+ case "organic": return "artistic";
15589
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
15590
+ case "technical": return "technical";
15591
+ case void 0: return "modern";
15592
+ }
15593
+ }
14477
15594
  //#endregion
14478
15595
  //#region ../theme-core/src/cards/types.ts
14479
15596
  const cardVariantRoleValues = ["default", "alternative"];
@@ -14710,67 +15827,6 @@ function generateDefaultCardSystem(theme) {
14710
15827
  return { variants: [defaultVariant, alternativeVariant] };
14711
15828
  }
14712
15829
  //#endregion
14713
- //#region ../theme-core/src/surfaces/foregroundRoles.ts
14714
- const SURFACE_FOREGROUND_ROLES = [
14715
- "text",
14716
- "heading",
14717
- "link",
14718
- "supporting"
14719
- ];
14720
- //#endregion
14721
- //#region ../theme-core/src/surfaces/foregroundContract.ts
14722
- const SURFACE_FOREGROUND_CSS_VARS = {
14723
- text: "--rb-surface-text-color",
14724
- heading: "--rb-surface-heading-color",
14725
- link: "--rb-surface-link-color",
14726
- supporting: "--rb-surface-supporting-color"
14727
- };
14728
- const DEFAULT_SURFACE_TEXT_COLOR = "rgb(var(--tb-text, 17 24 39))";
14729
- const DEFAULT_ROLE_FALLBACKS = {
14730
- text: DEFAULT_SURFACE_TEXT_COLOR,
14731
- heading: DEFAULT_SURFACE_TEXT_COLOR,
14732
- link: "rgb(var(--tb-primary, var(--tb-text, 17 24 39)))",
14733
- supporting: "rgb(var(--tb-mutedText, 100 116 139))"
14734
- };
14735
- function requireSurfaceColorValue(role, value) {
14736
- const normalized = value.trim();
14737
- if (normalized.length === 0) throw new RangeError(`Surface foreground ${role} must be a non-empty CSS color.`);
14738
- return normalized;
14739
- }
14740
- function completeSurfaceForegrounds(input) {
14741
- const text = requireSurfaceColorValue("text", input.text);
14742
- return {
14743
- text,
14744
- heading: input.heading === void 0 ? text : requireSurfaceColorValue("heading", input.heading),
14745
- link: input.link === void 0 ? text : requireSurfaceColorValue("link", input.link),
14746
- supporting: input.supporting === void 0 ? text : requireSurfaceColorValue("supporting", input.supporting)
14747
- };
14748
- }
14749
- function surfaceForegroundValue(role, outsideProviderFallback = DEFAULT_ROLE_FALLBACKS[role]) {
14750
- const roleVariable = SURFACE_FOREGROUND_CSS_VARS[role];
14751
- const fallback = requireSurfaceColorValue("fallback", outsideProviderFallback);
14752
- if (role === "text") return `var(${roleVariable}, ${fallback})`;
14753
- return `var(${roleVariable}, var(${SURFACE_FOREGROUND_CSS_VARS.text}, ${fallback}))`;
14754
- }
14755
- function surfaceForegroundValueWithOpacity(role, opacityPercent) {
14756
- if (!Number.isFinite(opacityPercent) || opacityPercent < 0 || opacityPercent > 100) throw new RangeError("Surface foreground opacity must be between 0 and 100.");
14757
- return `color-mix(in srgb, ${surfaceForegroundValue(role)} ${opacityPercent}%, transparent)`;
14758
- }
14759
- function surfaceForegroundStyle(input) {
14760
- const foregrounds = completeSurfaceForegrounds(input);
14761
- return {
14762
- color: foregrounds.text,
14763
- [SURFACE_FOREGROUND_CSS_VARS.text]: foregrounds.text,
14764
- [SURFACE_FOREGROUND_CSS_VARS.heading]: foregrounds.heading,
14765
- [SURFACE_FOREGROUND_CSS_VARS.link]: foregrounds.link,
14766
- [SURFACE_FOREGROUND_CSS_VARS.supporting]: foregrounds.supporting
14767
- };
14768
- }
14769
- function surfaceForegroundDeclarations(input) {
14770
- const foregrounds = completeSurfaceForegrounds(input);
14771
- return [`color: ${foregrounds.text}`, ...SURFACE_FOREGROUND_ROLES.map((role) => `${SURFACE_FOREGROUND_CSS_VARS[role]}: ${foregrounds[role]}`)];
14772
- }
14773
- //#endregion
14774
15830
  //#region ../theme-core/src/cards/generateCardCss.ts
14775
15831
  const PER_CORNER_RADIUS_MAP = {
14776
15832
  square: "0",
@@ -14881,7 +15937,7 @@ function generateVariantCSS(variant, themeId, tokens, theme) {
14881
15937
  rules.push(`display: flex`);
14882
15938
  rules.push(`flex-direction: column`);
14883
15939
  rules.push(`position: relative`);
14884
- rules.push(`overflow: hidden`);
15940
+ rules.push(`overflow: visible`);
14885
15941
  const mediaRadius = MEDIA_CORNER_MAP[corners];
14886
15942
  const mediaRules = [`border-top-left-radius: ${mediaRadius}`, `border-top-right-radius: ${mediaRadius}`];
14887
15943
  const contentRules = [`padding: ${CONTENT_PADDING_MAP[variant.spacing] || CONTENT_PADDING_MAP.comfortable}`];
@@ -15207,47 +16263,6 @@ const FONT_WEIGHT_MAP = {
15207
16263
  black: "800"
15208
16264
  };
15209
16265
  //#endregion
15210
- //#region ../theme-core/src/gradients/types.ts
15211
- /**
15212
- * Gradient configuration types and schemas
15213
- */
15214
- /**
15215
- * Gradient color stop
15216
- */
15217
- const gradientStopSchema = z$1.object({
15218
- color: themeColorTokenSchema,
15219
- position: z$1.number().min(0).max(100)
15220
- });
15221
- /**
15222
- * Radial gradient shape. Optional; defaults to `circle` (the historical shape)
15223
- * so existing radial gradients are byte-identical.
15224
- *
15225
- * Named `RadialGradientShape` to avoid clashing with `styles/gradients.ts`'s
15226
- * `GradientShape` (which names the gradient *kind*: linear/radial/conic).
15227
- */
15228
- const radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
15229
- /**
15230
- * Gradient configuration.
15231
- *
15232
- * `type` is optional and defaults to `'linear'` so gradients persisted without a
15233
- * type (or with an explicit `'linear'`) render exactly as before. `'radial'` and
15234
- * `'conic'` are additive kinds:
15235
- * - linear: `angle` (degrees)
15236
- * - radial: optional `shape` (circle/ellipse) + `position`
15237
- * - conic: optional `angle` (from-angle, degrees) + `position`
15238
- */
15239
- const gradientConfigSchema = z$1.object({
15240
- type: z$1.enum([
15241
- "linear",
15242
- "radial",
15243
- "conic"
15244
- ]).default("linear"),
15245
- angle: z$1.number().min(0).max(360).optional(),
15246
- shape: radialGradientShapeSchema.optional(),
15247
- position: z$1.string().optional(),
15248
- stops: z$1.array(gradientStopSchema).min(2)
15249
- });
15250
- //#endregion
15251
16266
  //#region ../theme-core/src/interactive/baseSchema.ts
15252
16267
  /**
15253
16268
  * Shared Base Schemas for Interactive Elements
@@ -16405,6 +17420,7 @@ const navFontWeight = z$1.enum([
16405
17420
  "bold"
16406
17421
  ]);
16407
17422
  const headerMaxWidth = z$1.enum(["container", "full"]);
17423
+ const headerBarFrame = z$1.enum(["full-bleed", "inset-shell"]);
16408
17424
  const headerContainerSchema = z$1.object({
16409
17425
  rounded: z$1.enum([
16410
17426
  "none",
@@ -16549,6 +17565,7 @@ const headerSchema = z$1.object({
16549
17565
  positioning: headerPositioning,
16550
17566
  shrinkOnScroll: z$1.boolean(),
16551
17567
  maxWidth: headerMaxWidth,
17568
+ barFrame: headerBarFrame.optional(),
16552
17569
  logoOverride: mediaSchema$1.nullable().optional(),
16553
17570
  background: headerBackgroundSchema.default({
16554
17571
  type: "color",
@@ -16558,6 +17575,7 @@ const headerSchema = z$1.object({
16558
17575
  navStyle: headerNavStyle,
16559
17576
  navColor: themeColorTokenSchema.nullable().optional(),
16560
17577
  navWeight: navFontWeight.default("medium"),
17578
+ navFontRole: z$1.enum(["body", "heading"]).optional(),
16561
17579
  navTypography: z$1.enum(["body", "heading"]).optional(),
16562
17580
  navTextSize: navLinkStyleSchema.shape.textSize,
16563
17581
  navPlacement: z$1.enum(["end", "center"]).optional(),
@@ -16573,7 +17591,21 @@ const headerSchema = z$1.object({
16573
17591
  ctaTreatment: headerCtaTreatmentSchema.optional(),
16574
17592
  ctaVariant: z$1.string().min(1).optional(),
16575
17593
  dropdownStyle: dropdownStyleSchema
16576
- });
17594
+ }).transform(normaliseHeaderNavFontRole);
17595
+ /**
17596
+ * Normalises the legacy `navTypography` font-role alias into the canonical
17597
+ * `navFontRole` field so persisted themes migrate at the parse boundary without
17598
+ * a data migration. `navFontRole` always wins when both are present; the legacy
17599
+ * field is dropped so we never carry a dual write forward.
17600
+ */
17601
+ function normaliseHeaderNavFontRole(header) {
17602
+ if (header.navTypography === void 0) return header;
17603
+ const { navTypography, ...rest } = header;
17604
+ return header.navFontRole === void 0 ? {
17605
+ ...rest,
17606
+ navFontRole: navTypography
17607
+ } : rest;
17608
+ }
16577
17609
  const footerVariant = z$1.enum([
16578
17610
  "simple",
16579
17611
  "columns",
@@ -16983,6 +18015,19 @@ z$1.object({
16983
18015
  }).strict();
16984
18016
  //#endregion
16985
18017
  //#region ../theme-core/src/site-styles/runtimeCompiler.ts
18018
+ function defineSectionForegroundRuntimeTokens(input) {
18019
+ return {
18020
+ textColor: requireThemeColorToken(input.textColor),
18021
+ headingColor: requireThemeColorToken(input.headingColor),
18022
+ linkColor: requireThemeColorToken(input.linkColor),
18023
+ supportingColor: requireThemeColorToken(input.supportingColor)
18024
+ };
18025
+ }
18026
+ function requireThemeColorToken(value) {
18027
+ const token = parseThemeColorToken(value);
18028
+ if (!token) throw new Error(`Invalid section foreground Theme color token: ${String(value)}`);
18029
+ return token;
18030
+ }
16986
18031
  function defineDesignRuntimeRules(rules) {
16987
18032
  return rules;
16988
18033
  }
@@ -17253,24 +18298,24 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
17253
18298
  type: "color",
17254
18299
  color: "muted"
17255
18300
  },
17256
- foreground: {
18301
+ foreground: defineSectionForegroundRuntimeTokens({
17257
18302
  textColor: "text",
17258
18303
  headingColor: "primary",
17259
18304
  linkColor: "primary",
17260
18305
  supportingColor: "text"
17261
- }
18306
+ })
17262
18307
  },
17263
18308
  "brand-depth-band": {
17264
18309
  background: {
17265
18310
  type: "color",
17266
18311
  color: "primary-800"
17267
18312
  },
17268
- foreground: {
18313
+ foreground: defineSectionForegroundRuntimeTokens({
17269
18314
  textColor: "text",
17270
18315
  headingColor: "primary",
17271
18316
  linkColor: "primary",
17272
18317
  supportingColor: "text"
17273
- }
18318
+ })
17274
18319
  },
17275
18320
  "hero-image": {
17276
18321
  background: {
@@ -17278,12 +18323,32 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
17278
18323
  opacity: 1,
17279
18324
  position: "center center"
17280
18325
  },
17281
- foreground: {
18326
+ foreground: defineSectionForegroundRuntimeTokens({
17282
18327
  textColor: "text",
17283
18328
  headingColor: "primary",
17284
18329
  linkColor: "primary",
17285
18330
  supportingColor: "text"
17286
- }
18331
+ })
18332
+ }
18333
+ }
18334
+ });
18335
+ const primaryGlowGradientPresetId = parseGradientPresetId("primary-glow");
18336
+ if (!primaryGlowGradientPresetId) throw new Error("Expected primary-glow in the Theme Core gradient catalog");
18337
+ const fulcrumDesignRuntimeRules = defineDesignRuntimeRules({
18338
+ ...defaultDesignRuntimeRules,
18339
+ sectionSurfaces: {
18340
+ ...defaultDesignRuntimeRules.sectionSurfaces,
18341
+ "accent-band": {
18342
+ background: {
18343
+ type: "gradient",
18344
+ gradientPresetId: primaryGlowGradientPresetId
18345
+ },
18346
+ foreground: defineSectionForegroundRuntimeTokens({
18347
+ textColor: "primaryForeground",
18348
+ headingColor: "primaryForeground",
18349
+ linkColor: "primaryForeground",
18350
+ supportingColor: "primaryForeground"
18351
+ })
17287
18352
  }
17288
18353
  }
17289
18354
  });
@@ -17607,6 +18672,7 @@ const curatedSiteStyles = [
17607
18672
  ],
17608
18673
  buttonPersonalityChoices: [
17609
18674
  buttonChoice("soft-pill"),
18675
+ buttonChoice("two-tone-pill"),
17610
18676
  buttonChoice("pebble"),
17611
18677
  buttonChoice("editorial-link"),
17612
18678
  buttonChoice("brushed-wash")
@@ -18670,6 +19736,8 @@ const curatedSiteStyles = [
18670
19736
  },
18671
19737
  compositionBudget: quietBudget,
18672
19738
  typography: fulcrumTypography,
19739
+ designRuntimeRules: fulcrumDesignRuntimeRules,
19740
+ recommendedAppearancePresetIds: ["cta-accent-band"],
18673
19741
  themeOverrides: {
18674
19742
  shadow: { colorToken: "primary" },
18675
19743
  accordions: {
@@ -18786,6 +19854,7 @@ const curatedSiteStyles = [
18786
19854
  ],
18787
19855
  buttonPersonalityChoices: [
18788
19856
  buttonChoice("quiet-arrow"),
19857
+ buttonChoice("two-tone-pill"),
18789
19858
  buttonChoice("flat-ink"),
18790
19859
  buttonChoice("editorial-link")
18791
19860
  ],
@@ -18995,6 +20064,21 @@ function toSiteChromeBackgroundColorTokens(tokenNames) {
18995
20064
  }
18996
20065
  //#endregion
18997
20066
  //#region ../theme-core/src/site-styles/siteChromeNavPreferences.ts
20067
+ /**
20068
+ * Applies the user's nav font-role/size overrides on top of a style-resolved
20069
+ * nav link style. This is where the precedence contract lands:
20070
+ *
20071
+ * - The nav typography TREATMENT (case/tracking identity: plain / heading /
20072
+ * quiet-caps / brand-caps) is ALWAYS owned by the active header style and is
20073
+ * baked into `style` before this call (see `applyNavTypography` in
20074
+ * headerLooks.ts).
20075
+ * - Each treatment resolves through a DEFAULT font role: `heading` resolves
20076
+ * through the heading role; `plain` / `quiet-caps` / `brand-caps` resolve
20077
+ * through the body role.
20078
+ * - The user's `navFontRole` (surfaced here as `preferences.typography`) only
20079
+ * overrides which font ROLE the treatment resolves through. It never changes
20080
+ * the treatment. `'inherit'` keeps the treatment's default role.
20081
+ */
18998
20082
  function mergeHeaderNavTypographyPreference(style, preferences) {
18999
20083
  return preferences.typography === "inherit" && preferences.fontSize === "inherit" ? style : {
19000
20084
  ...style,
@@ -20029,6 +21113,7 @@ function devValidate(node) {
20029
21113
  }
20030
21114
  //#endregion
20031
21115
  //#region ../blocks/src/system/node/fragments/backgroundLayer.ts
21116
+ const BACKGROUND_FRAME_BASE_CLASS = "rb-background-frame rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-isolate rb-pointer-events-none";
20032
21117
  /**
20033
21118
  * Creates background layer nodes for rendering backgrounds from field data.
20034
21119
  *
@@ -20094,6 +21179,34 @@ function backgroundLayer(path, options = {}) {
20094
21179
  ];
20095
21180
  }
20096
21181
  /**
21182
+ * Wrap decorative background layers in their own clipping frame.
21183
+ *
21184
+ * Foreground content remains outside this frame, so editor outlines, focus
21185
+ * rings, and floating controls are never clipped by a visual background.
21186
+ * Backgrounds that explicitly opt into overflow keep that behavior within
21187
+ * the decorative layer rather than changing the content root.
21188
+ */
21189
+ function backgroundFrame(path, options = {}) {
21190
+ const { leadingNodes = [], ...layerOptions } = options;
21191
+ const framedLayerOptions = {
21192
+ ...layerOptions,
21193
+ styleClassName: layerOptions.styleClassName ?? "background-style rb-absolute rb-inset-0 rb-z-0 rb-h-full rb-w-full rb-pointer-events-none",
21194
+ imageClassName: layerOptions.imageClassName ?? "rb-absolute rb-z-0",
21195
+ overlayClassName: layerOptions.overlayClassName ?? "background-overlay rb-absolute rb-inset-0 rb-z-0 rb-h-full rb-w-full rb-pointer-events-none"
21196
+ };
21197
+ return el("div", {
21198
+ className: { $bind: {
21199
+ from: path,
21200
+ transforms: [{
21201
+ id: "background.resolveFrameClassName",
21202
+ options: { baseClass: BACKGROUND_FRAME_BASE_CLASS }
21203
+ }],
21204
+ fallback: `${BACKGROUND_FRAME_BASE_CLASS} rb-overflow-hidden`
21205
+ } },
21206
+ style: { borderRadius: "inherit" }
21207
+ }, [...leadingNodes, ...backgroundLayer(path, framedLayerOptions)]);
21208
+ }
21209
+ /**
20097
21210
  * Creates a media node for rendering background image/video media with conditional rendering.
20098
21211
  *
20099
21212
  * This helper creates a media element that:
@@ -20255,8 +21368,8 @@ function sectionContainer(children, opts) {
20255
21368
  * - content
20256
21369
  */
20257
21370
  function styledContainer(config) {
20258
- const { children, rootType = "div", rootProps, bindFrom = "_containerStyles", baseClassName = "rb-relative rb-isolate rb-overflow-hidden", imageClassName = "rb-absolute rb-z-neg-10", constrainWidth = true } = config;
20259
- const backgroundNodes = backgroundLayer(`${bindFrom}.background`, { imageClassName });
21371
+ const { children, rootType = "div", rootProps, bindFrom = "_containerStyles", baseClassName = "rb-relative rb-isolate rb-overflow-visible", imageClassName = "rb-absolute rb-z-0", constrainWidth = true } = config;
21372
+ const backgroundNode = backgroundFrame(`${bindFrom}.background`, { imageClassName });
20260
21373
  const childrenArray = Array.isArray(children) ? children : [children];
20261
21374
  const { className: _ignoredClassName, style: _ignoredStyle, ...safeRootProps } = rootProps ?? {};
20262
21375
  return el(rootType, {
@@ -20279,7 +21392,7 @@ function styledContainer(config) {
20279
21392
  }],
20280
21393
  fallback: constrainWidth ? `${baseClassName} rb-container` : baseClassName
20281
21394
  } }
20282
- }, [...backgroundNodes, ...childrenArray]);
21395
+ }, [backgroundNode, ...childrenArray]);
20283
21396
  }
20284
21397
  //#endregion
20285
21398
  //#region ../blocks/src/system/spacing.ts
@@ -20412,7 +21525,7 @@ const DEFAULT_SECTION_SPACING = "medium";
20412
21525
  * - Creating a section wrapper with background theme
20413
21526
  * - Adding background color/gradient/image layers
20414
21527
  * - Binding className to section styles with transform
20415
- * - Binding allowOverflow for background positioning
21528
+ * - Keeping foreground overflow visible while decorative backgrounds clip independently
20416
21529
  * - Wrapping content children
20417
21530
  *
20418
21531
  * Use this helper to eliminate 25+ lines of boilerplate section setup code.
@@ -20448,8 +21561,8 @@ const DEFAULT_SECTION_SPACING = "medium";
20448
21561
  * });
20449
21562
  */
20450
21563
  function styledSection(config) {
20451
- const { children, baseClass = "rb-px-6", spacing = DEFAULT_SECTION_SPACING, background = "background", bindFrom = "_sectionStyles", imageClassName = "rb-absolute rb-z-neg-10", renderBackgroundImage = true, backgroundImageLoading, backgroundImageFetchPriority, allowOverflow = false, fullWidthPath } = config;
20452
- const renderedBackgroundNodes = backgroundLayer(`${bindFrom}.background`, {
21564
+ const { children, baseClass = "rb-px-6", spacing = DEFAULT_SECTION_SPACING, background = "background", bindFrom = "_sectionStyles", imageClassName = "rb-absolute rb-z-0", renderBackgroundImage = true, backgroundImageLoading, backgroundImageFetchPriority, fullWidthPath } = config;
21565
+ const renderedBackgroundNode = backgroundFrame(`${bindFrom}.background`, {
20453
21566
  imageClassName,
20454
21567
  fallbackToken: background,
20455
21568
  omitImageLayer: !renderBackgroundImage,
@@ -20472,13 +21585,8 @@ function styledSection(config) {
20472
21585
  fullWidthPath
20473
21586
  }
20474
21587
  }]
20475
- } },
20476
- allowOverflow: allowOverflow ? true : { $bind: {
20477
- from: `${bindFrom}.background`,
20478
- transforms: [{ id: "background.resolveAllowOverflow" }],
20479
- fallback: false
20480
21588
  } }
20481
- }, [...renderedBackgroundNodes, ...childrenArray]);
21589
+ }, [renderedBackgroundNode, ...childrenArray]);
20482
21590
  }
20483
21591
  //#endregion
20484
21592
  //#region ../blocks/src/system/node/fragments/ctaButton.ts
@@ -21339,9 +22447,12 @@ function responsiveTwoColumn({ image, text, ratioFrom, imagePositionFrom, gapCla
21339
22447
  //#endregion
21340
22448
  //#region ../blocks/src/system/node/fragments/styledCard.ts
21341
22449
  function styledCard(children, opts, ...mods) {
21342
- const baseClassName = opts.baseClassName ?? "rb-relative rb-isolate rb-overflow-hidden rb-border";
21343
- const defaultBackgroundLayer = el("div", { className: "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none rb-bg-surface" });
21344
- const backgroundNodes = backgroundLayer(opts.backgroundFrom);
22450
+ const baseClassName = opts.baseClassName ?? "rb-relative rb-isolate rb-overflow-visible rb-border";
22451
+ const defaultBackgroundLayer = el("div", {
22452
+ className: "rb-absolute rb-inset-0 rb-z-neg-10 rb-h-full rb-w-full rb-pointer-events-none rb-bg-surface",
22453
+ style: { borderRadius: "inherit" }
22454
+ });
22455
+ const backgroundNode = backgroundFrame(opts.backgroundFrom);
21345
22456
  const style = {
21346
22457
  ...opts.style ?? {},
21347
22458
  borderColor: { $bind: {
@@ -21368,7 +22479,7 @@ function styledCard(children, opts, ...mods) {
21368
22479
  ...style ? { style } : {}
21369
22480
  }, [
21370
22481
  defaultBackgroundLayer,
21371
- ...backgroundNodes,
22482
+ backgroundNode,
21372
22483
  ...children
21373
22484
  ], ...mods);
21374
22485
  }
@@ -22012,9 +23123,15 @@ function createButtonGroup(options = {}) {
22012
23123
  //#endregion
22013
23124
  //#region ../blocks/src/system/fields/ctas.ts
22014
23125
  function createCtasRepeater(options = {}) {
22015
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
23126
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
23127
+ const fieldId = id;
23128
+ const buttonField = createButtonGroup({
23129
+ showGroupLabel: false,
23130
+ ...button ?? {},
23131
+ flattenInRepeater: true
23132
+ });
22016
23133
  return {
22017
- id,
23134
+ id: fieldId,
22018
23135
  type: "repeater",
22019
23136
  label,
22020
23137
  itemLabel,
@@ -22023,11 +23140,8 @@ function createCtasRepeater(options = {}) {
22023
23140
  maxItems,
22024
23141
  required: false,
22025
23142
  allowConversion: true,
22026
- schema: { fields: [createButtonGroup({
22027
- showGroupLabel: false,
22028
- ...button ?? {},
22029
- flattenInRepeater: true
22030
- })] }
23143
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
23144
+ schema: { fields: [buttonField] }
22031
23145
  };
22032
23146
  }
22033
23147
  //#endregion
@@ -22077,6 +23191,7 @@ const heroCtaRowFragment = defineFragment({
22077
23191
  label: "Calls to action",
22078
23192
  itemLabel: "CTA",
22079
23193
  maxItems: 3,
23194
+ defaultValue: [],
22080
23195
  button: {
22081
23196
  variants: [
22082
23197
  {
@@ -22144,7 +23259,7 @@ const ctaCopyFragment = defineFragment({
22144
23259
  eyebrowPath: "content.eyebrow",
22145
23260
  titlePath: "content.title",
22146
23261
  className: "cta-heading"
22147
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
23262
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
22148
23263
  });
22149
23264
  //#endregion
22150
23265
  //#region ../blocks/src/system/fragments/library/testimonialsHeading.ts
@@ -22241,7 +23356,7 @@ function buildTestimonialCard(...mods) {
22241
23356
  }, props({ value: "“" })), richText({ className: "rb-prose rb-max-w-none" }, bind("testimonial.content.body"), when("testimonial.content.body"))]), el("div", { className: "rb-testimonial-attribution" }, buildAttributionNodes())])], {
22242
23357
  stylesFrom: "content._cardStyles",
22243
23358
  backgroundFrom: "content._cardStyles.background",
22244
- baseClassName: "rb-testimonial-card rb-relative rb-isolate rb-flex rb-h-full rb-flex-col rb-overflow-hidden rb-p-8"
23359
+ baseClassName: "rb-testimonial-card rb-relative rb-isolate rb-flex rb-h-full rb-flex-col rb-overflow-visible rb-p-8"
22245
23360
  }, ...mods);
22246
23361
  }
22247
23362
  /**
@@ -22969,7 +24084,7 @@ function createFaqAccordionLayout(options = {}) {
22969
24084
  options: {
22970
24085
  axis: "all",
22971
24086
  includeSpacing: false,
22972
- baseClass: "rb-faq-item rb-relative rb-isolate rb-overflow-hidden"
24087
+ baseClass: "rb-faq-item rb-relative rb-isolate rb-overflow-visible"
22973
24088
  }
22974
24089
  }]
22975
24090
  },
@@ -24168,6 +25283,7 @@ function createBlockManifest(config) {
24168
25283
  previewCustomize: config.previewCustomize,
24169
25284
  category: config.category,
24170
25285
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
25286
+ contentSource: config.contentSource,
24171
25287
  tags: config.tags ? [...config.tags] : [],
24172
25288
  icon: config.icon ?? "Box",
24173
25289
  layout,
@@ -24301,7 +25417,6 @@ function splitLayoutWith(children) {
24301
25417
  }
24302
25418
  }),
24303
25419
  renderBackgroundImage: false,
24304
- allowOverflow: true,
24305
25420
  baseClass: ""
24306
25421
  });
24307
25422
  }
@@ -24314,6 +25429,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
24314
25429
  title: "Hero",
24315
25430
  titleSource: "headline",
24316
25431
  category: "layout",
25432
+ contentSource: { kind: "inline" },
24317
25433
  includeContainerStyles: true,
24318
25434
  promotedFields: ["_sectionStyles.background.image"],
24319
25435
  fragments: [
@@ -24587,6 +25703,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
24587
25703
  id: "block.intro",
24588
25704
  title: "Intro",
24589
25705
  category: "layout",
25706
+ contentSource: { kind: "inline" },
24590
25707
  includeContainerStyles: true,
24591
25708
  titleSource: "title",
24592
25709
  previewCustomize: { quickFieldPriority: [
@@ -24772,6 +25889,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
24772
25889
  title: "Body Text",
24773
25890
  titleSource: "heading",
24774
25891
  category: "content",
25892
+ contentSource: { kind: "inline" },
24775
25893
  fragments: [{
24776
25894
  fragment: bodyCopyFragment,
24777
25895
  fieldPriority: 0
@@ -24828,6 +25946,10 @@ const blogPostBlockDefinition = {
24828
25946
  description: "Highlights a single blog post with title, image, and excerpt.",
24829
25947
  category: "blog",
24830
25948
  contentTypes: ["post"],
25949
+ contentSource: {
25950
+ kind: "entries",
25951
+ contentType: "post"
25952
+ },
24831
25953
  tags: [
24832
25954
  "blog",
24833
25955
  "post",
@@ -24929,7 +26051,7 @@ function postCard(children, ...mods) {
24929
26051
  return styledCard(children, {
24930
26052
  stylesFrom: "content._cardStyles",
24931
26053
  backgroundFrom: "content._cardStyles.background",
24932
- baseClassName: "rb-relative rb-isolate rb-overflow-hidden rb-border rb-flex rb-flex-col rb-h-full"
26054
+ baseClassName: "rb-relative rb-isolate rb-overflow-visible rb-border rb-flex rb-flex-col rb-h-full"
24933
26055
  }, ...mods);
24934
26056
  }
24935
26057
  const gridPostCard = postCard([postImageLink("rb-h-48 rb-w-full rb-object-cover rb-transition-transform rb-hover-scale-105", {
@@ -24965,7 +26087,7 @@ const stackPostCard = styledCard([inline({
24965
26087
  ])])], {
24966
26088
  stylesFrom: "content._cardStyles",
24967
26089
  backgroundFrom: "content._cardStyles.background",
24968
- baseClassName: "rb-relative rb-isolate rb-overflow-hidden rb-border"
26090
+ baseClassName: "rb-relative rb-isolate rb-overflow-visible rb-border"
24969
26091
  }, repeat("data.posts", "post"));
24970
26092
  const emptyState$2 = {
24971
26093
  ...styledCard([text({
@@ -24974,7 +26096,7 @@ const emptyState$2 = {
24974
26096
  }, bind("content.emptyMessage", { fallback: "No posts published yet." }))], {
24975
26097
  stylesFrom: "content._cardStyles",
24976
26098
  backgroundFrom: "content._cardStyles.background",
24977
- baseClassName: "rb-relative rb-isolate rb-overflow-hidden rb-border rb-border-dashed rb-p-8 rb-text-center"
26099
+ baseClassName: "rb-relative rb-isolate rb-overflow-visible rb-border rb-border-dashed rb-p-8 rb-text-center"
24978
26100
  }),
24979
26101
  $when: {
24980
26102
  when: { from: "data.posts[0]" },
@@ -24984,7 +26106,7 @@ const emptyState$2 = {
24984
26106
  function blogListingShell(children) {
24985
26107
  return styledSection({
24986
26108
  children: styledContainer({
24987
- baseClassName: "rb-relative rb-isolate rb-overflow-hidden",
26109
+ baseClassName: "rb-relative rb-isolate rb-overflow-visible",
24988
26110
  children
24989
26111
  }),
24990
26112
  baseClass: ""
@@ -25125,6 +26247,10 @@ const blogListingManifest = createBlockManifest({
25125
26247
  ],
25126
26248
  description: "Display a collection of blog posts in grid or stack layout.",
25127
26249
  contentTypes: ["post"],
26250
+ contentSource: {
26251
+ kind: "entries",
26252
+ contentType: "post"
26253
+ },
25128
26254
  tags: [
25129
26255
  "blog",
25130
26256
  "posts",
@@ -25167,6 +26293,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
25167
26293
  id: "block.cta-full",
25168
26294
  title: "Full-width CTA",
25169
26295
  category: "marketing",
26296
+ contentSource: { kind: "inline" },
25170
26297
  fragments: [{
25171
26298
  fragment: ctaCopyFragment,
25172
26299
  fieldPriority: 0
@@ -25200,6 +26327,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
25200
26327
  id: "block.single-button",
25201
26328
  title: "Single Button",
25202
26329
  category: "marketing",
26330
+ contentSource: { kind: "inline" },
25203
26331
  fragments: [{
25204
26332
  fragment: singleButtonFragment,
25205
26333
  fieldPriority: 0
@@ -25418,7 +26546,7 @@ const copyLayout = fragmentLayoutNode$1(formCopyFragment.layout);
25418
26546
  const formSurface = styledContainer({
25419
26547
  bindFrom: "_containerStyles",
25420
26548
  constrainWidth: false,
25421
- baseClassName: "rb-form-surface rb-relative rb-isolate rb-overflow-hidden",
26549
+ baseClassName: "rb-form-surface rb-relative rb-isolate rb-overflow-visible",
25422
26550
  children: fragmentLayoutNode$1(formEmbedFragment.layout)
25423
26551
  });
25424
26552
  function createFormLayout(variant) {
@@ -25482,6 +26610,7 @@ const formManifest = createBlockManifest({
25482
26610
  paletteHidden: false
25483
26611
  },
25484
26612
  category: "interactive",
26613
+ contentSource: { kind: "inline" },
25485
26614
  tags: [
25486
26615
  "form",
25487
26616
  "contact",
@@ -25544,6 +26673,7 @@ const contactNewsletterBlockDefinition = {
25544
26673
  titleSource: "contactTitle",
25545
26674
  description: "Two-column newsletter signup and contact form section.",
25546
26675
  category: "interactive",
26676
+ contentSource: { kind: "inline" },
25547
26677
  layout: contactNewsletterLayout,
25548
26678
  defaultVariant: "default",
25549
26679
  variants: { default: contactNewsletterLayout },
@@ -25747,6 +26877,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
25747
26877
  title: "FAQ",
25748
26878
  titleSource: "title",
25749
26879
  category: "content",
26880
+ contentSource: { kind: "inline" },
25750
26881
  includeContainerStyles: true,
25751
26882
  fragments: [{
25752
26883
  fragment: faqHeadingFragment,
@@ -26695,6 +27826,7 @@ const headerRootClassTransform = {
26695
27826
  ];
26696
27827
  const variant = header?.variant;
26697
27828
  if (variant && VALID_VARIANTS.includes(variant)) classes.push(`header-variant-${variant}`);
27829
+ if (header?.barFrame === "inset-shell" && variant === "classic") classes.push("header-bar-frame-inset-shell");
26698
27830
  return joinClasses$2(classes);
26699
27831
  }
26700
27832
  };
@@ -27251,7 +28383,7 @@ function markEditableSurfaceForwarding(component) {
27251
28383
  const SITE_CHROME_VISIBLE_HEADER_ATTR = "data-site-chrome-visible-header";
27252
28384
  //#endregion
27253
28385
  //#region ../blocks/src/system/blocks/site-header.ts
27254
- const whenTransformed$1 = (from, transformId, equals = true) => (node) => ({
28386
+ const whenTransformed = (from, transformId, equals = true) => (node) => ({
27255
28387
  ...node,
27256
28388
  $when: {
27257
28389
  when: {
@@ -27279,7 +28411,7 @@ const logoRow = link({
27279
28411
  text({
27280
28412
  as: "strong",
27281
28413
  className: "header-logo-text rb-truncate"
27282
- }, whenTransformed$1("$root.theme.header.logo", "layout.headerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
28414
+ }, whenTransformed("$root.theme.header.logo", "layout.headerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
27283
28415
  ]);
27284
28416
  const centeredLogoRow = link({
27285
28417
  href: "/",
@@ -27299,7 +28431,7 @@ const centeredLogoRow = link({
27299
28431
  text({
27300
28432
  as: "strong",
27301
28433
  className: "header-logo-text"
27302
- }, whenTransformed$1("$root.theme.header.logo", "layout.headerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
28434
+ }, whenTransformed("$root.theme.header.logo", "layout.headerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
27303
28435
  ]);
27304
28436
  const createNavRow = (className, align = "end") => navRow({
27305
28437
  className: `${className} header-nav-row`,
@@ -27431,7 +28563,7 @@ const classicLayout = inline({
27431
28563
  logoRow,
27432
28564
  createNavRow(`rb-ml-auto ${desktopOnlyDisplay("flex")} rb-gap-6`),
27433
28565
  headerCta
27434
- ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "inline"));
28566
+ ], whenTransformed("$root.theme.header", "layout.classicNavMode", "inline"));
27435
28567
  const classicCenteredNavLayout = inline({
27436
28568
  className: bindProp("$root.theme.header.maxWidth", {
27437
28569
  transforms: pipe(tx("layout.maxWidthClass", { base: `rb-header-layout ${desktopOnlyDisplay("flex")} rb-w-full rb-items-center rb-gap-6` })),
@@ -27442,7 +28574,7 @@ const classicCenteredNavLayout = inline({
27442
28574
  logoRow,
27443
28575
  createNavRow(`rb-flex-1 rb-justify-center ${desktopOnlyDisplay("flex")} rb-gap-6`, "center"),
27444
28576
  headerCta
27445
- ], whenTransformed$1("$root.theme.header", "layout.classicNavMode", "centered"));
28577
+ ], whenTransformed("$root.theme.header", "layout.classicNavMode", "centered"));
27446
28578
  const centeredLayout = stack({
27447
28579
  gap: "md",
27448
28580
  align: "center",
@@ -27482,6 +28614,7 @@ const siteHeaderManifest = createBlockManifest({
27482
28614
  id: "block.site-header",
27483
28615
  title: "Site Header",
27484
28616
  category: "layout",
28617
+ contentSource: { kind: "inline" },
27485
28618
  additionalFields: [{
27486
28619
  id: "mode",
27487
28620
  type: "select",
@@ -27505,7 +28638,6 @@ const siteHeaderManifest = createBlockManifest({
27505
28638
  transforms: pipe(tx("layout.headerSectionBackground")),
27506
28639
  fallback: "background"
27507
28640
  }),
27508
- allowOverflow: true,
27509
28641
  className: bindProp("$root.theme.header", {
27510
28642
  transforms: pipe(tx("layout.headerRootClass")),
27511
28643
  fallback: "header-root rb-z-40 rb-w-full transition-theme"
@@ -27556,218 +28688,155 @@ const footerNavGroupsLayout = stack({
27556
28688
  linkRequired: true,
27557
28689
  target: { $bind: { from: "entry.target" } },
27558
28690
  rel: { $bind: { from: "entry.rel" } }
27559
- }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], when("footerMenu.groups"));
28691
+ }, [text({ as: "span" }, bind("entry.label"))], repeat("group.children", "entry"))])], repeat("footerMenu.groups", "group"))], whenCollectionHasItems("footerMenu.groups"));
27560
28692
  //#endregion
27561
28693
  //#region ../blocks/src/system/blocks/site-footer.ts
27562
- const footerTextLayout = () => materializeFragment({ fragment: footerBottomTextFragment }).layout;
27563
- const whenTransformed = (from, transformId, equals = true) => (node) => ({
27564
- ...node,
27565
- $when: {
27566
- when: {
27567
- from,
27568
- transforms: [{ id: transformId }]
27569
- },
27570
- equals
27571
- }
27572
- });
27573
- const bottomBarTextLayout = () => {
27574
- const bottomTextNode = footerTextLayout()[1];
27575
- return bottomTextNode ? [bottomTextNode] : [];
27576
- };
27577
- const bodyTextLayout = () => {
27578
- const bodyTextNode = footerTextLayout()[0];
27579
- return bodyTextNode ? [bodyTextNode] : [];
27580
- };
27581
- const businessAddressLayout = () => [text({
27582
- as: "p",
27583
- className: "rb-caption rb-opacity-80"
27584
- }, bind("site.businessAddress.displayAddress"), when("content.showBusinessAddress", { equals: true }))];
27585
- const inlineBottomTextLayout = () => {
27586
- const bottomTextNode = footerTextLayout()[1];
27587
- if (!bottomTextNode) return [];
27588
- return [when("$root.theme.footer.bottomBar.enabled", {
27589
- equals: true,
27590
- not: true
27591
- })(bottomTextNode)];
27592
- };
27593
- const simpleFooterLayout = stack({
27594
- gap: "md",
27595
- align: "start",
27596
- className: { $bind: {
27597
- from: "$root.theme.footer",
27598
- transforms: [{ id: "layout.footerSimpleRootClass" }],
27599
- fallback: "rb-container rb-flex rb-w-full rb-flex-col rb-items-start rb-gap-4 rb-py-10 rb-text-left"
27600
- } }
27601
- }, [
27602
- link({
27603
- href: "/",
27604
- className: { $bind: {
27605
- from: "$root.theme.footer.logo",
27606
- transforms: [{
27607
- id: "layout.footerLogoClass",
27608
- options: { requireExplicitShow: true }
27609
- }],
27610
- fallback: "rb-hidden"
27611
- } }
27612
- }, [
27613
- media({ className: { $bind: {
27614
- from: "$root.theme.footer.logo",
27615
- transforms: [{ id: "layout.footerLogoMediaClass" }],
27616
- fallback: "rb-w-auto"
27617
- } } }, when("content.logo"), bind("content.logo")),
27618
- stack({ className: "rb-contents" }, [media({ className: { $bind: {
27619
- from: "$root.theme.footer.logo",
27620
- transforms: [{ id: "layout.footerLogoMediaClass" }],
27621
- fallback: "rb-w-auto"
27622
- } } }, when("site.logo"), bind("site.logo"))], when("content.logo", { not: true })),
27623
- text({
27624
- as: "strong",
27625
- className: "footer-logo-text rb-nav-text"
27626
- }, whenTransformed("$root.theme.footer", "layout.footerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
27627
- ]),
27628
- footerNav({
27629
- collectionPath: "footerMenu.items",
27630
- mode: "flatten",
27631
- className: { $bind: {
27632
- from: "$root.theme.footer.navLayout",
27633
- transforms: [{ id: "layout.footerSimpleNavClass" }],
27634
- fallback: "footer-nav rb-flex rb-flex-wrap rb-justify-start rb-gap-x-6 rb-gap-y-3"
27635
- } },
27636
- linkClassName: "footer-nav-link rb-inline-flex rb-items-center rb-px-4 rb-py-2 rb-nav-text transition-theme-standard"
27637
- }),
27638
- ...bodyTextLayout(),
27639
- ...businessAddressLayout(),
27640
- ...inlineBottomTextLayout()
27641
- ], when("$root.theme.footer.variant", { equals: "simple" }));
27642
- const columnsFooterLayout = stack({
27643
- gap: "xl",
27644
- align: "start",
28694
+ const brandLogo = link({
28695
+ href: "/",
27645
28696
  className: { $bind: {
27646
- from: "$root.theme.footer.maxWidth",
28697
+ from: "$root.theme.footer.logo",
27647
28698
  transforms: [{
27648
- id: "layout.maxWidthClass",
27649
- options: { base: "rb-flex rb-w-full rb-flex-col rb-gap-10 rb-py-12" }
28699
+ id: "layout.footerLogoClass",
28700
+ options: { base: "footer-logo rb-inline-flex rb-items-center rb-gap-3 rb-no-underline" }
27650
28701
  }],
27651
- fallback: "rb-container rb-flex rb-w-full rb-flex-col rb-gap-10 rb-py-12"
28702
+ fallback: "footer-logo rb-inline-flex rb-items-center rb-gap-3 rb-no-underline"
27652
28703
  } }
27653
- }, [
27654
- footerNavGroupsLayout,
27655
- inline({ className: "rb-flex rb-w-full rb-flex-wrap rb-items-center rb-justify-between rb-gap-4" }, [text({
27656
- as: "strong",
27657
- className: "rb-block rb-nav-text",
27658
- style: textColorStyle("text")
27659
- }, whenTransformed("$root.theme.footer", "layout.footerLogoTextVisible"), bind("site.title", { fallback: "Your Site" })), footerNav({
27660
- collectionPath: "footerMenu.items",
27661
- mode: "links-only",
27662
- className: "rb-flex rb-flex-wrap rb-justify-end rb-gap-x-6 rb-gap-y-3",
27663
- linkClassName: "footer-nav-link rb-inline-flex rb-items-center rb-px-4 rb-py-2 rb-nav-text transition-theme-standard"
27664
- })]),
27665
- ...bodyTextLayout(),
27666
- ...businessAddressLayout(),
27667
- ...inlineBottomTextLayout()
27668
- ], when("$root.theme.footer.variant", { equals: "columns" }));
27669
- const splitFooterLayout = stack({
27670
- gap: "xl",
27671
- align: "start",
28704
+ }, [media({ className: { $bind: {
28705
+ from: "$root.theme.footer.logo",
28706
+ transforms: [{
28707
+ id: "layout.footerLogoMediaClass",
28708
+ options: { base: "rb-h-10 rb-w-auto" }
28709
+ }],
28710
+ fallback: "rb-h-10 rb-w-auto"
28711
+ } } }, when("module.showLogo", { equals: true }), when("content.logo"), bind("content.logo")), text({
28712
+ as: "strong",
28713
+ className: "footer-logo-text rb-nav-text"
28714
+ }, when("module.showTitle", { equals: true }), bind("site.title", { fallback: "Your Site" }))], when("module.kind", { equals: "brand" }));
28715
+ const navigation = stack({
28716
+ gap: "md",
28717
+ className: "rb-w-full"
28718
+ }, [footerNavGroupsLayout, footerNav({
28719
+ collectionPath: "footerMenu.items",
28720
+ mode: "links-only",
27672
28721
  className: { $bind: {
27673
- from: "$root.theme.footer.maxWidth",
27674
- transforms: [{
27675
- id: "layout.maxWidthClass",
27676
- options: { base: "rb-flex rb-w-full rb-flex-col rb-gap-10 rb-py-12" }
27677
- }],
27678
- fallback: "rb-container rb-flex rb-w-full rb-flex-col rb-gap-10 rb-py-12"
27679
- } }
28722
+ from: "module.navigationClassName",
28723
+ fallback: "footer-nav rb-flex rb-flex-wrap rb-gap-x-6 rb-gap-y-3"
28724
+ } },
28725
+ linkClassName: "footer-nav-link rb-nav-text transition-theme-standard"
28726
+ })], when("module.kind", { equals: "navigation" }));
28727
+ const legalNavigation = footerNav({
28728
+ collectionPath: "legalFooterMenu.items",
28729
+ mode: "links-only",
28730
+ className: "rb-flex rb-flex-wrap rb-gap-x-4 rb-gap-y-2",
28731
+ linkClassName: "footer-nav-link rb-caption transition-theme-standard"
28732
+ });
28733
+ const address = text({
28734
+ as: "address",
28735
+ className: "rb-not-italic rb-opacity-80"
28736
+ }, when("module.kind", { equals: "business-address" }), bind("module.address"));
28737
+ const contact = stack({
28738
+ gap: "sm",
28739
+ className: "rb-items-start"
28740
+ }, [link({
28741
+ href: { $bind: { from: "contactLink.href" } },
28742
+ className: "rb-nav-text rb-break-words transition-theme-standard"
28743
+ }, [text({ as: "span" }, bind("contactLink.label"))], repeat("module.contactLinks", "contactLink"))], when("module.kind", { equals: "contact" }));
28744
+ const hours = stack({
28745
+ gap: "sm",
28746
+ className: "rb-w-full"
28747
+ }, [inline({ className: "rb-flex rb-w-full rb-justify-between rb-gap-4" }, [text({
28748
+ as: "span",
28749
+ className: "rb-label"
28750
+ }, bind("hoursDay.weekday")), text({
28751
+ as: "span",
28752
+ className: "rb-caption rb-opacity-80"
28753
+ }, bind("hoursDay.hours"))], repeat("module.openingHours", "hoursDay")), text({
28754
+ as: "p",
28755
+ className: "rb-caption rb-opacity-70"
28756
+ }, bind("module.timeZone"), when("module.timeZone"))], when("module.kind", { equals: "opening-hours" }));
28757
+ const socials = inline({ className: "rb-flex rb-flex-wrap rb-gap-x-5 rb-gap-y-3" }, [link({
28758
+ href: { $bind: { from: "social.href" } },
28759
+ target: "_blank",
28760
+ rel: "noreferrer noopener",
28761
+ "aria-label": { $bind: { from: "social.label" } },
28762
+ className: "rb-nav-text transition-theme-standard"
28763
+ }, [icon({ className: "rb-h-5 rb-w-5" }, bind("social.icon"), when("social.icon")), text({ as: "span" }, bind("social.label"), when("social.icon", { equals: null }))], repeat("module.socialLinks", "social"))], when("module.kind", { equals: "social-links" }));
28764
+ const authoredCopy = richText({
28765
+ className: "rb-prose rb-prose-sm rb-max-w-none",
28766
+ style: textColorStyle("text/80")
28767
+ }, when("module.content"), bind("module.content", { transforms: [{
28768
+ id: "content.interpolateRichTextTokens",
28769
+ options: { tokens: ["year", "site_name"] }
28770
+ }] }));
28771
+ const footerGroup = stack({
28772
+ gap: "md",
28773
+ align: "stretch",
28774
+ className: "rb-min-w-0",
28775
+ "data-footer-group": { $bind: { from: "group.kind" } }
28776
+ }, [stack({
28777
+ gap: "md",
28778
+ align: "start",
28779
+ "data-preview-footer-module-id": { $bind: { from: "module.id" } }
27680
28780
  }, [
27681
- inline({ className: { $bind: {
27682
- from: "$root.theme.footer.logo",
27683
- transforms: [{ id: "layout.footerSplitMainClass" }],
27684
- fallback: "rb-flex rb-w-full rb-flex-col rb-items-start rb-justify-between rb-gap-8 rb-md-flex-row rb-md-items-end"
27685
- } } }, [stack({}, [footerNav({
27686
- collectionPath: "footerMenu.items",
27687
- mode: "flatten",
27688
- className: { $bind: {
27689
- from: "$root.theme.footer.navLayout",
27690
- transforms: [{ id: "layout.footerSplitNavSingleClass" }],
27691
- fallback: "rb-w-full rb-space-y-3 rb-text-left"
27692
- } },
27693
- linkClassName: "footer-nav-link rb-inline-flex rb-items-center rb-whitespace-nowrap rb-nav-text transition-theme-standard"
27694
- })]), link({
27695
- href: "/",
27696
- className: { $bind: {
27697
- from: "$root.theme.footer.logo",
27698
- transforms: [{ id: "layout.footerLogoClass" }],
27699
- fallback: "footer-logo rb-inline-flex rb-items-center rb-justify-end rb-gap-3 rb-self-end rb-no-underline rb-text-right rb-transition-opacity rb-hover-opacity-80"
27700
- } }
27701
- }, [
27702
- media({ className: { $bind: {
27703
- from: "$root.theme.footer.logo",
27704
- transforms: [{ id: "layout.footerLogoMediaClass" }],
27705
- fallback: "rb-w-auto"
27706
- } } }, when("content.logo"), bind("content.logo")),
27707
- stack({ className: "rb-contents" }, [media({ className: { $bind: {
27708
- from: "$root.theme.footer.logo",
27709
- transforms: [{ id: "layout.footerLogoMediaClass" }],
27710
- fallback: "rb-w-auto"
27711
- } } }, when("site.logo"), bind("site.logo"))], when("content.logo", { not: true })),
27712
- text({
27713
- as: "strong",
27714
- className: "footer-logo-text rb-nav-text"
27715
- }, whenTransformed("$root.theme.footer", "layout.footerLogoTextVisible"), bind("site.title", { fallback: "Your Site" }))
27716
- ])]),
27717
- ...businessAddressLayout(),
27718
- ...inlineBottomTextLayout()
27719
- ], when("$root.theme.footer.variant", { equals: "split" }));
27720
- const footerLayout = section({
27721
- background: "background",
28781
+ text({
28782
+ as: "h2",
28783
+ className: "rb-label",
28784
+ style: textColorStyle("text/70")
28785
+ }, bind("module.heading"), when("module.heading")),
28786
+ brandLogo,
28787
+ navigation,
28788
+ stack({
28789
+ gap: "sm",
28790
+ className: "rb-w-full"
28791
+ }, [legalNavigation], when("module.kind", { equals: "legal-navigation" })),
28792
+ address,
28793
+ contact,
28794
+ hours,
28795
+ socials,
28796
+ stack({ className: "rb-w-full" }, [authoredCopy], when("module.kind", { equals: "supporting-text" })),
28797
+ stack({ className: "rb-w-full rb-lg-col-span-3" }, [authoredCopy], when("module.kind", { equals: "legal" }))
28798
+ ], repeat("group.modules", "module"))], repeat("region.groups", "group"));
28799
+ const footerMainRegion = stack({
28800
+ className: { $bind: { from: "region.className" } },
28801
+ "data-footer-region": { $bind: { from: "region.kind" } }
28802
+ }, [footerGroup], when("region.kind", { equals: "main" }), repeat("content.footerRuntime.regions", "region"));
28803
+ const footerBottomRegion = stack({ className: { $bind: {
28804
+ from: "$root.theme.footer",
28805
+ transforms: [{ id: "layout.footerBottomBarContainerClass" }],
28806
+ fallback: "rb-w-full"
28807
+ } } }, [stack({
27722
28808
  className: { $bind: {
27723
28809
  from: "$root.theme.footer",
27724
- transforms: [{ id: "layout.footerRootClass" }],
27725
- fallback: "rb-w-full rb-border-t transition-theme"
28810
+ transforms: [{ id: "layout.footerBottomBarClass" }],
28811
+ fallback: "rb-w-full rb-border-t rb-px-6 rb-py-6 rb-text-center"
27726
28812
  } },
27727
28813
  style: { $bind: {
27728
28814
  from: "$root.theme.footer",
27729
- transforms: [{ id: "layout.footerRootStyle" }],
27730
- fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
27731
- } }
27732
- }, [
27733
- simpleFooterLayout,
27734
- columnsFooterLayout,
27735
- splitFooterLayout,
27736
- stack({
27737
- className: { $bind: {
27738
- from: "$root.theme.footer",
27739
- transforms: [{ id: "layout.footerBottomBarClass" }],
27740
- fallback: "rb-w-full rb-border-t rb-py-5"
27741
- } },
27742
- style: { $bind: {
27743
- from: "$root.theme.footer",
27744
- transforms: [{ id: "layout.footerBottomBarStyle" }]
27745
- } }
27746
- }, [stack({ className: { $bind: {
27747
- from: "$root.theme.footer",
27748
- transforms: [{ id: "layout.footerBottomBarContainerClass" }],
27749
- fallback: "rb-container"
27750
- } } }, [...bottomBarTextLayout()])], when("$root.theme.footer.bottomBar.enabled", { equals: true }))
27751
- ]);
28815
+ transforms: [{ id: "layout.footerBottomBarStyle" }]
28816
+ } },
28817
+ "data-footer-region": "bottom"
28818
+ }, [footerGroup])], when("region.kind", { equals: "bottom" }), repeat("content.footerRuntime.regions", "region"));
27752
28819
  const siteFooterManifest = createBlockManifest({
27753
28820
  id: "block.site-footer",
27754
28821
  title: "Site Footer",
27755
28822
  category: "layout",
27756
- fragments: [{
27757
- fragment: footerBottomTextFragment,
27758
- fieldPriority: 0
27759
- }],
28823
+ contentSource: { kind: "inline" },
27760
28824
  skipSectionStyles: true,
27761
- additionalFields: [{
27762
- id: "showBusinessAddress",
27763
- type: "boolean",
27764
- label: "Add business address to site footer?",
27765
- required: false,
27766
- defaultValue: false,
27767
- ui: { intent: "content" }
27768
- }],
27769
- layout: footerLayout,
27770
- description: "Site-wide footer with navigation links and optional columns.",
28825
+ layout: section({
28826
+ background: "background",
28827
+ className: { $bind: {
28828
+ from: "$root.theme.footer",
28829
+ transforms: [{ id: "layout.footerRootClass" }],
28830
+ fallback: "rb-w-full rb-border-t transition-theme"
28831
+ } },
28832
+ style: { $bind: {
28833
+ from: "$root.theme.footer",
28834
+ transforms: [{ id: "layout.footerRootStyle" }],
28835
+ fallback: mergeStyles(backgroundColorStyle("surface"), surfaceForegroundStyle({ text: "rgb(var(--tb-text))" }), borderColorStyle("border"))
28836
+ } },
28837
+ "data-footer-membership": { $bind: { from: "content.footerRuntime.membershipKey" } }
28838
+ }, [footerMainRegion, footerBottomRegion]),
28839
+ description: "Site-wide composed footer with canonical shared details.",
27771
28840
  styleTokens: { spacing: "md" },
27772
28841
  paletteHidden: true
27773
28842
  });
@@ -27902,6 +28971,7 @@ const testimonialsBlockDefinition = {
27902
28971
  id: "block.testimonials",
27903
28972
  title: "Testimonials",
27904
28973
  category: "marketing",
28974
+ contentSource: { kind: "inline" },
27905
28975
  includeContainerStyles: true,
27906
28976
  previewCustomize: { quickFieldPriority: [
27907
28977
  "avatarLayout",
@@ -28060,6 +29130,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
28060
29130
  id: "block.columns",
28061
29131
  title: "Columns",
28062
29132
  category: "layout",
29133
+ contentSource: { kind: "inline" },
28063
29134
  additionalFields: [
28064
29135
  parseFieldDefinition({
28065
29136
  id: "equalHeight",
@@ -28246,7 +29317,7 @@ const repeatedItemsNode = repeaterFragmentLayout({
28246
29317
  id: "boxStyles.all",
28247
29318
  options: {
28248
29319
  axis: "all",
28249
- baseClass: "rb-collection-item rb-relative rb-isolate rb-overflow-hidden rb-border"
29320
+ baseClass: "rb-collection-item rb-relative rb-isolate rb-overflow-visible rb-border"
28250
29321
  }
28251
29322
  }]
28252
29323
  },
@@ -28293,6 +29364,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
28293
29364
  id: "block.collection",
28294
29365
  title: "Collection",
28295
29366
  category: "layout",
29367
+ contentSource: { kind: "inline" },
28296
29368
  additionalFields: [
28297
29369
  parseFieldDefinition({
28298
29370
  id: "layout",
@@ -28570,6 +29642,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
28570
29642
  id: "block.feature-cards",
28571
29643
  title: "Feature Cards",
28572
29644
  category: "layout",
29645
+ contentSource: { kind: "inline" },
28573
29646
  includeContainerStyles: true,
28574
29647
  titleSource: "title",
28575
29648
  additionalFields: [
@@ -28953,6 +30026,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
28953
30026
  id: "block.media-text",
28954
30027
  title: "Media and Text",
28955
30028
  category: "layout",
30029
+ contentSource: { kind: "inline" },
28956
30030
  includeContainerStyles: true,
28957
30031
  titleSource: "title",
28958
30032
  previewCustomize: { quickFieldPriority: [
@@ -29353,6 +30427,7 @@ const appointmentBookingBlockDefinition = {
29353
30427
  paletteHidden: false
29354
30428
  },
29355
30429
  category: "interactive",
30430
+ contentSource: { kind: "inline" },
29356
30431
  tags: [
29357
30432
  "booking",
29358
30433
  "appointment",
@@ -29517,6 +30592,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
29517
30592
  paletteHidden: false
29518
30593
  },
29519
30594
  category: "interactive",
30595
+ contentSource: { kind: "inline" },
29520
30596
  tags: [
29521
30597
  "booking",
29522
30598
  "appointment",
@@ -31215,6 +32291,7 @@ const eventRegistrationBlockDefinition = {
31215
32291
  titleSource: "heading",
31216
32292
  description: "Multi-step event registration form",
31217
32293
  category: "interactive",
32294
+ contentSource: { kind: "inline" },
31218
32295
  tags: [
31219
32296
  "events",
31220
32297
  "registration",
@@ -31321,15 +32398,9 @@ const eventRegistrationBlockDefinition = {
31321
32398
  defaultValue: "Complete Registration",
31322
32399
  maxLength: 40
31323
32400
  },
31324
- {
31325
- id: "buttonVariant",
31326
- type: "select",
31327
- label: "Button style",
32401
+ createButtonVariantField({
31328
32402
  description: "Choose a button style from your theme",
31329
- required: false,
31330
- multiple: false,
31331
- defaultValue: "primary",
31332
- options: [
32403
+ variants: [
31333
32404
  {
31334
32405
  value: "primary",
31335
32406
  label: "Primary"
@@ -31342,9 +32413,8 @@ const eventRegistrationBlockDefinition = {
31342
32413
  value: "outline",
31343
32414
  label: "Outline"
31344
32415
  }
31345
- ],
31346
- ui: { intent: "style" }
31347
- }
32416
+ ]
32417
+ })
31348
32418
  ],
31349
32419
  layout: [styledSection({
31350
32420
  baseClass: "",
@@ -31719,6 +32789,7 @@ const courseRegistrationBlockDefinition = {
31719
32789
  titleSource: "heading",
31720
32790
  description: "Enrollment form for multi-session courses",
31721
32791
  category: "interactive",
32792
+ contentSource: { kind: "inline" },
31722
32793
  tags: [
31723
32794
  "courses",
31724
32795
  "enrollment",
@@ -31832,15 +32903,9 @@ const courseRegistrationBlockDefinition = {
31832
32903
  defaultValue: "Sign up",
31833
32904
  maxLength: 40
31834
32905
  },
31835
- {
31836
- id: "buttonVariant",
31837
- type: "select",
31838
- label: "Button style",
32906
+ createButtonVariantField({
31839
32907
  description: "Choose a button style from your theme",
31840
- required: false,
31841
- multiple: false,
31842
- defaultValue: "primary",
31843
- options: [
32908
+ variants: [
31844
32909
  {
31845
32910
  value: "primary",
31846
32911
  label: "Primary"
@@ -31853,9 +32918,8 @@ const courseRegistrationBlockDefinition = {
31853
32918
  value: "outline",
31854
32919
  label: "Outline"
31855
32920
  }
31856
- ],
31857
- ui: { intent: "style" }
31858
- }
32921
+ ]
32922
+ })
31859
32923
  ],
31860
32924
  layout: [styledSection({
31861
32925
  baseClass: "",
@@ -31935,6 +32999,7 @@ const eventDetailsManifest = createBlockManifest({
31935
32999
  titleSource: "heading",
31936
33000
  description: "Date/time, venue, map, and other dates for an event",
31937
33001
  category: "content",
33002
+ contentSource: { kind: "entries" },
31938
33003
  tags: [
31939
33004
  "events",
31940
33005
  "venue",
@@ -32140,6 +33205,7 @@ const courseDetailsBlockDefinition = {
32140
33205
  titleSource: "heading",
32141
33206
  description: "Schedule, venue, price, and enrollment status for a course",
32142
33207
  category: "content",
33208
+ contentSource: { kind: "entries" },
32143
33209
  tags: [
32144
33210
  "courses",
32145
33211
  "schedule",
@@ -32431,6 +33497,7 @@ const eventSpotlightBlockDefinition = {
32431
33497
  paletteHidden: false
32432
33498
  },
32433
33499
  category: "content",
33500
+ contentSource: { kind: "entries" },
32434
33501
  tags: [
32435
33502
  "events",
32436
33503
  "featured",
@@ -35244,6 +36311,7 @@ const eventListingBlockDefinition = {
35244
36311
  paletteHidden: true
35245
36312
  },
35246
36313
  category: "interactive",
36314
+ contentSource: { kind: "entries" },
35247
36315
  tags: [
35248
36316
  "events",
35249
36317
  "listing",
@@ -36449,6 +37517,7 @@ const eventCalendarBlockDefinition = {
36449
37517
  paletteHidden: false
36450
37518
  },
36451
37519
  category: "interactive",
37520
+ contentSource: { kind: "entries" },
36452
37521
  tags: [
36453
37522
  "events",
36454
37523
  "calendar",
@@ -36846,6 +37915,7 @@ const recurringScheduleBlockDefinition = {
36846
37915
  titleSource: "heading",
36847
37916
  description: "A compact weekly schedule with one row per recurring series.",
36848
37917
  category: "interactive",
37918
+ contentSource: { kind: "entries" },
36849
37919
  icon: "CalendarDays",
36850
37920
  tags: [
36851
37921
  "schedule",
@@ -37476,7 +38546,10 @@ const offeringsPreviewFields = [
37476
38546
  label: "Link"
37477
38547
  }
37478
38548
  ],
37479
- ui: { intent: "display" }
38549
+ ui: {
38550
+ intent: "display",
38551
+ widget: "buttonVariant"
38552
+ }
37480
38553
  },
37481
38554
  {
37482
38555
  id: "buttonText",
@@ -37529,6 +38602,7 @@ const offeringsPreviewManifest = createBlockManifest({
37529
38602
  paletteHidden: false
37530
38603
  },
37531
38604
  category: "content",
38605
+ contentSource: { kind: "mixed" },
37532
38606
  tags: [
37533
38607
  "offerings",
37534
38608
  "events",
@@ -37697,6 +38771,7 @@ const embedManifest = createBlockManifest({
37697
38771
  id: "block.embed",
37698
38772
  title: "Embed Content",
37699
38773
  category: "content",
38774
+ contentSource: { kind: "entries" },
37700
38775
  titleSource: "heading",
37701
38776
  additionalFields: [
37702
38777
  parseFieldDefinition({
@@ -38184,6 +39259,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
38184
39259
  id: "block.image-gallery",
38185
39260
  title: "Image Gallery",
38186
39261
  category: "content",
39262
+ contentSource: { kind: "inline" },
38187
39263
  previewCustomize: { quickFieldPriority: [
38188
39264
  "aspectRatio",
38189
39265
  "slidesToShow",
@@ -38836,6 +39912,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
38836
39912
  id: "block.video-grid",
38837
39913
  title: "Video Grid",
38838
39914
  category: "media",
39915
+ contentSource: { kind: "inline" },
38839
39916
  skipSectionStyles: true,
38840
39917
  additionalFields: parseFieldDefinitions([
38841
39918
  {
@@ -39006,6 +40083,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
39006
40083
  title: "Audio Player",
39007
40084
  titleSource: "title",
39008
40085
  category: "media",
40086
+ contentSource: { kind: "inline" },
39009
40087
  description: "Add a branded audio player for a single track.",
39010
40088
  tags: [
39011
40089
  "audio",
@@ -39117,6 +40195,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
39117
40195
  title: "File Download",
39118
40196
  titleSource: ["title", "file.filename"],
39119
40197
  category: "media",
40198
+ contentSource: { kind: "inline" },
39120
40199
  description: "Add a simple public download link for a document, ZIP, or audio file.",
39121
40200
  tags: [
39122
40201
  "file",
@@ -40136,6 +41215,7 @@ const shopBlockDefinition = {
40136
41215
  paletteHidden: false
40137
41216
  },
40138
41217
  category: "interactive",
41218
+ contentSource: { kind: "entries" },
40139
41219
  tags: [
40140
41220
  "shop",
40141
41221
  "passes",
@@ -40335,6 +41415,7 @@ const productListBlockDefinition = {
40335
41415
  paletteHidden: false
40336
41416
  },
40337
41417
  category: "interactive",
41418
+ contentSource: { kind: "entries" },
40338
41419
  tags: [
40339
41420
  "shop",
40340
41421
  "products",
@@ -40476,6 +41557,7 @@ const productDetailBlockDefinition = {
40476
41557
  paletteHidden: false
40477
41558
  },
40478
41559
  category: "interactive",
41560
+ contentSource: { kind: "entries" },
40479
41561
  tags: [
40480
41562
  "shop",
40481
41563
  "product",
@@ -40592,6 +41674,7 @@ const cartBlockDefinition = {
40592
41674
  paletteHidden: false
40593
41675
  },
40594
41676
  category: "interactive",
41677
+ contentSource: { kind: "inline" },
40595
41678
  tags: [
40596
41679
  "shop",
40597
41680
  "cart",
@@ -40674,6 +41757,7 @@ const checkoutBlockDefinition = {
40674
41757
  paletteHidden: false
40675
41758
  },
40676
41759
  category: "interactive",
41760
+ contentSource: { kind: "inline" },
40677
41761
  tags: [
40678
41762
  "shop",
40679
41763
  "checkout",
@@ -40888,6 +41972,7 @@ const giftingBlockDefinition = {
40888
41972
  paletteHidden: false
40889
41973
  },
40890
41974
  category: "interactive",
41975
+ contentSource: { kind: "entries" },
40891
41976
  tags: [
40892
41977
  "gifting",
40893
41978
  "gift cards",
@@ -41242,6 +42327,7 @@ const newsletterSignupBlockDefinition = {
41242
42327
  titleSource: "title",
41243
42328
  description: "Newsletter subscription form with configurable field presets.",
41244
42329
  category: "interactive",
42330
+ contentSource: { kind: "inline" },
41245
42331
  fragments: [{
41246
42332
  fragment: newsletterCopyFragment,
41247
42333
  fieldPriority: 0
@@ -41423,6 +42509,7 @@ const teamMembersBlockDefinition = {
41423
42509
  id: "block.team-members",
41424
42510
  title: "Team Members",
41425
42511
  category: "content",
42512
+ contentSource: { kind: "mixed" },
41426
42513
  titleSource: "heading",
41427
42514
  additionalFields: [
41428
42515
  parseFieldDefinition({
@@ -41863,6 +42950,7 @@ const locationMapBlockDefinition = {
41863
42950
  titleSource: "heading",
41864
42951
  description: "Show a business location with an interactive map and directions link.",
41865
42952
  category: "content",
42953
+ contentSource: { kind: "inline" },
41866
42954
  tags: [
41867
42955
  "map",
41868
42956
  "location",
@@ -42869,213 +43957,6 @@ function getBlockDefinition(name) {
42869
43957
  return blockStore.get(name);
42870
43958
  }
42871
43959
  //#endregion
42872
- //#region ../theme-core/src/gradients/presets.ts
42873
- /**
42874
- * Curated library of gradient presets
42875
- * All gradients use theme color tokens, so they adapt to the site's palette
42876
- */
42877
- const GRADIENT_PRESETS = [
42878
- {
42879
- id: "primary-secondary",
42880
- name: "Primary to Secondary",
42881
- description: "Blend your primary and secondary brand colors",
42882
- type: "linear",
42883
- angle: 135,
42884
- stops: [{
42885
- color: "primary-500",
42886
- position: 0
42887
- }, {
42888
- color: "secondary-500",
42889
- position: 100
42890
- }]
42891
- },
42892
- {
42893
- id: "primary-accent",
42894
- name: "Primary to Accent",
42895
- description: "Energetic gradient from primary to accent",
42896
- type: "linear",
42897
- angle: 135,
42898
- stops: [{
42899
- color: "primary-500",
42900
- position: 0
42901
- }, {
42902
- color: "accent-500",
42903
- position: 100
42904
- }]
42905
- },
42906
- {
42907
- id: "secondary-accent",
42908
- name: "Secondary to Accent",
42909
- description: "Vibrant secondary to accent blend",
42910
- type: "linear",
42911
- angle: 135,
42912
- stops: [{
42913
- color: "secondary-500",
42914
- position: 0
42915
- }, {
42916
- color: "accent-500",
42917
- position: 100
42918
- }]
42919
- },
42920
- {
42921
- id: "primary-light-dark",
42922
- name: "Primary Light to Dark",
42923
- description: "Subtle primary color fade",
42924
- type: "linear",
42925
- angle: 180,
42926
- stops: [{
42927
- color: "primary-500",
42928
- position: 0
42929
- }, {
42930
- color: "primary-900",
42931
- position: 100
42932
- }]
42933
- },
42934
- {
42935
- id: "primary-dark-light",
42936
- name: "Primary Dark to Light",
42937
- description: "Reverse primary fade",
42938
- type: "linear",
42939
- angle: 180,
42940
- stops: [{
42941
- color: "primary-900",
42942
- position: 0
42943
- }, {
42944
- color: "primary-50",
42945
- position: 100
42946
- }]
42947
- },
42948
- {
42949
- id: "secondary-light-dark",
42950
- name: "Secondary Light to Dark",
42951
- description: "Subtle secondary color fade",
42952
- type: "linear",
42953
- angle: 180,
42954
- stops: [{
42955
- color: "secondary-500",
42956
- position: 0
42957
- }, {
42958
- color: "secondary-900",
42959
- position: 100
42960
- }]
42961
- },
42962
- {
42963
- id: "accent-light-dark",
42964
- name: "Accent Light to Dark",
42965
- description: "Accent color depth fade",
42966
- type: "linear",
42967
- angle: 180,
42968
- stops: [{
42969
- color: "accent-500",
42970
- position: 0
42971
- }, {
42972
- color: "accent-900",
42973
- position: 100
42974
- }]
42975
- },
42976
- {
42977
- id: "background-surface",
42978
- name: "Background to Surface",
42979
- description: "Subtle depth using base colors",
42980
- type: "linear",
42981
- angle: 180,
42982
- stops: [{
42983
- color: "background",
42984
- position: 0
42985
- }, {
42986
- color: "surface",
42987
- position: 100
42988
- }]
42989
- },
42990
- {
42991
- id: "neutral-fade",
42992
- name: "Neutral Gradient",
42993
- description: "Elegant neutral color fade",
42994
- type: "linear",
42995
- angle: 180,
42996
- stops: [{
42997
- color: "neutral-900",
42998
- position: 0
42999
- }, {
43000
- color: "neutral-50",
43001
- position: 100
43002
- }]
43003
- },
43004
- {
43005
- id: "primary-radial",
43006
- name: "Primary Spotlight",
43007
- description: "Radial primary gradient from center",
43008
- type: "radial",
43009
- position: "center",
43010
- stops: [{
43011
- color: "primary-500",
43012
- position: 0
43013
- }, {
43014
- color: "primary-900",
43015
- position: 100
43016
- }]
43017
- },
43018
- {
43019
- id: "accent-radial",
43020
- name: "Accent Spotlight",
43021
- description: "Radial accent gradient from center",
43022
- type: "radial",
43023
- position: "center",
43024
- stops: [{
43025
- color: "accent-500",
43026
- position: 0
43027
- }, {
43028
- color: "accent-900",
43029
- position: 100
43030
- }]
43031
- },
43032
- {
43033
- id: "primary-secondary-accent",
43034
- name: "Brand Trio",
43035
- description: "All three brand colors in harmony",
43036
- type: "linear",
43037
- angle: 135,
43038
- stops: [
43039
- {
43040
- color: "primary-500",
43041
- position: 0
43042
- },
43043
- {
43044
- color: "secondary-500",
43045
- position: 50
43046
- },
43047
- {
43048
- color: "accent-500",
43049
- position: 100
43050
- }
43051
- ]
43052
- }
43053
- ];
43054
- //#endregion
43055
- //#region ../theme-core/src/gradients/utils.ts
43056
- /**
43057
- * Convert a GradientConfig to a CSS gradient string
43058
- *
43059
- * @param config - The gradient configuration using theme tokens
43060
- * @param tokens - Map of theme color tokens to hex values
43061
- * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
43062
- */
43063
- function gradientToCss(config, tokens) {
43064
- const stops = config.stops.map((stop) => {
43065
- return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
43066
- }).join(", ");
43067
- const type = config.type ?? "linear";
43068
- if (type === "radial") {
43069
- const position = config.position ?? "center";
43070
- return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
43071
- }
43072
- if (type === "conic") {
43073
- const position = config.position ?? "center";
43074
- return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
43075
- }
43076
- return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
43077
- }
43078
- //#endregion
43079
43960
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
43080
43961
  function resolveBackgroundMedia(input) {
43081
43962
  const parsedMedia = mediaSchema.safeParse(input.image);
@@ -43113,9 +43994,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
43113
43994
  ].filter(Boolean).join(" ");
43114
43995
  }
43115
43996
  function gradientPresetCss(value) {
43116
- if (!isString(value)) return null;
43117
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
43118
- if (!preset) return null;
43997
+ const presetId = parseGradientPresetId(value);
43998
+ if (!presetId) return null;
43999
+ const preset = getGradientPreset(presetId);
43119
44000
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
43120
44001
  }
43121
44002
  const backgroundTransforms = [
@@ -43154,16 +44035,17 @@ const backgroundTransforms = [
43154
44035
  run: (value, _options, context) => resolveSurfaceForegroundStyles(value, context)
43155
44036
  },
43156
44037
  {
43157
- id: "background.resolveAllowOverflow",
44038
+ id: "background.resolveFrameClassName",
43158
44039
  kind: "formatter",
43159
- summary: "Resolve allowOverflow from background config (explicit overflow or scaled image)",
43160
- run: (value) => {
43161
- if (!value || typeof value !== "object") return false;
44040
+ summary: "Resolve clipping on a decorative background frame without clipping foreground content",
44041
+ run: (value, options) => {
44042
+ const baseClass = options?.baseClass?.trim() ?? "";
44043
+ if (!value || typeof value !== "object") return `${baseClass} rb-overflow-hidden`.trim();
43162
44044
  const input = value;
43163
- if (input.overflow === true) return true;
44045
+ if (input.overflow === true) return `${baseClass} rb-overflow-visible`.trim();
43164
44046
  const objectFit = isString(input.objectFit) ? input.objectFit.trim() : null;
43165
44047
  const scale = isString(input.scale) ? input.scale.trim() : isNumber(input.scale) ? String(input.scale) : null;
43166
- return Boolean((objectFit === "custom" || objectFit === "original") && scale && scale.trim().length > 0);
44048
+ return `${baseClass} ${Boolean((objectFit === "custom" || objectFit === "original") && scale && scale.trim().length > 0) ? "rb-overflow-visible" : "rb-overflow-hidden"}`.trim();
43167
44049
  }
43168
44050
  },
43169
44051
  {
@@ -43713,10 +44595,10 @@ function isRecord$7(value) {
43713
44595
  }
43714
44596
  //#endregion
43715
44597
  //#region ../blocks/src/primitives/layout/Section.tsx
43716
- const Section = forwardRef(function Section({ as: Comp = "section", children, background, className = "", allowOverflow = false, style, "data-slot": dataSlot }, ref) {
44598
+ const Section = forwardRef(function Section({ as: Comp = "section", children, background, className = "", style, "data-slot": dataSlot }, ref) {
43717
44599
  return /* @__PURE__ */ jsx(Comp, {
43718
44600
  ref,
43719
- className: clsx("rb-relative rb-isolate", allowOverflow ? "rb-overflow-visible" : "rb-overflow-hidden", className),
44601
+ className: clsx("rb-relative rb-isolate rb-overflow-visible", className),
43720
44602
  style: mergeStyles(typeof background === "string" && background.trim().length > 0 ? backgroundColorStyle(background.trim()) : void 0, style),
43721
44603
  "data-slot": dataSlot ?? "section",
43722
44604
  children
@@ -43837,10 +44719,7 @@ function Grid({ as: Comp = "div", cols = {
43837
44719
  }
43838
44720
  //#endregion
43839
44721
  //#region ../blocks/src/system/runtime/nodes/layout.tsx
43840
- const SectionNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, previewAuthoring: _previewAuthoring, pathBase: _pathBase, allowOverflow, ...props }) => /* @__PURE__ */ jsx(Section, {
43841
- ...props,
43842
- allowOverflow
43843
- });
44722
+ const SectionNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, previewAuthoring: _previewAuthoring, pathBase: _pathBase, ...props }) => /* @__PURE__ */ jsx(Section, { ...props });
43844
44723
  const StackNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, previewAuthoring: _previewAuthoring, pathBase: _pathBase, ...props }) => /* @__PURE__ */ jsx(Stack, { ...props });
43845
44724
  const InlineNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, previewAuthoring: _previewAuthoring, pathBase: _pathBase, ...props }) => /* @__PURE__ */ jsx(Inline, { ...props });
43846
44725
  const GridNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _blockContent, fragmentRegistry: _fragmentRegistry, previewAuthoring: _previewAuthoring, pathBase: _pathBase, ...props }) => /* @__PURE__ */ jsx(Grid, { ...props });
@@ -43850,6 +44729,28 @@ const FigureNode = ({ blockId: _blockId, blockKind: _blockKind, blockContent: _b
43850
44729
  //#region ../path-utils/src/index.ts
43851
44730
  const PATH_SEPARATOR_REGEX$1 = /\./g;
43852
44731
  const BRACKET_ACCESS_REGEX$1 = /\[([^\]]+)\]/g;
44732
+ /**
44733
+ * Segments that would traverse or mutate the prototype chain.
44734
+ *
44735
+ * `setAtPath` creates nested objects along the path, so allowing these
44736
+ * segments is a prototype-pollution vector. They are rejected everywhere a
44737
+ * path is parsed (string or pre-parsed array form) — fail closed.
44738
+ */
44739
+ const UNSAFE_PATH_SEGMENTS = /* @__PURE__ */ new Set([
44740
+ "__proto__",
44741
+ "constructor",
44742
+ "prototype"
44743
+ ]);
44744
+ var UnsafePathSegmentError = class extends Error {
44745
+ constructor(segment) {
44746
+ super(`Unsafe path segment: "${segment}"`);
44747
+ this.name = "UnsafePathSegmentError";
44748
+ this.segment = segment;
44749
+ }
44750
+ };
44751
+ function assertSafePathSegments(segments) {
44752
+ for (const segment of segments) if (typeof segment === "string" && UNSAFE_PATH_SEGMENTS.has(segment)) throw new UnsafePathSegmentError(segment);
44753
+ }
43853
44754
  function isRecord$6(value) {
43854
44755
  return typeof value === "object" && value !== null && !Array.isArray(value);
43855
44756
  }
@@ -43861,7 +44762,10 @@ function getContainerValue(container, segment) {
43861
44762
  if (segment in container) return Reflect.get(container, segment);
43862
44763
  }
43863
44764
  function parsePath(path) {
43864
- if (Array.isArray(path)) return path;
44765
+ if (Array.isArray(path)) {
44766
+ assertSafePathSegments(path);
44767
+ return path;
44768
+ }
43865
44769
  const segments = [];
43866
44770
  const parts = path.split(PATH_SEPARATOR_REGEX$1);
43867
44771
  for (const raw of parts) {
@@ -43881,6 +44785,7 @@ function parsePath(path) {
43881
44785
  }
43882
44786
  if (baseMatch === null && !raw.includes("[")) segments.push(raw);
43883
44787
  }
44788
+ assertSafePathSegments(segments);
43884
44789
  return segments;
43885
44790
  }
43886
44791
  function getAtPath(source, path) {
@@ -44122,6 +45027,58 @@ function getCtaIconComponent(name) {
44122
45027
  return CTA_ICON_COMPONENTS[name] ?? null;
44123
45028
  }
44124
45029
  //#endregion
45030
+ //#region ../blocks/src/system/icons/social.tsx
45031
+ const SOCIAL_ICON_NAMES = [
45032
+ "SocialFacebook",
45033
+ "SocialInstagram",
45034
+ "SocialLinkedIn",
45035
+ "SocialTikTok",
45036
+ "SocialX",
45037
+ "SocialYouTube"
45038
+ ];
45039
+ const socialIcons = {
45040
+ SocialFacebook: createIcon("SocialFacebookIcon", /* @__PURE__ */ jsx("path", { d: "M14 8h3V4h-3c-3 0-5 2-5 5v3H6v4h3v6h4v-6h3l1-4h-4V9c0-.7.3-1 1-1Z" })),
45041
+ SocialInstagram: createIcon("SocialInstagramIcon", /* @__PURE__ */ jsxs(Fragment, { children: [
45042
+ /* @__PURE__ */ jsx("rect", {
45043
+ x: "3",
45044
+ y: "3",
45045
+ width: "18",
45046
+ height: "18",
45047
+ rx: "5"
45048
+ }),
45049
+ /* @__PURE__ */ jsx("circle", {
45050
+ cx: "12",
45051
+ cy: "12",
45052
+ r: "4"
45053
+ }),
45054
+ /* @__PURE__ */ jsx("circle", {
45055
+ cx: "17.5",
45056
+ cy: "6.5",
45057
+ r: ".75",
45058
+ fill: "currentColor",
45059
+ stroke: "none"
45060
+ })
45061
+ ] })),
45062
+ SocialLinkedIn: createIcon("SocialLinkedInIcon", /* @__PURE__ */ jsxs(Fragment, { children: [
45063
+ /* @__PURE__ */ jsx("path", { d: "M6 9v10" }),
45064
+ /* @__PURE__ */ jsx("path", {
45065
+ d: "M6 5.5v.01",
45066
+ strokeWidth: "3"
45067
+ }),
45068
+ /* @__PURE__ */ jsx("path", { d: "M10.5 19v-6a4 4 0 0 1 8 0v6" }),
45069
+ /* @__PURE__ */ jsx("path", { d: "M10.5 9v10" })
45070
+ ] })),
45071
+ SocialTikTok: createIcon("SocialTikTokIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M14 4v11.5a4.5 4.5 0 1 1-4-4.47" }), /* @__PURE__ */ jsx("path", { d: "M14 4c.7 3 2.4 4.5 5 4.5" })] })),
45072
+ SocialX: createIcon("SocialXIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "m5 4 14 16" }), /* @__PURE__ */ jsx("path", { d: "M19 4 5 20" })] })),
45073
+ SocialYouTube: createIcon("SocialYouTubeIcon", /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("path", { d: "M21 12c0 3.5-.5 5.5-1.3 6.3S16.5 19.5 12 19.5s-6.9-.4-7.7-1.2S3 15.5 3 12s.5-5.5 1.3-6.3S7.5 4.5 12 4.5s6.9.4 7.7 1.2S21 8.5 21 12Z" }), /* @__PURE__ */ jsx("path", { d: "m10 9 5 3-5 3Z" })] }))
45074
+ };
45075
+ function isSocialIconName(value) {
45076
+ return typeof value === "string" && SOCIAL_ICON_NAMES.includes(value);
45077
+ }
45078
+ function getSocialIconComponent(value) {
45079
+ return isSocialIconName(value) ? socialIcons[value] : null;
45080
+ }
45081
+ //#endregion
44125
45082
  //#region ../blocks/src/system/icons/registry.ts
44126
45083
  function buildSearchText(parts) {
44127
45084
  return parts.map((part) => part.trim()).filter(Boolean).join(" ");
@@ -44151,7 +45108,7 @@ function semanticOptionsForPreset(preset) {
44151
45108
  }
44152
45109
  semanticOptionsForPreset("feature");
44153
45110
  function getIconComponent(name) {
44154
- return getCtaIconComponent(name) ?? getSemanticIconComponent(name);
45111
+ return getCtaIconComponent(name) ?? getSemanticIconComponent(name) ?? getSocialIconComponent(name);
44155
45112
  }
44156
45113
  //#endregion
44157
45114
  //#region ../blocks/src/system/runtime/nodes/buttonAffordance.ts
@@ -44943,7 +45900,6 @@ const HeaderSectionNode = ({ blockId, children, className, "data-preview-site-ch
44943
45900
  const asProp = rest.as;
44944
45901
  const styleProp = rest.style;
44945
45902
  const backgroundProp = typeof rest.background === "string" ? rest.background : void 0;
44946
- const allowOverflowProp = typeof rest.allowOverflow === "boolean" ? rest.allowOverflow : void 0;
44947
45903
  const dataSlotProp = typeof rest["data-slot"] === "string" ? rest["data-slot"] : void 0;
44948
45904
  return /* @__PURE__ */ jsxs("nav", {
44949
45905
  ...getIslandRootProps("headerSection", blockId),
@@ -44958,7 +45914,6 @@ const HeaderSectionNode = ({ blockId, children, className, "data-preview-site-ch
44958
45914
  as: asProp,
44959
45915
  style: styleProp,
44960
45916
  background: backgroundProp ?? "background",
44961
- allowOverflow: allowOverflowProp,
44962
45917
  "data-slot": dataSlotProp,
44963
45918
  className: sectionClasses || void 0,
44964
45919
  children
@@ -47205,7 +48160,7 @@ function resolveGroupFrame(cardStyles) {
47205
48160
  contentClassName: "offerings-preview-card-content rb-flex rb-h-full rb-min-h-full rb-flex-col rb-gap-5"
47206
48161
  };
47207
48162
  return {
47208
- containerClassName: ["offerings-preview-card offerings-preview-card--framed rb-relative rb-isolate rb-h-full rb-min-h-full rb-overflow-hidden rb-bg-surface rb-border rb-border-border", resolveGroupFrameClasses(cardStyles)].filter(Boolean).join(" "),
48163
+ containerClassName: ["offerings-preview-card offerings-preview-card--framed rb-relative rb-isolate rb-h-full rb-min-h-full rb-overflow-visible rb-bg-surface rb-border rb-border-border", resolveGroupFrameClasses(cardStyles)].filter(Boolean).join(" "),
47209
48164
  containerStyle: resolveGroupFrameStyle(cardStyles),
47210
48165
  contentClassName: "card-content offerings-preview-card-content rb-flex rb-h-full rb-min-h-full rb-flex-col rb-gap-5"
47211
48166
  };
@@ -50238,9 +51193,9 @@ function isReactNode(value) {
50238
51193
  * Handles conditionals ($when), scopes ($scopes), repeaters ($repeat), bindings ($bind), and children.
50239
51194
  */
50240
51195
  function resolveNode(node, context, indexFallback) {
50241
- if (!shouldRenderNode(node, context)) return null;
50242
51196
  const scopeContext = applyScopes(node, context);
50243
51197
  if (node.$repeat) return resolveRepeater(node, scopeContext);
51198
+ if (!shouldRenderNode(node, scopeContext)) return null;
50244
51199
  const registry = scopeContext.registry ?? serverComponentRegistry;
50245
51200
  const normalizedType = node.type.toLowerCase();
50246
51201
  const component = registry[node.type] ?? registry[normalizedType] ?? (normalizedType === "section" ? SectionNode : void 0);
@@ -51613,6 +52568,19 @@ const NAV_DROPDOWN_CONTAINER_RAIL_CSS_RULES = [
51613
52568
  //#region ../theme-core/src/header/generateHeaderCss.ts
51614
52569
  const HEADER_BLUR = "blur(12px)";
51615
52570
  const FLOATING_BLUR = "blur(16px)";
52571
+ const INSET_SHELL_MARKER_CLASS = "header-bar-frame-inset-shell";
52572
+ const INSET_SHELL_EDGE = "1rem";
52573
+ const INSET_SHELL_INSET_BLOCK = "0.875rem";
52574
+ const INSET_SHELL_RADIUS = "9999px";
52575
+ const INSET_SHELL_CONTAINER_MAX = "80rem";
52576
+ const INSET_SHELL_INTERIOR_PADDING_X = "1.75rem";
52577
+ /**
52578
+ * Whether the classic header should render as an inset "brand capsule" shell.
52579
+ * The facet is only meaningful for the classic layout; other variants ignore it.
52580
+ */
52581
+ function usesInsetShell(header) {
52582
+ return header.barFrame === "inset-shell" && header.variant === "classic";
52583
+ }
51616
52584
  /**
51617
52585
  * Generate complete CSS for header system from theme config
51618
52586
  *
@@ -51712,7 +52680,36 @@ function generateHeaderRootStyles(header, themeId, tokens, _theme) {
51712
52680
  const baseBlock = `\n${selector} {\n ${rules.join("\n ")}\n}\n`;
51713
52681
  const overlayFix = `\n${`${selector}:has([data-nav-mobile-overlay][aria-hidden="false"])`} {\n backdrop-filter: none !important;\n -webkit-backdrop-filter: none !important;\n}\n`;
51714
52682
  if (isContainedNav || backgroundRules.length === 0) return `${baseBlock}\n${overlayFix}`;
51715
- return `${baseBlock}\n${`\n${backgroundSelector} {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n border-radius: inherit;\n z-index: -1;\n ${backgroundRules.join("\n ")}\n}\n`}\n${overlayFix}`;
52683
+ return `${baseBlock}\n${`\n${backgroundSelector} {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n border-radius: inherit;\n z-index: -1;\n ${backgroundRules.join("\n ")}\n}\n`}\n${overlayFix}${usesInsetShell(header) ? generateInsetShellStyles(header, themeId) : ""}`;
52684
+ }
52685
+ /**
52686
+ * Reshapes the full-bleed header paint layer into a contained brand capsule at
52687
+ * the desktop breakpoint. The capsule is centred, capped to the page container
52688
+ * width, inset from the top, fully rounded, and carries the header depth so it
52689
+ * reads as a floating pill. Root border/shadow are neutralised on desktop so a
52690
+ * bordered style does not leave a full-width hairline around the capsule. Sticky
52691
+ * positioning is unaffected — the root stays full width and sticky while the
52692
+ * ::before paint provides the capsule.
52693
+ */
52694
+ function generateInsetShellStyles(header, themeId) {
52695
+ const scope = `:where([data-theme-scope="${themeId}"])`;
52696
+ const shellRootSelector = `${scope} .header-root.${INSET_SHELL_MARKER_CLASS}`;
52697
+ const shellBeforeSelector = `${scope} .header-root.${INSET_SHELL_MARKER_CLASS}::before`;
52698
+ const layoutSelector = `${scope} .header-root.${INSET_SHELL_MARKER_CLASS} .rb-header-layout`;
52699
+ const widthValue = header.maxWidth === "full" ? `calc(100% - (${INSET_SHELL_EDGE} * 2))` : `min(${INSET_SHELL_CONTAINER_MAX}, calc(100% - (${INSET_SHELL_EDGE} * 2)))`;
52700
+ const shadowVar = getComponentShadowVar(header.shadow?.elevation ?? "none");
52701
+ const rootRules = ["border: none;", "box-shadow: none;"];
52702
+ const beforeRules = [
52703
+ `inset: ${INSET_SHELL_INSET_BLOCK} auto;`,
52704
+ "left: 50%;",
52705
+ "right: auto;",
52706
+ "transform: translateX(-50%);",
52707
+ `width: ${widthValue};`,
52708
+ `border-radius: ${INSET_SHELL_RADIUS};`,
52709
+ ...shadowVar ? [`box-shadow: ${shadowVar};`] : []
52710
+ ];
52711
+ const layoutRules = [`padding-inline: ${INSET_SHELL_INTERIOR_PADDING_X};`];
52712
+ return `\n@media ${MQ_MD_UP} {\n${shellRootSelector} {\n ${rootRules.join("\n ")}\n}\n${shellBeforeSelector} {\n ${beforeRules.join("\n ")}\n}\n${layoutSelector} {\n ${layoutRules.join("\n ")}\n}\n}\n`;
51716
52713
  }
51717
52714
  /**
51718
52715
  * Generate logo typography styles
@@ -51790,7 +52787,7 @@ function generateLogoTextBehaviorStyles(logoText, themeId) {
51790
52787
  */
51791
52788
  function generateNavLinkStyles(header, themeId, tokens, theme, contrastTreatment, navTextSize) {
51792
52789
  const navPreferences = {
51793
- typography: header.navTypography ?? "inherit",
52790
+ typography: header.navFontRole ?? header.navTypography ?? "inherit",
51794
52791
  fontSize: readHeaderNavFontSizePreference(header.navTextSize)
51795
52792
  };
51796
52793
  if (header.navLinkStyle) return generateNavLinkCSS({
@@ -53975,6 +54972,8 @@ function buildThemeCssVars(theme) {
53975
54972
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
53976
54973
  return {
53977
54974
  ...generateCssVars(theme.palette),
54975
+ ["--tb-secondaryForeground"]: "var(--tb-onSecondary)",
54976
+ ["--tb-accentForeground"]: "var(--tb-onAccent)",
53978
54977
  ["--tb-scrim"]: "0 0 0",
53979
54978
  ["--tb-shadow"]: "0 0 0",
53980
54979
  ...generateShadowCssVars(theme),
@@ -56140,6 +57139,12 @@ const containerResponsiveThemeCss = `/*
56140
57139
  .rb-lg-hidden {
56141
57140
  display: none;
56142
57141
  }
57142
+ .rb-lg-flex-row {
57143
+ flex-direction: row;
57144
+ }
57145
+ .rb-lg-items-center {
57146
+ align-items: center;
57147
+ }
56143
57148
  }
56144
57149
 
56145
57150
  }
@@ -62649,6 +63654,11 @@ const containerResponsiveThemeCss = `/*
62649
63654
  flex-wrap: wrap;
62650
63655
  }
62651
63656
 
63657
+ /* Text-style CTA actions belong to the section foreground contract. */
63658
+ :where(.theme-scope) [data-block="cta-full"] .cta-row .button-link {
63659
+ color: var(--rb-surface-link-color, var(--rb-surface-text-color, rgb(var(--tb-primary))));
63660
+ }
63661
+
62652
63662
  /* =============================================================================
62653
63663
  * Block: Body Text (content block, Phase 2)
62654
63664
  *
@@ -67576,7 +68586,7 @@ const containerResponsiveThemeCss = `/*
67576
68586
  [data-block="feature-cards"][data-block-composition="asymmetric-emphasis"]
67577
68587
  .rb-feature-card {
67578
68588
  height: auto;
67579
- overflow: hidden;
68589
+ overflow: visible;
67580
68590
  border: 0;
67581
68591
  border-radius: 0;
67582
68592
  background: transparent;
@@ -68607,19 +69617,9 @@ function getPrimaryNavigation(navigation) {
68607
69617
  return a.id.localeCompare(b.id);
68608
69618
  })[0] ?? null;
68609
69619
  }
68610
- /**
68611
- * Get the footer navigation menu object.
68612
- * Returns menu marked as isFooter, or null if none marked.
68613
- *
68614
- * @example
68615
- * ```ts
68616
- * const menu = getFooterNavigation(siteData.navigation);
68617
- * console.log(menu?.name); // "Footer menu"
68618
- * ```
68619
- */
68620
- function getFooterNavigation(navigation) {
69620
+ function getFooterNavigationByRole(navigation, role) {
68621
69621
  if (!navigation || navigation.length === 0) return null;
68622
- const footerMenus = navigation.filter((menu) => menu.isFooter);
69622
+ const footerMenus = navigation.filter((menu) => menu.footerRole === role || role === "main" && menu.footerRole == null && menu.isFooter);
68623
69623
  if (footerMenus.length > 1) console.warn(`[riverbank/sdk] Multiple footer navigation menus detected (${footerMenus.length}); using first flagged menu by input order.`);
68624
69624
  return footerMenus[0] ?? null;
68625
69625
  }
@@ -68832,7 +69832,10 @@ function buildMenu(navigation, routes, options) {
68832
69832
  * ```
68833
69833
  */
68834
69834
  function buildFooterMenu(navigation, routes, options) {
68835
- const menu = getFooterNavigation(navigation);
69835
+ return buildFooterMenuForRole(navigation, routes, "main", options);
69836
+ }
69837
+ function buildFooterMenuForRole(navigation, routes, role, options) {
69838
+ const menu = getFooterNavigationByRole(navigation, role);
68836
69839
  if (!menu) return {
68837
69840
  items: [],
68838
69841
  ctaItem: null,
@@ -68999,6 +70002,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
68999
70002
  };
69000
70003
  const menuViewModel = buildMenu(navigation, routes, navigationOptions);
69001
70004
  const footerMenuViewModel = buildFooterMenu(navigation, routes, navigationOptions);
70005
+ const legalFooterMenuViewModel = buildFooterMenuForRole(navigation, routes, "legal-policy", navigationOptions);
69002
70006
  const logoViewModel = buildLogo(layout.logo ?? null, site.title);
69003
70007
  const headerData = {
69004
70008
  menu: menuViewModel,
@@ -69010,6 +70014,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69010
70014
  const footerData = {
69011
70015
  menu: menuViewModel,
69012
70016
  footerMenu: footerMenuViewModel,
70017
+ legalFooterMenu: legalFooterMenuViewModel,
69013
70018
  logo: logoViewModel,
69014
70019
  site,
69015
70020
  theme,
@@ -69045,6 +70050,7 @@ async function Layout({ siteData: providedSiteData, client, siteId, slug, domain
69045
70050
  site,
69046
70051
  menu: menuViewModel,
69047
70052
  footerMenu: footerMenuViewModel,
70053
+ legalFooterMenu: legalFooterMenuViewModel,
69048
70054
  content: { logo: logoViewModel }
69049
70055
  };
69050
70056
  let headerElement = null;
@@ -69471,8 +70477,6 @@ function normalizeLoaderParams(endpoint, params, context) {
69471
70477
  ensureSiteId(out, context);
69472
70478
  return out;
69473
70479
  }
69474
- //#endregion
69475
- //#region ../api/src/apiEndpointTypes.ts
69476
70480
  function blockedDemoMutationPolicy(classification, publicMessage) {
69477
70481
  if (publicMessage.trim() === "") throw new Error(`Demo mutation policy ${classification} requires publicMessage.`);
69478
70482
  return {
@@ -69500,6 +70504,7 @@ const TAG_TEMPLATES = {
69500
70504
  siteRouteOutcomes: "riverbank:site:{siteId}:route-outcomes",
69501
70505
  routeById: "riverbank:route:{routeId}",
69502
70506
  pageById: "riverbank:page:{pageId}",
70507
+ pageSurfaceById: "riverbank:page-surface:{pageSurfaceId}",
69503
70508
  workflowRunById: "riverbank:workflow-run:{runId}",
69504
70509
  siteForms: "riverbank:site:{siteId}:forms",
69505
70510
  formById: "riverbank:form:{formId}",
@@ -69523,7 +70528,7 @@ const TAG_TEMPLATES = {
69523
70528
  blockedDemoMutationPolicy("blocked-hidden", "This action is not available in demo sites.");
69524
70529
  blockedDemoMutationPolicy("blocked-disabled", "This setting is disabled in demo sites.");
69525
70530
  blockedDemoMutationPolicy("internal-only", "This internal operation is not available in demo sites.");
69526
- TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.formById, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicTeamMembers, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicPasses, TAG_TEMPLATES.publicMemberships, TAG_TEMPLATES.publicProducts, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents;
70531
+ TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteBookingSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteById, TAG_TEMPLATES.siteBySlug, TAG_TEMPLATES.siteByDomain, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.workflowRunById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.routeById, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.site, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.site, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.navigationItemById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteNavigation, TAG_TEMPLATES.navigationMenuById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteSettings, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.siteTheme, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteCollection, TAG_TEMPLATES.pageSurfaceById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.pageById, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteRedirects, TAG_TEMPLATES.siteRouteOutcomes, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.formSubmissionsBySlug, TAG_TEMPLATES.formById, TAG_TEMPLATES.siteForms, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEventFilters, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicTeamMembers, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicCourses, TAG_TEMPLATES.publicPasses, TAG_TEMPLATES.publicMemberships, TAG_TEMPLATES.publicProducts, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicGifting, TAG_TEMPLATES.publicShop, TAG_TEMPLATES.publicCheckout, TAG_TEMPLATES.siteRoutableContent, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents, TAG_TEMPLATES.publicEvents;
69527
70532
  z$1.object({
69528
70533
  formulaVersion: z$1.literal("managed-domain-overage-v1"),
69529
70534
  conversionRule: z$1.literal("usd-to-gbp-1-to-1-v1"),
@@ -69893,6 +70898,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
69893
70898
  "already_refunded",
69894
70899
  "idempotency_amount_mismatch",
69895
70900
  "idempotency_method_mismatch",
70901
+ "idempotency_receipt_mismatch",
69896
70902
  "refund_in_progress"
69897
70903
  ],
69898
70904
  "invalid_amount",
@@ -69905,7 +70911,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
69905
70911
  "payment_intent_not_found",
69906
70912
  "stripe_error",
69907
70913
  "stale_pending_missing_context",
69908
- "non_refundable_deposit_remaining"
70914
+ "non_refundable_deposit_remaining",
70915
+ "deposit_refund_override_required",
70916
+ "refund_revoke_requires_full_line_refund",
70917
+ "payment_receipt_not_found",
70918
+ "payment_receipt_not_refundable",
70919
+ "payment_receipt_attribution_required"
69909
70920
  ];
69910
70921
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
69911
70922
  //#endregion
@@ -69918,7 +70929,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
69918
70929
  "missing_credit_customer",
69919
70930
  "deposit_refund_override_required",
69920
70931
  "refund_revoke_requires_full_line_refund",
69921
- "unified_order_link_required"
70932
+ "unified_order_link_required",
70933
+ "payment_receipt_not_found",
70934
+ "payment_receipt_not_refundable",
70935
+ "payment_receipt_attribution_required"
69922
70936
  ];
69923
70937
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
69924
70938
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];