@riverbankcms/sdk 0.108.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 (189) hide show
  1. package/README.md +21 -1
  2. package/dist/{PreviewEditorSidebar-BBT-kZAM.mjs → PreviewEditorSidebar-DWqwfy3_.mjs} +7 -22
  3. package/dist/{PreviewEditorUI-D69xNKT2.mjs → PreviewEditorUI-B7OL4sfR.mjs} +3 -3
  4. package/dist/{PreviewQueryProvider-RRu7wyQ5.mjs → PreviewQueryProvider-D0y2l8JN.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CuDjXH6o.mjs → SdkPreviewModeRuntime-D8Gt9Gbe.mjs} +212 -153
  6. package/dist/{SiteChromeCustomizeContext-BQUY2dEk.mjs → SiteChromeCustomizeContext-DUpalEdL.mjs} +1919 -1032
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +11244 -10741
  8. package/dist/_dts/api/src/bookingAdjustments.d.ts +5 -0
  9. package/dist/_dts/api/src/bookingOperations.d.ts +4 -0
  10. package/dist/_dts/api/src/bookingRecords.d.ts +2 -17
  11. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  12. package/dist/_dts/api/src/common/envelope.d.ts +7 -0
  13. package/dist/_dts/api/src/courses.d.ts +1 -0
  14. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +5 -5
  15. package/dist/_dts/api/src/endpoints.d.ts +35 -0
  16. package/dist/_dts/api/src/index.d.ts +2 -2
  17. package/dist/_dts/api/src/participantMessaging.d.ts +18 -12
  18. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +1 -0
  19. package/dist/_dts/api/src/sdkContracts.d.ts +247 -1
  20. package/dist/_dts/api/src/siteInfrastructure.d.ts +13 -0
  21. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +1 -5
  22. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +29 -1
  23. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +33 -27
  24. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientField.d.ts +9 -0
  25. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientWidget.d.ts +3 -4
  26. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  27. package/dist/_dts/blocks/src/index.d.ts +1 -1
  28. package/dist/_dts/blocks/src/system/blocks/audio-player.d.ts +3 -0
  29. package/dist/_dts/blocks/src/system/blocks/body-text.d.ts +3 -0
  30. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +3 -0
  31. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +1 -22
  32. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +3 -0
  33. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +1 -22
  34. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +3 -0
  35. package/dist/_dts/blocks/src/system/blocks/form.d.ts +3 -0
  36. package/dist/_dts/blocks/src/system/blocks/image-gallery.d.ts +3 -0
  37. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +3 -0
  38. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +3 -0
  39. package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +3 -0
  40. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  41. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +3 -0
  42. package/dist/_dts/blocks/src/system/blocks/video-grid.d.ts +3 -0
  43. package/dist/_dts/blocks/src/system/constants/background.d.ts +1 -1
  44. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +16 -6
  45. package/dist/_dts/blocks/src/system/defineBlock.d.ts +9 -1
  46. package/dist/_dts/blocks/src/system/fields/ctas.d.ts +8 -0
  47. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +31 -0
  48. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +6 -6
  49. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  50. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +1 -1
  51. package/dist/_dts/content-model/src/content-types/entryValidation.d.ts +31 -0
  52. package/dist/_dts/content-model/src/content-types/scaffold.d.ts +58 -0
  53. package/dist/_dts/content-model/src/content-types/sentinels.d.ts +36 -0
  54. package/dist/_dts/content-model/src/index.d.ts +3 -0
  55. package/dist/_dts/core/src/booking-date-time.d.ts +8 -0
  56. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3071 -3157
  57. package/dist/_dts/media-core/src/fileMimeDetection.d.ts +16 -0
  58. package/dist/_dts/media-core/src/fileStorage.d.ts +8 -0
  59. package/dist/_dts/media-core/src/storagePathDomain.d.ts +2 -0
  60. package/dist/_dts/media-core/src/uploadVerificationContract.d.ts +3 -0
  61. package/dist/_dts/preview-next/src/client/blocks/BlockToolbar.d.ts +2 -0
  62. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +1 -0
  63. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -1
  64. package/dist/_dts/sdk/src/cli/commands/audit.d.ts +1 -1
  65. package/dist/_dts/sdk/src/cli/commands/compare.d.ts +1 -1
  66. package/dist/_dts/sdk/src/cli/commands/deploy.d.ts +1 -1
  67. package/dist/_dts/sdk/src/cli/commands/drafts.d.ts +18 -0
  68. package/dist/_dts/sdk/src/cli/commands/entry.d.ts +15 -0
  69. package/dist/_dts/sdk/src/cli/commands/init-docs.d.ts +2 -2
  70. package/dist/_dts/sdk/src/cli/commands/publish-all.d.ts +1 -1
  71. package/dist/_dts/sdk/src/cli/commands/pull.d.ts +1 -0
  72. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +1 -1
  73. package/dist/_dts/sdk/src/cli/commands/push/options.d.ts +3 -0
  74. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +12 -1
  75. package/dist/_dts/sdk/src/cli/commands/setup.d.ts +1 -0
  76. package/dist/_dts/sdk/src/cli/commands/verify.d.ts +1 -0
  77. package/dist/_dts/sdk/src/cli/helpers.d.ts +22 -1
  78. package/dist/_dts/sdk/src/cli/index.d.ts +4 -0
  79. package/dist/_dts/sdk/src/cli/output.d.ts +88 -0
  80. package/dist/_dts/sdk/src/cli/program.d.ts +29 -0
  81. package/dist/_dts/sdk/src/cli/push-config.d.ts +1 -1
  82. package/dist/_dts/sdk/src/client/management/catalog.d.ts +10 -0
  83. package/dist/_dts/sdk/src/client/management/http.d.ts +7 -1
  84. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  85. package/dist/_dts/sdk/src/client/management/types.d.ts +43 -19
  86. package/dist/_dts/sdk/src/date-time/index.d.ts +68 -0
  87. package/dist/_dts/sdk/src/public-api/contracts.d.ts +2 -0
  88. package/dist/_dts/sdk/src/version.d.ts +1 -1
  89. package/dist/_dts/site-commands/src/commands.d.ts +893 -823
  90. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
  91. package/dist/_dts/theme-core/src/buttons/core.d.ts +15 -46
  92. package/dist/_dts/theme-core/src/buttons/effectClassification.d.ts +147 -0
  93. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +2 -3
  94. package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +1 -1
  95. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -0
  96. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +44 -32
  97. package/dist/_dts/theme-core/src/buttons/presets.d.ts +4 -25
  98. package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +100 -0
  99. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +16 -0
  100. package/dist/_dts/theme-core/src/buttons/types.d.ts +101 -83
  101. package/dist/_dts/theme-core/src/cards/types.d.ts +16 -16
  102. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  103. package/dist/_dts/theme-core/src/gradients/presets.d.ts +200 -8
  104. package/dist/_dts/theme-core/src/gradients/utils.d.ts +6 -2
  105. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +87 -126
  106. package/dist/_dts/theme-core/src/mock-themes/modern-minimal.d.ts +1 -1
  107. package/dist/_dts/theme-core/src/navigation/types.d.ts +2 -2
  108. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +2 -2
  109. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +5 -8
  110. package/dist/_dts/theme-core/src/palette/index.d.ts +0 -1
  111. package/dist/_dts/theme-core/src/schema.d.ts +112 -138
  112. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  113. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +10 -10
  114. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +3 -2
  115. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +13 -6
  116. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +29 -8
  117. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +2 -2
  118. package/dist/cli/index.mjs +67956 -66745
  119. package/dist/cli/init-docs/content/cli-reference.md +50 -7
  120. package/dist/cli/init-docs/content/content-management.md +7 -4
  121. package/dist/cli/init-docs/content/workflow-publish.md +5 -1
  122. package/dist/client/{DiscountCodeDisclosure-D6TOf6Hi.mjs → DiscountCodeDisclosure-DU1ygxU2.mjs} +1 -1
  123. package/dist/client/{EventCombined.client-Dao3zxRk.mjs → EventCombined.client-DB5zagCo.mjs} +3 -3
  124. package/dist/client/{EventListing.client-B2NNt4y1.mjs → EventListing.client-CTX9JHBL.mjs} +2 -2
  125. package/dist/client/{LeafletStaticMap-BhwFo16w.mjs → LeafletStaticMap-BYImhgiB.mjs} +1 -1
  126. package/dist/client/{MagicLinkForm-BWnB7cMR.mjs → MagicLinkForm-CRkw_M3l.mjs} +2 -2
  127. package/dist/client/{StepIndicator-TzRiQ0BY.mjs → StepIndicator-BnmVBJJh.mjs} +2 -2
  128. package/dist/client/{accordion-BPy-AJ4_.mjs → accordion-CeGreumd.mjs} +1 -1
  129. package/dist/client/{bookingForm-BL4PGZds.mjs → bookingForm-CSzFNrpN.mjs} +6 -6
  130. package/dist/client/bookings.mjs +512 -252
  131. package/dist/client/{buttons-EBjyslaX.mjs → buttons-DoFV7KDL.mjs} +493 -230
  132. package/dist/client/{carousel-C2b7Cn9-.mjs → carousel-B2jDtogf.mjs} +1 -1
  133. package/dist/client/{cart-BQcbXIVD.mjs → cart-D-jZ-vaY.mjs} +3 -3
  134. package/dist/client/{checkout-DEmpGRJu.mjs → checkout-Dza-LA7N.mjs} +3 -3
  135. package/dist/client/client.mjs +1673 -785
  136. package/dist/client/{colorStyles-jZS6KfkP.mjs → colorStyles-CrgzoXsm.mjs} +1 -30
  137. package/dist/client/{courseRegistration-BqRZPmsq.mjs → courseRegistration-TYkNychb.mjs} +7 -7
  138. package/dist/client/{eventCalendar-B8N_tSl5.mjs → eventCalendar-BI_90SsT.mjs} +5 -5
  139. package/dist/client/{eventCombined-Gjn6gtq7.mjs → eventCombined-mNrpryE9.mjs} +2 -2
  140. package/dist/client/{eventDetails-M-VCxA-r.mjs → eventDetails-D4GVlCIY.mjs} +3 -3
  141. package/dist/client/{eventListing-DR19hqYi.mjs → eventListing-YhKN018y.mjs} +2 -2
  142. package/dist/client/{eventRegistration-BR02a0k3.mjs → eventRegistration-CdHGtilr.mjs} +7 -7
  143. package/dist/client/foregroundContract-xICPq59x.mjs +31 -0
  144. package/dist/client/{form-LY2xIbwg.mjs → form-AcAL45rA.mjs} +2 -2
  145. package/dist/client/{headerSection-CYwwXJfh.mjs → headerSection-uEC52ueD.mjs} +3 -3
  146. package/dist/client/hooks.mjs +890 -497
  147. package/dist/client/{locationMap-DWnBXrFq.mjs → locationMap-_wJDSUYe.mjs} +3 -3
  148. package/dist/client/{media-DHtSxS5V.mjs → media-BK0O3b-U.mjs} +3 -2
  149. package/dist/client/{newsletterForm-D9s-fQ2P.mjs → newsletterForm-DrArsb2B.mjs} +2 -2
  150. package/dist/client/{pricing-DDq80oYc.mjs → pricing-BSYVghwo.mjs} +1 -1
  151. package/dist/client/{productDetail-B0SbWd45.mjs → productDetail-Dyk90sMs.mjs} +3 -3
  152. package/dist/client/{productList-PwYlZn0y.mjs → productList-BCKThwAI.mjs} +3 -3
  153. package/dist/client/{propsDecoder-BRWBiH7i.mjs → propsDecoder-CkXxkdSR.mjs} +63 -24
  154. package/dist/client/rendering/client.mjs +1034 -486
  155. package/dist/client/rendering/islands.mjs +19 -19
  156. package/dist/client/rendering.mjs +1832 -760
  157. package/dist/client/{shop-CMwZPYME.mjs → shop-DeltVH10.mjs} +6 -6
  158. package/dist/client/{shop-commerce-BuxsFate.mjs → shop-commerce-BD9Jsm2Z.mjs} +6 -6
  159. package/dist/client/{shop-commerce-store-boYlEJ91.mjs → shop-commerce-store-CmXD6FDS.mjs} +1 -1
  160. package/dist/client/{shopShared-D2naaOes.mjs → shopShared-B8v-lH_F.mjs} +2 -2
  161. package/dist/client/{useDiscountCodeUi-D9RHpVoj.mjs → useDiscountCodeUi-DbWJN8ld.mjs} +1 -1
  162. package/dist/client/{useEventFilters-igGiK1re.mjs → useEventFilters-EJIMUnqT.mjs} +46 -69
  163. package/dist/client/{usePolling-CI7MbsFB.mjs → usePolling-Cmh14fc7.mjs} +2 -2
  164. package/dist/preview-next/before-render.mjs +35 -0
  165. package/dist/preview-next/client/runtime.mjs +4 -4
  166. package/dist/preview-next/middleware.mjs +35 -0
  167. package/dist/{previewAuthStore-a_cBD28m.mjs → previewAuthStore-CTO7CRPk.mjs} +35 -0
  168. package/dist/{sdk-runtime-MBzD-GmP.mjs → sdk-runtime-Dou0GAav.mjs} +2 -2
  169. package/dist/{separator-5ahRBC85.mjs → separator-CI5wZNXT.mjs} +1 -1
  170. package/dist/server/components.mjs +1832 -784
  171. package/dist/server/config-validation.mjs +890 -497
  172. package/dist/server/config.mjs +890 -497
  173. package/dist/server/data.mjs +890 -497
  174. package/dist/server/date-time.mjs +386 -0
  175. package/dist/server/index.mjs +36 -1
  176. package/dist/server/next.mjs +1868 -785
  177. package/dist/server/page-converter.mjs +849 -285
  178. package/dist/server/prebuild.mjs +1 -1
  179. package/dist/server/rendering/server.mjs +1553 -718
  180. package/dist/server/rendering.mjs +1832 -784
  181. package/dist/server/routing.mjs +933 -522
  182. package/dist/server/server.mjs +929 -501
  183. package/dist/server/theme-bridge.mjs +1408 -392
  184. package/dist/server/theme.mjs +471 -228
  185. package/dist/styles/index.css +5 -0
  186. package/package.json +7 -1
  187. package/dist/_dts/theme-core/src/buttons/presets/types.d.ts +0 -88
  188. package/dist/_dts/theme-core/src/buttons/utils/contrast.d.ts +0 -38
  189. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +0 -57
@@ -521,18 +521,25 @@ var init_booking_instalments = __esmMin((() => {}));
521
521
  //#endregion
522
522
  //#region ../core/src/booking-date-time.ts
523
523
  function isValidTimeZone$1(timeZone) {
524
+ const cached = timeZoneValidityCache.get(timeZone);
525
+ if (cached !== void 0) return cached;
526
+ let isValid;
524
527
  try {
525
528
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
526
- return true;
529
+ isValid = true;
527
530
  } catch {
528
- return false;
531
+ isValid = false;
529
532
  }
533
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
534
+ timeZoneValidityCache.set(timeZone, isValid);
535
+ return isValid;
530
536
  }
531
537
  function getSafeTimeZone(timeZone) {
532
538
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
533
539
  return normalized.length > 0 && isValidTimeZone$1(normalized) ? normalized : FALLBACK_TIMEZONE;
534
540
  }
535
541
  function parseStrictBookingTimeZone(timeZone) {
542
+ if (typeof timeZone !== "string") return null;
536
543
  const normalized = timeZone.trim();
537
544
  if (normalized.length === 0 || !isValidTimeZone$1(normalized)) return null;
538
545
  return normalized;
@@ -545,10 +552,19 @@ function formatParseError(error) {
545
552
  }
546
553
  }
547
554
  function formatToPartsLookup(date, locale, timeZone, format) {
548
- return new Map(new Intl.DateTimeFormat(locale, {
555
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
556
+ }
557
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
558
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
559
+ const cached = dateTimeFormatterCache.get(key);
560
+ if (cached !== void 0) return cached;
561
+ const formatter = new Intl.DateTimeFormat(locale, {
549
562
  ...format,
550
563
  timeZone
551
- }).formatToParts(date).map((part) => [part.type, part.value]));
564
+ });
565
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
566
+ dateTimeFormatterCache.set(key, formatter);
567
+ return formatter;
552
568
  }
553
569
  function getZonedDateTimeParts(date, timeZone) {
554
570
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -601,23 +617,9 @@ function toUtcIsoDateTimeString(value) {
601
617
  return parsed.value;
602
618
  }
603
619
  function parseScheduledBookingDateTime(input) {
620
+ let startsAt;
604
621
  try {
605
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
606
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
607
- if (timeZone === null) return {
608
- ok: false,
609
- field: "timeZone",
610
- reason: "invalid_time_zone",
611
- value: input.timeZone
612
- };
613
- return {
614
- ok: true,
615
- value: {
616
- startsAt,
617
- timeZone,
618
- locale: input.locale
619
- }
620
- };
622
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
621
623
  } catch {
622
624
  return {
623
625
  ok: false,
@@ -626,6 +628,21 @@ function parseScheduledBookingDateTime(input) {
626
628
  value: input.startsAt
627
629
  };
628
630
  }
631
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
632
+ if (timeZone === null) return {
633
+ ok: false,
634
+ field: "timeZone",
635
+ reason: "invalid_time_zone",
636
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
637
+ };
638
+ return {
639
+ ok: true,
640
+ value: {
641
+ startsAt,
642
+ timeZone,
643
+ locale: input.locale
644
+ }
645
+ };
629
646
  }
630
647
  function parseScheduledBookingDateRange(input) {
631
648
  const start = parseScheduledBookingDateTime(input);
@@ -664,10 +681,7 @@ function toScheduledBookingDateRange(input) {
664
681
  function formatBookingInstant(isoString, options) {
665
682
  const date = new Date(isoString);
666
683
  if (Number.isNaN(date.getTime())) return isoString;
667
- return new Intl.DateTimeFormat(options.locale ?? DEFAULT_LOCALE, {
668
- ...options.format,
669
- timeZone: getSafeTimeZone(options.timeZone)
670
- }).format(date);
684
+ return getCachedDateTimeFormatter(options.locale ?? DEFAULT_LOCALE, getSafeTimeZone(options.timeZone), options.format).format(date);
671
685
  }
672
686
  function formatBookingDate(input, format = {
673
687
  weekday: "long",
@@ -755,7 +769,7 @@ function addLocalScheduleDays(date, days) {
755
769
  day: utcDate.getUTCDate()
756
770
  };
757
771
  }
758
- var DEFAULT_LOCALE, FALLBACK_TIMEZONE, DEFAULT_BOOKING_DATE_TIME_FORMAT, LOCAL_DATE_PATTERN;
772
+ var DEFAULT_LOCALE, FALLBACK_TIMEZONE, DEFAULT_BOOKING_DATE_TIME_FORMAT, LOCAL_DATE_PATTERN, DATE_TIME_FORMATTER_CACHE_LIMIT, dateTimeFormatterCache, timeZoneValidityCache;
759
773
  var init_booking_date_time = __esmMin((() => {
760
774
  init_result();
761
775
  DEFAULT_LOCALE = "en-US";
@@ -768,6 +782,9 @@ var init_booking_date_time = __esmMin((() => {
768
782
  minute: "2-digit"
769
783
  };
770
784
  LOCAL_DATE_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/u;
785
+ DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
786
+ dateTimeFormatterCache = /* @__PURE__ */ new Map();
787
+ timeZoneValidityCache = /* @__PURE__ */ new Map();
771
788
  })), init_dated_offering_settlement = __esmMin((() => {
772
789
  init_result();
773
790
  }));
@@ -1061,7 +1078,8 @@ function validateRelativeStoragePath(value) {
1061
1078
  if (value.startsWith("sites/")) return fail({ tag: "SITE_SCOPED_PATH" });
1062
1079
  if (value.startsWith("/")) return fail({ tag: "LEADING_SLASH" });
1063
1080
  if (value.includes("//")) return fail({ tag: "DOUBLE_SLASH" });
1064
- if (value.split("/").some((segment) => segment === "..")) return fail({ tag: "TRAVERSAL" });
1081
+ if (value.includes("%")) return fail({ tag: "PERCENT_ENCODING" });
1082
+ if (value.split("/").some((segment) => segment === "." || segment === "..")) return fail({ tag: "TRAVERSAL" });
1065
1083
  return ok$2(value);
1066
1084
  }
1067
1085
  function brandRelativeStoragePath(value) {
@@ -3658,7 +3676,7 @@ function createTransformRegistry(definitions) {
3658
3676
  var init_core$2 = __esmMin((() => {}));
3659
3677
  //#endregion
3660
3678
  //#region ../theme-core/src/palette/utils/colorConversion.ts
3661
- function hexToRgb$2(hex) {
3679
+ function hexToRgb$1(hex) {
3662
3680
  const h = hex.replace(/^#/, "");
3663
3681
  const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
3664
3682
  if (m.length !== 6) throw new Error("Bad hex");
@@ -3768,7 +3786,7 @@ function oklchToHexGamut(L, C, h) {
3768
3786
  return rgbToHex$1(r, g, bb);
3769
3787
  }
3770
3788
  function featuresFromHex(hex) {
3771
- const { r, g, b } = hexToRgb$2(hex);
3789
+ const { r, g, b } = hexToRgb$1(hex);
3772
3790
  const { h, s, l } = rgbToHsl$1(r, g, b);
3773
3791
  const { L, a, b: b2 } = srgbToOklab(r, g, b);
3774
3792
  const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
@@ -3801,14 +3819,14 @@ function relativeLuminance(r, g, b) {
3801
3819
  return .2126 * R + .7152 * G + .0722 * B;
3802
3820
  }
3803
3821
  function contrastRatio(hex1, hex2) {
3804
- const { r: r1, g: g1, b: b1 } = hexToRgb$2(hex1);
3805
- const { r: r2, g: g2, b: b2 } = hexToRgb$2(hex2);
3822
+ const { r: r1, g: g1, b: b1 } = hexToRgb$1(hex1);
3823
+ const { r: r2, g: g2, b: b2 } = hexToRgb$1(hex2);
3806
3824
  const L1 = relativeLuminance(r1, g1, b1);
3807
3825
  const L2 = relativeLuminance(r2, g2, b2);
3808
3826
  const [hi, lo] = L1 >= L2 ? [L1, L2] : [L2, L1];
3809
3827
  return (hi + .05) / (lo + .05);
3810
3828
  }
3811
- var init_contrast$2 = __esmMin((() => {
3829
+ var init_contrast$1 = __esmMin((() => {
3812
3830
  init_colorConversion();
3813
3831
  }));
3814
3832
  //#endregion
@@ -3864,7 +3882,7 @@ function asAccessibleSurfaceToken(token) {
3864
3882
  }
3865
3883
  var ON_BACKGROUND;
3866
3884
  var init_accessibleSurfaces = __esmMin((() => {
3867
- init_contrast$2();
3885
+ init_contrast$1();
3868
3886
  init_onColor();
3869
3887
  }));
3870
3888
  //#endregion
@@ -4869,6 +4887,10 @@ var init_modern_minimal = __esmMin((() => {
4869
4887
  name: "primary",
4870
4888
  hex: "#1f2937"
4871
4889
  },
4890
+ {
4891
+ name: "primaryForeground",
4892
+ hex: "#ffffff"
4893
+ },
4872
4894
  {
4873
4895
  name: "secondary",
4874
4896
  hex: "#6b7280"
@@ -4897,6 +4919,14 @@ var init_modern_minimal = __esmMin((() => {
4897
4919
  name: "surface",
4898
4920
  hex: "#ffffff"
4899
4921
  },
4922
+ {
4923
+ name: "surfaceAlt",
4924
+ hex: "#f9fafb"
4925
+ },
4926
+ {
4927
+ name: "muted",
4928
+ hex: "#f3f4f6"
4929
+ },
4900
4930
  {
4901
4931
  name: "text",
4902
4932
  hex: "#1f2937"
@@ -5007,7 +5037,7 @@ function generateCssVars(palette) {
5007
5037
  const cssVars = {};
5008
5038
  Object.entries(palette).forEach(([key, value]) => {
5009
5039
  if (key === "meta" || value === null || value === void 0 || typeof value !== "string") return;
5010
- const { r, g, b } = hexToRgb$2(value);
5040
+ const { r, g, b } = hexToRgb$1(value);
5011
5041
  cssVars[`--tb-${key}`] = `${r} ${g} ${b}`;
5012
5042
  });
5013
5043
  return cssVars;
@@ -5054,48 +5084,48 @@ var init_neutralScale = __esmMin((() => {
5054
5084
  }));
5055
5085
  var init_colorPlacement = __esmMin((() => {
5056
5086
  init_colorConversion();
5057
- init_contrast$2();
5087
+ init_contrast$1();
5058
5088
  }));
5059
5089
  var init_backgroundGeneration = __esmMin((() => {
5060
5090
  init_colorConversion();
5061
5091
  }));
5062
5092
  var init_analogous_harmony = __esmMin((() => {
5063
- init_utils$5();
5093
+ init_utils$6();
5064
5094
  init_colorConversion();
5065
5095
  }));
5066
5096
  var init_complementary_contrast = __esmMin((() => {
5067
- init_utils$5();
5097
+ init_utils$6();
5068
5098
  }));
5069
5099
  var init_earthy_natural = __esmMin((() => {
5070
5100
  init_colorConversion();
5071
5101
  }));
5072
5102
  var init_high_contrast_modern = __esmMin((() => {
5073
- init_utils$5();
5103
+ init_utils$6();
5074
5104
  }));
5075
5105
  var init_jewel_dark = __esmMin((() => {
5076
5106
  init_colorConversion();
5077
5107
  }));
5078
5108
  var init_minimal_monochrome = __esmMin((() => {
5079
- init_utils$5();
5109
+ init_utils$6();
5080
5110
  }));
5081
5111
  var init_neon_pop = __esmMin((() => {
5082
- init_utils$5();
5112
+ init_utils$6();
5083
5113
  }));
5084
5114
  var init_pastel_light = __esmMin((() => {
5085
- init_utils$5();
5115
+ init_utils$6();
5086
5116
  init_colorConversion();
5087
5117
  }));
5088
5118
  var init_soft_modern = __esmMin((() => {
5089
5119
  init_colorConversion();
5090
5120
  }));
5091
5121
  var init_split_complementary = __esmMin((() => {
5092
- init_utils$5();
5122
+ init_utils$6();
5093
5123
  }));
5094
5124
  var init_tetradic = __esmMin((() => {
5095
- init_utils$5();
5125
+ init_utils$6();
5096
5126
  }));
5097
5127
  var init_triadic_balance = __esmMin((() => {
5098
- init_utils$5();
5128
+ init_utils$6();
5099
5129
  })), init_allRecipes = __esmMin((() => {
5100
5130
  init_analogous_harmony();
5101
5131
  init_complementary_contrast();
@@ -5111,7 +5141,7 @@ var init_triadic_balance = __esmMin((() => {
5111
5141
  init_triadic_balance();
5112
5142
  }));
5113
5143
  var init_legs = __esmMin((() => {
5114
- init_contrast$2();
5144
+ init_contrast$1();
5115
5145
  init_colorConversion();
5116
5146
  })), init_supportRoles = __esmMin((() => {
5117
5147
  init_colorConversion();
@@ -5119,7 +5149,7 @@ var init_legs = __esmMin((() => {
5119
5149
  })), init_generatePalette = __esmMin((() => {
5120
5150
  init_backgroundGeneration();
5121
5151
  init_colorConversion();
5122
- init_contrast$2();
5152
+ init_contrast$1();
5123
5153
  init_legs();
5124
5154
  init_supportRoles();
5125
5155
  }));
@@ -5129,7 +5159,7 @@ var init_classifyColor = __esmMin((() => {
5129
5159
  var init_suggestRecipes = __esmMin((() => {
5130
5160
  init_allRecipes();
5131
5161
  init_colorConversion();
5132
- init_contrast$2();
5162
+ init_contrast$1();
5133
5163
  init_generatePalette();
5134
5164
  init_classifyColor();
5135
5165
  }));
@@ -5161,7 +5191,7 @@ function getTextColorForBackground(background) {
5161
5191
  }
5162
5192
  function parseColorToRgb(input) {
5163
5193
  const trimmed = input.trim();
5164
- if (trimmed.startsWith("#")) return hexToRgb$2(trimmed);
5194
+ if (trimmed.startsWith("#")) return hexToRgb$1(trimmed);
5165
5195
  const rgbMatch = trimmed.match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i);
5166
5196
  if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) return {
5167
5197
  r: clamp255(Number(rgbMatch[1])),
@@ -5176,16 +5206,16 @@ function clamp255(value) {
5176
5206
  }
5177
5207
  var init_textColor = __esmMin((() => {
5178
5208
  init_colorConversion();
5179
- init_contrast$2();
5209
+ init_contrast$1();
5180
5210
  }));
5181
5211
  var init_legibility = __esmMin((() => {
5182
- init_contrast$2();
5212
+ init_contrast$1();
5183
5213
  }));
5184
5214
  //#endregion
5185
5215
  //#region ../theme-core/src/palette/utils/index.ts
5186
- var init_utils$5 = __esmMin((() => {
5216
+ var init_utils$6 = __esmMin((() => {
5187
5217
  init_colorConversion();
5188
- init_contrast$2();
5218
+ init_contrast$1();
5189
5219
  init_colorPlacement();
5190
5220
  init_backgroundGeneration();
5191
5221
  init_suggestRecipes();
@@ -5306,7 +5336,7 @@ var init_swatch = __esmMin((() => {}));
5306
5336
  var init_PaletteCard = __esmMin((() => {
5307
5337
  init_generateCssVars();
5308
5338
  init_neutralScale();
5309
- init_utils$5();
5339
+ init_utils$6();
5310
5340
  init_paletteAccess();
5311
5341
  init_expandPalette();
5312
5342
  init_swatch();
@@ -5538,7 +5568,7 @@ function assignDeep(target, ...sources) {
5538
5568
  });
5539
5569
  return target;
5540
5570
  }
5541
- var init_utils$4 = __esmMin((() => {}));
5571
+ var init_utils$5 = __esmMin((() => {}));
5542
5572
  //#endregion
5543
5573
  //#region ../../node_modules/.pnpm/@vibrant+core@4.0.4/node_modules/@vibrant/core/dist/esm/options.js
5544
5574
  function buildProcessOptions(opts, override) {
@@ -5556,13 +5586,13 @@ function buildProcessOptions(opts, override) {
5556
5586
  }, override);
5557
5587
  }
5558
5588
  var init_options = __esmMin((() => {
5559
- init_utils$4();
5589
+ init_utils$5();
5560
5590
  }));
5561
5591
  //#endregion
5562
5592
  //#region ../../node_modules/.pnpm/@vibrant+core@4.0.4/node_modules/@vibrant/core/dist/esm/builder.js
5563
5593
  var Builder;
5564
5594
  var init_builder$1 = __esmMin((() => {
5565
- init_utils$4();
5595
+ init_utils$5();
5566
5596
  init_esm$2();
5567
5597
  Builder = class {
5568
5598
  /**
@@ -5924,7 +5954,7 @@ var init_esm$3 = __esmMin((() => {
5924
5954
  var init_client$2 = __esmMin((() => {
5925
5955
  init_esm$4();
5926
5956
  init_esm$3();
5927
- init_utils$4();
5957
+ init_utils$5();
5928
5958
  }));
5929
5959
  var init_host = __esmMin((() => {
5930
5960
  init_esm$4();
@@ -5935,7 +5965,7 @@ var _Vibrant, Vibrant;
5935
5965
  var init_esm$2 = __esmMin((() => {
5936
5966
  init_options();
5937
5967
  init_builder$1();
5938
- init_utils$4();
5968
+ init_utils$5();
5939
5969
  init_pipeline$1();
5940
5970
  init_client$2();
5941
5971
  init_host();
@@ -8124,12 +8154,8 @@ var init_sitePalettePersistence = __esmMin((() => {
8124
8154
  init_colors();
8125
8155
  init_selection();
8126
8156
  }));
8127
- var init_themePaletteCompatibility = __esmMin((() => {
8128
- init_themeColorTokens();
8129
- init_colors();
8130
- }));
8131
8157
  var init_fromVibrant = __esmMin((() => {
8132
- init_utils$5();
8158
+ init_utils$6();
8133
8159
  }));
8134
8160
  //#endregion
8135
8161
  //#region ../theme-core/src/palette/index.ts
@@ -8141,7 +8167,7 @@ var init_palette$1 = __esmMin((() => {
8141
8167
  init_generateShades();
8142
8168
  init_neutralScale();
8143
8169
  init_types$15();
8144
- init_utils$5();
8170
+ init_utils$6();
8145
8171
  init_paletteAccess();
8146
8172
  init_extractPalette();
8147
8173
  init_colors();
@@ -8151,7 +8177,6 @@ var init_palette$1 = __esmMin((() => {
8151
8177
  init_resolveSelection();
8152
8178
  init_selection();
8153
8179
  init_sitePalettePersistence();
8154
- init_themePaletteCompatibility();
8155
8180
  init_fromVibrant();
8156
8181
  init_suggestRecipes();
8157
8182
  init_allRecipes();
@@ -8597,6 +8622,108 @@ var init_contentTemplateDesignIntent = __esmMin((() => {
8597
8622
  init_types$16();
8598
8623
  }));
8599
8624
  //#endregion
8625
+ //#region ../theme-core/src/buttons/effectClassification.ts
8626
+ function getButtonEffectPolicy(effectId) {
8627
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
8628
+ }
8629
+ function classifyButtonEffectId(effectId) {
8630
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
8631
+ }
8632
+ var BUTTON_EFFECT_POLICIES;
8633
+ var init_effectClassification = __esmMin((() => {
8634
+ BUTTON_EFFECT_POLICIES = {
8635
+ "darken-background": {
8636
+ classification: "colour-transition",
8637
+ transition: {
8638
+ kind: "adjust-shade",
8639
+ direction: "darker"
8640
+ }
8641
+ },
8642
+ "lighten-background": {
8643
+ classification: "colour-transition",
8644
+ transition: {
8645
+ kind: "adjust-shade",
8646
+ direction: "lighter"
8647
+ }
8648
+ },
8649
+ "background-on-hover": {
8650
+ classification: "colour-transition",
8651
+ transition: { kind: "replace-background" }
8652
+ },
8653
+ "background-on-hover-alpha": {
8654
+ classification: "unsupported-colour",
8655
+ reason: "alpha_requires_surface"
8656
+ },
8657
+ "fade-background": {
8658
+ classification: "unsupported-colour",
8659
+ reason: "changes_element_opacity"
8660
+ },
8661
+ "opacity-reduce": {
8662
+ classification: "unsupported-colour",
8663
+ reason: "changes_element_opacity"
8664
+ },
8665
+ "gradient-text": {
8666
+ classification: "unsupported-colour",
8667
+ reason: "changes_foreground"
8668
+ },
8669
+ "text-color-change": {
8670
+ classification: "unsupported-colour",
8671
+ reason: "changes_foreground"
8672
+ },
8673
+ "border-color-change": {
8674
+ classification: "unsupported-colour",
8675
+ reason: "changes_border"
8676
+ },
8677
+ "aurora-glow": {
8678
+ classification: "unsupported-background-overlay",
8679
+ reason: "unresolved_background_overlay"
8680
+ },
8681
+ "cosmic-stardust": {
8682
+ classification: "unsupported-background-overlay",
8683
+ reason: "unresolved_background_overlay"
8684
+ },
8685
+ "gradient-border-fill": {
8686
+ classification: "unsupported-background-overlay",
8687
+ reason: "unresolved_background_overlay"
8688
+ },
8689
+ "animated-gradient-border-fill": {
8690
+ classification: "unsupported-background-overlay",
8691
+ reason: "unresolved_background_overlay"
8692
+ },
8693
+ "nav-underline": {
8694
+ classification: "not-button",
8695
+ reason: "not_button_effect"
8696
+ },
8697
+ "nav-frosted-base": {
8698
+ classification: "not-button",
8699
+ reason: "not_button_effect"
8700
+ },
8701
+ "nav-frosted-hover": {
8702
+ classification: "not-button",
8703
+ reason: "not_button_effect"
8704
+ },
8705
+ "nav-frosted-active": {
8706
+ classification: "not-button",
8707
+ reason: "not_button_effect"
8708
+ },
8709
+ "animated-gradient": { classification: "non-colour" },
8710
+ "border-glow": { classification: "non-colour" },
8711
+ "drop-shadow": { classification: "non-colour" },
8712
+ "inner-shadow": { classification: "non-colour" },
8713
+ "neumorphic-shadow": { classification: "non-colour" },
8714
+ "outer-glow": { classification: "non-colour" },
8715
+ "retro-3d-shadow": { classification: "non-colour" },
8716
+ "scale-up": { classification: "non-colour" },
8717
+ "scale-down": { classification: "non-colour" },
8718
+ lift: { classification: "non-colour" },
8719
+ "press-down": { classification: "non-colour" },
8720
+ pop: { classification: "non-colour" },
8721
+ "border-bottom-grow": { classification: "non-colour" },
8722
+ "sketchy-border": { classification: "non-colour" },
8723
+ "pulse-animation": { classification: "non-colour" }
8724
+ };
8725
+ }));
8726
+ //#endregion
8600
8727
  //#region ../theme-core/src/buttons/types.ts
8601
8728
  function isVariantRole(value) {
8602
8729
  return VARIANT_ROLES.includes(value);
@@ -8605,9 +8732,155 @@ function asSpecialVariantId(value) {
8605
8732
  if (value.length === 0) throw new Error("SpecialVariantId must be a non-empty string");
8606
8733
  return value;
8607
8734
  }
8608
- var VARIANT_ROLES, DEFAULT_VARIANT_ALIAS_ID, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonBackgroundSchema, effectApplicationSchema$1, buttonBorderSchema, buttonVariantAffordanceSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, buttonVariantSchema, buttonSystemSchema;
8735
+ function parseOpaqueButtonColourToken(value) {
8736
+ const token = parseThemeColorToken(value);
8737
+ if (token === null) return null;
8738
+ const parts = parseColorTokenParts(token);
8739
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
8740
+ }
8741
+ function unsafeAsOpaqueButtonColourToken(value) {
8742
+ return value;
8743
+ }
8744
+ function normalizeLegacyButtonVariantInput(input) {
8745
+ if (!isUnknownRecord(input)) return input;
8746
+ const background = input.background;
8747
+ if (!isUnknownRecord(background)) return input;
8748
+ 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;
8749
+ const { textColorToken, ...withoutLegacyText } = input;
8750
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
8751
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
8752
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
8753
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
8754
+ if (background.type === "transparent") return {
8755
+ ...withoutLegacyText,
8756
+ background: {
8757
+ type: "surface",
8758
+ role: "link"
8759
+ },
8760
+ border: normalizedBorder,
8761
+ affordance: normalizedAffordance,
8762
+ effects: normalizedEffects,
8763
+ hoverBackgroundToken
8764
+ };
8765
+ if (background.type === "gradient") {
8766
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
8767
+ return {
8768
+ ...withoutLegacyText,
8769
+ background: {
8770
+ ...background,
8771
+ stops,
8772
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
8773
+ },
8774
+ border: normalizedBorder,
8775
+ affordance: normalizedAffordance,
8776
+ effects: normalizedEffects,
8777
+ hoverBackgroundToken
8778
+ };
8779
+ }
8780
+ return {
8781
+ ...withoutLegacyText,
8782
+ background: background.type === "solid" ? {
8783
+ ...background,
8784
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
8785
+ } : background,
8786
+ border: normalizedBorder,
8787
+ affordance: normalizedAffordance,
8788
+ effects: normalizedEffects,
8789
+ hoverBackgroundToken
8790
+ };
8791
+ }
8792
+ function normalizeLegacyButtonGlobalInput(input) {
8793
+ if (!isUnknownRecord(input)) return input;
8794
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
8795
+ return hoverColorToken === input.hoverColorToken ? input : {
8796
+ ...input,
8797
+ hoverColorToken
8798
+ };
8799
+ }
8800
+ function hasLegacyAlphaToken(input, background) {
8801
+ const stops = isUnknownArray$4(background.stops) ? background.stops : [];
8802
+ return [
8803
+ input.hoverBackgroundToken,
8804
+ background.colorToken,
8805
+ background.foregroundToken,
8806
+ ...stops
8807
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
8808
+ }
8809
+ function stripLegacyTokenAlpha(value) {
8810
+ if (typeof value !== "string") return value;
8811
+ const slashIndex = value.indexOf("/");
8812
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
8813
+ }
8814
+ function hasLegacyButtonEffects(input) {
8815
+ if (!isUnknownRecord(input)) return false;
8816
+ return [
8817
+ "base",
8818
+ "hover",
8819
+ "active",
8820
+ "focus"
8821
+ ].some((state) => {
8822
+ const effects = input[state];
8823
+ return Array.isArray(effects) && effects.some((effect) => {
8824
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
8825
+ const classification = classifyButtonEffectId(effect.effectId);
8826
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
8827
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
8828
+ });
8829
+ });
8830
+ }
8831
+ function normalizeLegacyButtonEffects(input, backgroundType) {
8832
+ if (!isUnknownRecord(input)) return input;
8833
+ const normalized = {};
8834
+ for (const state of [
8835
+ "base",
8836
+ "hover",
8837
+ "active",
8838
+ "focus"
8839
+ ]) {
8840
+ const effects = input[state];
8841
+ if (!Array.isArray(effects)) continue;
8842
+ const safeEffects = effects.flatMap((effect) => {
8843
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
8844
+ const classification = classifyButtonEffectId(effect.effectId);
8845
+ if (classification === "non-colour") return [effect];
8846
+ if (classification !== "colour-transition") return [];
8847
+ if (effect.effectId === "background-on-hover") {
8848
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
8849
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
8850
+ return colorToken === null ? [] : [{
8851
+ ...effect,
8852
+ options: {
8853
+ ...options,
8854
+ colorToken
8855
+ }
8856
+ }];
8857
+ }
8858
+ if (backgroundType !== "solid") return [];
8859
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
8860
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
8861
+ return [{
8862
+ ...effect,
8863
+ options: {
8864
+ ...isUnknownRecord(effect.options) ? effect.options : {},
8865
+ amount
8866
+ }
8867
+ }];
8868
+ });
8869
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
8870
+ }
8871
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
8872
+ }
8873
+ function isUnknownRecord(value) {
8874
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8875
+ }
8876
+ function isUnknownArray$4(value) {
8877
+ return Array.isArray(value);
8878
+ }
8879
+ var VARIANT_ROLES, DEFAULT_VARIANT_ALIAS_ID, opaqueButtonColourTokenSchema, cornerStyleSchema, shadowSizeSchema, textTransformSchema, fontWeightSchema, buttonTypographySchema, letterSpacingSchema, hoverTransformSchema, hoverColorSchema, buttonPaddingPresetSchema, gradientStyleSchema, gradientSharpnessSchema, prioritySchema, buttonSizeNameSchema, PADDING_TOKEN_PATTERN, paddingShorthandSchema, buttonSizeConfigSchema, buttonSizesSchema, canonicalButtonGlobalSettingsSchema, buttonGlobalSettingsSchema, gradientDirectionSchema$1, buttonColourTreatmentSchema, buttonBackgroundSchema, effectApplicationSchema$1, buttonBorderSchema, buttonVariantAffordanceSchema, variantShadowSchema, variantEffectsSchema, variantSizeOverridesSchema, canonicalButtonVariantSchema, buttonVariantSchema, buttonSystemSchema;
8609
8880
  var init_types$13 = __esmMin((() => {
8881
+ init_effectClassification();
8610
8882
  init_themeColorTokens();
8883
+ init_colorTokenParts();
8611
8884
  VARIANT_ROLES = [
8612
8885
  "primary",
8613
8886
  "secondary",
@@ -8618,6 +8891,11 @@ var init_types$13 = __esmMin((() => {
8618
8891
  "accent"
8619
8892
  ];
8620
8893
  DEFAULT_VARIANT_ALIAS_ID = "default";
8894
+ opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
8895
+ const token = parseOpaqueButtonColourToken(value);
8896
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
8897
+ return token;
8898
+ });
8621
8899
  cornerStyleSchema = z$1.enum([
8622
8900
  "square",
8623
8901
  "rounded",
@@ -8706,7 +8984,7 @@ var init_types$13 = __esmMin((() => {
8706
8984
  lg,
8707
8985
  xl: xl ?? lg
8708
8986
  }));
8709
- buttonGlobalSettingsSchema = z$1.object({
8987
+ canonicalButtonGlobalSettingsSchema = z$1.object({
8710
8988
  cornerStyle: cornerStyleSchema,
8711
8989
  cornerRadius: z$1.number().min(0).max(24).optional(),
8712
8990
  /**
@@ -8737,11 +9015,12 @@ var init_types$13 = __esmMin((() => {
8737
9015
  paddingPreset: buttonPaddingPresetSchema.optional(),
8738
9016
  hoverTransform: hoverTransformSchema,
8739
9017
  hoverColor: hoverColorSchema,
8740
- hoverColorToken: themeColorTokenSchema.optional(),
9018
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
8741
9019
  gradientStyle: gradientStyleSchema.optional(),
8742
9020
  gradientAngle: z$1.number().min(0).max(360).optional(),
8743
9021
  gradientSharpness: gradientSharpnessSchema.optional()
8744
9022
  });
9023
+ buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
8745
9024
  gradientDirectionSchema$1 = z$1.enum([
8746
9025
  "to-r",
8747
9026
  "to-l",
@@ -8752,30 +9031,37 @@ var init_types$13 = __esmMin((() => {
8752
9031
  "to-br",
8753
9032
  "to-bl"
8754
9033
  ]);
8755
- buttonBackgroundSchema = z$1.discriminatedUnion("type", [
9034
+ buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
8756
9035
  z$1.object({
8757
9036
  type: z$1.literal("solid"),
8758
- colorToken: themeColorTokenSchema
9037
+ colorToken: opaqueButtonColourTokenSchema
8759
9038
  }),
8760
9039
  z$1.object({
8761
9040
  type: z$1.literal("gradient"),
8762
- stops: z$1.array(themeColorTokenSchema).min(2),
8763
- direction: gradientDirectionSchema$1
9041
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
9042
+ const [first, second, ...rest] = stops;
9043
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
9044
+ return [
9045
+ first,
9046
+ second,
9047
+ ...rest
9048
+ ];
9049
+ }),
9050
+ direction: gradientDirectionSchema$1,
9051
+ foregroundToken: opaqueButtonColourTokenSchema
8764
9052
  }),
8765
- z$1.object({ type: z$1.literal("transparent") })
9053
+ z$1.object({
9054
+ type: z$1.literal("surface"),
9055
+ role: z$1.literal("link")
9056
+ })
8766
9057
  ]);
9058
+ buttonBackgroundSchema = buttonColourTreatmentSchema;
8767
9059
  effectApplicationSchema$1 = z$1.object({
8768
9060
  effectId: z$1.string(),
8769
- options: z$1.record(z$1.string(), z$1.any()).optional()
8770
- });
8771
- buttonBorderSchema = z$1.object({
8772
- widthClass: z$1.string(),
8773
- colorToken: themeColorTokenSchema
8774
- });
8775
- buttonVariantAffordanceSchema = z$1.object({
8776
- iconId: z$1.string().min(1),
8777
- colorToken: themeColorTokenSchema.optional()
9061
+ options: z$1.record(z$1.string(), z$1.json()).optional()
8778
9062
  });
9063
+ buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
9064
+ buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
8779
9065
  variantShadowSchema = z$1.object({
8780
9066
  elevation: z$1.enum([
8781
9067
  "none",
@@ -8803,22 +9089,22 @@ var init_types$13 = __esmMin((() => {
8803
9089
  lg: buttonSizeConfigSchema.optional(),
8804
9090
  xl: buttonSizeConfigSchema.optional()
8805
9091
  });
8806
- buttonVariantSchema = z$1.object({
9092
+ canonicalButtonVariantSchema = z$1.object({
8807
9093
  id: z$1.string(),
8808
9094
  name: z$1.string().min(1).max(20),
8809
9095
  enabled: z$1.boolean(),
8810
9096
  priority: prioritySchema,
8811
9097
  background: buttonBackgroundSchema,
8812
- textColorToken: themeColorTokenSchema,
8813
9098
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
8814
9099
  borderRadius: z$1.string().optional(),
8815
9100
  shadow: variantShadowSchema.optional(),
8816
9101
  border: buttonBorderSchema.optional(),
8817
- hoverBackgroundToken: z$1.string().optional(),
9102
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
8818
9103
  effects: variantEffectsSchema.optional(),
8819
9104
  sizes: variantSizeOverridesSchema.optional(),
8820
9105
  affordance: buttonVariantAffordanceSchema.optional()
8821
9106
  });
9107
+ buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
8822
9108
  buttonSystemSchema = z$1.object({
8823
9109
  global: buttonGlobalSettingsSchema,
8824
9110
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
@@ -8842,7 +9128,7 @@ function defineButtonPersonality(input) {
8842
9128
  name: input.name,
8843
9129
  description: input.description,
8844
9130
  tags: input.tags,
8845
- buttonSystem: input.buttonSystem
9131
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
8846
9132
  };
8847
9133
  }
8848
9134
  var buttonPersonalityIdSchema;
@@ -8907,19 +9193,15 @@ var init_brushed_wash = __esmMin((() => {
8907
9193
  background: {
8908
9194
  type: "gradient",
8909
9195
  stops: ["primary", "accent"],
8910
- direction: "to-r"
9196
+ direction: "to-r",
9197
+ foregroundToken: "primaryForeground"
8911
9198
  },
8912
- textColorToken: "primaryForeground",
8913
9199
  borderRadius: "rounded-lg",
8914
9200
  shadow: {
8915
9201
  elevation: "low",
8916
9202
  softness: "soft",
8917
9203
  position: "bottom"
8918
- },
8919
- effects: { hover: [{
8920
- effectId: "opacity-reduce",
8921
- options: { reduction: -15 }
8922
- }] }
9204
+ }
8923
9205
  },
8924
9206
  {
8925
9207
  id: "secondary",
@@ -8929,32 +9211,27 @@ var init_brushed_wash = __esmMin((() => {
8929
9211
  background: {
8930
9212
  type: "gradient",
8931
9213
  stops: ["secondary", "accent"],
8932
- direction: "to-br"
9214
+ direction: "to-br",
9215
+ foregroundToken: "primaryForeground"
8933
9216
  },
8934
- textColorToken: "primaryForeground",
8935
9217
  borderRadius: "rounded-lg",
8936
9218
  shadow: {
8937
9219
  elevation: "low",
8938
9220
  softness: "soft",
8939
9221
  position: "bottom"
8940
- },
8941
- effects: { hover: [{
8942
- effectId: "opacity-reduce",
8943
- options: { reduction: -15 }
8944
- }] }
9222
+ }
8945
9223
  },
8946
9224
  {
8947
9225
  id: "outline",
8948
9226
  name: "Outline",
8949
9227
  enabled: true,
8950
9228
  priority: 3,
8951
- background: { type: "transparent" },
8952
- textColorToken: "primary",
8953
- borderRadius: "rounded-lg",
8954
- border: {
8955
- widthClass: "border",
8956
- colorToken: "primary"
9229
+ background: {
9230
+ type: "surface",
9231
+ role: "link"
8957
9232
  },
9233
+ borderRadius: "rounded-lg",
9234
+ border: { widthClass: "border" },
8958
9235
  effects: { hover: [{
8959
9236
  effectId: "background-on-hover",
8960
9237
  options: { colorToken: "surface" }
@@ -8965,8 +9242,10 @@ var init_brushed_wash = __esmMin((() => {
8965
9242
  name: "Ghost",
8966
9243
  enabled: true,
8967
9244
  priority: 3,
8968
- background: { type: "transparent" },
8969
- textColorToken: "text",
9245
+ background: {
9246
+ type: "surface",
9247
+ role: "link"
9248
+ },
8970
9249
  borderRadius: "rounded-lg",
8971
9250
  effects: { hover: [{
8972
9251
  effectId: "background-on-hover",
@@ -9012,7 +9291,6 @@ var init_confident_chip = __esmMin((() => {
9012
9291
  type: "solid",
9013
9292
  colorToken: "primary"
9014
9293
  },
9015
- textColorToken: "primaryForeground",
9016
9294
  borderRadius: "rounded-md",
9017
9295
  shadow: {
9018
9296
  elevation: "medium",
@@ -9022,7 +9300,7 @@ var init_confident_chip = __esmMin((() => {
9022
9300
  effects: {
9023
9301
  hover: [{
9024
9302
  effectId: "darken-background",
9025
- options: { amount: 60 }
9303
+ options: { amount: 100 }
9026
9304
  }],
9027
9305
  active: [{
9028
9306
  effectId: "scale-down",
@@ -9039,12 +9317,8 @@ var init_confident_chip = __esmMin((() => {
9039
9317
  type: "solid",
9040
9318
  colorToken: "surface"
9041
9319
  },
9042
- textColorToken: "text",
9043
9320
  borderRadius: "rounded-md",
9044
- border: {
9045
- widthClass: "border",
9046
- colorToken: "border"
9047
- },
9321
+ border: { widthClass: "border" },
9048
9322
  effects: { hover: [{
9049
9323
  effectId: "background-on-hover",
9050
9324
  options: { colorToken: "background" }
@@ -9055,13 +9329,12 @@ var init_confident_chip = __esmMin((() => {
9055
9329
  name: "Outline",
9056
9330
  enabled: true,
9057
9331
  priority: 3,
9058
- background: { type: "transparent" },
9059
- textColorToken: "primary",
9060
- borderRadius: "rounded-md",
9061
- border: {
9062
- widthClass: "border",
9063
- colorToken: "primary"
9332
+ background: {
9333
+ type: "surface",
9334
+ role: "link"
9064
9335
  },
9336
+ borderRadius: "rounded-md",
9337
+ border: { widthClass: "border" },
9065
9338
  effects: { hover: [{
9066
9339
  effectId: "background-on-hover",
9067
9340
  options: { colorToken: "surface" }
@@ -9072,8 +9345,10 @@ var init_confident_chip = __esmMin((() => {
9072
9345
  name: "Ghost",
9073
9346
  enabled: true,
9074
9347
  priority: 3,
9075
- background: { type: "transparent" },
9076
- textColorToken: "primary",
9348
+ background: {
9349
+ type: "surface",
9350
+ role: "link"
9351
+ },
9077
9352
  borderRadius: "rounded-md",
9078
9353
  effects: { hover: [{
9079
9354
  effectId: "background-on-hover",
@@ -9136,7 +9411,6 @@ var init_earth_pill = __esmMin((() => {
9136
9411
  type: "solid",
9137
9412
  colorToken: "primary"
9138
9413
  },
9139
- textColorToken: "primaryForeground",
9140
9414
  borderRadius: "rounded-full",
9141
9415
  shadow: {
9142
9416
  elevation: "low",
@@ -9162,13 +9436,12 @@ var init_earth_pill = __esmMin((() => {
9162
9436
  name: "Secondary",
9163
9437
  enabled: true,
9164
9438
  priority: 2,
9165
- background: { type: "transparent" },
9166
- textColorToken: "primary",
9167
- borderRadius: "rounded-full",
9168
- border: {
9169
- widthClass: "border",
9170
- colorToken: "primary"
9439
+ background: {
9440
+ type: "surface",
9441
+ role: "link"
9171
9442
  },
9443
+ borderRadius: "rounded-full",
9444
+ border: { widthClass: "border" },
9172
9445
  effects: { hover: [{
9173
9446
  effectId: "background-on-hover",
9174
9447
  options: { colorToken: "muted" }
@@ -9179,13 +9452,12 @@ var init_earth_pill = __esmMin((() => {
9179
9452
  name: "Outline",
9180
9453
  enabled: true,
9181
9454
  priority: 3,
9182
- background: { type: "transparent" },
9183
- textColorToken: "text",
9184
- borderRadius: "rounded-full",
9185
- border: {
9186
- widthClass: "border",
9187
- colorToken: "border"
9455
+ background: {
9456
+ type: "surface",
9457
+ role: "link"
9188
9458
  },
9459
+ borderRadius: "rounded-full",
9460
+ border: { widthClass: "border" },
9189
9461
  effects: { hover: [{
9190
9462
  effectId: "background-on-hover",
9191
9463
  options: { colorToken: "surfaceAlt" }
@@ -9196,8 +9468,10 @@ var init_earth_pill = __esmMin((() => {
9196
9468
  name: "Ghost",
9197
9469
  enabled: true,
9198
9470
  priority: 3,
9199
- background: { type: "transparent" },
9200
- textColorToken: "primary",
9471
+ background: {
9472
+ type: "surface",
9473
+ role: "link"
9474
+ },
9201
9475
  borderRadius: "rounded-full",
9202
9476
  shadow: {
9203
9477
  elevation: "none",
@@ -9218,11 +9492,7 @@ var init_earth_pill = __esmMin((() => {
9218
9492
  padding: "0.625rem 0",
9219
9493
  fontSize: "text-xl"
9220
9494
  }
9221
- },
9222
- effects: { hover: [{
9223
- effectId: "opacity-reduce",
9224
- options: { reduction: 25 }
9225
- }] }
9495
+ }
9226
9496
  }
9227
9497
  ]
9228
9498
  }
@@ -9258,8 +9528,10 @@ var init_editorial_link = __esmMin((() => {
9258
9528
  name: "Primary",
9259
9529
  enabled: true,
9260
9530
  priority: 1,
9261
- background: { type: "transparent" },
9262
- textColorToken: "text",
9531
+ background: {
9532
+ type: "surface",
9533
+ role: "link"
9534
+ },
9263
9535
  borderRadius: "rounded-none",
9264
9536
  sizes: {
9265
9537
  sm: { padding: "0.25rem 0" },
@@ -9281,8 +9553,10 @@ var init_editorial_link = __esmMin((() => {
9281
9553
  name: "Secondary",
9282
9554
  enabled: true,
9283
9555
  priority: 2,
9284
- background: { type: "transparent" },
9285
- textColorToken: "mutedText",
9556
+ background: {
9557
+ type: "surface",
9558
+ role: "link"
9559
+ },
9286
9560
  borderRadius: "rounded-none",
9287
9561
  sizes: {
9288
9562
  sm: { padding: "0.25rem 0" },
@@ -9304,8 +9578,10 @@ var init_editorial_link = __esmMin((() => {
9304
9578
  name: "Outline",
9305
9579
  enabled: true,
9306
9580
  priority: 3,
9307
- background: { type: "transparent" },
9308
- textColorToken: "accent",
9581
+ background: {
9582
+ type: "surface",
9583
+ role: "link"
9584
+ },
9309
9585
  borderRadius: "rounded-none",
9310
9586
  sizes: {
9311
9587
  sm: { padding: "0.25rem 0" },
@@ -9327,19 +9603,17 @@ var init_editorial_link = __esmMin((() => {
9327
9603
  name: "Ghost",
9328
9604
  enabled: true,
9329
9605
  priority: 3,
9330
- background: { type: "transparent" },
9331
- textColorToken: "mutedText",
9606
+ background: {
9607
+ type: "surface",
9608
+ role: "link"
9609
+ },
9332
9610
  borderRadius: "rounded-none",
9333
9611
  sizes: {
9334
9612
  sm: { padding: "0.25rem 0" },
9335
9613
  md: { padding: "0.5rem 0" },
9336
9614
  lg: { padding: "0.625rem 0" },
9337
9615
  xl: { padding: "0.75rem 0" }
9338
- },
9339
- effects: { hover: [{
9340
- effectId: "opacity-reduce",
9341
- options: { reduction: -20 }
9342
- }] }
9616
+ }
9343
9617
  }
9344
9618
  ]
9345
9619
  }
@@ -9397,12 +9671,8 @@ var init_flat_ink = __esmMin((() => {
9397
9671
  type: "solid",
9398
9672
  colorToken: "primary"
9399
9673
  },
9400
- textColorToken: "primaryForeground",
9401
9674
  borderRadius: "rounded-lg",
9402
- affordance: {
9403
- iconId: "ArrowRight",
9404
- colorToken: "accent"
9405
- },
9675
+ affordance: { iconId: "ArrowRight" },
9406
9676
  effects: { hover: [{
9407
9677
  effectId: "lift",
9408
9678
  options: { translateY: "-2px" }
@@ -9416,13 +9686,12 @@ var init_flat_ink = __esmMin((() => {
9416
9686
  name: "Secondary",
9417
9687
  enabled: true,
9418
9688
  priority: 2,
9419
- background: { type: "transparent" },
9420
- textColorToken: "primary",
9421
- borderRadius: "rounded-lg",
9422
- border: {
9423
- widthClass: "border",
9424
- colorToken: "border"
9689
+ background: {
9690
+ type: "surface",
9691
+ role: "link"
9425
9692
  },
9693
+ borderRadius: "rounded-lg",
9694
+ border: { widthClass: "border" },
9426
9695
  effects: { hover: [{
9427
9696
  effectId: "lift",
9428
9697
  options: { translateY: "-2px" }
@@ -9440,12 +9709,8 @@ var init_flat_ink = __esmMin((() => {
9440
9709
  type: "solid",
9441
9710
  colorToken: "accent"
9442
9711
  },
9443
- textColorToken: "accentForeground",
9444
9712
  borderRadius: "rounded-lg",
9445
- affordance: {
9446
- iconId: "ArrowRight",
9447
- colorToken: "accentForeground"
9448
- },
9713
+ affordance: { iconId: "ArrowRight" },
9449
9714
  effects: { hover: [{
9450
9715
  effectId: "lift",
9451
9716
  options: { translateY: "-2px" }
@@ -9508,7 +9773,6 @@ var init_ink_stamp = __esmMin((() => {
9508
9773
  type: "solid",
9509
9774
  colorToken: "primary"
9510
9775
  },
9511
- textColorToken: "primaryForeground",
9512
9776
  borderRadius: "rounded-md",
9513
9777
  effects: {
9514
9778
  hover: [{
@@ -9529,13 +9793,12 @@ var init_ink_stamp = __esmMin((() => {
9529
9793
  name: "Secondary",
9530
9794
  enabled: true,
9531
9795
  priority: 2,
9532
- background: { type: "transparent" },
9533
- textColorToken: "primary",
9534
- borderRadius: "rounded-md",
9535
- border: {
9536
- widthClass: "border-2",
9537
- colorToken: "primary"
9796
+ background: {
9797
+ type: "surface",
9798
+ role: "link"
9538
9799
  },
9800
+ borderRadius: "rounded-md",
9801
+ border: { widthClass: "border-2" },
9539
9802
  effects: { hover: [{
9540
9803
  effectId: "background-on-hover",
9541
9804
  options: { colorToken: "surface" }
@@ -9546,13 +9809,12 @@ var init_ink_stamp = __esmMin((() => {
9546
9809
  name: "Outline",
9547
9810
  enabled: true,
9548
9811
  priority: 3,
9549
- background: { type: "transparent" },
9550
- textColorToken: "text",
9551
- borderRadius: "rounded-md",
9552
- border: {
9553
- widthClass: "border-2",
9554
- colorToken: "border"
9812
+ background: {
9813
+ type: "surface",
9814
+ role: "link"
9555
9815
  },
9816
+ borderRadius: "rounded-md",
9817
+ border: { widthClass: "border-2" },
9556
9818
  effects: { hover: [{
9557
9819
  effectId: "background-on-hover",
9558
9820
  options: { colorToken: "surface" }
@@ -9563,8 +9825,10 @@ var init_ink_stamp = __esmMin((() => {
9563
9825
  name: "Ghost",
9564
9826
  enabled: true,
9565
9827
  priority: 3,
9566
- background: { type: "transparent" },
9567
- textColorToken: "accent",
9828
+ background: {
9829
+ type: "surface",
9830
+ role: "link"
9831
+ },
9568
9832
  borderRadius: "rounded-none",
9569
9833
  sizes: {
9570
9834
  sm: {
@@ -9651,7 +9915,6 @@ var init_joy_stamp = __esmMin((() => {
9651
9915
  type: "solid",
9652
9916
  colorToken: "primary"
9653
9917
  },
9654
- textColorToken: "primaryForeground",
9655
9918
  borderRadius: "rounded-full",
9656
9919
  shadow: {
9657
9920
  elevation: "high",
@@ -9665,13 +9928,12 @@ var init_joy_stamp = __esmMin((() => {
9665
9928
  name: "Secondary",
9666
9929
  enabled: true,
9667
9930
  priority: 2,
9668
- background: { type: "transparent" },
9669
- textColorToken: "text",
9670
- borderRadius: "rounded-full",
9671
- border: {
9672
- widthClass: "border-2",
9673
- colorToken: "text"
9931
+ background: {
9932
+ type: "surface",
9933
+ role: "link"
9674
9934
  },
9935
+ borderRadius: "rounded-full",
9936
+ border: { widthClass: "border-2" },
9675
9937
  shadow: {
9676
9938
  elevation: "high",
9677
9939
  softness: "hard",
@@ -9736,12 +9998,8 @@ var init_ornate_ritual = __esmMin((() => {
9736
9998
  type: "solid",
9737
9999
  colorToken: "primary"
9738
10000
  },
9739
- textColorToken: "primaryForeground",
9740
10001
  borderRadius: "rounded-md",
9741
- border: {
9742
- widthClass: "border",
9743
- colorToken: "primary"
9744
- },
10002
+ border: { widthClass: "border" },
9745
10003
  effects: {
9746
10004
  hover: [{
9747
10005
  effectId: "background-on-hover",
@@ -9762,12 +10020,8 @@ var init_ornate_ritual = __esmMin((() => {
9762
10020
  type: "solid",
9763
10021
  colorToken: "secondary"
9764
10022
  },
9765
- textColorToken: "primaryForeground",
9766
10023
  borderRadius: "rounded-md",
9767
- border: {
9768
- widthClass: "border",
9769
- colorToken: "primary"
9770
- },
10024
+ border: { widthClass: "border" },
9771
10025
  effects: { hover: [{
9772
10026
  effectId: "background-on-hover",
9773
10027
  options: { colorToken: "surface" }
@@ -9778,13 +10032,12 @@ var init_ornate_ritual = __esmMin((() => {
9778
10032
  name: "Outline",
9779
10033
  enabled: true,
9780
10034
  priority: 3,
9781
- background: { type: "transparent" },
9782
- textColorToken: "primary",
9783
- borderRadius: "rounded-md",
9784
- border: {
9785
- widthClass: "border",
9786
- colorToken: "primary"
10035
+ background: {
10036
+ type: "surface",
10037
+ role: "link"
9787
10038
  },
10039
+ borderRadius: "rounded-md",
10040
+ border: { widthClass: "border" },
9788
10041
  effects: { hover: [{
9789
10042
  effectId: "background-on-hover",
9790
10043
  options: { colorToken: "muted" }
@@ -9795,8 +10048,10 @@ var init_ornate_ritual = __esmMin((() => {
9795
10048
  name: "Ghost",
9796
10049
  enabled: true,
9797
10050
  priority: 3,
9798
- background: { type: "transparent" },
9799
- textColorToken: "accent",
10051
+ background: {
10052
+ type: "surface",
10053
+ role: "link"
10054
+ },
9800
10055
  borderRadius: "rounded-none",
9801
10056
  sizes: {
9802
10057
  sm: {
@@ -9878,14 +10133,10 @@ var init_pebble = __esmMin((() => {
9878
10133
  type: "solid",
9879
10134
  colorToken: "primary"
9880
10135
  },
9881
- textColorToken: "primaryForeground",
9882
10136
  borderRadius: "rounded-full",
9883
10137
  effects: { hover: [{
9884
- effectId: "background-on-hover-alpha",
9885
- options: {
9886
- colorToken: "primary",
9887
- opacity: 88
9888
- }
10138
+ effectId: "darken-background",
10139
+ options: { amount: 100 }
9889
10140
  }] }
9890
10141
  },
9891
10142
  {
@@ -9893,13 +10144,12 @@ var init_pebble = __esmMin((() => {
9893
10144
  name: "Secondary",
9894
10145
  enabled: true,
9895
10146
  priority: 2,
9896
- background: { type: "transparent" },
9897
- textColorToken: "primary",
9898
- borderRadius: "rounded-full",
9899
- border: {
9900
- widthClass: "border-2",
9901
- colorToken: "accent"
10147
+ background: {
10148
+ type: "surface",
10149
+ role: "link"
9902
10150
  },
10151
+ borderRadius: "rounded-full",
10152
+ border: { widthClass: "border-2" },
9903
10153
  effects: { hover: [{
9904
10154
  effectId: "background-on-hover",
9905
10155
  options: { colorToken: "accent" }
@@ -9910,13 +10160,12 @@ var init_pebble = __esmMin((() => {
9910
10160
  name: "Outline",
9911
10161
  enabled: true,
9912
10162
  priority: 3,
9913
- background: { type: "transparent" },
9914
- textColorToken: "text",
9915
- borderRadius: "rounded-full",
9916
- border: {
9917
- widthClass: "border",
9918
- colorToken: "border"
10163
+ background: {
10164
+ type: "surface",
10165
+ role: "link"
9919
10166
  },
10167
+ borderRadius: "rounded-full",
10168
+ border: { widthClass: "border" },
9920
10169
  effects: { hover: [{
9921
10170
  effectId: "background-on-hover",
9922
10171
  options: { colorToken: "surface" }
@@ -9927,8 +10176,10 @@ var init_pebble = __esmMin((() => {
9927
10176
  name: "Ghost",
9928
10177
  enabled: true,
9929
10178
  priority: 3,
9930
- background: { type: "transparent" },
9931
- textColorToken: "primary",
10179
+ background: {
10180
+ type: "surface",
10181
+ role: "link"
10182
+ },
9932
10183
  borderRadius: "rounded-full",
9933
10184
  sizes: {
9934
10185
  sm: {
@@ -9944,11 +10195,7 @@ var init_pebble = __esmMin((() => {
9944
10195
  padding: "0.75rem 1.5rem",
9945
10196
  fontSize: "text-xl"
9946
10197
  }
9947
- },
9948
- effects: { hover: [{
9949
- effectId: "opacity-reduce",
9950
- options: { reduction: 30 }
9951
- }] }
10198
+ }
9952
10199
  }
9953
10200
  ]
9954
10201
  }
@@ -10009,15 +10256,11 @@ var init_quiet_arrow = __esmMin((() => {
10009
10256
  type: "solid",
10010
10257
  colorToken: "primary"
10011
10258
  },
10012
- textColorToken: "primaryForeground",
10013
10259
  borderRadius: "rounded-xl",
10014
10260
  affordance: { iconId: "ArrowRight" },
10015
10261
  effects: { hover: [{
10016
- effectId: "background-on-hover-alpha",
10017
- options: {
10018
- colorToken: "primary",
10019
- opacity: 90
10020
- }
10262
+ effectId: "darken-background",
10263
+ options: { amount: 100 }
10021
10264
  }] }
10022
10265
  },
10023
10266
  {
@@ -10025,13 +10268,12 @@ var init_quiet_arrow = __esmMin((() => {
10025
10268
  name: "Secondary",
10026
10269
  enabled: true,
10027
10270
  priority: 2,
10028
- background: { type: "transparent" },
10029
- textColorToken: "primary",
10030
- borderRadius: "rounded-xl",
10031
- border: {
10032
- widthClass: "border",
10033
- colorToken: "primary"
10271
+ background: {
10272
+ type: "surface",
10273
+ role: "link"
10034
10274
  },
10275
+ borderRadius: "rounded-xl",
10276
+ border: { widthClass: "border" },
10035
10277
  affordance: { iconId: "ArrowRight" },
10036
10278
  effects: { hover: [{
10037
10279
  effectId: "background-on-hover",
@@ -10043,21 +10285,22 @@ var init_quiet_arrow = __esmMin((() => {
10043
10285
  name: "Outline",
10044
10286
  enabled: true,
10045
10287
  priority: 3,
10046
- background: { type: "transparent" },
10047
- textColorToken: "primary",
10288
+ background: {
10289
+ type: "surface",
10290
+ role: "link"
10291
+ },
10048
10292
  borderRadius: "rounded-xl",
10049
- border: {
10050
- widthClass: "border",
10051
- colorToken: "primary"
10052
- }
10293
+ border: { widthClass: "border" }
10053
10294
  },
10054
10295
  {
10055
10296
  id: "ghost",
10056
10297
  name: "Ghost",
10057
10298
  enabled: true,
10058
10299
  priority: 3,
10059
- background: { type: "transparent" },
10060
- textColorToken: "primary",
10300
+ background: {
10301
+ type: "surface",
10302
+ role: "link"
10303
+ },
10061
10304
  borderRadius: "rounded-xl"
10062
10305
  }
10063
10306
  ]
@@ -10120,7 +10363,6 @@ var init_showtime_pill = __esmMin((() => {
10120
10363
  type: "solid",
10121
10364
  colorToken: "primary"
10122
10365
  },
10123
- textColorToken: "background",
10124
10366
  borderRadius: "rounded-full",
10125
10367
  effects: { hover: [{ effectId: "pop" }] }
10126
10368
  },
@@ -10129,13 +10371,12 @@ var init_showtime_pill = __esmMin((() => {
10129
10371
  name: "Secondary",
10130
10372
  enabled: true,
10131
10373
  priority: 2,
10132
- background: { type: "transparent" },
10133
- textColorToken: "primary",
10134
- borderRadius: "rounded-full",
10135
- border: {
10136
- widthClass: "border-2",
10137
- colorToken: "primary"
10374
+ background: {
10375
+ type: "surface",
10376
+ role: "link"
10138
10377
  },
10378
+ borderRadius: "rounded-full",
10379
+ border: { widthClass: "border-2" },
10139
10380
  effects: { hover: [{ effectId: "pop" }] }
10140
10381
  },
10141
10382
  {
@@ -10147,7 +10388,6 @@ var init_showtime_pill = __esmMin((() => {
10147
10388
  type: "solid",
10148
10389
  colorToken: "secondary"
10149
10390
  },
10150
- textColorToken: "primary",
10151
10391
  borderRadius: "rounded-full",
10152
10392
  effects: { hover: [{ effectId: "pop" }] }
10153
10393
  },
@@ -10160,12 +10400,8 @@ var init_showtime_pill = __esmMin((() => {
10160
10400
  type: "solid",
10161
10401
  colorToken: "background"
10162
10402
  },
10163
- textColorToken: "primary",
10164
10403
  borderRadius: "rounded-full",
10165
- border: {
10166
- widthClass: "border-2",
10167
- colorToken: "primary"
10168
- },
10404
+ border: { widthClass: "border-2" },
10169
10405
  effects: { hover: [{
10170
10406
  effectId: "background-on-hover",
10171
10407
  options: { colorToken: "surface" }
@@ -10176,13 +10412,12 @@ var init_showtime_pill = __esmMin((() => {
10176
10412
  name: "Outline",
10177
10413
  enabled: true,
10178
10414
  priority: 3,
10179
- background: { type: "transparent" },
10180
- textColorToken: "primary",
10181
- borderRadius: "rounded-full",
10182
- border: {
10183
- widthClass: "border-2",
10184
- colorToken: "primary"
10415
+ background: {
10416
+ type: "surface",
10417
+ role: "link"
10185
10418
  },
10419
+ borderRadius: "rounded-full",
10420
+ border: { widthClass: "border-2" },
10186
10421
  effects: { hover: [{
10187
10422
  effectId: "background-on-hover",
10188
10423
  options: { colorToken: "background" }
@@ -10193,8 +10428,10 @@ var init_showtime_pill = __esmMin((() => {
10193
10428
  name: "Ghost",
10194
10429
  enabled: true,
10195
10430
  priority: 3,
10196
- background: { type: "transparent" },
10197
- textColorToken: "primary",
10431
+ background: {
10432
+ type: "surface",
10433
+ role: "link"
10434
+ },
10198
10435
  borderRadius: "rounded-full",
10199
10436
  effects: { hover: [{
10200
10437
  effectId: "background-on-hover",
@@ -10240,7 +10477,6 @@ var init_soft_pill = __esmMin((() => {
10240
10477
  type: "solid",
10241
10478
  colorToken: "primary"
10242
10479
  },
10243
- textColorToken: "primaryForeground",
10244
10480
  borderRadius: "rounded-full",
10245
10481
  shadow: {
10246
10482
  elevation: "low",
@@ -10263,13 +10499,12 @@ var init_soft_pill = __esmMin((() => {
10263
10499
  name: "Secondary",
10264
10500
  enabled: true,
10265
10501
  priority: 2,
10266
- background: { type: "transparent" },
10267
- textColorToken: "primary",
10268
- borderRadius: "rounded-full",
10269
- border: {
10270
- widthClass: "border-2",
10271
- colorToken: "primary"
10502
+ background: {
10503
+ type: "surface",
10504
+ role: "link"
10272
10505
  },
10506
+ borderRadius: "rounded-full",
10507
+ border: { widthClass: "border-2" },
10273
10508
  effects: { hover: [{
10274
10509
  effectId: "background-on-hover",
10275
10510
  options: { colorToken: "surface" }
@@ -10280,13 +10515,12 @@ var init_soft_pill = __esmMin((() => {
10280
10515
  name: "Outline",
10281
10516
  enabled: true,
10282
10517
  priority: 3,
10283
- background: { type: "transparent" },
10284
- textColorToken: "text",
10285
- borderRadius: "rounded-full",
10286
- border: {
10287
- widthClass: "border",
10288
- colorToken: "border"
10518
+ background: {
10519
+ type: "surface",
10520
+ role: "link"
10289
10521
  },
10522
+ borderRadius: "rounded-full",
10523
+ border: { widthClass: "border" },
10290
10524
  effects: { hover: [{
10291
10525
  effectId: "background-on-hover",
10292
10526
  options: { colorToken: "surface" }
@@ -10297,8 +10531,10 @@ var init_soft_pill = __esmMin((() => {
10297
10531
  name: "Ghost",
10298
10532
  enabled: true,
10299
10533
  priority: 3,
10300
- background: { type: "transparent" },
10301
- textColorToken: "text",
10534
+ background: {
10535
+ type: "surface",
10536
+ role: "link"
10537
+ },
10302
10538
  borderRadius: "rounded-full",
10303
10539
  effects: { hover: [{
10304
10540
  effectId: "background-on-hover",
@@ -10313,6 +10549,7 @@ var init_soft_pill = __esmMin((() => {
10313
10549
  //#region ../theme-core/src/buttons/personalities/two-tone-pill.ts
10314
10550
  var solidSecondary, twoTonePill;
10315
10551
  var init_two_tone_pill = __esmMin((() => {
10552
+ init_types$13();
10316
10553
  init_soft_pill();
10317
10554
  init_types$12();
10318
10555
  solidSecondary = {
@@ -10322,9 +10559,8 @@ var init_two_tone_pill = __esmMin((() => {
10322
10559
  priority: 2,
10323
10560
  background: {
10324
10561
  type: "solid",
10325
- colorToken: "secondary"
10562
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
10326
10563
  },
10327
- textColorToken: "onSecondary",
10328
10564
  borderRadius: "rounded-full",
10329
10565
  shadow: {
10330
10566
  elevation: "none",
@@ -10705,6 +10941,276 @@ var init_testimonialQuotePresets = __esmMin((() => {
10705
10941
  serifDisplayQuote = { style: "serif-display" };
10706
10942
  accentGlyphQuote = { style: "accent-glyph" };
10707
10943
  }));
10944
+ //#endregion
10945
+ //#region ../theme-core/src/gradients/types.ts
10946
+ /**
10947
+ * Gradient configuration types and schemas
10948
+ */
10949
+ var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
10950
+ var init_types$11 = __esmMin((() => {
10951
+ init_themeColorTokens();
10952
+ gradientStopSchema = z$1.object({
10953
+ color: themeColorTokenSchema,
10954
+ position: z$1.number().min(0).max(100)
10955
+ });
10956
+ radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
10957
+ gradientConfigSchema = z$1.object({
10958
+ type: z$1.enum([
10959
+ "linear",
10960
+ "radial",
10961
+ "conic"
10962
+ ]).default("linear"),
10963
+ angle: z$1.number().min(0).max(360).optional(),
10964
+ shape: radialGradientShapeSchema.optional(),
10965
+ position: z$1.string().optional(),
10966
+ stops: z$1.array(gradientStopSchema).min(2)
10967
+ });
10968
+ }));
10969
+ //#endregion
10970
+ //#region ../theme-core/src/gradients/presets.ts
10971
+ function parseGradientPresetId(value) {
10972
+ if (typeof value !== "string") return null;
10973
+ const normalized = value.trim();
10974
+ if (!gradientPresetIdSet.has(normalized)) return null;
10975
+ return normalized;
10976
+ }
10977
+ function getGradientPreset(id) {
10978
+ return gradientPresetById[id];
10979
+ }
10980
+ var rawGradientPresets, GRADIENT_PRESETS, GRADIENT_PRESET_IDS, gradientPresetIdSet, gradientPresetById;
10981
+ var init_presets$2 = __esmMin((() => {
10982
+ rawGradientPresets = [
10983
+ {
10984
+ id: "primary-secondary",
10985
+ name: "Primary to Secondary",
10986
+ description: "Blend your primary and secondary brand colors",
10987
+ type: "linear",
10988
+ angle: 135,
10989
+ stops: [{
10990
+ color: "primary-500",
10991
+ position: 0
10992
+ }, {
10993
+ color: "secondary-500",
10994
+ position: 100
10995
+ }]
10996
+ },
10997
+ {
10998
+ id: "primary-accent",
10999
+ name: "Primary to Accent",
11000
+ description: "Energetic gradient from primary to accent",
11001
+ type: "linear",
11002
+ angle: 135,
11003
+ stops: [{
11004
+ color: "primary-500",
11005
+ position: 0
11006
+ }, {
11007
+ color: "accent-500",
11008
+ position: 100
11009
+ }]
11010
+ },
11011
+ {
11012
+ id: "secondary-accent",
11013
+ name: "Secondary to Accent",
11014
+ description: "Vibrant secondary to accent blend",
11015
+ type: "linear",
11016
+ angle: 135,
11017
+ stops: [{
11018
+ color: "secondary-500",
11019
+ position: 0
11020
+ }, {
11021
+ color: "accent-500",
11022
+ position: 100
11023
+ }]
11024
+ },
11025
+ {
11026
+ id: "primary-light-dark",
11027
+ name: "Primary Light to Dark",
11028
+ description: "Subtle primary color fade",
11029
+ type: "linear",
11030
+ angle: 180,
11031
+ stops: [{
11032
+ color: "primary-500",
11033
+ position: 0
11034
+ }, {
11035
+ color: "primary-900",
11036
+ position: 100
11037
+ }]
11038
+ },
11039
+ {
11040
+ id: "primary-dark-light",
11041
+ name: "Primary Dark to Light",
11042
+ description: "Reverse primary fade",
11043
+ type: "linear",
11044
+ angle: 180,
11045
+ stops: [{
11046
+ color: "primary-900",
11047
+ position: 0
11048
+ }, {
11049
+ color: "primary-50",
11050
+ position: 100
11051
+ }]
11052
+ },
11053
+ {
11054
+ id: "secondary-light-dark",
11055
+ name: "Secondary Light to Dark",
11056
+ description: "Subtle secondary color fade",
11057
+ type: "linear",
11058
+ angle: 180,
11059
+ stops: [{
11060
+ color: "secondary-500",
11061
+ position: 0
11062
+ }, {
11063
+ color: "secondary-900",
11064
+ position: 100
11065
+ }]
11066
+ },
11067
+ {
11068
+ id: "accent-light-dark",
11069
+ name: "Accent Light to Dark",
11070
+ description: "Accent color depth fade",
11071
+ type: "linear",
11072
+ angle: 180,
11073
+ stops: [{
11074
+ color: "accent-500",
11075
+ position: 0
11076
+ }, {
11077
+ color: "accent-900",
11078
+ position: 100
11079
+ }]
11080
+ },
11081
+ {
11082
+ id: "background-surface",
11083
+ name: "Background to Surface",
11084
+ description: "Subtle depth using base colors",
11085
+ type: "linear",
11086
+ angle: 180,
11087
+ stops: [{
11088
+ color: "background",
11089
+ position: 0
11090
+ }, {
11091
+ color: "surface",
11092
+ position: 100
11093
+ }]
11094
+ },
11095
+ {
11096
+ id: "neutral-fade",
11097
+ name: "Neutral Gradient",
11098
+ description: "Elegant neutral color fade",
11099
+ type: "linear",
11100
+ angle: 180,
11101
+ stops: [{
11102
+ color: "neutral-900",
11103
+ position: 0
11104
+ }, {
11105
+ color: "neutral-50",
11106
+ position: 100
11107
+ }]
11108
+ },
11109
+ {
11110
+ id: "primary-glow",
11111
+ name: "Primary glow",
11112
+ description: "A soft top-centred glow using your primary palette",
11113
+ type: "radial",
11114
+ shape: "ellipse",
11115
+ position: "top center",
11116
+ stops: [{
11117
+ color: "primary-900",
11118
+ position: 0
11119
+ }, {
11120
+ color: "primary-950",
11121
+ position: 100
11122
+ }],
11123
+ foreground: {
11124
+ textColor: "onPrimary900",
11125
+ headingColor: "onPrimary900",
11126
+ linkColor: "onPrimary900",
11127
+ supportingColor: "onPrimary900"
11128
+ }
11129
+ },
11130
+ {
11131
+ id: "accent-glow",
11132
+ name: "Accent glow",
11133
+ description: "A soft top-centred glow using your accent palette",
11134
+ type: "radial",
11135
+ shape: "ellipse",
11136
+ position: "top center",
11137
+ stops: [{
11138
+ color: "accent-900",
11139
+ position: 0
11140
+ }, {
11141
+ color: "accent-950",
11142
+ position: 100
11143
+ }],
11144
+ foreground: {
11145
+ textColor: "onAccent900",
11146
+ headingColor: "onAccent900",
11147
+ linkColor: "onAccent900",
11148
+ supportingColor: "onAccent900"
11149
+ }
11150
+ },
11151
+ {
11152
+ id: "primary-secondary-accent",
11153
+ name: "Brand Trio",
11154
+ description: "All three brand colors in harmony",
11155
+ type: "linear",
11156
+ angle: 135,
11157
+ stops: [
11158
+ {
11159
+ color: "primary-500",
11160
+ position: 0
11161
+ },
11162
+ {
11163
+ color: "secondary-500",
11164
+ position: 50
11165
+ },
11166
+ {
11167
+ color: "accent-500",
11168
+ position: 100
11169
+ }
11170
+ ]
11171
+ }
11172
+ ];
11173
+ GRADIENT_PRESETS = rawGradientPresets.map((preset) => ({
11174
+ ...preset,
11175
+ id: preset.id,
11176
+ stops: preset.stops
11177
+ }));
11178
+ GRADIENT_PRESET_IDS = GRADIENT_PRESETS.map((preset) => preset.id);
11179
+ gradientPresetIdSet = new Set(GRADIENT_PRESET_IDS);
11180
+ gradientPresetById = Object.fromEntries(GRADIENT_PRESETS.map((preset) => [preset.id, preset]));
11181
+ }));
11182
+ //#endregion
11183
+ //#region ../theme-core/src/gradients/utils.ts
11184
+ /**
11185
+ * Convert a GradientConfig to a CSS gradient string
11186
+ *
11187
+ * @param config - The gradient configuration using theme tokens
11188
+ * @param tokens - Map of theme color tokens to hex values
11189
+ * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
11190
+ */
11191
+ function gradientToCss(config, tokens) {
11192
+ const stops = config.stops.map((stop) => {
11193
+ return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
11194
+ }).join(", ");
11195
+ const type = config.type ?? "linear";
11196
+ if (type === "radial") {
11197
+ const position = config.position ?? "center";
11198
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
11199
+ }
11200
+ if (type === "conic") {
11201
+ const position = config.position ?? "center";
11202
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
11203
+ }
11204
+ return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
11205
+ }
11206
+ var init_utils$4 = __esmMin((() => {}));
11207
+ //#endregion
11208
+ //#region ../theme-core/src/gradients/index.ts
11209
+ var init_gradients = __esmMin((() => {
11210
+ init_types$11();
11211
+ init_presets$2();
11212
+ init_utils$4();
11213
+ }));
10708
11214
  var init_customizableSurfaces = __esmMin((() => {
10709
11215
  init_types$16();
10710
11216
  })), logoTextConfidenceValues, logoAssetShapeValues, logoKindValues, logoDensityValues, logoContainsTextSchema, logoAnalysisSourceSchema, brandDisplayModeValues, logoAccommodationPatternValues, logoSizePolicyValues;
@@ -13026,14 +13532,12 @@ var init_background$2 = __esmMin((() => {
13026
13532
  ]
13027
13533
  },
13028
13534
  generateCSS: (ctx) => {
13029
- const { themeId, variantId, options, tokens } = ctx;
13535
+ const { themeId, variantId, options, tokens, buttonConfig } = ctx;
13030
13536
  const colorToken = options.colorToken || "neutral-800";
13031
- const color = tokens.getColor(colorToken);
13032
- const textColorToken = typeof options.textColorToken === "string" ? options.textColorToken : null;
13033
13537
  return `
13034
13538
  /* Add background on hover */
13035
13539
  :where([data-theme-scope="${themeId}"]) .${variantId}:hover {
13036
- background-color: ${color};${textColorToken ? `\n color: ${tokens.getColor(textColorToken)};` : ""}
13540
+ background-color: ${tokens.getColor(colorToken)};${"textColorToken" in buttonConfig && typeof options.textColorToken === "string" ? `\n color: ${tokens.getColor(options.textColorToken)};` : ""}
13037
13541
  }
13038
13542
  `;
13039
13543
  }
@@ -13052,10 +13556,10 @@ var init_background$2 = __esmMin((() => {
13052
13556
  default: 50
13053
13557
  },
13054
13558
  generateCSS: (ctx) => {
13055
- const { themeId, variantId, stateGroup, options, buttonConfig } = ctx;
13559
+ const { themeId, variantId, stateGroup, options } = ctx;
13056
13560
  const rawOpacity = options.opacity;
13057
13561
  const clampedOpacity = Math.max(0, Math.min(100, typeof rawOpacity === "number" && !Number.isNaN(rawOpacity) ? rawOpacity : 50));
13058
- const cssVar = `var(--tb-${options.colorToken || buttonConfig.textColorToken || "neutral-800"})`;
13562
+ const cssVar = `var(--tb-${options.colorToken || "neutral-800"})`;
13059
13563
  return `
13060
13564
  /* Add semi-transparent background (${stateGroup}) */
13061
13565
  :where([data-theme-scope="${themeId}"]) .${variantId}${stateGroup === "base" ? "" : `:${stateGroup}`} {
@@ -13232,7 +13736,7 @@ var init_shadow = __esmMin((() => {
13232
13736
  const spread = options.spread || 10;
13233
13737
  let glowColor;
13234
13738
  if (options.glowColorToken && typeof options.glowColorToken === "string") glowColor = tokens.getColor(options.glowColorToken);
13235
- else if (buttonConfig.border?.colorToken) glowColor = tokens.getColor(buttonConfig.border.colorToken);
13739
+ else if (buttonConfig.border) glowColor = "colorToken" in buttonConfig.border ? tokens.getColor(buttonConfig.border.colorToken) : "currentColor";
13236
13740
  else if (buttonConfig.background.type === "solid") glowColor = tokens.getColor(buttonConfig.background.colorToken ?? "primary-400");
13237
13741
  else glowColor = tokens.getColor("primary-400");
13238
13742
  return `
@@ -13314,9 +13818,9 @@ function generateShadowValue$1(elevation, softness, position = "bottom", color)
13314
13818
  case "crisp": return `${xOffset}px ${yOffset}px ${baseOffset}px ${config.spread}px ${color ?? "rgb(0 0 0 / 0.4)"}`;
13315
13819
  }
13316
13820
  }
13317
- var GRADIENT_DIRECTION_MAP$3, BORDER_RADIUS_MAP, ELEVATION_OFFSET, BORDER_WIDTH_MAP$4, FONT_SIZE_MAP, DEFAULT_BUTTON_SIZES;
13821
+ var GRADIENT_DIRECTION_MAP$2, BORDER_RADIUS_MAP, ELEVATION_OFFSET, BORDER_WIDTH_MAP$4, FONT_SIZE_MAP, DEFAULT_BUTTON_SIZES;
13318
13822
  var init_constants$2 = __esmMin((() => {
13319
- GRADIENT_DIRECTION_MAP$3 = {
13823
+ GRADIENT_DIRECTION_MAP$2 = {
13320
13824
  "to-r": "to right",
13321
13825
  "to-l": "to left",
13322
13826
  "to-t": "to top",
@@ -14261,30 +14765,6 @@ function generateSingleEffectCSS(themeId, variantId, stateGroup, effectApp, elem
14261
14765
  var init_generateEffectsCSS = __esmMin((() => {
14262
14766
  init_registry$1();
14263
14767
  }));
14264
- /**
14265
- * Get contrasting text color for a button background
14266
- *
14267
- * This function returns theme-aware text colors using the neutral scale,
14268
- * which is guaranteed to exist in every theme and harmonizes with the design.
14269
- *
14270
- * Uses neutral-50 (lightest) for dark backgrounds and neutral-950 (darkest)
14271
- * for light backgrounds. This ensures excellent contrast while respecting
14272
- * the theme's neutral palette (warm/cool tinting).
14273
- *
14274
- * For solid backgrounds with primary/secondary/neutral colors:
14275
- * - Dark backgrounds (shade >= 500): neutral-50 (very light)
14276
- * - Light backgrounds (shade < 500): neutral-950 (very dark)
14277
- */
14278
- function getContrastingTextColorToken(backgroundToken, theme) {
14279
- const isLightTheme = theme.palette.meta.mode === "light";
14280
- if (backgroundToken.startsWith("primary-") || backgroundToken.startsWith("secondary-")) return "neutral-50";
14281
- if (backgroundToken.startsWith("neutral-")) {
14282
- const match = backgroundToken.match(/neutral-(\d+)/);
14283
- if (match?.[1]) return parseInt(match[1], 10) >= 500 ? "neutral-50" : "neutral-950";
14284
- }
14285
- return isLightTheme ? "neutral-50" : "neutral-950";
14286
- }
14287
- var init_contrast$1 = __esmMin((() => {}));
14288
14768
  //#endregion
14289
14769
  //#region ../theme-core/src/buttons/generateDefaultButtonSystem.ts
14290
14770
  /**
@@ -14328,13 +14808,8 @@ function generateDefaultButtonSystem(theme) {
14328
14808
  priority: 1,
14329
14809
  background: {
14330
14810
  type: "solid",
14331
- colorToken: "primary"
14332
- },
14333
- textColorToken: getContrastingTextColorToken("primary", theme),
14334
- effects: { hover: [{
14335
- effectId: "opacity-reduce",
14336
- options: { reduction: 15 }
14337
- }] }
14811
+ colorToken: unsafeAsOpaqueButtonColourToken("primary")
14812
+ }
14338
14813
  },
14339
14814
  {
14340
14815
  id: "secondary",
@@ -14343,51 +14818,39 @@ function generateDefaultButtonSystem(theme) {
14343
14818
  priority: 2,
14344
14819
  background: {
14345
14820
  type: "solid",
14346
- colorToken: "neutral-700"
14347
- },
14348
- textColorToken: getContrastingTextColorToken("neutral-700", theme),
14349
- effects: { hover: [{
14350
- effectId: "opacity-reduce",
14351
- options: { reduction: 15 }
14352
- }] }
14821
+ colorToken: unsafeAsOpaqueButtonColourToken("neutral-700")
14822
+ }
14353
14823
  },
14354
14824
  {
14355
14825
  id: "outline",
14356
14826
  name: "Outline",
14357
14827
  enabled: true,
14358
14828
  priority: 3,
14359
- background: { type: "transparent" },
14360
- textColorToken: "primary",
14829
+ background: {
14830
+ type: "surface",
14831
+ role: "link"
14832
+ },
14361
14833
  shadow: {
14362
14834
  elevation: "none",
14363
14835
  softness: null,
14364
14836
  position: "bottom"
14365
14837
  },
14366
- border: {
14367
- colorToken: "primary",
14368
- widthClass: borderWidthClass
14369
- },
14370
- effects: { hover: [{
14371
- effectId: "opacity-reduce",
14372
- options: { reduction: 15 }
14373
- }] }
14838
+ border: { widthClass: borderWidthClass }
14374
14839
  },
14375
14840
  {
14376
14841
  id: "ghost",
14377
14842
  name: "Ghost",
14378
14843
  enabled: true,
14379
14844
  priority: 3,
14380
- background: { type: "transparent" },
14381
- textColorToken: "primary",
14845
+ background: {
14846
+ type: "surface",
14847
+ role: "link"
14848
+ },
14382
14849
  shadow: {
14383
14850
  elevation: "none",
14384
14851
  softness: null,
14385
14852
  position: "bottom"
14386
- },
14387
- effects: { hover: [{
14388
- effectId: "opacity-reduce",
14389
- options: { reduction: 15 }
14390
- }] }
14853
+ }
14391
14854
  }
14392
14855
  ];
14393
14856
  return {
@@ -14404,7 +14867,7 @@ function generateDefaultButtonSystem(theme) {
14404
14867
  }
14405
14868
  var BORDER_WIDTH_TO_CLASS_MAP, VALID_CORNER_STYLES;
14406
14869
  var init_generateDefaultButtonSystem = __esmMin((() => {
14407
- init_contrast$1();
14870
+ init_types$13();
14408
14871
  BORDER_WIDTH_TO_CLASS_MAP = {
14409
14872
  none: "border-0",
14410
14873
  hairline: "border",
@@ -14440,8 +14903,420 @@ var init_affordanceIcons = __esmMin((() => {
14440
14903
  };
14441
14904
  }));
14442
14905
  //#endregion
14906
+ //#region ../theme-core/src/buttons/resolveButtonColourStates.ts
14907
+ function compileButtonColourStates(input) {
14908
+ const baseTransition = applyColourEffects({
14909
+ variantId: input.variant.id,
14910
+ state: "base",
14911
+ treatment: input.variant.background,
14912
+ effects: input.variant.effects?.base,
14913
+ palette: input.palette
14914
+ });
14915
+ if (!baseTransition.ok) return baseTransition;
14916
+ const stateTreatments = {
14917
+ base: baseTransition.treatment,
14918
+ hover: hoverTreatment(input.variant, input.global, baseTransition.treatment),
14919
+ focus: baseTransition.treatment,
14920
+ active: baseTransition.treatment,
14921
+ disabled: baseTransition.treatment
14922
+ };
14923
+ const nonColourEffects = { ...baseTransition.nonColourEffects.length > 0 ? { base: [...baseTransition.nonColourEffects] } : {} };
14924
+ for (const state of [
14925
+ "hover",
14926
+ "focus",
14927
+ "active"
14928
+ ]) {
14929
+ const transition = applyColourEffects({
14930
+ variantId: input.variant.id,
14931
+ state,
14932
+ treatment: stateTreatments[state],
14933
+ effects: input.variant.effects?.[state],
14934
+ palette: input.palette
14935
+ });
14936
+ if (!transition.ok) return transition;
14937
+ stateTreatments[state] = transition.treatment;
14938
+ if (transition.nonColourEffects.length > 0) nonColourEffects[state] = [...transition.nonColourEffects];
14939
+ }
14940
+ const resolved = {};
14941
+ for (const state of BUTTON_VISUAL_STATES) {
14942
+ const result = resolveTreatment$1({
14943
+ variantId: input.variant.id,
14944
+ state,
14945
+ treatment: stateTreatments[state],
14946
+ palette: input.palette
14947
+ });
14948
+ if (!result.ok) return result;
14949
+ resolved[state] = result.colour;
14950
+ }
14951
+ return {
14952
+ ok: true,
14953
+ states: resolved,
14954
+ focusIndicator: resolveFocusIndicator(resolved.focus),
14955
+ nonColourEffects
14956
+ };
14957
+ }
14958
+ function formatButtonColourContractError(error) {
14959
+ switch (error.tag) {
14960
+ case "unknown_palette_token": return `Button "${error.variantId}" ${error.state} state uses unknown palette token "${error.token}".`;
14961
+ case "missing_on_colour": return `Button "${error.variantId}" ${error.state} state cannot derive ${error.foregroundToken} from ${error.backgroundToken}.`;
14962
+ case "insufficient_contrast": return `Button "${error.variantId}" ${error.state} state has ${error.ratio.toFixed(2)}:1 contrast (${error.requiredRatio}:1 required).`;
14963
+ case "unsupported_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" is not contrast-safe (${error.reason}).`;
14964
+ case "invalid_colour_effect_options": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" has an invalid ${error.option} option.`;
14965
+ case "inapplicable_colour_effect": return `Button "${error.variantId}" ${error.state} effect "${error.effectId}" cannot apply to a ${error.treatment} treatment.`;
14966
+ case "unknown_button_effect": return `Button "${error.variantId}" ${error.state} uses unknown effect "${error.effectId}".`;
14967
+ }
14968
+ }
14969
+ function hoverTreatment(variant, global, fallback) {
14970
+ const token = variant.hoverBackgroundToken ?? (global.hoverColor === "token" ? global.hoverColorToken : void 0);
14971
+ return token === void 0 ? fallback : {
14972
+ type: "solid",
14973
+ colorToken: token
14974
+ };
14975
+ }
14976
+ function applyColourEffects(input) {
14977
+ let treatment = input.treatment;
14978
+ const nonColourEffects = [];
14979
+ for (const effect of input.effects ?? []) {
14980
+ const policy = getButtonEffectPolicy(effect.effectId);
14981
+ if (policy === null) return unknownEffect(input, effect);
14982
+ switch (policy.classification) {
14983
+ case "non-colour":
14984
+ nonColourEffects.push(effect);
14985
+ break;
14986
+ case "unsupported-colour":
14987
+ case "unsupported-background-overlay":
14988
+ case "not-button": return unsupportedEffect(input, effect, policy.reason);
14989
+ case "colour-transition":
14990
+ if (policy.transition.kind === "adjust-shade") {
14991
+ if (treatment.type !== "solid") return inapplicableEffect(input, effect, treatment);
14992
+ const amount = readShadeAmount(effect);
14993
+ if (amount === null) return invalidEffectOption(input, effect, "amount");
14994
+ const signedAmount = policy.transition.direction === "darker" ? amount : -amount;
14995
+ treatment = {
14996
+ type: "solid",
14997
+ colorToken: adjustShade(treatment.colorToken, signedAmount, input.palette)
14998
+ };
14999
+ break;
15000
+ }
15001
+ if (policy.transition.kind === "replace-background") {
15002
+ const colorToken = readOpaqueToken(effect, "colorToken", "neutral-800");
15003
+ if (colorToken === null) return invalidEffectOption(input, effect, "colorToken");
15004
+ treatment = {
15005
+ type: "solid",
15006
+ colorToken
15007
+ };
15008
+ break;
15009
+ }
15010
+ return unknownEffect(input, effect);
15011
+ }
15012
+ }
15013
+ return {
15014
+ ok: true,
15015
+ treatment,
15016
+ nonColourEffects
15017
+ };
15018
+ }
15019
+ function resolveTreatment$1(input) {
15020
+ const treatment = input.treatment;
15021
+ switch (treatment.type) {
15022
+ case "surface": return {
15023
+ ok: true,
15024
+ colour: {
15025
+ kind: "surface",
15026
+ role: treatment.role,
15027
+ backgroundCss: "transparent",
15028
+ foregroundCss: surfaceForegroundValue(treatment.role)
15029
+ }
15030
+ };
15031
+ case "solid": return resolveSolid(input, treatment.colorToken);
15032
+ case "gradient": return resolveGradient$2(input, treatment);
15033
+ }
15034
+ }
15035
+ function resolveFocusIndicator(colour) {
15036
+ switch (colour.kind) {
15037
+ case "solid": return {
15038
+ kind: "two-tone",
15039
+ innerCss: colour.foregroundCss,
15040
+ outerCss: colour.backgroundCss,
15041
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
15042
+ };
15043
+ case "gradient": return {
15044
+ kind: "two-tone",
15045
+ innerCss: colour.foregroundCss,
15046
+ outerCss: tokenCss(colour.backgroundTokens[0]),
15047
+ minimumPairContrast: BUTTON_CONTRAST_POLICY.textMinimumRatio
15048
+ };
15049
+ case "surface": return {
15050
+ kind: "surface-role",
15051
+ colorCss: colour.foregroundCss,
15052
+ minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
15053
+ };
15054
+ }
15055
+ }
15056
+ function resolveSolid(input, backgroundToken) {
15057
+ const backgroundHex = paletteHex(input, backgroundToken);
15058
+ if (!backgroundHex.ok) return backgroundHex;
15059
+ const foregroundToken = unsafeAsOpaqueButtonColourToken(onColorTokenName(backgroundToken));
15060
+ const foregroundHex = input.palette[foregroundToken];
15061
+ if (typeof foregroundHex !== "string") return {
15062
+ ok: false,
15063
+ error: {
15064
+ tag: "missing_on_colour",
15065
+ variantId: input.variantId,
15066
+ state: input.state,
15067
+ backgroundToken,
15068
+ foregroundToken
15069
+ }
15070
+ };
15071
+ const contrast = validateContrast({
15072
+ ...input,
15073
+ background: backgroundToken,
15074
+ backgroundHex: backgroundHex.hex,
15075
+ foreground: foregroundToken,
15076
+ foregroundHex
15077
+ });
15078
+ if (!contrast.ok) return contrast;
15079
+ return {
15080
+ ok: true,
15081
+ colour: {
15082
+ kind: "solid",
15083
+ backgroundToken,
15084
+ foregroundToken,
15085
+ backgroundCss: tokenCss(backgroundToken),
15086
+ foregroundCss: tokenCss(foregroundToken)
15087
+ }
15088
+ };
15089
+ }
15090
+ function resolveGradient$2(input, treatment) {
15091
+ const foregroundHex = paletteHex(input, treatment.foregroundToken);
15092
+ if (!foregroundHex.ok) return foregroundHex;
15093
+ const stopHexes = [];
15094
+ for (const token of treatment.stops) {
15095
+ const stop = paletteHex(input, token);
15096
+ if (!stop.ok) return stop;
15097
+ stopHexes.push(stop.hex);
15098
+ }
15099
+ for (let segment = 0; segment < stopHexes.length - 1; segment += 1) {
15100
+ const start = stopHexes[segment];
15101
+ const end = stopHexes[segment + 1];
15102
+ const startToken = treatment.stops[segment];
15103
+ const endToken = treatment.stops[segment + 1];
15104
+ if (start === void 0 || end === void 0 || startToken === void 0 || endToken === void 0) continue;
15105
+ for (let sample = 0; sample <= BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment; sample += 1) {
15106
+ const position = sample / BUTTON_CONTRAST_POLICY.gradientSamplesPerSegment;
15107
+ const sampleHex = interpolateHex(start, end, position);
15108
+ const contrast = validateContrast({
15109
+ ...input,
15110
+ background: `${startToken}→${endToken}@${position.toFixed(2)}`,
15111
+ backgroundHex: sampleHex,
15112
+ foreground: treatment.foregroundToken,
15113
+ foregroundHex: foregroundHex.hex
15114
+ });
15115
+ if (!contrast.ok) return contrast;
15116
+ }
15117
+ }
15118
+ const direction = GRADIENT_DIRECTION_MAP$2[treatment.direction] ?? "to right";
15119
+ return {
15120
+ ok: true,
15121
+ colour: {
15122
+ kind: "gradient",
15123
+ backgroundTokens: treatment.stops,
15124
+ foregroundToken: treatment.foregroundToken,
15125
+ backgroundCss: `linear-gradient(${direction}, ${treatment.stops.map(tokenCss).join(", ")})`,
15126
+ foregroundCss: tokenCss(treatment.foregroundToken)
15127
+ }
15128
+ };
15129
+ }
15130
+ function paletteHex(input, token) {
15131
+ const hex = input.palette[token];
15132
+ return typeof hex === "string" ? {
15133
+ ok: true,
15134
+ hex
15135
+ } : {
15136
+ ok: false,
15137
+ error: {
15138
+ tag: "unknown_palette_token",
15139
+ variantId: input.variantId,
15140
+ state: input.state,
15141
+ token
15142
+ }
15143
+ };
15144
+ }
15145
+ function validateContrast(input) {
15146
+ const ratio = contrastRatio(input.backgroundHex, input.foregroundHex);
15147
+ return ratio >= BUTTON_CONTRAST_POLICY.textMinimumRatio ? { ok: true } : {
15148
+ ok: false,
15149
+ error: {
15150
+ tag: "insufficient_contrast",
15151
+ variantId: input.variantId,
15152
+ state: input.state,
15153
+ background: input.background,
15154
+ foreground: input.foreground,
15155
+ ratio,
15156
+ requiredRatio: BUTTON_CONTRAST_POLICY.textMinimumRatio
15157
+ }
15158
+ };
15159
+ }
15160
+ function tokenCss(token) {
15161
+ return `rgb(var(--tb-${token}))`;
15162
+ }
15163
+ function adjustShade(token, amount, palette) {
15164
+ const match = token.match(/^(.*)-(\d{2,3})$/);
15165
+ const base = match?.[1] ?? token;
15166
+ const currentShade = match?.[2] === void 0 ? 500 : Number(match[2]);
15167
+ const availableShades = [
15168
+ 50,
15169
+ 100,
15170
+ 200,
15171
+ 300,
15172
+ 400,
15173
+ 500,
15174
+ 600,
15175
+ 700,
15176
+ 800,
15177
+ 900,
15178
+ 950
15179
+ ].filter((shade) => typeof palette[`${base}-${shade}`] === "string");
15180
+ if (availableShades.length === 0) return token;
15181
+ const firstShade = availableShades[0];
15182
+ if (firstShade === void 0) return token;
15183
+ const exactIndex = availableShades.indexOf(currentShade);
15184
+ const startingIndex = exactIndex >= 0 ? exactIndex : availableShades.indexOf(availableShades.reduce((closestShade, shade) => Math.abs(shade - currentShade) < Math.abs(closestShade - currentShade) ? shade : closestShade, firstShade));
15185
+ const stepCount = Math.abs(amount) / 100;
15186
+ const direction = amount < 0 ? -1 : 1;
15187
+ const targetShade = availableShades[Math.max(0, Math.min(availableShades.length - 1, startingIndex + direction * stepCount))];
15188
+ return targetShade === void 0 ? token : unsafeAsOpaqueButtonColourToken(`${base}-${targetShade}`);
15189
+ }
15190
+ function readShadeAmount(effect) {
15191
+ const value = effect.options?.amount ?? 100;
15192
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 && value % 100 === 0 ? value : null;
15193
+ }
15194
+ function readOpaqueToken(effect, key, fallback) {
15195
+ return parseOpaqueButtonColourToken(effect.options?.[key] ?? fallback);
15196
+ }
15197
+ function unsupportedEffect(input, effect, reason) {
15198
+ return {
15199
+ ok: false,
15200
+ error: {
15201
+ tag: "unsupported_colour_effect",
15202
+ variantId: input.variantId,
15203
+ state: input.state,
15204
+ effectId: effect.effectId,
15205
+ reason
15206
+ }
15207
+ };
15208
+ }
15209
+ function invalidEffectOption(input, effect, option) {
15210
+ return {
15211
+ ok: false,
15212
+ error: {
15213
+ tag: "invalid_colour_effect_options",
15214
+ variantId: input.variantId,
15215
+ state: input.state,
15216
+ effectId: effect.effectId,
15217
+ option
15218
+ }
15219
+ };
15220
+ }
15221
+ function inapplicableEffect(input, effect, treatment) {
15222
+ return {
15223
+ ok: false,
15224
+ error: {
15225
+ tag: "inapplicable_colour_effect",
15226
+ variantId: input.variantId,
15227
+ state: input.state,
15228
+ effectId: effect.effectId,
15229
+ treatment: treatment.type
15230
+ }
15231
+ };
15232
+ }
15233
+ function unknownEffect(input, effect) {
15234
+ return {
15235
+ ok: false,
15236
+ error: {
15237
+ tag: "unknown_button_effect",
15238
+ variantId: input.variantId,
15239
+ state: input.state,
15240
+ effectId: effect.effectId
15241
+ }
15242
+ };
15243
+ }
15244
+ function interpolateHex(startHex, endHex, position) {
15245
+ const start = hexToRgb$1(startHex);
15246
+ const end = hexToRgb$1(endHex);
15247
+ const channel = (from, to) => Math.round(from + (to - from) * position).toString(16).padStart(2, "0");
15248
+ return `#${channel(start.r, end.r)}${channel(start.g, end.g)}${channel(start.b, end.b)}`;
15249
+ }
15250
+ var BUTTON_VISUAL_STATES, BUTTON_CONTRAST_POLICY;
15251
+ var init_resolveButtonColourStates = __esmMin((() => {
15252
+ init_contrast$1();
15253
+ init_colorConversion();
15254
+ init_onColor();
15255
+ init_foregroundContract();
15256
+ init_types$13();
15257
+ init_constants$2();
15258
+ init_effectClassification();
15259
+ BUTTON_VISUAL_STATES = [
15260
+ "base",
15261
+ "hover",
15262
+ "focus",
15263
+ "active",
15264
+ "disabled"
15265
+ ];
15266
+ BUTTON_CONTRAST_POLICY = {
15267
+ textMinimumRatio: 4.5,
15268
+ nonTextMinimumRatio: 3,
15269
+ gradientSamplesPerSegment: 20,
15270
+ alphaBackgrounds: "reject-without-known-surface",
15271
+ disabled: "retain-full-colour-contract"
15272
+ };
15273
+ }));
15274
+ //#endregion
15275
+ //#region ../theme-core/src/buttons/resolvedButtonCss.ts
15276
+ /**
15277
+ * Canonical colour declaration mapping shared by full themes and ThemeBridge.
15278
+ * Both background properties are always emitted so transitions cannot retain
15279
+ * a stale gradient or solid layer.
15280
+ */
15281
+ function resolvedButtonColourDeclarations(colour) {
15282
+ switch (colour.kind) {
15283
+ case "solid": return [
15284
+ ["background-color", colour.backgroundCss],
15285
+ ["background-image", "none"],
15286
+ ["color", colour.foregroundCss]
15287
+ ];
15288
+ case "gradient": return [
15289
+ ["background-color", "transparent"],
15290
+ ["background-image", colour.backgroundCss],
15291
+ ["color", colour.foregroundCss]
15292
+ ];
15293
+ case "surface": return [
15294
+ ["background-color", colour.backgroundCss],
15295
+ ["background-image", "none"],
15296
+ ["color", colour.foregroundCss]
15297
+ ];
15298
+ }
15299
+ }
15300
+ function resolvedButtonFocusDeclarations(indicator) {
15301
+ return indicator.kind === "two-tone" ? [
15302
+ ["outline", `2px solid ${indicator.innerCss}`],
15303
+ ["outline-offset", "2px"],
15304
+ ["box-shadow", `0 0 0 4px ${indicator.outerCss}`]
15305
+ ] : [["outline", `3px solid ${indicator.colorCss}`], ["outline-offset", "3px"]];
15306
+ }
15307
+ var RESOLVED_BUTTON_DISABLED_DECLARATIONS;
15308
+ var init_resolvedButtonCss = __esmMin((() => {
15309
+ RESOLVED_BUTTON_DISABLED_DECLARATIONS = [
15310
+ ["cursor", "not-allowed"],
15311
+ ["transform", "none"],
15312
+ ["box-shadow", "none"],
15313
+ ["outline", "2px dashed currentColor"],
15314
+ ["outline-offset", "-4px"]
15315
+ ];
15316
+ }));
15317
+ //#endregion
14443
15318
  //#region ../theme-core/src/buttons/generateButtonCss.ts
14444
- function rule(selector, declarations) {
15319
+ function rule$1(selector, declarations) {
14445
15320
  return {
14446
15321
  selectors: typeof selector === "string" ? [selector] : selector,
14447
15322
  declarations
@@ -14482,6 +15357,7 @@ function shadowSizeToShadow(size, theme) {
14482
15357
  function generateButtonCss(options) {
14483
15358
  const { themeId, theme, buttonSystem: providedButtonSystem } = options;
14484
15359
  const tokens = new TokenResolver(theme);
15360
+ const palette = expandPalette(theme.palette);
14485
15361
  const buttonSystem = providedButtonSystem ?? generateDefaultButtonSystem(theme);
14486
15362
  const themeSizes = {
14487
15363
  ...DEFAULT_BUTTON_SIZES,
@@ -14490,34 +15366,109 @@ function generateButtonCss(options) {
14490
15366
  const enabledVariants = buttonSystem.variants.filter((v) => v.enabled);
14491
15367
  const aliasSource = resolveAliasSource(enabledVariants);
14492
15368
  const chunks = [];
14493
- for (const variant of enabledVariants) chunks.push(...variantChunks(variant, buttonSystem.global, themeSizes, themeId, tokens, theme));
15369
+ for (const variant of enabledVariants) {
15370
+ const compiled = compileRuntimeVariant(variant, buttonSystem.global, palette);
15371
+ if (compiled.fallbackError) chunks.push({ raw: `/* ${formatButtonColourContractError(compiled.fallbackError)} Using contrast-safe surface fallback. */` });
15372
+ chunks.push(...variantChunks(compiled.variant, compiled.global, themeSizes, themeId, tokens, theme, compiled.colours, compiled.focusIndicator, compiled.nonColourEffects));
15373
+ }
14494
15374
  if (aliasSource) {
14495
- const alias = {
15375
+ const compiled = compileRuntimeVariant({
14496
15376
  ...aliasSource,
14497
15377
  id: DEFAULT_VARIANT_ALIAS_ID,
14498
15378
  name: "Default"
14499
- };
14500
- chunks.push(...variantChunks(alias, buttonSystem.global, themeSizes, themeId, tokens, theme));
15379
+ }, buttonSystem.global, palette);
15380
+ if (compiled.fallbackError) chunks.push({ raw: `/* ${formatButtonColourContractError(compiled.fallbackError)} Using contrast-safe surface fallback. */` });
15381
+ chunks.push(...variantChunks(compiled.variant, compiled.global, themeSizes, themeId, tokens, theme, compiled.colours, compiled.focusIndicator, compiled.nonColourEffects));
14501
15382
  }
14502
15383
  return chunks.map(renderChunk).join("\n\n");
14503
15384
  }
15385
+ function compileRuntimeVariant(variant, global, palette) {
15386
+ const result = compileButtonColourStates({
15387
+ variant,
15388
+ global,
15389
+ palette
15390
+ });
15391
+ if (result.ok) return {
15392
+ variant,
15393
+ global,
15394
+ colours: result.states,
15395
+ focusIndicator: result.focusIndicator,
15396
+ nonColourEffects: result.nonColourEffects
15397
+ };
15398
+ const fallbackVariant = {
15399
+ ...variant,
15400
+ background: {
15401
+ type: "surface",
15402
+ role: "link"
15403
+ },
15404
+ hoverBackgroundToken: void 0,
15405
+ effects: void 0
15406
+ };
15407
+ const fallbackGlobal = {
15408
+ ...global,
15409
+ hoverColor: "none",
15410
+ hoverColorToken: void 0
15411
+ };
15412
+ const fallback = compileButtonColourStates({
15413
+ variant: fallbackVariant,
15414
+ global: fallbackGlobal,
15415
+ palette
15416
+ });
15417
+ if (!fallback.ok) {
15418
+ const colour = {
15419
+ kind: "surface",
15420
+ role: "link",
15421
+ backgroundCss: "transparent",
15422
+ foregroundCss: surfaceForegroundValue("link")
15423
+ };
15424
+ return {
15425
+ variant: fallbackVariant,
15426
+ global: fallbackGlobal,
15427
+ colours: {
15428
+ base: colour,
15429
+ hover: colour,
15430
+ focus: colour,
15431
+ active: colour,
15432
+ disabled: colour
15433
+ },
15434
+ focusIndicator: {
15435
+ kind: "surface-role",
15436
+ colorCss: colour.foregroundCss,
15437
+ minimumSurfaceContrast: BUTTON_CONTRAST_POLICY.nonTextMinimumRatio
15438
+ },
15439
+ nonColourEffects: {},
15440
+ fallbackError: result.error
15441
+ };
15442
+ }
15443
+ return {
15444
+ variant: fallbackVariant,
15445
+ global: fallbackGlobal,
15446
+ colours: fallback.states,
15447
+ focusIndicator: fallback.focusIndicator,
15448
+ nonColourEffects: fallback.nonColourEffects,
15449
+ fallbackError: result.error
15450
+ };
15451
+ }
14504
15452
  /** Pick the highest-priority variant whose role we'll alias to `.default`. */
14505
15453
  function resolveAliasSource(enabled) {
14506
15454
  if (enabled.some((v) => v.id === DEFAULT_VARIANT_ALIAS_ID)) return null;
14507
15455
  return enabled.slice().sort((a, b) => a.priority - b.priority)[0] ?? null;
14508
15456
  }
14509
- function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
15457
+ function variantChunks(variant, global, themeSizes, themeId, tokens, theme, colours, focusIndicator, nonColourEffects) {
14510
15458
  const out = [];
14511
15459
  const variantId = parseButtonVariantIdForCss(variant.id);
14512
15460
  const selector = `:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}`;
14513
- out.push(variantBaseRule(variant, selector, global, tokens, theme));
15461
+ out.push(variantBaseRule(variant, selector, global, tokens, theme, colours.base));
14514
15462
  out.push({ raw: generateInteractiveChildInheritanceCSS(selector) });
14515
- const hoverBg = variantHoverBackgroundRule(variant, variantId, global, themeId, tokens);
14516
- if (hoverBg) out.push(hoverBg);
14517
- out.push(variantFocusVisibleRule(variantId, themeId));
14518
- const effects = variantEffectsCss(variant, themeId, tokens, theme);
15463
+ for (const state of [
15464
+ "hover",
15465
+ "focus",
15466
+ "active"
15467
+ ]) if (!resolvedColoursEqual(colours.base, colours[state])) out.push(variantStateColourRule(variantId, themeId, state, colours[state]));
15468
+ const effects = variantEffectsCss(variant, nonColourEffects, themeId, tokens, theme);
14519
15469
  if (effects) out.push({ raw: effects });
14520
- const affordance = variantAffordanceRule(variant, selector, tokens);
15470
+ out.push(variantFocusVisibleRule(variantId, themeId, focusIndicator));
15471
+ const affordance = variantAffordanceRule(variant, selector);
14521
15472
  if (affordance) out.push(affordance);
14522
15473
  out.push(...variantDisabledRules(variantId, themeId));
14523
15474
  out.push(...variantSizeRules(variant, variantId, themeSizes, themeId));
@@ -14532,21 +15483,20 @@ function variantChunks(variant, global, themeSizes, themeId, tokens, theme) {
14532
15483
  * one (node overrides personality). Colour comes from the affordance token, or
14533
15484
  * `currentColor` (the button text colour) when no token is given.
14534
15485
  */
14535
- function variantAffordanceRule(variant, selector, tokens) {
15486
+ function variantAffordanceRule(variant, selector) {
14536
15487
  const affordance = variant.affordance;
14537
15488
  if (!affordance) return null;
14538
15489
  const maskUrl = affordanceIconMaskUrl(affordance.iconId);
14539
15490
  if (!maskUrl) return null;
14540
- const color = affordance.colorToken ? variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(affordance.colorToken)) : tokens.getColor(affordance.colorToken) : "currentColor";
14541
15491
  const mask = `url("${maskUrl}") no-repeat center / contain`;
14542
- return rule(`${selector}:not(.${AFFORDANCE_SUPPRESS_CLASS})::after`, [
15492
+ return rule$1(`${selector}:not(.${AFFORDANCE_SUPPRESS_CLASS})::after`, [
14543
15493
  ["content", "\"\""],
14544
15494
  ["display", "inline-block"],
14545
15495
  ["width", "1em"],
14546
15496
  ["height", "1em"],
14547
15497
  ["margin-inline-start", "0.5em"],
14548
15498
  ["flex", "0 0 auto"],
14549
- ["background-color", color],
15499
+ ["background-color", "currentColor"],
14550
15500
  ["-webkit-mask", mask],
14551
15501
  ["mask", mask]
14552
15502
  ]);
@@ -14556,7 +15506,7 @@ function parseButtonVariantIdForCss(value) {
14556
15506
  if (!variantId) throw new Error("Button variant id must be a non-empty string");
14557
15507
  return variantId;
14558
15508
  }
14559
- function variantBaseRule(variant, selector, global, tokens, theme) {
15509
+ function variantBaseRule(variant, selector, global, tokens, theme, colour) {
14560
15510
  const decls = [];
14561
15511
  decls.push(["font-weight", String(global.fontWeight)]);
14562
15512
  decls.push(["font-family", resolveFontFamily(global)]);
@@ -14568,20 +15518,12 @@ function variantBaseRule(variant, selector, global, tokens, theme) {
14568
15518
  for (const decl of STRUCTURAL_DECLARATIONS) decls.push(decl);
14569
15519
  decls.push(["border-radius", resolveBorderRadius(variant, global)]);
14570
15520
  decls.push(["box-shadow", resolveBoxShadow(variant, global, theme, tokens)]);
14571
- if (variant.background.type === "solid") decls.push(["background-color", tokens.getColor(variant.background.colorToken)]);
14572
- else if (variant.background.type === "gradient") {
14573
- const colors = variant.background.stops.map((stop) => tokens.getColor(stop)).join(", ");
14574
- const direction = GRADIENT_DIRECTION_MAP$3[variant.background.direction] || "to right";
14575
- decls.push(["background-image", `linear-gradient(${direction}, ${colors})`]);
14576
- } else decls.push(["background-color", "transparent"]);
14577
- const foregroundColor = variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(variant.textColorToken)) : tokens.getColor(variant.textColorToken);
14578
- decls.push(["color", foregroundColor]);
15521
+ decls.push(...resolvedButtonColourDeclarations(colour));
14579
15522
  if (variant.border) {
14580
15523
  const borderWidth = BORDER_WIDTH_MAP$4[variant.border.widthClass] || "1px";
14581
- const borderColor = variant.background.type === "transparent" ? surfaceLinkColor(tokens.getColor(variant.border.colorToken)) : tokens.getColor(variant.border.colorToken);
14582
- decls.push(["border", `${borderWidth} solid ${borderColor}`]);
15524
+ decls.push(["border", `${borderWidth} solid currentColor`]);
14583
15525
  }
14584
- return rule(selector, decls);
15526
+ return rule$1(selector, decls);
14585
15527
  }
14586
15528
  /**
14587
15529
  * Resolve a colour for a button that does not own its own background.
@@ -14590,30 +15532,22 @@ function variantBaseRule(variant, selector, global, tokens, theme) {
14590
15532
  * token fallback keeps buttons usable in contexts that do not provide that
14591
15533
  * contract (and preserves the existing theme behaviour there).
14592
15534
  */
14593
- function surfaceLinkColor(fallbackColor) {
14594
- return `var(--rb-surface-link-color, ${fallbackColor})`;
14595
- }
14596
- function variantHoverBackgroundRule(variant, variantId, global, themeId, tokens) {
14597
- let hoverToken = variant.hoverBackgroundToken;
14598
- if (!hoverToken && global.hoverColor === "token" && global.hoverColorToken) hoverToken = global.hoverColorToken;
14599
- if (!hoverToken) return null;
14600
- return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:hover`, [["background-color", tokens.getColor(hoverToken)]]);
15535
+ function variantStateColourRule(variantId, themeId, state, colour) {
15536
+ return rule$1(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:${state}`, resolvedButtonColourDeclarations(colour));
14601
15537
  }
14602
- function variantFocusVisibleRule(variantId, themeId) {
14603
- return rule(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:focus-visible`, [["outline", "2px solid currentColor"], ["outline-offset", "3px"]]);
15538
+ function variantFocusVisibleRule(variantId, themeId, focusIndicator) {
15539
+ return rule$1(`:where([data-theme-scope="${themeId}"]) ${themeButtonSelector(variantId)}:focus-visible`, resolvedButtonFocusDeclarations(focusIndicator));
14604
15540
  }
14605
- function variantEffectsCss(variant, themeId, tokens, theme) {
14606
- if (!variant.effects) return "";
15541
+ function variantEffectsCss(variant, effects, themeId, tokens, theme) {
15542
+ if (!effects) return "";
14607
15543
  const elementConfig = {
14608
- background: variant.background,
14609
- textColorToken: variant.textColorToken,
14610
- border: variant.border ? { colorToken: variant.border.colorToken } : void 0,
15544
+ background: variant.background.type === "surface" ? { type: "transparent" } : variant.background,
14611
15545
  shadow: variant.shadow
14612
15546
  };
14613
15547
  return generateEffectsCSS({
14614
15548
  themeId,
14615
15549
  variantId: variant.id,
14616
- effects: variant.effects,
15550
+ effects,
14617
15551
  elementConfig,
14618
15552
  tokens,
14619
15553
  theme
@@ -14628,18 +15562,15 @@ function variantDisabledRules(variantId, themeId) {
14628
15562
  `${base}:focus`
14629
15563
  ];
14630
15564
  const pseudoSelectors = [`${base}::before`, `${base}::after`];
14631
- return [rule(disabledSelectors, [
14632
- ["opacity", "0.5"],
14633
- ["cursor", "not-allowed"],
14634
- ["pointer-events", "none"],
14635
- ["transform", "none"],
14636
- ["box-shadow", "none"]
14637
- ]), rule(pseudoSelectors, [
15565
+ return [rule$1(disabledSelectors, [...RESOLVED_BUTTON_DISABLED_DECLARATIONS]), rule$1(pseudoSelectors, [
14638
15566
  ["opacity", "0"],
14639
15567
  ["animation", "none"],
14640
15568
  ["pointer-events", "none"]
14641
15569
  ])];
14642
15570
  }
15571
+ function resolvedColoursEqual(left, right) {
15572
+ return JSON.stringify(left) === JSON.stringify(right);
15573
+ }
14643
15574
  function variantSizeRules(variant, variantId, themeSizes, themeId) {
14644
15575
  const borderWidth = variant.border ? BORDER_WIDTH_MAP$4[variant.border.widthClass] || "1px" : "0px";
14645
15576
  const rules = [];
@@ -14649,7 +15580,7 @@ function variantSizeRules(variant, variantId, themeSizes, themeId) {
14649
15580
  const decls = [];
14650
15581
  for (const decl of paddingDeclarations(config.padding, borderWidth)) decls.push(decl);
14651
15582
  if (config.fontSize) decls.push(["font-size", FONT_SIZE_MAP[config.fontSize] || "1rem"]);
14652
- rules.push(rule(selector, decls));
15583
+ rules.push(rule$1(selector, decls));
14653
15584
  }
14654
15585
  return rules;
14655
15586
  }
@@ -14718,6 +15649,10 @@ var init_generateButtonCss = __esmMin((() => {
14718
15649
  init_constants$2();
14719
15650
  init_generateDefaultButtonSystem();
14720
15651
  init_affordanceIcons();
15652
+ init_expandPalette();
15653
+ init_foregroundContract();
15654
+ init_resolveButtonColourStates();
15655
+ init_resolvedButtonCss();
14721
15656
  AFFORDANCE_SUPPRESS_CLASS = "rb-affordance-off";
14722
15657
  BUTTON_SIZE_NAMES = buttonSizeNameSchema.options;
14723
15658
  LETTER_SPACING_MAP = {
@@ -14734,23 +15669,51 @@ var init_generateButtonCss = __esmMin((() => {
14734
15669
  ["outline", "none"]
14735
15670
  ];
14736
15671
  }));
14737
- var init_presets$1 = __esmMin((() => {}));
15672
+ function presetCategory(personality) {
15673
+ switch (personality.tags.era) {
15674
+ case "retro": return "retro";
15675
+ case "editorial": return "minimal";
15676
+ case "organic": return "artistic";
15677
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
15678
+ case "technical": return "technical";
15679
+ case void 0: return "modern";
15680
+ }
15681
+ }
15682
+ var init_presets$1 = __esmMin((() => {
15683
+ init_personalities();
15684
+ buttonPersonalities.map((personality) => ({
15685
+ id: personality.id,
15686
+ name: personality.name,
15687
+ description: personality.description,
15688
+ category: presetCategory(personality),
15689
+ buttonSystem: personality.buttonSystem,
15690
+ compatibility: {
15691
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
15692
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
15693
+ }
15694
+ }));
15695
+ }));
14738
15696
  //#endregion
14739
15697
  //#region ../theme-core/src/buttons/effects/types.ts
14740
- var init_types$11 = __esmMin((() => {}));
14741
- var init_core$1 = __esmMin((() => {}));
15698
+ var init_types$10 = __esmMin((() => {}));
15699
+ var init_core$1 = __esmMin((() => {
15700
+ init_resolveButtonColourStates();
15701
+ init_resolvedButtonCss();
15702
+ init_types$13();
15703
+ }));
14742
15704
  //#endregion
14743
15705
  //#region ../theme-core/src/buttons/index.ts
14744
15706
  var init_buttons = __esmMin((() => {
14745
15707
  init_types$13();
14746
15708
  init_classNames();
14747
15709
  init_generateButtonCss();
15710
+ init_resolveButtonColourStates();
14748
15711
  init_affordanceIcons();
14749
15712
  init_generateDefaultButtonSystem();
14750
15713
  init_constants$2();
14751
15714
  init_presets$1();
14752
15715
  init_personalities();
14753
- init_types$11();
15716
+ init_types$10();
14754
15717
  init_registry$1();
14755
15718
  init_transform();
14756
15719
  init_core$1();
@@ -14770,7 +15733,7 @@ function normalizeBoxStylesCardVariant(value) {
14770
15733
  return normalizeCardVariantRole(value);
14771
15734
  }
14772
15735
  var cardVariantRoleValues, boxlessCardVariantValue, legacyCardVariantRoleAliases, cardSpacingSchema, gradientDirectionSchema, cardVariantRoleSchema, boxStylesCardVariantSchema, cardBackgroundSchema, cardBorderSchema, cardCornerValueSchema, cardAccentEdgeSchema, cardCornerRadiiSchema, cardVariantSchema, cardSystemSchema;
14773
- var init_types$10 = __esmMin((() => {
15736
+ var init_types$9 = __esmMin((() => {
14774
15737
  init_themeColorTokens();
14775
15738
  cardVariantRoleValues = ["default", "alternative"];
14776
15739
  boxlessCardVariantValue = "none";
@@ -15112,7 +16075,7 @@ var init_core = __esmMin((() => {
15112
16075
  //#endregion
15113
16076
  //#region ../theme-core/src/cards/index.ts
15114
16077
  var init_cards = __esmMin((() => {
15115
- init_types$10();
16078
+ init_types$9();
15116
16079
  init_constants$1();
15117
16080
  init_generateCardCss();
15118
16081
  init_generateDefaultCardSystem();
@@ -15121,7 +16084,7 @@ var init_cards = __esmMin((() => {
15121
16084
  //#endregion
15122
16085
  //#region ../theme-core/src/accordions/types.ts
15123
16086
  var accordionIconSchema, accordionSystemSchema, ICON_CONFIG, ICON_SIZE_PX, ACCORDION_SPACING_MAP, ACCORDION_TRIGGER_FONT_SCALE, ACCORDION_TRIGGER_LETTER_SPACING, ACCORDION_OPEN_ACCENT_THICKNESS;
15124
- var init_types$9 = __esmMin((() => {
16087
+ var init_types$8 = __esmMin((() => {
15125
16088
  init_themeColorTokens();
15126
16089
  accordionIconSchema = z$1.enum([
15127
16090
  "plus-minus",
@@ -15278,7 +16241,7 @@ var init_types$9 = __esmMin((() => {
15278
16241
  //#endregion
15279
16242
  //#region ../theme-core/src/inputs/types.ts
15280
16243
  var inputSystemSchema, INPUT_SPACING_MAP, INPUT_FONT_SIZE_MAP, LABEL_FONT_SIZE_MAP, FONT_WEIGHT_MAP;
15281
- var init_types$8 = __esmMin((() => {
16244
+ var init_types$7 = __esmMin((() => {
15282
16245
  init_themeColorTokens();
15283
16246
  inputSystemSchema = z$1.object({
15284
16247
  base: z$1.object({
@@ -15397,31 +16360,6 @@ var init_types$8 = __esmMin((() => {
15397
16360
  };
15398
16361
  }));
15399
16362
  //#endregion
15400
- //#region ../theme-core/src/gradients/types.ts
15401
- /**
15402
- * Gradient configuration types and schemas
15403
- */
15404
- var gradientStopSchema, radialGradientShapeSchema, gradientConfigSchema;
15405
- var init_types$7 = __esmMin((() => {
15406
- init_themeColorTokens();
15407
- gradientStopSchema = z$1.object({
15408
- color: themeColorTokenSchema,
15409
- position: z$1.number().min(0).max(100)
15410
- });
15411
- radialGradientShapeSchema = z$1.enum(["circle", "ellipse"]);
15412
- gradientConfigSchema = z$1.object({
15413
- type: z$1.enum([
15414
- "linear",
15415
- "radial",
15416
- "conic"
15417
- ]).default("linear"),
15418
- angle: z$1.number().min(0).max(360).optional(),
15419
- shape: radialGradientShapeSchema.optional(),
15420
- position: z$1.string().optional(),
15421
- stops: z$1.array(gradientStopSchema).min(2)
15422
- });
15423
- }));
15424
- //#endregion
15425
16363
  //#region ../theme-core/src/interactive/baseSchema.ts
15426
16364
  /**
15427
16365
  * Shared Base Schemas for Interactive Elements
@@ -15977,9 +16915,9 @@ var init_schema$1 = __esmMin((() => {
15977
16915
  init_media$1();
15978
16916
  init_buttons();
15979
16917
  init_cards();
15980
- init_types$9();
15981
16918
  init_types$8();
15982
16919
  init_types$7();
16920
+ init_types$11();
15983
16921
  init_types$6();
15984
16922
  init_validation$2();
15985
16923
  init_atRuleValidation();
@@ -16984,6 +17922,21 @@ var init_designState = __esmMin((() => {
16984
17922
  styleAuthorities: z$1.array(blockRuntimeStyleAuthoritySchema)
16985
17923
  }).strict();
16986
17924
  }));
17925
+ //#endregion
17926
+ //#region ../theme-core/src/site-styles/runtimeCompiler.ts
17927
+ function defineSectionForegroundRuntimeTokens(input) {
17928
+ return {
17929
+ textColor: requireThemeColorToken(input.textColor),
17930
+ headingColor: requireThemeColorToken(input.headingColor),
17931
+ linkColor: requireThemeColorToken(input.linkColor),
17932
+ supportingColor: requireThemeColorToken(input.supportingColor)
17933
+ };
17934
+ }
17935
+ function requireThemeColorToken(value) {
17936
+ const token = parseThemeColorToken(value);
17937
+ if (!token) throw new Error(`Invalid section foreground Theme color token: ${String(value)}`);
17938
+ return token;
17939
+ }
16987
17940
  function defineDesignRuntimeRules(rules) {
16988
17941
  return rules;
16989
17942
  }
@@ -17009,6 +17962,8 @@ var init_runtimeCompiler = __esmMin((() => {
17009
17962
  init_types$16();
17010
17963
  init_accessibleSurfaces();
17011
17964
  init_sectionTransitions();
17965
+ init_tokens();
17966
+ init_gradients();
17012
17967
  defaultDesignRuntimeRules = defineDesignRuntimeRules({
17013
17968
  sectionSurfaces: {
17014
17969
  base: {},
@@ -17407,13 +18362,14 @@ function inferHeaderCurationFromLegacyLooks(lookIds, recipes) {
17407
18362
  function getCuratedSiteStyle(id) {
17408
18363
  return curatedSiteStylesById.get(id) ?? null;
17409
18364
  }
17410
- var SOFT_EARTH_SITE_STYLE_ID_VALUE, SOFT_EARTH_SITE_STYLE_ID, curatedSiteStyleIdValues, quietBudget, accentLedQuietBudget, balancedBudget, expressiveBudget, kirtanOrnateDesignRuntimeRules, expressiveUnderlineInputs, ornateDarkInputs, generatedContentFrameKinds, curatedSiteStyles, curatedSiteStylesById;
18365
+ var SOFT_EARTH_SITE_STYLE_ID_VALUE, SOFT_EARTH_SITE_STYLE_ID, curatedSiteStyleIdValues, quietBudget, accentLedQuietBudget, balancedBudget, expressiveBudget, kirtanOrnateDesignRuntimeRules, primaryGlowGradientPresetId, fulcrumDesignRuntimeRules, expressiveUnderlineInputs, ornateDarkInputs, generatedContentFrameKinds, curatedSiteStyles, curatedSiteStylesById;
17411
18366
  var init_curatedSiteStyles = __esmMin((() => {
17412
18367
  init_personalities();
17413
18368
  init_curated();
17414
18369
  init_siteStyleDefaults$1();
17415
18370
  init_siteStyleDefaults();
17416
18371
  init_testimonialQuotePresets();
18372
+ init_gradients();
17417
18373
  init_headerLooks();
17418
18374
  init_footerLooks();
17419
18375
  init_curatedChoices();
@@ -17481,24 +18437,24 @@ var init_curatedSiteStyles = __esmMin((() => {
17481
18437
  type: "color",
17482
18438
  color: "muted"
17483
18439
  },
17484
- foreground: {
18440
+ foreground: defineSectionForegroundRuntimeTokens({
17485
18441
  textColor: "text",
17486
18442
  headingColor: "primary",
17487
18443
  linkColor: "primary",
17488
18444
  supportingColor: "text"
17489
- }
18445
+ })
17490
18446
  },
17491
18447
  "brand-depth-band": {
17492
18448
  background: {
17493
18449
  type: "color",
17494
18450
  color: "primary-800"
17495
18451
  },
17496
- foreground: {
18452
+ foreground: defineSectionForegroundRuntimeTokens({
17497
18453
  textColor: "text",
17498
18454
  headingColor: "primary",
17499
18455
  linkColor: "primary",
17500
18456
  supportingColor: "text"
17501
- }
18457
+ })
17502
18458
  },
17503
18459
  "hero-image": {
17504
18460
  background: {
@@ -17506,12 +18462,32 @@ var init_curatedSiteStyles = __esmMin((() => {
17506
18462
  opacity: 1,
17507
18463
  position: "center center"
17508
18464
  },
17509
- foreground: {
18465
+ foreground: defineSectionForegroundRuntimeTokens({
17510
18466
  textColor: "text",
17511
18467
  headingColor: "primary",
17512
18468
  linkColor: "primary",
17513
18469
  supportingColor: "text"
17514
- }
18470
+ })
18471
+ }
18472
+ }
18473
+ });
18474
+ primaryGlowGradientPresetId = parseGradientPresetId("primary-glow");
18475
+ if (!primaryGlowGradientPresetId) throw new Error("Expected primary-glow in the Theme Core gradient catalog");
18476
+ fulcrumDesignRuntimeRules = defineDesignRuntimeRules({
18477
+ ...defaultDesignRuntimeRules,
18478
+ sectionSurfaces: {
18479
+ ...defaultDesignRuntimeRules.sectionSurfaces,
18480
+ "accent-band": {
18481
+ background: {
18482
+ type: "gradient",
18483
+ gradientPresetId: primaryGlowGradientPresetId
18484
+ },
18485
+ foreground: defineSectionForegroundRuntimeTokens({
18486
+ textColor: "primaryForeground",
18487
+ headingColor: "primaryForeground",
18488
+ linkColor: "primaryForeground",
18489
+ supportingColor: "primaryForeground"
18490
+ })
17515
18491
  }
17516
18492
  }
17517
18493
  });
@@ -18688,6 +19664,8 @@ var init_curatedSiteStyles = __esmMin((() => {
18688
19664
  },
18689
19665
  compositionBudget: quietBudget,
18690
19666
  typography: fulcrumTypography,
19667
+ designRuntimeRules: fulcrumDesignRuntimeRules,
19668
+ recommendedAppearancePresetIds: ["cta-accent-band"],
18691
19669
  themeOverrides: {
18692
19670
  shadow: { colorToken: "primary" },
18693
19671
  accordions: {
@@ -20599,7 +21577,7 @@ function createSdkSelectField(input) {
20599
21577
  }
20600
21578
  }));
20601
21579
  }
20602
- var visibilityLevels, MEDIA_KINDS, DISPLAY_MEDIA_KINDS$2, PUBLIC_FILE_FIELD_KINDS, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, visibleWhenPredicateSchema, visibleWhenSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, inlineTextFieldSchema, mediaFieldSchema, fileFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens, colorTokens, spacingTokens, radiusTokens, styleTokenSchema, behaviourSchema, quickFieldPrioritySchema, previewCustomizeManifestCurationSchema, blockCategoryEnum;
21580
+ var visibilityLevels, MEDIA_KINDS, DISPLAY_MEDIA_KINDS$2, PUBLIC_FILE_FIELD_KINDS, siteOptionSources, mediaDeliverySchema, selectOptionSchema, selectSourceSchema, visibleWhenPredicateSchema, visibleWhenSchema, uiSchema, baseFieldSchema, textFieldSchema, richTextFieldSchema, inlineTextFieldSchema, mediaFieldSchema, fileFieldSchema, booleanFieldSchema, dateFieldSchema, timeFieldSchema, dateTimeFieldSchema, slugFieldSchema, urlFieldSchema, linkFieldSchema, selectFieldSchema, referenceFieldSchema, itemTypeSchema, repeaterFieldSchema, groupFieldSchema, modalFieldSchema, numberFieldSchema, tabDefinitionSchema, tabGroupFieldSchema, presetOptionSchema, presetOrCustomFieldSchema, contentTypeSelectFieldSchema, entryPickerFieldSchema, _fieldSchemaInternal, fieldSchema, slotSchema, typographyTokens, colorTokens, spacingTokens, radiusTokens, styleTokenSchema, behaviourSchema, quickFieldPrioritySchema, previewCustomizeManifestCurationSchema, blockCategoryEnum, blockContentSourceKinds, blockContentSourceSchema;
20603
21581
  var init_schema = __esmMin((() => {
20604
21582
  init_src$2();
20605
21583
  init_node();
@@ -21130,6 +22108,21 @@ var init_schema = __esmMin((() => {
21130
22108
  "layout",
21131
22109
  "interactive"
21132
22110
  ]);
22111
+ blockContentSourceKinds = [
22112
+ "inline",
22113
+ "entries",
22114
+ "mixed"
22115
+ ];
22116
+ blockContentSourceSchema = z$1.object({
22117
+ kind: z$1.enum(blockContentSourceKinds),
22118
+ contentType: z$1.string().min(1).optional()
22119
+ }).superRefine((value, ctx) => {
22120
+ if (value.kind === "inline" && value.contentType) ctx.addIssue({
22121
+ code: z$1.ZodIssueCode.custom,
22122
+ path: ["contentType"],
22123
+ message: "contentType is not allowed when contentSource.kind is \"inline\""
22124
+ });
22125
+ });
21133
22126
  z$1.object({
21134
22127
  name: z$1.string().min(1),
21135
22128
  version: z$1.string().min(1),
@@ -21160,6 +22153,12 @@ var init_schema = __esmMin((() => {
21160
22153
  }).optional()).optional(),
21161
22154
  category: blockCategoryEnum.optional(),
21162
22155
  contentTypes: z$1.array(z$1.string()).optional(),
22156
+ /**
22157
+ * Explicit content-source classification (inline / entries / mixed). Optional at the
22158
+ * schema level for backward compatibility with SDK-defined custom blocks, but every
22159
+ * registered SYSTEM block must declare it (enforced by a registry-wide test).
22160
+ */
22161
+ contentSource: blockContentSourceSchema.optional(),
21163
22162
  tags: z$1.array(z$1.string()).optional(),
21164
22163
  icon: z$1.string().optional()
21165
22164
  });
@@ -21555,9 +22554,15 @@ var init_heroCopy = __esmMin((() => {
21555
22554
  //#endregion
21556
22555
  //#region ../blocks/src/system/fields/ctas.ts
21557
22556
  function createCtasRepeater(options = {}) {
21558
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
22557
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
22558
+ const fieldId = id;
22559
+ const buttonField = createButtonGroup({
22560
+ showGroupLabel: false,
22561
+ ...button ?? {},
22562
+ flattenInRepeater: true
22563
+ });
21559
22564
  return {
21560
- id,
22565
+ id: fieldId,
21561
22566
  type: "repeater",
21562
22567
  label,
21563
22568
  itemLabel,
@@ -21566,11 +22571,8 @@ function createCtasRepeater(options = {}) {
21566
22571
  maxItems,
21567
22572
  required: false,
21568
22573
  allowConversion: true,
21569
- schema: { fields: [createButtonGroup({
21570
- showGroupLabel: false,
21571
- ...button ?? {},
21572
- flattenInRepeater: true
21573
- })] }
22574
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
22575
+ schema: { fields: [buttonField] }
21574
22576
  };
21575
22577
  }
21576
22578
  var init_ctas = __esmMin((() => {
@@ -21632,6 +22634,7 @@ var init_heroCtaRow = __esmMin((() => {
21632
22634
  label: "Calls to action",
21633
22635
  itemLabel: "CTA",
21634
22636
  maxItems: 3,
22637
+ defaultValue: [],
21635
22638
  button: {
21636
22639
  variants: [
21637
22640
  {
@@ -21710,7 +22713,7 @@ var init_ctaCopy = __esmMin((() => {
21710
22713
  eyebrowPath: "content.eyebrow",
21711
22714
  titlePath: "content.title",
21712
22715
  className: "cta-heading"
21713
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
22716
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
21714
22717
  });
21715
22718
  }));
21716
22719
  //#endregion
@@ -24887,6 +25890,7 @@ function createBlockManifest(config) {
24887
25890
  previewCustomize: config.previewCustomize,
24888
25891
  category: config.category,
24889
25892
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
25893
+ contentSource: config.contentSource,
24890
25894
  tags: config.tags ? [...config.tags] : [],
24891
25895
  icon: config.icon ?? "Box",
24892
25896
  layout,
@@ -24942,6 +25946,7 @@ var init_event_details = __esmMin((() => {
24942
25946
  titleSource: "heading",
24943
25947
  description: "Date/time, venue, map, and other dates for an event",
24944
25948
  category: "content",
25949
+ contentSource: { kind: "entries" },
24945
25950
  tags: [
24946
25951
  "events",
24947
25952
  "venue",
@@ -111950,7 +112955,7 @@ function validateNormalizedFieldValue(plan, value, ctx) {
111950
112955
  case "select": return validateSelectPlan(plan, value);
111951
112956
  case "richText": return isValidRichTextDoc(value) ? [] : [issue(plan, "invalidRichText")];
111952
112957
  case "inlineText": return validateInlineTextPlan(plan, value);
111953
- case "media": return isPlainObject$4(value) ? [] : [issue(plan, "invalidMedia")];
112958
+ case "media": return isPlainObject$5(value) ? [] : [issue(plan, "invalidMedia")];
111954
112959
  case "link": return linkSchema.safeParse(value).success ? [] : [issue(plan, "invalidLink")];
111955
112960
  case "repeater": return validateRepeaterPlan(plan, value, ctx);
111956
112961
  case "group": return validateGroupPlan(plan, value, ctx);
@@ -112043,7 +113048,7 @@ function validateRepeaterPlan(plan, value, ctx) {
112043
113048
  }), ...value.flatMap((item, index) => validateRepeaterItem(plan, item, index, ctx))];
112044
113049
  }
112045
113050
  function validateRepeaterItem(plan, item, index, ctx) {
112046
- if (!isPlainObject$4(item)) return [];
113051
+ if (!isPlainObject$5(item)) return [];
112047
113052
  const itemType = item._type;
112048
113053
  const fields = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === itemType)?.fields : plan.repeatedItemPlan;
112049
113054
  if (!fields) return [];
@@ -112052,7 +113057,7 @@ function validateRepeaterItem(plan, item, index, ctx) {
112052
113057
  });
112053
113058
  }
112054
113059
  function validateGroupPlan(plan, value, ctx) {
112055
- if (!isPlainObject$4(value)) return [issue(plan, "wrongType", { expected: "an object" })];
113060
+ if (!isPlainObject$5(value)) return [issue(plan, "wrongType", { expected: "an object" })];
112056
113061
  const childCtx = childValidationContext(plan, ctx);
112057
113062
  return plan.children.flatMap((childPlan) => validateNormalizedFieldValue(childPlan, value[childPlan.fieldId], childCtx));
112058
113063
  }
@@ -112249,7 +113254,7 @@ function sameFieldPath(left, right) {
112249
113254
  return left.length === right.length && left.every((segment, index) => segment === right[index]);
112250
113255
  }
112251
113256
  function validateExplicitNullsForPush(plans, content, ctx) {
112252
- if (!isPlainObject$4(content)) return [];
113257
+ if (!isPlainObject$5(content)) return [];
112253
113258
  return plans.flatMap((plan) => validateExplicitNullForPushPlan(plan, content[plan.fieldId], ctx));
112254
113259
  }
112255
113260
  function validateExplicitNullForPushPlan(plan, value, ctx) {
@@ -112272,7 +113277,7 @@ function validateExplicitNullForPushPlan(plan, value, ctx) {
112272
113277
  function validateExplicitNullsForPushRepeater(plan, value, ctx) {
112273
113278
  if (!isUnknownArray$2(value)) return [];
112274
113279
  return value.flatMap((item, index) => {
112275
- if (!isPlainObject$4(item)) return [];
113280
+ if (!isPlainObject$5(item)) return [];
112276
113281
  const childPlans = plan.repeatedItemVariants ? plan.repeatedItemVariants.find((variant) => variant.typeId === item._type)?.fields : plan.repeatedItemPlan;
112277
113282
  if (!childPlans) return [];
112278
113283
  return childPlans.flatMap((childPlan) => validateExplicitNullForPushPlan(materializeRepeaterItemPlan(childPlan, plan.path, index), item[childPlan.fieldId], ctx));
@@ -112355,7 +113360,7 @@ function isEmptyValue$1(value) {
112355
113360
  if (isEmptyRichTextDoc(value)) return true;
112356
113361
  return false;
112357
113362
  }
112358
- function isPlainObject$4(value) {
113363
+ function isPlainObject$5(value) {
112359
113364
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
112360
113365
  }
112361
113366
  function isUnknownArray$2(value) {
@@ -112363,11 +113368,11 @@ function isUnknownArray$2(value) {
112363
113368
  }
112364
113369
  function isValidRichTextDoc(value) {
112365
113370
  const doc = richTextDoc(value);
112366
- return Boolean(isPlainObject$4(doc) && doc.type === "doc");
113371
+ return Boolean(isPlainObject$5(doc) && doc.type === "doc");
112367
113372
  }
112368
113373
  function isEmptyRichTextDoc(value) {
112369
113374
  const doc = richTextDoc(value);
112370
- if (!isPlainObject$4(doc)) return false;
113375
+ if (!isPlainObject$5(doc)) return false;
112371
113376
  if (doc.type !== "doc") return false;
112372
113377
  const content = doc.content;
112373
113378
  if (!Array.isArray(content) || content.length === 0) return true;
@@ -112376,8 +113381,8 @@ function isEmptyRichTextDoc(value) {
112376
113381
  return first?.type === "paragraph" && (!Array.isArray(first.content) || first.content.length === 0);
112377
113382
  }
112378
113383
  function richTextDoc(value) {
112379
- if (!isPlainObject$4(value)) return value;
112380
- return isPlainObject$4(value.doc) ? value.doc : value;
113384
+ if (!isPlainObject$5(value)) return value;
113385
+ return isPlainObject$5(value.doc) ? value.doc : value;
112381
113386
  }
112382
113387
  //#endregion
112383
113388
  //#region ../blocks/src/system/manifest/registry.ts
@@ -112638,6 +113643,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
112638
113643
  title: "Hero",
112639
113644
  titleSource: "headline",
112640
113645
  category: "layout",
113646
+ contentSource: { kind: "inline" },
112641
113647
  includeContainerStyles: true,
112642
113648
  promotedFields: ["_sectionStyles.background.image"],
112643
113649
  fragments: [
@@ -112915,6 +113921,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
112915
113921
  id: "block.intro",
112916
113922
  title: "Intro",
112917
113923
  category: "layout",
113924
+ contentSource: { kind: "inline" },
112918
113925
  includeContainerStyles: true,
112919
113926
  titleSource: "title",
112920
113927
  previewCustomize: { quickFieldPriority: [
@@ -113104,6 +114111,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
113104
114111
  title: "Body Text",
113105
114112
  titleSource: "heading",
113106
114113
  category: "content",
114114
+ contentSource: { kind: "inline" },
113107
114115
  fragments: [{
113108
114116
  fragment: bodyCopyFragment,
113109
114117
  fieldPriority: 0
@@ -113163,6 +114171,10 @@ const blogPostBlockDefinition = {
113163
114171
  description: "Highlights a single blog post with title, image, and excerpt.",
113164
114172
  category: "blog",
113165
114173
  contentTypes: ["post"],
114174
+ contentSource: {
114175
+ kind: "entries",
114176
+ contentType: "post"
114177
+ },
113166
114178
  tags: [
113167
114179
  "blog",
113168
114180
  "post",
@@ -113466,6 +114478,10 @@ const blogListingManifest = createBlockManifest({
113466
114478
  ],
113467
114479
  description: "Display a collection of blog posts in grid or stack layout.",
113468
114480
  contentTypes: ["post"],
114481
+ contentSource: {
114482
+ kind: "entries",
114483
+ contentType: "post"
114484
+ },
113469
114485
  tags: [
113470
114486
  "blog",
113471
114487
  "posts",
@@ -113512,6 +114528,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
113512
114528
  id: "block.cta-full",
113513
114529
  title: "Full-width CTA",
113514
114530
  category: "marketing",
114531
+ contentSource: { kind: "inline" },
113515
114532
  fragments: [{
113516
114533
  fragment: ctaCopyFragment,
113517
114534
  fieldPriority: 0
@@ -113549,6 +114566,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
113549
114566
  id: "block.single-button",
113550
114567
  title: "Single Button",
113551
114568
  category: "marketing",
114569
+ contentSource: { kind: "inline" },
113552
114570
  fragments: [{
113553
114571
  fragment: singleButtonFragment,
113554
114572
  fieldPriority: 0
@@ -113655,6 +114673,7 @@ const formManifest = createBlockManifest({
113655
114673
  paletteHidden: false
113656
114674
  },
113657
114675
  category: "interactive",
114676
+ contentSource: { kind: "inline" },
113658
114677
  tags: [
113659
114678
  "form",
113660
114679
  "contact",
@@ -113722,6 +114741,7 @@ const contactNewsletterBlockDefinition = {
113722
114741
  titleSource: "contactTitle",
113723
114742
  description: "Two-column newsletter signup and contact form section.",
113724
114743
  category: "interactive",
114744
+ contentSource: { kind: "inline" },
113725
114745
  layout: contactNewsletterLayout,
113726
114746
  defaultVariant: "default",
113727
114747
  variants: { default: contactNewsletterLayout },
@@ -113932,6 +114952,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
113932
114952
  title: "FAQ",
113933
114953
  titleSource: "title",
113934
114954
  category: "content",
114955
+ contentSource: { kind: "inline" },
113935
114956
  includeContainerStyles: true,
113936
114957
  fragments: [{
113937
114958
  fragment: faqHeadingFragment,
@@ -114237,7 +115258,7 @@ const heroTitleLengthThresholds = {
114237
115258
  maxWords: 11
114238
115259
  }
114239
115260
  };
114240
- function isPlainObject$3(value) {
115261
+ function isPlainObject$4(value) {
114241
115262
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
114242
115263
  }
114243
115264
  function readString$1(obj, key) {
@@ -114246,7 +115267,7 @@ function readString$1(obj, key) {
114246
115267
  }
114247
115268
  function resolveGeneratedHeroLayoutStyles(content) {
114248
115269
  const raw = content._heroLayoutStyles;
114249
- return isPlainObject$3(raw) ? raw : null;
115270
+ return isPlainObject$4(raw) ? raw : null;
114250
115271
  }
114251
115272
  function readHeroLayoutString(content, generatedKey, fallbackKey = generatedKey) {
114252
115273
  const explicitValue = readString$1(content, fallbackKey);
@@ -114302,7 +115323,7 @@ const heroContentWrapperClassTransform = {
114302
115323
  summary: "Resolve hero content wrapper className from alignment + max width controls",
114303
115324
  schema: z$1.object({ base: z$1.string().optional() }),
114304
115325
  run: (value, options, context) => {
114305
- const content = isPlainObject$3(value) ? value : isPlainObject$3(context.data) ? context.data : {};
115326
+ const content = isPlainObject$4(value) ? value : isPlainObject$4(context.data) ? context.data : {};
114306
115327
  const alignment = resolveHeroContentAlignment(content);
114307
115328
  const maxWidth = resolveHeroContentMaxWidth(content);
114308
115329
  const typographyScale = resolveHeroTypographyScale(content);
@@ -114325,7 +115346,7 @@ const heroCtaJustifyTransform = {
114325
115346
  kind: "string",
114326
115347
  summary: "Map hero contentAlignment to CTA row justify value",
114327
115348
  run: (value, _options, context) => {
114328
- const alignment = resolveHeroContentAlignment(isPlainObject$3(value) ? value : isPlainObject$3(context.data) ? context.data : {});
115349
+ const alignment = resolveHeroContentAlignment(isPlainObject$4(value) ? value : isPlainObject$4(context.data) ? context.data : {});
114329
115350
  return alignment === "left" ? "start" : alignment === "right" ? "end" : "center";
114330
115351
  }
114331
115352
  };
@@ -114334,7 +115355,7 @@ const heroStackJustifyFromVerticalAlignmentTransform = {
114334
115355
  kind: "string",
114335
115356
  summary: "Map hero verticalAlignment to stack justify value",
114336
115357
  run: (value, _options, context) => {
114337
- const vertical = resolveHeroVerticalAlignment(isPlainObject$3(value) ? value : isPlainObject$3(context.data) ? context.data : {});
115358
+ const vertical = resolveHeroVerticalAlignment(isPlainObject$4(value) ? value : isPlainObject$4(context.data) ? context.data : {});
114338
115359
  return vertical === "top" ? "start" : vertical === "bottom" ? "end" : "center";
114339
115360
  }
114340
115361
  };
@@ -114344,7 +115365,7 @@ const heroGridClassFromVerticalAlignmentTransform = {
114344
115365
  summary: "Append align-items class for hero split layouts based on verticalAlignment",
114345
115366
  schema: z$1.object({ base: z$1.string() }),
114346
115367
  run: (value, options, context) => {
114347
- const vertical = resolveHeroVerticalAlignment(isPlainObject$3(value) ? value : isPlainObject$3(context.data) ? context.data : {});
115368
+ const vertical = resolveHeroVerticalAlignment(isPlainObject$4(value) ? value : isPlainObject$4(context.data) ? context.data : {});
114348
115369
  const itemsClass = vertical === "top" ? "rb-items-start" : vertical === "bottom" ? "rb-items-end" : "rb-items-center";
114349
115370
  return joinClasses$2([options.base, itemsClass]);
114350
115371
  }
@@ -115656,6 +116677,7 @@ const siteHeaderManifest = createBlockManifest({
115656
116677
  id: "block.site-header",
115657
116678
  title: "Site Header",
115658
116679
  category: "layout",
116680
+ contentSource: { kind: "inline" },
115659
116681
  additionalFields: [{
115660
116682
  id: "mode",
115661
116683
  type: "select",
@@ -115870,6 +116892,7 @@ const siteFooterManifest = createBlockManifest({
115870
116892
  id: "block.site-footer",
115871
116893
  title: "Site Footer",
115872
116894
  category: "layout",
116895
+ contentSource: { kind: "inline" },
115873
116896
  skipSectionStyles: true,
115874
116897
  layout: section$1({
115875
116898
  background: "background",
@@ -116029,6 +117052,7 @@ const testimonialsBlockDefinition = {
116029
117052
  id: "block.testimonials",
116030
117053
  title: "Testimonials",
116031
117054
  category: "marketing",
117055
+ contentSource: { kind: "inline" },
116032
117056
  includeContainerStyles: true,
116033
117057
  previewCustomize: { quickFieldPriority: [
116034
117058
  "avatarLayout",
@@ -116193,6 +117217,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
116193
117217
  id: "block.columns",
116194
117218
  title: "Columns",
116195
117219
  category: "layout",
117220
+ contentSource: { kind: "inline" },
116196
117221
  additionalFields: [
116197
117222
  parseFieldDefinition({
116198
117223
  id: "equalHeight",
@@ -116433,6 +117458,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
116433
117458
  id: "block.collection",
116434
117459
  title: "Collection",
116435
117460
  category: "layout",
117461
+ contentSource: { kind: "inline" },
116436
117462
  additionalFields: [
116437
117463
  parseFieldDefinition({
116438
117464
  id: "layout",
@@ -116727,6 +117753,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
116727
117753
  id: "block.feature-cards",
116728
117754
  title: "Feature Cards",
116729
117755
  category: "layout",
117756
+ contentSource: { kind: "inline" },
116730
117757
  includeContainerStyles: true,
116731
117758
  titleSource: "title",
116732
117759
  additionalFields: [
@@ -117119,6 +118146,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
117119
118146
  id: "block.media-text",
117120
118147
  title: "Media and Text",
117121
118148
  category: "layout",
118149
+ contentSource: { kind: "inline" },
117122
118150
  includeContainerStyles: true,
117123
118151
  titleSource: "title",
117124
118152
  previewCustomize: { quickFieldPriority: [
@@ -117527,6 +118555,7 @@ const appointmentBookingBlockDefinition = {
117527
118555
  paletteHidden: false
117528
118556
  },
117529
118557
  category: "interactive",
118558
+ contentSource: { kind: "inline" },
117530
118559
  tags: [
117531
118560
  "booking",
117532
118561
  "appointment",
@@ -117697,6 +118726,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
117697
118726
  paletteHidden: false
117698
118727
  },
117699
118728
  category: "interactive",
118729
+ contentSource: { kind: "inline" },
117700
118730
  tags: [
117701
118731
  "booking",
117702
118732
  "appointment",
@@ -117790,6 +118820,7 @@ const weeklySlotAvailabilityBlockDefinition = {
117790
118820
  init_builder$2();
117791
118821
  init_styledSection();
117792
118822
  init_fragments$1();
118823
+ init_button();
117793
118824
  init_api_bindings();
117794
118825
  init_shared$4();
117795
118826
  init_shop_shared();
@@ -117804,6 +118835,7 @@ const eventRegistrationBlockDefinition = {
117804
118835
  titleSource: "heading",
117805
118836
  description: "Multi-step event registration form",
117806
118837
  category: "interactive",
118838
+ contentSource: { kind: "inline" },
117807
118839
  tags: [
117808
118840
  "events",
117809
118841
  "registration",
@@ -117910,15 +118942,9 @@ const eventRegistrationBlockDefinition = {
117910
118942
  defaultValue: "Complete Registration",
117911
118943
  maxLength: 40
117912
118944
  },
117913
- {
117914
- id: "buttonVariant",
117915
- type: "select",
117916
- label: "Button style",
118945
+ createButtonVariantField({
117917
118946
  description: "Choose a button style from your theme",
117918
- required: false,
117919
- multiple: false,
117920
- defaultValue: "primary",
117921
- options: [
118947
+ variants: [
117922
118948
  {
117923
118949
  value: "primary",
117924
118950
  label: "Primary"
@@ -117931,9 +118957,8 @@ const eventRegistrationBlockDefinition = {
117931
118957
  value: "outline",
117932
118958
  label: "Outline"
117933
118959
  }
117934
- ],
117935
- ui: { intent: "style" }
117936
- }
118960
+ ]
118961
+ })
117937
118962
  ],
117938
118963
  layout: [styledSection({
117939
118964
  baseClass: "",
@@ -118022,6 +119047,7 @@ const eventRegistrationBlockDefinition = {
118022
119047
  init_builder$2();
118023
119048
  init_styledSection();
118024
119049
  init_fragments$1();
119050
+ init_button();
118025
119051
  init_api_bindings();
118026
119052
  init_shared();
118027
119053
  init_defineBlock();
@@ -118034,6 +119060,7 @@ const courseRegistrationBlockDefinition = {
118034
119060
  titleSource: "heading",
118035
119061
  description: "Enrollment form for multi-session courses",
118036
119062
  category: "interactive",
119063
+ contentSource: { kind: "inline" },
118037
119064
  tags: [
118038
119065
  "courses",
118039
119066
  "enrollment",
@@ -118147,15 +119174,9 @@ const courseRegistrationBlockDefinition = {
118147
119174
  defaultValue: "Sign up",
118148
119175
  maxLength: 40
118149
119176
  },
118150
- {
118151
- id: "buttonVariant",
118152
- type: "select",
118153
- label: "Button style",
119177
+ createButtonVariantField({
118154
119178
  description: "Choose a button style from your theme",
118155
- required: false,
118156
- multiple: false,
118157
- defaultValue: "primary",
118158
- options: [
119179
+ variants: [
118159
119180
  {
118160
119181
  value: "primary",
118161
119182
  label: "Primary"
@@ -118168,9 +119189,8 @@ const courseRegistrationBlockDefinition = {
118168
119189
  value: "outline",
118169
119190
  label: "Outline"
118170
119191
  }
118171
- ],
118172
- ui: { intent: "style" }
118173
- }
119192
+ ]
119193
+ })
118174
119194
  ],
118175
119195
  layout: [styledSection({
118176
119196
  baseClass: "",
@@ -118246,6 +119266,7 @@ const courseDetailsBlockDefinition = {
118246
119266
  titleSource: "heading",
118247
119267
  description: "Schedule, venue, price, and enrollment status for a course",
118248
119268
  category: "content",
119269
+ contentSource: { kind: "entries" },
118249
119270
  tags: [
118250
119271
  "courses",
118251
119272
  "schedule",
@@ -118545,6 +119566,7 @@ const eventSpotlightBlockDefinition = {
118545
119566
  paletteHidden: false
118546
119567
  },
118547
119568
  category: "content",
119569
+ contentSource: { kind: "entries" },
118548
119570
  tags: [
118549
119571
  "events",
118550
119572
  "featured",
@@ -118878,6 +119900,7 @@ const eventListingBlockDefinition = {
118878
119900
  paletteHidden: true
118879
119901
  },
118880
119902
  category: "interactive",
119903
+ contentSource: { kind: "entries" },
118881
119904
  tags: [
118882
119905
  "events",
118883
119906
  "listing",
@@ -119888,6 +120911,7 @@ const eventCalendarBlockDefinition = {
119888
120911
  paletteHidden: false
119889
120912
  },
119890
120913
  category: "interactive",
120914
+ contentSource: { kind: "entries" },
119891
120915
  tags: [
119892
120916
  "events",
119893
120917
  "calendar",
@@ -120295,6 +121319,7 @@ const recurringScheduleBlockDefinition = {
120295
121319
  titleSource: "heading",
120296
121320
  description: "A compact weekly schedule with one row per recurring series.",
120297
121321
  category: "interactive",
121322
+ contentSource: { kind: "entries" },
120298
121323
  icon: "CalendarDays",
120299
121324
  tags: [
120300
121325
  "schedule",
@@ -120935,7 +121960,10 @@ const offeringsPreviewFields = [
120935
121960
  label: "Link"
120936
121961
  }
120937
121962
  ],
120938
- ui: { intent: "display" }
121963
+ ui: {
121964
+ intent: "display",
121965
+ widget: "buttonVariant"
121966
+ }
120939
121967
  },
120940
121968
  {
120941
121969
  id: "buttonText",
@@ -120988,6 +122016,7 @@ const offeringsPreviewManifest = createBlockManifest({
120988
122016
  paletteHidden: false
120989
122017
  },
120990
122018
  category: "content",
122019
+ contentSource: { kind: "mixed" },
120991
122020
  tags: [
120992
122021
  "offerings",
120993
122022
  "events",
@@ -121163,6 +122192,7 @@ const embedManifest = createBlockManifest({
121163
122192
  id: "block.embed",
121164
122193
  title: "Embed Content",
121165
122194
  category: "content",
122195
+ contentSource: { kind: "entries" },
121166
122196
  titleSource: "heading",
121167
122197
  additionalFields: [
121168
122198
  parseFieldDefinition({
@@ -121655,6 +122685,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
121655
122685
  id: "block.image-gallery",
121656
122686
  title: "Image Gallery",
121657
122687
  category: "content",
122688
+ contentSource: { kind: "inline" },
121658
122689
  previewCustomize: { quickFieldPriority: [
121659
122690
  "aspectRatio",
121660
122691
  "slidesToShow",
@@ -122313,6 +123344,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
122313
123344
  id: "block.video-grid",
122314
123345
  title: "Video Grid",
122315
123346
  category: "media",
123347
+ contentSource: { kind: "inline" },
122316
123348
  skipSectionStyles: true,
122317
123349
  additionalFields: parseFieldDefinitions([
122318
123350
  {
@@ -122518,6 +123550,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
122518
123550
  title: "Audio Player",
122519
123551
  titleSource: "title",
122520
123552
  category: "media",
123553
+ contentSource: { kind: "inline" },
122521
123554
  description: "Add a branded audio player for a single track.",
122522
123555
  tags: [
122523
123556
  "audio",
@@ -122607,6 +123640,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
122607
123640
  title: "File Download",
122608
123641
  titleSource: ["title", "file.filename"],
122609
123642
  category: "media",
123643
+ contentSource: { kind: "inline" },
122610
123644
  description: "Add a simple public download link for a document, ZIP, or audio file.",
122611
123645
  tags: [
122612
123646
  "file",
@@ -122866,6 +123900,7 @@ const shopBlockDefinition = {
122866
123900
  paletteHidden: false
122867
123901
  },
122868
123902
  category: "interactive",
123903
+ contentSource: { kind: "entries" },
122869
123904
  tags: [
122870
123905
  "shop",
122871
123906
  "passes",
@@ -123075,6 +124110,7 @@ const productListBlockDefinition = {
123075
124110
  paletteHidden: false
123076
124111
  },
123077
124112
  category: "interactive",
124113
+ contentSource: { kind: "entries" },
123078
124114
  tags: [
123079
124115
  "shop",
123080
124116
  "products",
@@ -123226,6 +124262,7 @@ const productDetailBlockDefinition = {
123226
124262
  paletteHidden: false
123227
124263
  },
123228
124264
  category: "interactive",
124265
+ contentSource: { kind: "entries" },
123229
124266
  tags: [
123230
124267
  "shop",
123231
124268
  "product",
@@ -123351,6 +124388,7 @@ const cartBlockDefinition = {
123351
124388
  paletteHidden: false
123352
124389
  },
123353
124390
  category: "interactive",
124391
+ contentSource: { kind: "inline" },
123354
124392
  tags: [
123355
124393
  "shop",
123356
124394
  "cart",
@@ -123442,6 +124480,7 @@ const checkoutBlockDefinition = {
123442
124480
  paletteHidden: false
123443
124481
  },
123444
124482
  category: "interactive",
124483
+ contentSource: { kind: "inline" },
123445
124484
  tags: [
123446
124485
  "shop",
123447
124486
  "checkout",
@@ -123561,6 +124600,7 @@ const giftingBlockDefinition = {
123561
124600
  paletteHidden: false
123562
124601
  },
123563
124602
  category: "interactive",
124603
+ contentSource: { kind: "entries" },
123564
124604
  tags: [
123565
124605
  "gifting",
123566
124606
  "gift cards",
@@ -123656,6 +124696,7 @@ const newsletterSignupBlockDefinition = {
123656
124696
  titleSource: "title",
123657
124697
  description: "Newsletter subscription form with configurable field presets.",
123658
124698
  category: "interactive",
124699
+ contentSource: { kind: "inline" },
123659
124700
  fragments: [{
123660
124701
  fragment: newsletterCopyFragment,
123661
124702
  fieldPriority: 0
@@ -123843,6 +124884,7 @@ const teamMembersBlockDefinition = {
123843
124884
  id: "block.team-members",
123844
124885
  title: "Team Members",
123845
124886
  category: "content",
124887
+ contentSource: { kind: "mixed" },
123846
124888
  titleSource: "heading",
123847
124889
  additionalFields: [
123848
124890
  parseFieldDefinition({
@@ -124141,6 +125183,7 @@ const locationMapBlockDefinition = {
124141
125183
  titleSource: "heading",
124142
125184
  description: "Show a business location with an interactive map and directions link.",
124143
125185
  category: "content",
125186
+ contentSource: { kind: "inline" },
124144
125187
  tags: [
124145
125188
  "map",
124146
125189
  "location",
@@ -125153,216 +126196,6 @@ function getBlockDefinition(name) {
125153
126196
  //#region ../blocks/src/system/theme/index.ts
125154
126197
  init_tokens();
125155
126198
  //#endregion
125156
- //#region ../theme-core/src/gradients/presets.ts
125157
- /**
125158
- * Curated library of gradient presets
125159
- * All gradients use theme color tokens, so they adapt to the site's palette
125160
- */
125161
- const GRADIENT_PRESETS = [
125162
- {
125163
- id: "primary-secondary",
125164
- name: "Primary to Secondary",
125165
- description: "Blend your primary and secondary brand colors",
125166
- type: "linear",
125167
- angle: 135,
125168
- stops: [{
125169
- color: "primary-500",
125170
- position: 0
125171
- }, {
125172
- color: "secondary-500",
125173
- position: 100
125174
- }]
125175
- },
125176
- {
125177
- id: "primary-accent",
125178
- name: "Primary to Accent",
125179
- description: "Energetic gradient from primary to accent",
125180
- type: "linear",
125181
- angle: 135,
125182
- stops: [{
125183
- color: "primary-500",
125184
- position: 0
125185
- }, {
125186
- color: "accent-500",
125187
- position: 100
125188
- }]
125189
- },
125190
- {
125191
- id: "secondary-accent",
125192
- name: "Secondary to Accent",
125193
- description: "Vibrant secondary to accent blend",
125194
- type: "linear",
125195
- angle: 135,
125196
- stops: [{
125197
- color: "secondary-500",
125198
- position: 0
125199
- }, {
125200
- color: "accent-500",
125201
- position: 100
125202
- }]
125203
- },
125204
- {
125205
- id: "primary-light-dark",
125206
- name: "Primary Light to Dark",
125207
- description: "Subtle primary color fade",
125208
- type: "linear",
125209
- angle: 180,
125210
- stops: [{
125211
- color: "primary-500",
125212
- position: 0
125213
- }, {
125214
- color: "primary-900",
125215
- position: 100
125216
- }]
125217
- },
125218
- {
125219
- id: "primary-dark-light",
125220
- name: "Primary Dark to Light",
125221
- description: "Reverse primary fade",
125222
- type: "linear",
125223
- angle: 180,
125224
- stops: [{
125225
- color: "primary-900",
125226
- position: 0
125227
- }, {
125228
- color: "primary-50",
125229
- position: 100
125230
- }]
125231
- },
125232
- {
125233
- id: "secondary-light-dark",
125234
- name: "Secondary Light to Dark",
125235
- description: "Subtle secondary color fade",
125236
- type: "linear",
125237
- angle: 180,
125238
- stops: [{
125239
- color: "secondary-500",
125240
- position: 0
125241
- }, {
125242
- color: "secondary-900",
125243
- position: 100
125244
- }]
125245
- },
125246
- {
125247
- id: "accent-light-dark",
125248
- name: "Accent Light to Dark",
125249
- description: "Accent color depth fade",
125250
- type: "linear",
125251
- angle: 180,
125252
- stops: [{
125253
- color: "accent-500",
125254
- position: 0
125255
- }, {
125256
- color: "accent-900",
125257
- position: 100
125258
- }]
125259
- },
125260
- {
125261
- id: "background-surface",
125262
- name: "Background to Surface",
125263
- description: "Subtle depth using base colors",
125264
- type: "linear",
125265
- angle: 180,
125266
- stops: [{
125267
- color: "background",
125268
- position: 0
125269
- }, {
125270
- color: "surface",
125271
- position: 100
125272
- }]
125273
- },
125274
- {
125275
- id: "neutral-fade",
125276
- name: "Neutral Gradient",
125277
- description: "Elegant neutral color fade",
125278
- type: "linear",
125279
- angle: 180,
125280
- stops: [{
125281
- color: "neutral-900",
125282
- position: 0
125283
- }, {
125284
- color: "neutral-50",
125285
- position: 100
125286
- }]
125287
- },
125288
- {
125289
- id: "primary-radial",
125290
- name: "Primary Spotlight",
125291
- description: "Radial primary gradient from center",
125292
- type: "radial",
125293
- position: "center",
125294
- stops: [{
125295
- color: "primary-500",
125296
- position: 0
125297
- }, {
125298
- color: "primary-900",
125299
- position: 100
125300
- }]
125301
- },
125302
- {
125303
- id: "accent-radial",
125304
- name: "Accent Spotlight",
125305
- description: "Radial accent gradient from center",
125306
- type: "radial",
125307
- position: "center",
125308
- stops: [{
125309
- color: "accent-500",
125310
- position: 0
125311
- }, {
125312
- color: "accent-900",
125313
- position: 100
125314
- }]
125315
- },
125316
- {
125317
- id: "primary-secondary-accent",
125318
- name: "Brand Trio",
125319
- description: "All three brand colors in harmony",
125320
- type: "linear",
125321
- angle: 135,
125322
- stops: [
125323
- {
125324
- color: "primary-500",
125325
- position: 0
125326
- },
125327
- {
125328
- color: "secondary-500",
125329
- position: 50
125330
- },
125331
- {
125332
- color: "accent-500",
125333
- position: 100
125334
- }
125335
- ]
125336
- }
125337
- ];
125338
- //#endregion
125339
- //#region ../theme-core/src/gradients/utils.ts
125340
- /**
125341
- * Convert a GradientConfig to a CSS gradient string
125342
- *
125343
- * @param config - The gradient configuration using theme tokens
125344
- * @param tokens - Map of theme color tokens to hex values
125345
- * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
125346
- */
125347
- function gradientToCss(config, tokens) {
125348
- const stops = config.stops.map((stop) => {
125349
- return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
125350
- }).join(", ");
125351
- const type = config.type ?? "linear";
125352
- if (type === "radial") {
125353
- const position = config.position ?? "center";
125354
- return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
125355
- }
125356
- if (type === "conic") {
125357
- const position = config.position ?? "center";
125358
- return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
125359
- }
125360
- return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
125361
- }
125362
- //#endregion
125363
- //#region ../theme-core/src/gradients/index.ts
125364
- init_types$7();
125365
- //#endregion
125366
126199
  //#region ../blocks/src/system/helpers/backgroundMedia.ts
125367
126200
  init_media$2();
125368
126201
  function resolveBackgroundMedia(input) {
@@ -125384,6 +126217,7 @@ function backgroundVideoMobileClassNames(input) {
125384
126217
  //#endregion
125385
126218
  //#region ../blocks/src/system/transforms/registry/background.ts
125386
126219
  init_background$1();
126220
+ init_gradients();
125387
126221
  init_themeColorResolution();
125388
126222
  init_surfaceForegroundStyles();
125389
126223
  init_media();
@@ -125405,9 +126239,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
125405
126239
  ].filter(Boolean).join(" ");
125406
126240
  }
125407
126241
  function gradientPresetCss(value) {
125408
- if (!isString$1(value)) return null;
125409
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
125410
- if (!preset) return null;
126242
+ const presetId = parseGradientPresetId(value);
126243
+ if (!presetId) return null;
126244
+ const preset = getGradientPreset(presetId);
125411
126245
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
125412
126246
  }
125413
126247
  const backgroundTransforms = [
@@ -127018,7 +127852,7 @@ function normalizeBoolean(value) {
127018
127852
  }
127019
127853
  //#endregion
127020
127854
  //#region ../blocks/src/system/runtime/nodes/accordionIconTreatment.ts
127021
- init_types$9();
127855
+ init_types$8();
127022
127856
  init_colorStyles();
127023
127857
  function resolveAccordionIconStyle(iconStyle, iconTreatment) {
127024
127858
  if (iconTreatment) switch (iconTreatment.iconSet) {
@@ -127050,7 +127884,7 @@ init_clsx();
127050
127884
  init_RichText();
127051
127885
  init_richText_coerce();
127052
127886
  init_svg();
127053
- init_types$9();
127887
+ init_types$8();
127054
127888
  /**
127055
127889
  * Lookup map for accordion icons - only these 6 icons are bundled
127056
127890
  */
@@ -130239,7 +131073,7 @@ function readFromSource$1(source, segments) {
130239
131073
  /**
130240
131074
  * Type guard for plain objects.
130241
131075
  */
130242
- function isPlainObject$2(value) {
131076
+ function isPlainObject$3(value) {
130243
131077
  return typeof value === "object" && value !== null && !Array.isArray(value);
130244
131078
  }
130245
131079
  /**
@@ -130248,18 +131082,18 @@ function isPlainObject$2(value) {
130248
131082
  function parseRouteEntry(routeId, value) {
130249
131083
  if (typeof routeId !== "string" || routeId.length === 0) return null;
130250
131084
  if (typeof value === "string") return [routeId, value];
130251
- if (isPlainObject$2(value)) return [routeId, value];
131085
+ if (isPlainObject$3(value)) return [routeId, value];
130252
131086
  return null;
130253
131087
  }
130254
131088
  /**
130255
131089
  * Extracts route map from $root.routes in the viewModel.
130256
131090
  */
130257
131091
  function extractRouteMapFromViewModel(viewModel) {
130258
- if (!isPlainObject$2(viewModel)) return void 0;
131092
+ if (!isPlainObject$3(viewModel)) return void 0;
130259
131093
  const root = viewModel.$root;
130260
- if (!isPlainObject$2(root)) return void 0;
131094
+ if (!isPlainObject$3(root)) return void 0;
130261
131095
  const routes = root.routes;
130262
- if (!isPlainObject$2(routes)) return void 0;
131096
+ if (!isPlainObject$3(routes)) return void 0;
130263
131097
  const entries = Object.entries(routes).map(([routeId, value]) => parseRouteEntry(routeId, value)).filter((entry) => entry !== null);
130264
131098
  if (entries.length === 0) return void 0;
130265
131099
  return Object.fromEntries(entries);
@@ -130268,22 +131102,22 @@ function extractRouteMapFromViewModel(viewModel) {
130268
131102
  * Extracts pagesByIdentifier from $root.pagesByIdentifier in the viewModel.
130269
131103
  */
130270
131104
  function extractPagesByIdentifierFromViewModel(viewModel) {
130271
- if (!isPlainObject$2(viewModel)) return void 0;
131105
+ if (!isPlainObject$3(viewModel)) return void 0;
130272
131106
  const root = viewModel.$root;
130273
- if (!isPlainObject$2(root)) return void 0;
131107
+ if (!isPlainObject$3(root)) return void 0;
130274
131108
  const pagesByIdentifier = root.pagesByIdentifier;
130275
- if (!isPlainObject$2(pagesByIdentifier)) return void 0;
131109
+ if (!isPlainObject$3(pagesByIdentifier)) return void 0;
130276
131110
  return pagesByIdentifier;
130277
131111
  }
130278
131112
  /**
130279
131113
  * Extracts entriesByIdentifier from $root.entriesByIdentifier in the viewModel.
130280
131114
  */
130281
131115
  function extractEntriesByIdentifierFromViewModel(viewModel) {
130282
- if (!isPlainObject$2(viewModel)) return void 0;
131116
+ if (!isPlainObject$3(viewModel)) return void 0;
130283
131117
  const root = viewModel.$root;
130284
- if (!isPlainObject$2(root)) return void 0;
131118
+ if (!isPlainObject$3(root)) return void 0;
130285
131119
  const entriesByIdentifier = root.entriesByIdentifier;
130286
- if (!isPlainObject$2(entriesByIdentifier)) return void 0;
131120
+ if (!isPlainObject$3(entriesByIdentifier)) return void 0;
130287
131121
  return entriesByIdentifier;
130288
131122
  }
130289
131123
  /**
@@ -130305,7 +131139,7 @@ function applyTransformsAndFallback(value, binding, context) {
130305
131139
  const routeMap = context.routes ?? extractRouteMapFromViewModel(context.viewModel);
130306
131140
  const pagesByIdentifier = context.pagesByIdentifier ?? extractPagesByIdentifierFromViewModel(context.viewModel);
130307
131141
  const entriesByIdentifier = context.entriesByIdentifier ?? extractEntriesByIdentifierFromViewModel(context.viewModel);
130308
- const stage = (isPlainObject$2(context.viewModel.$root) ? context.viewModel.$root : null)?.previewStage === "preview" ? "preview" : "published";
131142
+ const stage = (isPlainObject$3(context.viewModel.$root) ? context.viewModel.$root : null)?.previewStage === "preview" ? "preview" : "published";
130309
131143
  const transformed = runTransforms(value, binding.transforms?.map((step) => ({
130310
131144
  id: step.id,
130311
131145
  options: step.options
@@ -130334,15 +131168,15 @@ function resolveTransformData(context, bindingPath) {
130334
131168
  const [first] = splitPath$1(bindingPath);
130335
131169
  if (typeof first === "string" && first !== "$root") {
130336
131170
  const namedScope = context.scopes.find((entry) => entry.name === first);
130337
- if (namedScope && isPlainObject$2(namedScope.value)) return namedScope.value;
131171
+ if (namedScope && isPlainObject$3(namedScope.value)) return namedScope.value;
130338
131172
  }
130339
131173
  for (let i = context.scopes.length - 1; i >= 0; i -= 1) {
130340
131174
  const scope = context.scopes[i];
130341
- if (scope && isPlainObject$2(scope.value)) return scope.value;
131175
+ if (scope && isPlainObject$3(scope.value)) return scope.value;
130342
131176
  }
130343
131177
  const content = context.viewModel.content;
130344
- if (isPlainObject$2(content)) return content;
130345
- if (isPlainObject$2(context.viewModel)) return context.viewModel;
131178
+ if (isPlainObject$3(content)) return content;
131179
+ if (isPlainObject$3(context.viewModel)) return context.viewModel;
130346
131180
  }
130347
131181
  function coerceBindingValue(value, binding) {
130348
131182
  const mode = binding.coerce;
@@ -130404,7 +131238,7 @@ function isRichTextConditionValueEmpty(value) {
130404
131238
  return richTextStructuralPresence(root).kind === "empty";
130405
131239
  }
130406
131240
  function isTipTapNode(value) {
130407
- return isPlainObject$2(value) && typeof value.type === "string";
131241
+ return isPlainObject$3(value) && typeof value.type === "string";
130408
131242
  }
130409
131243
  function richTextStructuralPresence(node) {
130410
131244
  if (typeof node.text === "string" && node.text.trim().length > 0) return {
@@ -130433,7 +131267,7 @@ function richTextSelfPresence(node) {
130433
131267
  }
130434
131268
  }
130435
131269
  function hasResolvableRichTextImageSource(node) {
130436
- const attrs = isPlainObject$2(node.attrs) ? node.attrs : {};
131270
+ const attrs = isPlainObject$3(node.attrs) ? node.attrs : {};
130437
131271
  return hasNonBlankStringAttr(attrs, "src") || hasNonBlankStringAttr(attrs, "identifier");
130438
131272
  }
130439
131273
  function hasNonBlankStringAttr(attrs, key) {
@@ -130625,7 +131459,7 @@ function getNestedBinding(bindings, path) {
130625
131459
  const segments = path.split(".");
130626
131460
  let current = bindings;
130627
131461
  for (const segment of segments) {
130628
- if (!isPlainObject$2(current)) return void 0;
131462
+ if (!isPlainObject$3(current)) return void 0;
130629
131463
  current = current[segment];
130630
131464
  }
130631
131465
  return current;
@@ -130648,7 +131482,7 @@ function resolveBindingToEditorPath(fieldName, bindings, editableRouteMetadataFi
130648
131482
  };
130649
131483
  const binding = bindings[fieldName] ?? getNestedBinding(bindings, fieldName);
130650
131484
  if (!binding) return null;
130651
- if (isPlainObject$2(binding) && "source" in binding) {
131485
+ if (isPlainObject$3(binding) && "source" in binding) {
130652
131486
  const source = binding.source;
130653
131487
  if (source === "field" && "path" in binding) {
130654
131488
  const path = binding.path;
@@ -130665,7 +131499,7 @@ function resolveBindingToEditorPath(fieldName, bindings, editableRouteMetadataFi
130665
131499
  if (!Array.isArray(options)) return null;
130666
131500
  for (const option of options) {
130667
131501
  if (typeof option === "string") return `content.${option}`;
130668
- if (isPlainObject$2(option) && "source" in option) {
131502
+ if (isPlainObject$3(option) && "source" in option) {
130669
131503
  const optSource = option.source;
130670
131504
  if (optSource === "field" && "path" in option) {
130671
131505
  const path = option.path;
@@ -130717,7 +131551,7 @@ function derivePreviewTextEditableTarget(parsedBinding, context) {
130717
131551
  };
130718
131552
  }
130719
131553
  const root = context.viewModel?.$root;
130720
- if (isPlainObject$2(root) && root.contentEntry != null && context.pathBase) return {
131554
+ if (isPlainObject$3(root) && root.contentEntry != null && context.pathBase) return {
130721
131555
  kind: "read-only",
130722
131556
  reason: "entry-template-block-field"
130723
131557
  };
@@ -130776,7 +131610,7 @@ function injectMediaSlotPath(props, node, parsedBinding, context) {
130776
131610
  if (resolveBindingToEditorPath(fieldPath, context.blockBindings, context.editableRouteMetadataFieldIds)) return props;
130777
131611
  }
130778
131612
  const root = context.viewModel?.$root;
130779
- if (isPlainObject$2(root) && root.contentEntry != null && context.pathBase) return props;
131613
+ if (isPlainObject$3(root) && root.contentEntry != null && context.pathBase) return props;
130780
131614
  return {
130781
131615
  ...props,
130782
131616
  fieldPath
@@ -130923,7 +131757,7 @@ function getNodeProps(node) {
130923
131757
  if (key.startsWith("$")) continue;
130924
131758
  legacy[key] = value;
130925
131759
  }
130926
- const props = isPlainObject$2(node.props) ? node.props : {};
131760
+ const props = isPlainObject$3(node.props) ? node.props : {};
130927
131761
  return {
130928
131762
  ...legacy,
130929
131763
  ...props
@@ -131036,7 +131870,7 @@ function generateHoverEffects(axes, _space) {
131036
131870
  //#endregion
131037
131871
  //#region ../theme-core/src/blockOverrides.ts
131038
131872
  const BLOCK_PREFIX = "block.";
131039
- function isPlainObject$1(value) {
131873
+ function isPlainObject$2(value) {
131040
131874
  return typeof value === "object" && value !== null && !Array.isArray(value);
131041
131875
  }
131042
131876
  function isUnknownArray$1(value) {
@@ -131044,7 +131878,7 @@ function isUnknownArray$1(value) {
131044
131878
  }
131045
131879
  function cloneValue(value) {
131046
131880
  if (isUnknownArray$1(value)) return value.map((item) => cloneValue(item));
131047
- if (isPlainObject$1(value)) {
131881
+ if (isPlainObject$2(value)) {
131048
131882
  const cloned = {};
131049
131883
  for (const [key, child] of Object.entries(value)) cloned[key] = cloneValue(child);
131050
131884
  return cloned;
@@ -131054,7 +131888,7 @@ function cloneValue(value) {
131054
131888
  function mergeDeep(defaultValue, overrideValue) {
131055
131889
  if (overrideValue === void 0) return cloneValue(defaultValue);
131056
131890
  if (overrideValue === null) return null;
131057
- if (isPlainObject$1(defaultValue) && isPlainObject$1(overrideValue)) {
131891
+ if (isPlainObject$2(defaultValue) && isPlainObject$2(overrideValue)) {
131058
131892
  const merged = {};
131059
131893
  const keys = /* @__PURE__ */ new Set([...Object.keys(defaultValue), ...Object.keys(overrideValue)]);
131060
131894
  for (const key of keys) merged[key] = mergeDeep(defaultValue[key], overrideValue[key]);
@@ -131111,7 +131945,7 @@ function mergeContentWithBlockStyleOverrides(content, theme, blockKind) {
131111
131945
  */
131112
131946
  function applyHeadingDecorationSignature(target, themeDecoration) {
131113
131947
  const existing = target["_sectionStyles"];
131114
- const existingObj = isPlainObject$1(existing) ? existing : void 0;
131948
+ const existingObj = isPlainObject$2(existing) ? existing : void 0;
131115
131949
  const rawOverride = existingObj?.["headingDecorationOverride"];
131116
131950
  const effective = resolveEffectiveHeadingDecoration(themeDecoration, rawOverride === "site-default" || rawOverride === "off" ? rawOverride : void 0);
131117
131951
  if (effective.kind === "none") {
@@ -131606,7 +132440,7 @@ function parseBorderWidth(widthClass) {
131606
132440
  }
131607
132441
  //#endregion
131608
132442
  //#region ../theme-core/src/accordions/generateAccordionCss.ts
131609
- init_types$9();
132443
+ init_types$8();
131610
132444
  init_constants$1();
131611
132445
  init_colorStyles();
131612
132446
  init_surfaces();
@@ -131791,7 +132625,7 @@ function generateAccordionCss({ themeId, theme, accordionSystem }) {
131791
132625
  }
131792
132626
  //#endregion
131793
132627
  //#region ../theme-core/src/inputs/generateInputCss.ts
131794
- init_types$8();
132628
+ init_types$7();
131795
132629
  init_constants$2();
131796
132630
  init_colorStyles();
131797
132631
  /**
@@ -134715,6 +135549,8 @@ function buildThemeCssVars(theme) {
134715
135549
  const inputRadius = mapInputRadius(inputSystem.base.corners, theme.corners);
134716
135550
  return {
134717
135551
  ...generateCssVars(theme.palette),
135552
+ ["--tb-secondaryForeground"]: "var(--tb-onSecondary)",
135553
+ ["--tb-accentForeground"]: "var(--tb-onAccent)",
134718
135554
  ["--tb-scrim"]: "0 0 0",
134719
135555
  ["--tb-shadow"]: "0 0 0",
134720
135556
  ...generateShadowCssVars(theme),
@@ -143368,6 +144204,11 @@ const containerResponsiveThemeCss = `/*
143368
144204
  flex-wrap: wrap;
143369
144205
  }
143370
144206
 
144207
+ /* Text-style CTA actions belong to the section foreground contract. */
144208
+ :where(.theme-scope) [data-block="cta-full"] .cta-row .button-link {
144209
+ color: var(--rb-surface-link-color, var(--rb-surface-text-color, rgb(var(--tb-primary))));
144210
+ }
144211
+
143371
144212
  /* =============================================================================
143372
144213
  * Block: Body Text (content block, Phase 2)
143373
144214
  *
@@ -148992,6 +149833,8 @@ init_types$16();
148992
149833
  * always emitting the structural CSS contract system blocks rely on.
148993
149834
  */
148994
149835
  init_colorConversion();
149836
+ init_textColor();
149837
+ init_onColor();
148995
149838
  init_core$1();
148996
149839
  init_core();
148997
149840
  z$1.object({
@@ -149954,35 +150797,35 @@ init_expandPalette();
149954
150797
  //#region ../blocks/src/system/runtime/bindings.ts
149955
150798
  init_node();
149956
150799
  const shouldLogWarnings = isNonProductionEnv();
149957
- function isPlainObject(value) {
150800
+ function isPlainObject$1(value) {
149958
150801
  return typeof value === "object" && value !== null && !Array.isArray(value);
149959
150802
  }
149960
150803
  function isRouteMapEntry(value) {
149961
150804
  if (typeof value === "string") return true;
149962
- return isPlainObject(value);
150805
+ return isPlainObject$1(value);
149963
150806
  }
149964
150807
  function isRouteMap(value) {
149965
- if (!isPlainObject(value)) return false;
150808
+ if (!isPlainObject$1(value)) return false;
149966
150809
  return Object.values(value).every(isRouteMapEntry);
149967
150810
  }
149968
150811
  function isPageIdentifierMap(value) {
149969
- if (!isPlainObject(value)) return false;
150812
+ if (!isPlainObject$1(value)) return false;
149970
150813
  return Object.values(value).every((v) => typeof v === "string");
149971
150814
  }
149972
150815
  function isEntryIdentifierMap(value) {
149973
- if (!isPlainObject(value)) return false;
150816
+ if (!isPlainObject$1(value)) return false;
149974
150817
  for (const v of Object.values(value)) {
149975
- if (!isPlainObject(v)) return false;
150818
+ if (!isPlainObject$1(v)) return false;
149976
150819
  if (!Object.values(v).every((inner) => typeof inner === "string")) return false;
149977
150820
  }
149978
150821
  return true;
149979
150822
  }
149980
150823
  function buildTransformContext(vm) {
149981
150824
  const root = vm.$root;
149982
- const stage = root && isPlainObject(root) && root.previewStage === "preview" ? "preview" : "published";
149983
- const routes = root && isPlainObject(root) && isRouteMap(root.routes) ? root.routes : void 0;
149984
- const pagesByIdentifier = root && isPlainObject(root) && isPageIdentifierMap(root.pagesByIdentifier) ? root.pagesByIdentifier : void 0;
149985
- const entriesByIdentifier = root && isPlainObject(root) && isEntryIdentifierMap(root.entriesByIdentifier) ? root.entriesByIdentifier : void 0;
150825
+ const stage = root && isPlainObject$1(root) && root.previewStage === "preview" ? "preview" : "published";
150826
+ const routes = root && isPlainObject$1(root) && isRouteMap(root.routes) ? root.routes : void 0;
150827
+ const pagesByIdentifier = root && isPlainObject$1(root) && isPageIdentifierMap(root.pagesByIdentifier) ? root.pagesByIdentifier : void 0;
150828
+ const entriesByIdentifier = root && isPlainObject$1(root) && isEntryIdentifierMap(root.entriesByIdentifier) ? root.entriesByIdentifier : void 0;
149986
150829
  return {
149987
150830
  theme: defaultThemeTokens,
149988
150831
  stage,
@@ -150353,6 +151196,7 @@ const RichText$1 = RichText$2;
150353
151196
  * behavior of the default declarative block system.
150354
151197
  */
150355
151198
  init_clsx();
151199
+ init_gradients();
150356
151200
  init_background$1();
150357
151201
  init_media();
150358
151202
  //#endregion
@@ -150382,6 +151226,7 @@ Array.from(new Set(systemCustomizeFacetDefinitions.flatMap((definition) => defin
150382
151226
  //#region ../blocks/src/system/customize/backgrounds.ts
150383
151227
  init_src$3();
150384
151228
  init_site_styles();
151229
+ init_gradients();
150385
151230
  const backgroundColorTokenNames = backgroundAppearanceColorTokenNames;
150386
151231
  const backgroundColorTokenNameSet = new Set(backgroundColorTokenNames);
150387
151232
  const backgroundColorTokens = toBackgroundColorTokens(backgroundColorTokenNames);
@@ -150402,18 +151247,17 @@ function parseBackgroundColorToken(value) {
150402
151247
  if (!token) return null;
150403
151248
  return token ? token : null;
150404
151249
  }
150405
- const gradientPresetIds = GRADIENT_PRESETS.map((preset) => preset.id);
150406
- new Set(gradientPresetIds);
150407
151250
  //#endregion
150408
151251
  //#region ../blocks/src/index.ts
150409
151252
  init_palette$1();
150410
151253
  init_generateShades();
150411
- init_utils$5();
151254
+ init_utils$6();
150412
151255
  init_schema$1();
150413
151256
  init_site_styles();
150414
151257
  init_buttons();
150415
151258
  init_cards();
150416
151259
  init_tokens();
151260
+ init_gradients();
150417
151261
  init_richTextSchema();
150418
151262
  init_media();
150419
151263
  init_media$2();
@@ -150974,6 +151818,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
150974
151818
  "already_refunded",
150975
151819
  "idempotency_amount_mismatch",
150976
151820
  "idempotency_method_mismatch",
151821
+ "idempotency_receipt_mismatch",
150977
151822
  "refund_in_progress"
150978
151823
  ],
150979
151824
  "invalid_amount",
@@ -150986,7 +151831,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
150986
151831
  "payment_intent_not_found",
150987
151832
  "stripe_error",
150988
151833
  "stale_pending_missing_context",
150989
- "non_refundable_deposit_remaining"
151834
+ "non_refundable_deposit_remaining",
151835
+ "deposit_refund_override_required",
151836
+ "refund_revoke_requires_full_line_refund",
151837
+ "payment_receipt_not_found",
151838
+ "payment_receipt_not_refundable",
151839
+ "payment_receipt_attribution_required"
150990
151840
  ];
150991
151841
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
150992
151842
  //#endregion
@@ -150999,7 +151849,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
150999
151849
  "missing_credit_customer",
151000
151850
  "deposit_refund_override_required",
151001
151851
  "refund_revoke_requires_full_line_refund",
151002
- "unified_order_link_required"
151852
+ "unified_order_link_required",
151853
+ "payment_receipt_not_found",
151854
+ "payment_receipt_not_refundable",
151855
+ "payment_receipt_attribution_required"
151003
151856
  ];
151004
151857
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
151005
151858
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];
@@ -153807,6 +154660,225 @@ function isDisplayMediaKind(value) {
153807
154660
  function isFileFieldKind(value) {
153808
154661
  return FILE_FIELD_KINDS.includes(value);
153809
154662
  }
154663
+ /** Matches the closed sentinel shape `"<REQUIRED: …>"`. */
154664
+ const SENTINEL_PATTERN = /^<REQUIRED:.*>$/;
154665
+ /**
154666
+ * True when a value is an unfilled placeholder sentinel. Shared by the emitter
154667
+ * (self-check) and the validator (rejection) so recognition can't drift.
154668
+ */
154669
+ function isPlaceholderSentinel(value) {
154670
+ return typeof value === "string" && SENTINEL_PATTERN.test(value);
154671
+ }
154672
+ function effectiveReferenceKind(field) {
154673
+ const kind = field.referenceKind;
154674
+ const legacy = field.reference?.type;
154675
+ return kind ?? legacy;
154676
+ }
154677
+ function selectOptionValues$1(field) {
154678
+ const options = field.options;
154679
+ return options ? options.map((o) => o.value) : [];
154680
+ }
154681
+ /**
154682
+ * The placeholder sentinel for a leaf field. Container types (group/button/
154683
+ * repeater) do not have a leaf sentinel — they expand structurally — and calling
154684
+ * this for them returns a generic marker only for completeness.
154685
+ */
154686
+ function buildSentinel(field) {
154687
+ switch (field.type) {
154688
+ case "text":
154689
+ case "textarea": return "<REQUIRED: text>";
154690
+ case "richText": return "<REQUIRED: rich-text>";
154691
+ case "number": return "<REQUIRED: number>";
154692
+ case "date": return "<REQUIRED: date (YYYY-MM-DD)>";
154693
+ case "datetime": return "<REQUIRED: datetime (ISO 8601)>";
154694
+ case "url": return "<REQUIRED: url>";
154695
+ case "link": return "<REQUIRED: link>";
154696
+ case "media": return "<REQUIRED: media-identifier>";
154697
+ case "file": return "<REQUIRED: file-identifier>";
154698
+ case "boolean": return "<REQUIRED: boolean>";
154699
+ case "select": {
154700
+ const values = selectOptionValues$1(field);
154701
+ return values.length > 0 ? `<REQUIRED: select (${values.join("|")})>` : "<REQUIRED: select>";
154702
+ }
154703
+ case "reference": {
154704
+ const kind = effectiveReferenceKind(field);
154705
+ return kind ? `<REQUIRED: reference-identifier (${kind})>` : "<REQUIRED: reference-identifier>";
154706
+ }
154707
+ case "group": return "<REQUIRED: group>";
154708
+ case "button": return "<REQUIRED: button>";
154709
+ case "repeater": return "<REQUIRED: repeater>";
154710
+ }
154711
+ }
154712
+ //#endregion
154713
+ //#region ../content-model/src/content-types/entryValidation.ts
154714
+ function subfieldsOf$1(field) {
154715
+ const direct = field.fields;
154716
+ if (direct && direct.length > 0) return direct;
154717
+ return field.schema?.fields ?? [];
154718
+ }
154719
+ function selectOptionValues(field) {
154720
+ const options = field.options;
154721
+ return options ? options.map((o) => o.value) : [];
154722
+ }
154723
+ function isPlainObject(value) {
154724
+ return value !== null && typeof value === "object" && !Array.isArray(value);
154725
+ }
154726
+ /** Field types whose value must be a string. */
154727
+ const STRING_TYPES = /* @__PURE__ */ new Set([
154728
+ "text",
154729
+ "textarea",
154730
+ "url",
154731
+ "link",
154732
+ "media",
154733
+ "file",
154734
+ "reference",
154735
+ "date",
154736
+ "datetime",
154737
+ "select"
154738
+ ]);
154739
+ function checkLeafType(field, value, path, errors) {
154740
+ const push = (code, message) => {
154741
+ errors.push({
154742
+ path,
154743
+ fieldType: field.type,
154744
+ code,
154745
+ message
154746
+ });
154747
+ };
154748
+ if (field.type === "number") {
154749
+ if (typeof value !== "number" || Number.isNaN(value)) push("wrong_type", `"${path}" must be a number.`);
154750
+ return;
154751
+ }
154752
+ if (field.type === "boolean") {
154753
+ if (typeof value !== "boolean") push("wrong_type", `"${path}" must be a boolean.`);
154754
+ return;
154755
+ }
154756
+ if (field.type === "richText") {
154757
+ if (typeof value !== "string" && !isPlainObject(value)) push("wrong_type", `"${path}" must be rich-text (string or document object).`);
154758
+ return;
154759
+ }
154760
+ if (field.type === "select") {
154761
+ if (typeof value !== "string") {
154762
+ push("wrong_type", `"${path}" must be a string.`);
154763
+ return;
154764
+ }
154765
+ const options = selectOptionValues(field);
154766
+ if (options.length > 0 && !options.includes(value)) push("invalid_option", `"${path}" must be one of: ${options.join(", ")}.`);
154767
+ return;
154768
+ }
154769
+ if (STRING_TYPES.has(field.type)) {
154770
+ if (typeof value !== "string") push("wrong_type", `"${path}" must be a string.`);
154771
+ }
154772
+ }
154773
+ function validateField(field, value, path, errors) {
154774
+ if (value === void 0 || value === null || value === "") {
154775
+ if (field.required === true) errors.push({
154776
+ path,
154777
+ fieldType: field.type,
154778
+ code: "missing_required",
154779
+ message: `Required field "${path}" is missing.`
154780
+ });
154781
+ return;
154782
+ }
154783
+ if (isPlaceholderSentinel(value)) {
154784
+ errors.push({
154785
+ path,
154786
+ fieldType: field.type,
154787
+ code: "unfilled_placeholder",
154788
+ message: `"${path}" still contains an unfilled placeholder (${value}).`
154789
+ });
154790
+ return;
154791
+ }
154792
+ if (field.type === "group" || field.type === "button") {
154793
+ if (!isPlainObject(value)) {
154794
+ errors.push({
154795
+ path,
154796
+ fieldType: field.type,
154797
+ code: "wrong_type",
154798
+ message: `"${path}" must be an object.`
154799
+ });
154800
+ return;
154801
+ }
154802
+ validateFields(subfieldsOf$1(field), value, path, errors);
154803
+ return;
154804
+ }
154805
+ if (field.type === "repeater") {
154806
+ if (!Array.isArray(value)) {
154807
+ errors.push({
154808
+ path,
154809
+ fieldType: field.type,
154810
+ code: "wrong_type",
154811
+ message: `"${path}" must be an array.`
154812
+ });
154813
+ return;
154814
+ }
154815
+ const itemFields = subfieldsOf$1(field);
154816
+ value.forEach((item, index) => {
154817
+ const itemPath = `${path}[${index}]`;
154818
+ if (!isPlainObject(item)) {
154819
+ errors.push({
154820
+ path: itemPath,
154821
+ fieldType: "repeater",
154822
+ code: "wrong_type",
154823
+ message: `"${itemPath}" must be an object.`
154824
+ });
154825
+ return;
154826
+ }
154827
+ validateFields(itemFields, item, itemPath, errors);
154828
+ });
154829
+ return;
154830
+ }
154831
+ checkLeafType(field, value, path, errors);
154832
+ }
154833
+ function validateFields(fields, data, pathPrefix, errors) {
154834
+ for (const field of fields) {
154835
+ const path = pathPrefix ? `${pathPrefix}.${field.id}` : field.id;
154836
+ validateField(field, data[field.id], path, errors);
154837
+ }
154838
+ }
154839
+ //#endregion
154840
+ //#region ../content-model/src/content-types/scaffold.ts
154841
+ /** Nested subfields for group/repeater/button-style fields (both DSL shapes). */
154842
+ function subfieldsOf(field) {
154843
+ const direct = field.fields;
154844
+ if (direct && direct.length > 0) return direct;
154845
+ return field.schema?.fields ?? [];
154846
+ }
154847
+ const CONTAINER_TYPES = /* @__PURE__ */ new Set([
154848
+ "group",
154849
+ "button",
154850
+ "repeater"
154851
+ ]);
154852
+ /**
154853
+ * Build the placeholder value for a required field. Group/button fields recurse
154854
+ * into their required subfields; repeaters emit a single seed item so agents see
154855
+ * the item shape.
154856
+ */
154857
+ function buildFieldValue(field) {
154858
+ if (field.type === "repeater") return [buildObjectFromFields(subfieldsOf(field))];
154859
+ if (CONTAINER_TYPES.has(field.type)) {
154860
+ const subfields = subfieldsOf(field);
154861
+ if (subfields.length > 0) return buildObjectFromFields(subfields);
154862
+ if (field.type === "button") return {
154863
+ label: "<REQUIRED: text>",
154864
+ link: "<REQUIRED: link>"
154865
+ };
154866
+ return {};
154867
+ }
154868
+ return buildSentinel(field);
154869
+ }
154870
+ /**
154871
+ * Build a template object from a list of fields, stubbing required fields and
154872
+ * omitting optional ones.
154873
+ */
154874
+ function buildObjectFromFields(fields) {
154875
+ const template = {};
154876
+ for (const field of fields) {
154877
+ if (field.required !== true) continue;
154878
+ template[field.id] = buildFieldValue(field);
154879
+ }
154880
+ return template;
154881
+ }
153810
154882
  //#endregion
153811
154883
  //#region ../content-model/src/content-types/builtins.ts
153812
154884
  /**