@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
@@ -211,19 +211,29 @@ function isRecord$9(value) {
211
211
  //#region ../core/src/booking-date-time.ts
212
212
  const DEFAULT_LOCALE = "en-US";
213
213
  const FALLBACK_TIMEZONE = "UTC";
214
+ const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
215
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
216
+ const timeZoneValidityCache = /* @__PURE__ */ new Map();
214
217
  function isValidTimeZone(timeZone) {
218
+ const cached = timeZoneValidityCache.get(timeZone);
219
+ if (cached !== void 0) return cached;
220
+ let isValid;
215
221
  try {
216
222
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
217
- return true;
223
+ isValid = true;
218
224
  } catch {
219
- return false;
225
+ isValid = false;
220
226
  }
227
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
228
+ timeZoneValidityCache.set(timeZone, isValid);
229
+ return isValid;
221
230
  }
222
231
  function getSafeTimeZone(timeZone) {
223
232
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
224
233
  return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
225
234
  }
226
235
  function parseStrictBookingTimeZone(timeZone) {
236
+ if (typeof timeZone !== "string") return null;
227
237
  const normalized = timeZone.trim();
228
238
  if (normalized.length === 0 || !isValidTimeZone(normalized)) return null;
229
239
  return normalized;
@@ -236,10 +246,19 @@ function formatParseError(error) {
236
246
  }
237
247
  }
238
248
  function formatToPartsLookup(date, locale, timeZone, format) {
239
- return new Map(new Intl.DateTimeFormat(locale, {
249
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
250
+ }
251
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
252
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
253
+ const cached = dateTimeFormatterCache.get(key);
254
+ if (cached !== void 0) return cached;
255
+ const formatter = new Intl.DateTimeFormat(locale, {
240
256
  ...format,
241
257
  timeZone
242
- }).formatToParts(date).map((part) => [part.type, part.value]));
258
+ });
259
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
260
+ dateTimeFormatterCache.set(key, formatter);
261
+ return formatter;
243
262
  }
244
263
  function getZonedDateTimeParts(date, timeZone) {
245
264
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -282,23 +301,9 @@ function toUtcIsoDateTimeString(value) {
282
301
  return parsed.value;
283
302
  }
284
303
  function parseScheduledBookingDateTime(input) {
304
+ let startsAt;
285
305
  try {
286
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
287
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
288
- if (timeZone === null) return {
289
- ok: false,
290
- field: "timeZone",
291
- reason: "invalid_time_zone",
292
- value: input.timeZone
293
- };
294
- return {
295
- ok: true,
296
- value: {
297
- startsAt,
298
- timeZone,
299
- locale: input.locale
300
- }
301
- };
306
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
302
307
  } catch {
303
308
  return {
304
309
  ok: false,
@@ -307,6 +312,21 @@ function parseScheduledBookingDateTime(input) {
307
312
  value: input.startsAt
308
313
  };
309
314
  }
315
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
316
+ if (timeZone === null) return {
317
+ ok: false,
318
+ field: "timeZone",
319
+ reason: "invalid_time_zone",
320
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
321
+ };
322
+ return {
323
+ ok: true,
324
+ value: {
325
+ startsAt,
326
+ timeZone,
327
+ locale: input.locale
328
+ }
329
+ };
310
330
  }
311
331
  function toScheduledBookingDateTime(input) {
312
332
  const result = parseScheduledBookingDateTime(input);
@@ -3436,6 +3456,111 @@ const mediaSchema$1 = z.object({
3436
3456
  transform: transformSchema$1.optional()
3437
3457
  });
3438
3458
  //#endregion
3459
+ //#region ../theme-core/src/buttons/effectClassification.ts
3460
+ /**
3461
+ * Exhaustive live policy for every registered effect id.
3462
+ *
3463
+ * The resolver consumes the transition payload directly, so adding an effect
3464
+ * cannot update classification without also defining its runtime behavior.
3465
+ */
3466
+ const BUTTON_EFFECT_POLICIES = {
3467
+ "darken-background": {
3468
+ classification: "colour-transition",
3469
+ transition: {
3470
+ kind: "adjust-shade",
3471
+ direction: "darker"
3472
+ }
3473
+ },
3474
+ "lighten-background": {
3475
+ classification: "colour-transition",
3476
+ transition: {
3477
+ kind: "adjust-shade",
3478
+ direction: "lighter"
3479
+ }
3480
+ },
3481
+ "background-on-hover": {
3482
+ classification: "colour-transition",
3483
+ transition: { kind: "replace-background" }
3484
+ },
3485
+ "background-on-hover-alpha": {
3486
+ classification: "unsupported-colour",
3487
+ reason: "alpha_requires_surface"
3488
+ },
3489
+ "fade-background": {
3490
+ classification: "unsupported-colour",
3491
+ reason: "changes_element_opacity"
3492
+ },
3493
+ "opacity-reduce": {
3494
+ classification: "unsupported-colour",
3495
+ reason: "changes_element_opacity"
3496
+ },
3497
+ "gradient-text": {
3498
+ classification: "unsupported-colour",
3499
+ reason: "changes_foreground"
3500
+ },
3501
+ "text-color-change": {
3502
+ classification: "unsupported-colour",
3503
+ reason: "changes_foreground"
3504
+ },
3505
+ "border-color-change": {
3506
+ classification: "unsupported-colour",
3507
+ reason: "changes_border"
3508
+ },
3509
+ "aurora-glow": {
3510
+ classification: "unsupported-background-overlay",
3511
+ reason: "unresolved_background_overlay"
3512
+ },
3513
+ "cosmic-stardust": {
3514
+ classification: "unsupported-background-overlay",
3515
+ reason: "unresolved_background_overlay"
3516
+ },
3517
+ "gradient-border-fill": {
3518
+ classification: "unsupported-background-overlay",
3519
+ reason: "unresolved_background_overlay"
3520
+ },
3521
+ "animated-gradient-border-fill": {
3522
+ classification: "unsupported-background-overlay",
3523
+ reason: "unresolved_background_overlay"
3524
+ },
3525
+ "nav-underline": {
3526
+ classification: "not-button",
3527
+ reason: "not_button_effect"
3528
+ },
3529
+ "nav-frosted-base": {
3530
+ classification: "not-button",
3531
+ reason: "not_button_effect"
3532
+ },
3533
+ "nav-frosted-hover": {
3534
+ classification: "not-button",
3535
+ reason: "not_button_effect"
3536
+ },
3537
+ "nav-frosted-active": {
3538
+ classification: "not-button",
3539
+ reason: "not_button_effect"
3540
+ },
3541
+ "animated-gradient": { classification: "non-colour" },
3542
+ "border-glow": { classification: "non-colour" },
3543
+ "drop-shadow": { classification: "non-colour" },
3544
+ "inner-shadow": { classification: "non-colour" },
3545
+ "neumorphic-shadow": { classification: "non-colour" },
3546
+ "outer-glow": { classification: "non-colour" },
3547
+ "retro-3d-shadow": { classification: "non-colour" },
3548
+ "scale-up": { classification: "non-colour" },
3549
+ "scale-down": { classification: "non-colour" },
3550
+ lift: { classification: "non-colour" },
3551
+ "press-down": { classification: "non-colour" },
3552
+ pop: { classification: "non-colour" },
3553
+ "border-bottom-grow": { classification: "non-colour" },
3554
+ "sketchy-border": { classification: "non-colour" },
3555
+ "pulse-animation": { classification: "non-colour" }
3556
+ };
3557
+ function getButtonEffectPolicy(effectId) {
3558
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
3559
+ }
3560
+ function classifyButtonEffectId(effectId) {
3561
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
3562
+ }
3563
+ //#endregion
3439
3564
  //#region ../theme-core/src/buttons/types.ts
3440
3565
  /**
3441
3566
  * Standard semantic variant roles a theme exposes.
@@ -3452,6 +3577,20 @@ const VARIANT_ROLES = [
3452
3577
  "tertiary",
3453
3578
  "accent"
3454
3579
  ];
3580
+ function parseOpaqueButtonColourToken(value) {
3581
+ const token = parseThemeColorToken(value);
3582
+ if (token === null) return null;
3583
+ const parts = parseColorTokenParts(token);
3584
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
3585
+ }
3586
+ function unsafeAsOpaqueButtonColourToken(value) {
3587
+ return value;
3588
+ }
3589
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
3590
+ const token = parseOpaqueButtonColourToken(value);
3591
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
3592
+ return token;
3593
+ });
3455
3594
  const cornerStyleSchema = z$1.enum([
3456
3595
  "square",
3457
3596
  "rounded",
@@ -3553,7 +3692,7 @@ const buttonSizesSchema = z$1.object({
3553
3692
  lg,
3554
3693
  xl: xl ?? lg
3555
3694
  }));
3556
- const buttonGlobalSettingsSchema = z$1.object({
3695
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
3557
3696
  cornerStyle: cornerStyleSchema,
3558
3697
  cornerRadius: z$1.number().min(0).max(24).optional(),
3559
3698
  /**
@@ -3584,11 +3723,12 @@ const buttonGlobalSettingsSchema = z$1.object({
3584
3723
  paddingPreset: buttonPaddingPresetSchema.optional(),
3585
3724
  hoverTransform: hoverTransformSchema,
3586
3725
  hoverColor: hoverColorSchema,
3587
- hoverColorToken: themeColorTokenSchema.optional(),
3726
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
3588
3727
  gradientStyle: gradientStyleSchema.optional(),
3589
3728
  gradientAngle: z$1.number().min(0).max(360).optional(),
3590
3729
  gradientSharpness: gradientSharpnessSchema.optional()
3591
3730
  });
3731
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
3592
3732
  const gradientDirectionSchema$1 = z$1.enum([
3593
3733
  "to-r",
3594
3734
  "to-l",
@@ -3602,27 +3742,33 @@ const gradientDirectionSchema$1 = z$1.enum([
3602
3742
  const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
3603
3743
  z$1.object({
3604
3744
  type: z$1.literal("solid"),
3605
- colorToken: themeColorTokenSchema
3745
+ colorToken: opaqueButtonColourTokenSchema
3606
3746
  }),
3607
3747
  z$1.object({
3608
3748
  type: z$1.literal("gradient"),
3609
- stops: z$1.array(themeColorTokenSchema).min(2),
3610
- direction: gradientDirectionSchema$1
3749
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
3750
+ const [first, second, ...rest] = stops;
3751
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
3752
+ return [
3753
+ first,
3754
+ second,
3755
+ ...rest
3756
+ ];
3757
+ }),
3758
+ direction: gradientDirectionSchema$1,
3759
+ foregroundToken: opaqueButtonColourTokenSchema
3611
3760
  }),
3612
- z$1.object({ type: z$1.literal("transparent") })
3761
+ z$1.object({
3762
+ type: z$1.literal("surface"),
3763
+ role: z$1.literal("link")
3764
+ })
3613
3765
  ]);
3614
3766
  const effectApplicationSchema$1 = z$1.object({
3615
3767
  effectId: z$1.string(),
3616
- options: z$1.record(z$1.string(), z$1.any()).optional()
3617
- });
3618
- const buttonBorderSchema = z$1.object({
3619
- widthClass: z$1.string(),
3620
- colorToken: themeColorTokenSchema
3621
- });
3622
- const buttonVariantAffordanceSchema = z$1.object({
3623
- iconId: z$1.string().min(1),
3624
- colorToken: themeColorTokenSchema.optional()
3768
+ options: z$1.record(z$1.string(), z$1.json()).optional()
3625
3769
  });
3770
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
3771
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
3626
3772
  const variantShadowSchema = z$1.object({
3627
3773
  elevation: z$1.enum([
3628
3774
  "none",
@@ -3663,27 +3809,170 @@ const variantSizeOverridesSchema = z$1.object({
3663
3809
  * default (e.g. link-style variants declaring zero horizontal padding at
3664
3810
  * every size).
3665
3811
  */
3666
- const buttonVariantSchema = z$1.object({
3812
+ const canonicalButtonVariantSchema = z$1.object({
3667
3813
  id: z$1.string(),
3668
3814
  name: z$1.string().min(1).max(20),
3669
3815
  enabled: z$1.boolean(),
3670
3816
  priority: prioritySchema,
3671
3817
  background: buttonBackgroundSchema,
3672
- textColorToken: themeColorTokenSchema,
3673
3818
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
3674
3819
  borderRadius: z$1.string().optional(),
3675
3820
  shadow: variantShadowSchema.optional(),
3676
3821
  border: buttonBorderSchema.optional(),
3677
- hoverBackgroundToken: z$1.string().optional(),
3822
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
3678
3823
  effects: variantEffectsSchema.optional(),
3679
3824
  sizes: variantSizeOverridesSchema.optional(),
3680
3825
  affordance: buttonVariantAffordanceSchema.optional()
3681
3826
  });
3827
+ /**
3828
+ * Temporary persisted-theme admission boundary for issue #1206.
3829
+ *
3830
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
3831
+ * `textColorToken`/border colour shape. New source and all downstream code use
3832
+ * only the canonical relationship. Delete this preprocessor after the reviewed
3833
+ * production rewrite reports zero legacy rows.
3834
+ */
3835
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
3682
3836
  const buttonSystemSchema = z$1.object({
3683
3837
  global: buttonGlobalSettingsSchema,
3684
3838
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
3685
3839
  sizes: buttonSizesSchema.optional()
3686
3840
  });
3841
+ function normalizeLegacyButtonVariantInput(input) {
3842
+ if (!isUnknownRecord(input)) return input;
3843
+ const background = input.background;
3844
+ if (!isUnknownRecord(background)) return input;
3845
+ 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;
3846
+ const { textColorToken, ...withoutLegacyText } = input;
3847
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
3848
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
3849
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
3850
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
3851
+ if (background.type === "transparent") return {
3852
+ ...withoutLegacyText,
3853
+ background: {
3854
+ type: "surface",
3855
+ role: "link"
3856
+ },
3857
+ border: normalizedBorder,
3858
+ affordance: normalizedAffordance,
3859
+ effects: normalizedEffects,
3860
+ hoverBackgroundToken
3861
+ };
3862
+ if (background.type === "gradient") {
3863
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
3864
+ return {
3865
+ ...withoutLegacyText,
3866
+ background: {
3867
+ ...background,
3868
+ stops,
3869
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
3870
+ },
3871
+ border: normalizedBorder,
3872
+ affordance: normalizedAffordance,
3873
+ effects: normalizedEffects,
3874
+ hoverBackgroundToken
3875
+ };
3876
+ }
3877
+ return {
3878
+ ...withoutLegacyText,
3879
+ background: background.type === "solid" ? {
3880
+ ...background,
3881
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
3882
+ } : background,
3883
+ border: normalizedBorder,
3884
+ affordance: normalizedAffordance,
3885
+ effects: normalizedEffects,
3886
+ hoverBackgroundToken
3887
+ };
3888
+ }
3889
+ function normalizeLegacyButtonGlobalInput(input) {
3890
+ if (!isUnknownRecord(input)) return input;
3891
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
3892
+ return hoverColorToken === input.hoverColorToken ? input : {
3893
+ ...input,
3894
+ hoverColorToken
3895
+ };
3896
+ }
3897
+ function hasLegacyAlphaToken(input, background) {
3898
+ const stops = isUnknownArray(background.stops) ? background.stops : [];
3899
+ return [
3900
+ input.hoverBackgroundToken,
3901
+ background.colorToken,
3902
+ background.foregroundToken,
3903
+ ...stops
3904
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
3905
+ }
3906
+ function stripLegacyTokenAlpha(value) {
3907
+ if (typeof value !== "string") return value;
3908
+ const slashIndex = value.indexOf("/");
3909
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
3910
+ }
3911
+ function hasLegacyButtonEffects(input) {
3912
+ if (!isUnknownRecord(input)) return false;
3913
+ return [
3914
+ "base",
3915
+ "hover",
3916
+ "active",
3917
+ "focus"
3918
+ ].some((state) => {
3919
+ const effects = input[state];
3920
+ return Array.isArray(effects) && effects.some((effect) => {
3921
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
3922
+ const classification = classifyButtonEffectId(effect.effectId);
3923
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
3924
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
3925
+ });
3926
+ });
3927
+ }
3928
+ function normalizeLegacyButtonEffects(input, backgroundType) {
3929
+ if (!isUnknownRecord(input)) return input;
3930
+ const normalized = {};
3931
+ for (const state of [
3932
+ "base",
3933
+ "hover",
3934
+ "active",
3935
+ "focus"
3936
+ ]) {
3937
+ const effects = input[state];
3938
+ if (!Array.isArray(effects)) continue;
3939
+ const safeEffects = effects.flatMap((effect) => {
3940
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
3941
+ const classification = classifyButtonEffectId(effect.effectId);
3942
+ if (classification === "non-colour") return [effect];
3943
+ if (classification !== "colour-transition") return [];
3944
+ if (effect.effectId === "background-on-hover") {
3945
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
3946
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
3947
+ return colorToken === null ? [] : [{
3948
+ ...effect,
3949
+ options: {
3950
+ ...options,
3951
+ colorToken
3952
+ }
3953
+ }];
3954
+ }
3955
+ if (backgroundType !== "solid") return [];
3956
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
3957
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
3958
+ return [{
3959
+ ...effect,
3960
+ options: {
3961
+ ...isUnknownRecord(effect.options) ? effect.options : {},
3962
+ amount
3963
+ }
3964
+ }];
3965
+ });
3966
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
3967
+ }
3968
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
3969
+ }
3970
+ function isUnknownRecord(value) {
3971
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3972
+ }
3973
+ function isUnknownArray(value) {
3974
+ return Array.isArray(value);
3975
+ }
3687
3976
  buttonSizeNameSchema.options;
3688
3977
  //#endregion
3689
3978
  //#region ../theme-core/src/buttons/personalities/types.ts
@@ -3710,7 +3999,7 @@ function defineButtonPersonality(input) {
3710
3999
  name: input.name,
3711
4000
  description: input.description,
3712
4001
  tags: input.tags,
3713
- buttonSystem: input.buttonSystem
4002
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
3714
4003
  };
3715
4004
  }
3716
4005
  //#endregion
@@ -3763,19 +4052,15 @@ const brushedWash = defineButtonPersonality({
3763
4052
  background: {
3764
4053
  type: "gradient",
3765
4054
  stops: ["primary", "accent"],
3766
- direction: "to-r"
4055
+ direction: "to-r",
4056
+ foregroundToken: "primaryForeground"
3767
4057
  },
3768
- textColorToken: "primaryForeground",
3769
4058
  borderRadius: "rounded-lg",
3770
4059
  shadow: {
3771
4060
  elevation: "low",
3772
4061
  softness: "soft",
3773
4062
  position: "bottom"
3774
- },
3775
- effects: { hover: [{
3776
- effectId: "opacity-reduce",
3777
- options: { reduction: -15 }
3778
- }] }
4063
+ }
3779
4064
  },
3780
4065
  {
3781
4066
  id: "secondary",
@@ -3785,32 +4070,27 @@ const brushedWash = defineButtonPersonality({
3785
4070
  background: {
3786
4071
  type: "gradient",
3787
4072
  stops: ["secondary", "accent"],
3788
- direction: "to-br"
4073
+ direction: "to-br",
4074
+ foregroundToken: "primaryForeground"
3789
4075
  },
3790
- textColorToken: "primaryForeground",
3791
4076
  borderRadius: "rounded-lg",
3792
4077
  shadow: {
3793
4078
  elevation: "low",
3794
4079
  softness: "soft",
3795
4080
  position: "bottom"
3796
- },
3797
- effects: { hover: [{
3798
- effectId: "opacity-reduce",
3799
- options: { reduction: -15 }
3800
- }] }
4081
+ }
3801
4082
  },
3802
4083
  {
3803
4084
  id: "outline",
3804
4085
  name: "Outline",
3805
4086
  enabled: true,
3806
4087
  priority: 3,
3807
- background: { type: "transparent" },
3808
- textColorToken: "primary",
3809
- borderRadius: "rounded-lg",
3810
- border: {
3811
- widthClass: "border",
3812
- colorToken: "primary"
4088
+ background: {
4089
+ type: "surface",
4090
+ role: "link"
3813
4091
  },
4092
+ borderRadius: "rounded-lg",
4093
+ border: { widthClass: "border" },
3814
4094
  effects: { hover: [{
3815
4095
  effectId: "background-on-hover",
3816
4096
  options: { colorToken: "surface" }
@@ -3821,8 +4101,10 @@ const brushedWash = defineButtonPersonality({
3821
4101
  name: "Ghost",
3822
4102
  enabled: true,
3823
4103
  priority: 3,
3824
- background: { type: "transparent" },
3825
- textColorToken: "text",
4104
+ background: {
4105
+ type: "surface",
4106
+ role: "link"
4107
+ },
3826
4108
  borderRadius: "rounded-lg",
3827
4109
  effects: { hover: [{
3828
4110
  effectId: "background-on-hover",
@@ -3868,7 +4150,6 @@ const confidentChip = defineButtonPersonality({
3868
4150
  type: "solid",
3869
4151
  colorToken: "primary"
3870
4152
  },
3871
- textColorToken: "primaryForeground",
3872
4153
  borderRadius: "rounded-md",
3873
4154
  shadow: {
3874
4155
  elevation: "medium",
@@ -3878,7 +4159,7 @@ const confidentChip = defineButtonPersonality({
3878
4159
  effects: {
3879
4160
  hover: [{
3880
4161
  effectId: "darken-background",
3881
- options: { amount: 60 }
4162
+ options: { amount: 100 }
3882
4163
  }],
3883
4164
  active: [{
3884
4165
  effectId: "scale-down",
@@ -3895,12 +4176,8 @@ const confidentChip = defineButtonPersonality({
3895
4176
  type: "solid",
3896
4177
  colorToken: "surface"
3897
4178
  },
3898
- textColorToken: "text",
3899
4179
  borderRadius: "rounded-md",
3900
- border: {
3901
- widthClass: "border",
3902
- colorToken: "border"
3903
- },
4180
+ border: { widthClass: "border" },
3904
4181
  effects: { hover: [{
3905
4182
  effectId: "background-on-hover",
3906
4183
  options: { colorToken: "background" }
@@ -3911,13 +4188,12 @@ const confidentChip = defineButtonPersonality({
3911
4188
  name: "Outline",
3912
4189
  enabled: true,
3913
4190
  priority: 3,
3914
- background: { type: "transparent" },
3915
- textColorToken: "primary",
3916
- borderRadius: "rounded-md",
3917
- border: {
3918
- widthClass: "border",
3919
- colorToken: "primary"
4191
+ background: {
4192
+ type: "surface",
4193
+ role: "link"
3920
4194
  },
4195
+ borderRadius: "rounded-md",
4196
+ border: { widthClass: "border" },
3921
4197
  effects: { hover: [{
3922
4198
  effectId: "background-on-hover",
3923
4199
  options: { colorToken: "surface" }
@@ -3928,8 +4204,10 @@ const confidentChip = defineButtonPersonality({
3928
4204
  name: "Ghost",
3929
4205
  enabled: true,
3930
4206
  priority: 3,
3931
- background: { type: "transparent" },
3932
- textColorToken: "primary",
4207
+ background: {
4208
+ type: "surface",
4209
+ role: "link"
4210
+ },
3933
4211
  borderRadius: "rounded-md",
3934
4212
  effects: { hover: [{
3935
4213
  effectId: "background-on-hover",
@@ -3992,7 +4270,6 @@ const earthPill = defineButtonPersonality({
3992
4270
  type: "solid",
3993
4271
  colorToken: "primary"
3994
4272
  },
3995
- textColorToken: "primaryForeground",
3996
4273
  borderRadius: "rounded-full",
3997
4274
  shadow: {
3998
4275
  elevation: "low",
@@ -4018,13 +4295,12 @@ const earthPill = defineButtonPersonality({
4018
4295
  name: "Secondary",
4019
4296
  enabled: true,
4020
4297
  priority: 2,
4021
- background: { type: "transparent" },
4022
- textColorToken: "primary",
4023
- borderRadius: "rounded-full",
4024
- border: {
4025
- widthClass: "border",
4026
- colorToken: "primary"
4298
+ background: {
4299
+ type: "surface",
4300
+ role: "link"
4027
4301
  },
4302
+ borderRadius: "rounded-full",
4303
+ border: { widthClass: "border" },
4028
4304
  effects: { hover: [{
4029
4305
  effectId: "background-on-hover",
4030
4306
  options: { colorToken: "muted" }
@@ -4035,13 +4311,12 @@ const earthPill = defineButtonPersonality({
4035
4311
  name: "Outline",
4036
4312
  enabled: true,
4037
4313
  priority: 3,
4038
- background: { type: "transparent" },
4039
- textColorToken: "text",
4040
- borderRadius: "rounded-full",
4041
- border: {
4042
- widthClass: "border",
4043
- colorToken: "border"
4314
+ background: {
4315
+ type: "surface",
4316
+ role: "link"
4044
4317
  },
4318
+ borderRadius: "rounded-full",
4319
+ border: { widthClass: "border" },
4045
4320
  effects: { hover: [{
4046
4321
  effectId: "background-on-hover",
4047
4322
  options: { colorToken: "surfaceAlt" }
@@ -4052,8 +4327,10 @@ const earthPill = defineButtonPersonality({
4052
4327
  name: "Ghost",
4053
4328
  enabled: true,
4054
4329
  priority: 3,
4055
- background: { type: "transparent" },
4056
- textColorToken: "primary",
4330
+ background: {
4331
+ type: "surface",
4332
+ role: "link"
4333
+ },
4057
4334
  borderRadius: "rounded-full",
4058
4335
  shadow: {
4059
4336
  elevation: "none",
@@ -4074,11 +4351,7 @@ const earthPill = defineButtonPersonality({
4074
4351
  padding: "0.625rem 0",
4075
4352
  fontSize: "text-xl"
4076
4353
  }
4077
- },
4078
- effects: { hover: [{
4079
- effectId: "opacity-reduce",
4080
- options: { reduction: 25 }
4081
- }] }
4354
+ }
4082
4355
  }
4083
4356
  ]
4084
4357
  }
@@ -4114,8 +4387,10 @@ const editorialLink = defineButtonPersonality({
4114
4387
  name: "Primary",
4115
4388
  enabled: true,
4116
4389
  priority: 1,
4117
- background: { type: "transparent" },
4118
- textColorToken: "text",
4390
+ background: {
4391
+ type: "surface",
4392
+ role: "link"
4393
+ },
4119
4394
  borderRadius: "rounded-none",
4120
4395
  sizes: {
4121
4396
  sm: { padding: "0.25rem 0" },
@@ -4137,8 +4412,10 @@ const editorialLink = defineButtonPersonality({
4137
4412
  name: "Secondary",
4138
4413
  enabled: true,
4139
4414
  priority: 2,
4140
- background: { type: "transparent" },
4141
- textColorToken: "mutedText",
4415
+ background: {
4416
+ type: "surface",
4417
+ role: "link"
4418
+ },
4142
4419
  borderRadius: "rounded-none",
4143
4420
  sizes: {
4144
4421
  sm: { padding: "0.25rem 0" },
@@ -4160,8 +4437,10 @@ const editorialLink = defineButtonPersonality({
4160
4437
  name: "Outline",
4161
4438
  enabled: true,
4162
4439
  priority: 3,
4163
- background: { type: "transparent" },
4164
- textColorToken: "accent",
4440
+ background: {
4441
+ type: "surface",
4442
+ role: "link"
4443
+ },
4165
4444
  borderRadius: "rounded-none",
4166
4445
  sizes: {
4167
4446
  sm: { padding: "0.25rem 0" },
@@ -4183,19 +4462,17 @@ const editorialLink = defineButtonPersonality({
4183
4462
  name: "Ghost",
4184
4463
  enabled: true,
4185
4464
  priority: 3,
4186
- background: { type: "transparent" },
4187
- textColorToken: "mutedText",
4465
+ background: {
4466
+ type: "surface",
4467
+ role: "link"
4468
+ },
4188
4469
  borderRadius: "rounded-none",
4189
4470
  sizes: {
4190
4471
  sm: { padding: "0.25rem 0" },
4191
4472
  md: { padding: "0.5rem 0" },
4192
4473
  lg: { padding: "0.625rem 0" },
4193
4474
  xl: { padding: "0.75rem 0" }
4194
- },
4195
- effects: { hover: [{
4196
- effectId: "opacity-reduce",
4197
- options: { reduction: -20 }
4198
- }] }
4475
+ }
4199
4476
  }
4200
4477
  ]
4201
4478
  }
@@ -4257,12 +4534,8 @@ const flatInk = defineButtonPersonality({
4257
4534
  type: "solid",
4258
4535
  colorToken: "primary"
4259
4536
  },
4260
- textColorToken: "primaryForeground",
4261
4537
  borderRadius: "rounded-lg",
4262
- affordance: {
4263
- iconId: "ArrowRight",
4264
- colorToken: "accent"
4265
- },
4538
+ affordance: { iconId: "ArrowRight" },
4266
4539
  effects: { hover: [{
4267
4540
  effectId: "lift",
4268
4541
  options: { translateY: "-2px" }
@@ -4276,13 +4549,12 @@ const flatInk = defineButtonPersonality({
4276
4549
  name: "Secondary",
4277
4550
  enabled: true,
4278
4551
  priority: 2,
4279
- background: { type: "transparent" },
4280
- textColorToken: "primary",
4281
- borderRadius: "rounded-lg",
4282
- border: {
4283
- widthClass: "border",
4284
- colorToken: "border"
4552
+ background: {
4553
+ type: "surface",
4554
+ role: "link"
4285
4555
  },
4556
+ borderRadius: "rounded-lg",
4557
+ border: { widthClass: "border" },
4286
4558
  effects: { hover: [{
4287
4559
  effectId: "lift",
4288
4560
  options: { translateY: "-2px" }
@@ -4300,12 +4572,8 @@ const flatInk = defineButtonPersonality({
4300
4572
  type: "solid",
4301
4573
  colorToken: "accent"
4302
4574
  },
4303
- textColorToken: "accentForeground",
4304
4575
  borderRadius: "rounded-lg",
4305
- affordance: {
4306
- iconId: "ArrowRight",
4307
- colorToken: "accentForeground"
4308
- },
4576
+ affordance: { iconId: "ArrowRight" },
4309
4577
  effects: { hover: [{
4310
4578
  effectId: "lift",
4311
4579
  options: { translateY: "-2px" }
@@ -4368,7 +4636,6 @@ const inkStamp = defineButtonPersonality({
4368
4636
  type: "solid",
4369
4637
  colorToken: "primary"
4370
4638
  },
4371
- textColorToken: "primaryForeground",
4372
4639
  borderRadius: "rounded-md",
4373
4640
  effects: {
4374
4641
  hover: [{
@@ -4389,13 +4656,12 @@ const inkStamp = defineButtonPersonality({
4389
4656
  name: "Secondary",
4390
4657
  enabled: true,
4391
4658
  priority: 2,
4392
- background: { type: "transparent" },
4393
- textColorToken: "primary",
4394
- borderRadius: "rounded-md",
4395
- border: {
4396
- widthClass: "border-2",
4397
- colorToken: "primary"
4659
+ background: {
4660
+ type: "surface",
4661
+ role: "link"
4398
4662
  },
4663
+ borderRadius: "rounded-md",
4664
+ border: { widthClass: "border-2" },
4399
4665
  effects: { hover: [{
4400
4666
  effectId: "background-on-hover",
4401
4667
  options: { colorToken: "surface" }
@@ -4406,13 +4672,12 @@ const inkStamp = defineButtonPersonality({
4406
4672
  name: "Outline",
4407
4673
  enabled: true,
4408
4674
  priority: 3,
4409
- background: { type: "transparent" },
4410
- textColorToken: "text",
4411
- borderRadius: "rounded-md",
4412
- border: {
4413
- widthClass: "border-2",
4414
- colorToken: "border"
4675
+ background: {
4676
+ type: "surface",
4677
+ role: "link"
4415
4678
  },
4679
+ borderRadius: "rounded-md",
4680
+ border: { widthClass: "border-2" },
4416
4681
  effects: { hover: [{
4417
4682
  effectId: "background-on-hover",
4418
4683
  options: { colorToken: "surface" }
@@ -4423,8 +4688,10 @@ const inkStamp = defineButtonPersonality({
4423
4688
  name: "Ghost",
4424
4689
  enabled: true,
4425
4690
  priority: 3,
4426
- background: { type: "transparent" },
4427
- textColorToken: "accent",
4691
+ background: {
4692
+ type: "surface",
4693
+ role: "link"
4694
+ },
4428
4695
  borderRadius: "rounded-none",
4429
4696
  sizes: {
4430
4697
  sm: {
@@ -4517,7 +4784,6 @@ const joyStamp = defineButtonPersonality({
4517
4784
  type: "solid",
4518
4785
  colorToken: "primary"
4519
4786
  },
4520
- textColorToken: "primaryForeground",
4521
4787
  borderRadius: "rounded-full",
4522
4788
  shadow: {
4523
4789
  elevation: "high",
@@ -4531,13 +4797,12 @@ const joyStamp = defineButtonPersonality({
4531
4797
  name: "Secondary",
4532
4798
  enabled: true,
4533
4799
  priority: 2,
4534
- background: { type: "transparent" },
4535
- textColorToken: "text",
4536
- borderRadius: "rounded-full",
4537
- border: {
4538
- widthClass: "border-2",
4539
- colorToken: "text"
4800
+ background: {
4801
+ type: "surface",
4802
+ role: "link"
4540
4803
  },
4804
+ borderRadius: "rounded-full",
4805
+ border: { widthClass: "border-2" },
4541
4806
  shadow: {
4542
4807
  elevation: "high",
4543
4808
  softness: "hard",
@@ -4602,12 +4867,8 @@ const ornateRitual = defineButtonPersonality({
4602
4867
  type: "solid",
4603
4868
  colorToken: "primary"
4604
4869
  },
4605
- textColorToken: "primaryForeground",
4606
4870
  borderRadius: "rounded-md",
4607
- border: {
4608
- widthClass: "border",
4609
- colorToken: "primary"
4610
- },
4871
+ border: { widthClass: "border" },
4611
4872
  effects: {
4612
4873
  hover: [{
4613
4874
  effectId: "background-on-hover",
@@ -4628,12 +4889,8 @@ const ornateRitual = defineButtonPersonality({
4628
4889
  type: "solid",
4629
4890
  colorToken: "secondary"
4630
4891
  },
4631
- textColorToken: "primaryForeground",
4632
4892
  borderRadius: "rounded-md",
4633
- border: {
4634
- widthClass: "border",
4635
- colorToken: "primary"
4636
- },
4893
+ border: { widthClass: "border" },
4637
4894
  effects: { hover: [{
4638
4895
  effectId: "background-on-hover",
4639
4896
  options: { colorToken: "surface" }
@@ -4644,13 +4901,12 @@ const ornateRitual = defineButtonPersonality({
4644
4901
  name: "Outline",
4645
4902
  enabled: true,
4646
4903
  priority: 3,
4647
- background: { type: "transparent" },
4648
- textColorToken: "primary",
4649
- borderRadius: "rounded-md",
4650
- border: {
4651
- widthClass: "border",
4652
- colorToken: "primary"
4904
+ background: {
4905
+ type: "surface",
4906
+ role: "link"
4653
4907
  },
4908
+ borderRadius: "rounded-md",
4909
+ border: { widthClass: "border" },
4654
4910
  effects: { hover: [{
4655
4911
  effectId: "background-on-hover",
4656
4912
  options: { colorToken: "muted" }
@@ -4661,8 +4917,10 @@ const ornateRitual = defineButtonPersonality({
4661
4917
  name: "Ghost",
4662
4918
  enabled: true,
4663
4919
  priority: 3,
4664
- background: { type: "transparent" },
4665
- textColorToken: "accent",
4920
+ background: {
4921
+ type: "surface",
4922
+ role: "link"
4923
+ },
4666
4924
  borderRadius: "rounded-none",
4667
4925
  sizes: {
4668
4926
  sm: {
@@ -4744,14 +5002,10 @@ const pebble = defineButtonPersonality({
4744
5002
  type: "solid",
4745
5003
  colorToken: "primary"
4746
5004
  },
4747
- textColorToken: "primaryForeground",
4748
5005
  borderRadius: "rounded-full",
4749
5006
  effects: { hover: [{
4750
- effectId: "background-on-hover-alpha",
4751
- options: {
4752
- colorToken: "primary",
4753
- opacity: 88
4754
- }
5007
+ effectId: "darken-background",
5008
+ options: { amount: 100 }
4755
5009
  }] }
4756
5010
  },
4757
5011
  {
@@ -4759,13 +5013,12 @@ const pebble = defineButtonPersonality({
4759
5013
  name: "Secondary",
4760
5014
  enabled: true,
4761
5015
  priority: 2,
4762
- background: { type: "transparent" },
4763
- textColorToken: "primary",
4764
- borderRadius: "rounded-full",
4765
- border: {
4766
- widthClass: "border-2",
4767
- colorToken: "accent"
5016
+ background: {
5017
+ type: "surface",
5018
+ role: "link"
4768
5019
  },
5020
+ borderRadius: "rounded-full",
5021
+ border: { widthClass: "border-2" },
4769
5022
  effects: { hover: [{
4770
5023
  effectId: "background-on-hover",
4771
5024
  options: { colorToken: "accent" }
@@ -4776,13 +5029,12 @@ const pebble = defineButtonPersonality({
4776
5029
  name: "Outline",
4777
5030
  enabled: true,
4778
5031
  priority: 3,
4779
- background: { type: "transparent" },
4780
- textColorToken: "text",
4781
- borderRadius: "rounded-full",
4782
- border: {
4783
- widthClass: "border",
4784
- colorToken: "border"
5032
+ background: {
5033
+ type: "surface",
5034
+ role: "link"
4785
5035
  },
5036
+ borderRadius: "rounded-full",
5037
+ border: { widthClass: "border" },
4786
5038
  effects: { hover: [{
4787
5039
  effectId: "background-on-hover",
4788
5040
  options: { colorToken: "surface" }
@@ -4793,8 +5045,10 @@ const pebble = defineButtonPersonality({
4793
5045
  name: "Ghost",
4794
5046
  enabled: true,
4795
5047
  priority: 3,
4796
- background: { type: "transparent" },
4797
- textColorToken: "primary",
5048
+ background: {
5049
+ type: "surface",
5050
+ role: "link"
5051
+ },
4798
5052
  borderRadius: "rounded-full",
4799
5053
  sizes: {
4800
5054
  sm: {
@@ -4810,11 +5064,7 @@ const pebble = defineButtonPersonality({
4810
5064
  padding: "0.75rem 1.5rem",
4811
5065
  fontSize: "text-xl"
4812
5066
  }
4813
- },
4814
- effects: { hover: [{
4815
- effectId: "opacity-reduce",
4816
- options: { reduction: 30 }
4817
- }] }
5067
+ }
4818
5068
  }
4819
5069
  ]
4820
5070
  }
@@ -4876,15 +5126,11 @@ const quietArrow = defineButtonPersonality({
4876
5126
  type: "solid",
4877
5127
  colorToken: "primary"
4878
5128
  },
4879
- textColorToken: "primaryForeground",
4880
5129
  borderRadius: "rounded-xl",
4881
5130
  affordance: { iconId: "ArrowRight" },
4882
5131
  effects: { hover: [{
4883
- effectId: "background-on-hover-alpha",
4884
- options: {
4885
- colorToken: "primary",
4886
- opacity: 90
4887
- }
5132
+ effectId: "darken-background",
5133
+ options: { amount: 100 }
4888
5134
  }] }
4889
5135
  },
4890
5136
  {
@@ -4892,13 +5138,12 @@ const quietArrow = defineButtonPersonality({
4892
5138
  name: "Secondary",
4893
5139
  enabled: true,
4894
5140
  priority: 2,
4895
- background: { type: "transparent" },
4896
- textColorToken: "primary",
4897
- borderRadius: "rounded-xl",
4898
- border: {
4899
- widthClass: "border",
4900
- colorToken: "primary"
5141
+ background: {
5142
+ type: "surface",
5143
+ role: "link"
4901
5144
  },
5145
+ borderRadius: "rounded-xl",
5146
+ border: { widthClass: "border" },
4902
5147
  affordance: { iconId: "ArrowRight" },
4903
5148
  effects: { hover: [{
4904
5149
  effectId: "background-on-hover",
@@ -4910,21 +5155,22 @@ const quietArrow = defineButtonPersonality({
4910
5155
  name: "Outline",
4911
5156
  enabled: true,
4912
5157
  priority: 3,
4913
- background: { type: "transparent" },
4914
- textColorToken: "primary",
5158
+ background: {
5159
+ type: "surface",
5160
+ role: "link"
5161
+ },
4915
5162
  borderRadius: "rounded-xl",
4916
- border: {
4917
- widthClass: "border",
4918
- colorToken: "primary"
4919
- }
5163
+ border: { widthClass: "border" }
4920
5164
  },
4921
5165
  {
4922
5166
  id: "ghost",
4923
5167
  name: "Ghost",
4924
5168
  enabled: true,
4925
5169
  priority: 3,
4926
- background: { type: "transparent" },
4927
- textColorToken: "primary",
5170
+ background: {
5171
+ type: "surface",
5172
+ role: "link"
5173
+ },
4928
5174
  borderRadius: "rounded-xl"
4929
5175
  }
4930
5176
  ]
@@ -4988,7 +5234,6 @@ const showtimePill = defineButtonPersonality({
4988
5234
  type: "solid",
4989
5235
  colorToken: "primary"
4990
5236
  },
4991
- textColorToken: "background",
4992
5237
  borderRadius: "rounded-full",
4993
5238
  effects: { hover: [{ effectId: "pop" }] }
4994
5239
  },
@@ -4997,13 +5242,12 @@ const showtimePill = defineButtonPersonality({
4997
5242
  name: "Secondary",
4998
5243
  enabled: true,
4999
5244
  priority: 2,
5000
- background: { type: "transparent" },
5001
- textColorToken: "primary",
5002
- borderRadius: "rounded-full",
5003
- border: {
5004
- widthClass: "border-2",
5005
- colorToken: "primary"
5245
+ background: {
5246
+ type: "surface",
5247
+ role: "link"
5006
5248
  },
5249
+ borderRadius: "rounded-full",
5250
+ border: { widthClass: "border-2" },
5007
5251
  effects: { hover: [{ effectId: "pop" }] }
5008
5252
  },
5009
5253
  {
@@ -5015,7 +5259,6 @@ const showtimePill = defineButtonPersonality({
5015
5259
  type: "solid",
5016
5260
  colorToken: "secondary"
5017
5261
  },
5018
- textColorToken: "primary",
5019
5262
  borderRadius: "rounded-full",
5020
5263
  effects: { hover: [{ effectId: "pop" }] }
5021
5264
  },
@@ -5028,12 +5271,8 @@ const showtimePill = defineButtonPersonality({
5028
5271
  type: "solid",
5029
5272
  colorToken: "background"
5030
5273
  },
5031
- textColorToken: "primary",
5032
5274
  borderRadius: "rounded-full",
5033
- border: {
5034
- widthClass: "border-2",
5035
- colorToken: "primary"
5036
- },
5275
+ border: { widthClass: "border-2" },
5037
5276
  effects: { hover: [{
5038
5277
  effectId: "background-on-hover",
5039
5278
  options: { colorToken: "surface" }
@@ -5044,13 +5283,12 @@ const showtimePill = defineButtonPersonality({
5044
5283
  name: "Outline",
5045
5284
  enabled: true,
5046
5285
  priority: 3,
5047
- background: { type: "transparent" },
5048
- textColorToken: "primary",
5049
- borderRadius: "rounded-full",
5050
- border: {
5051
- widthClass: "border-2",
5052
- colorToken: "primary"
5286
+ background: {
5287
+ type: "surface",
5288
+ role: "link"
5053
5289
  },
5290
+ borderRadius: "rounded-full",
5291
+ border: { widthClass: "border-2" },
5054
5292
  effects: { hover: [{
5055
5293
  effectId: "background-on-hover",
5056
5294
  options: { colorToken: "background" }
@@ -5061,8 +5299,10 @@ const showtimePill = defineButtonPersonality({
5061
5299
  name: "Ghost",
5062
5300
  enabled: true,
5063
5301
  priority: 3,
5064
- background: { type: "transparent" },
5065
- textColorToken: "primary",
5302
+ background: {
5303
+ type: "surface",
5304
+ role: "link"
5305
+ },
5066
5306
  borderRadius: "rounded-full",
5067
5307
  effects: { hover: [{
5068
5308
  effectId: "background-on-hover",
@@ -5108,7 +5348,6 @@ const softPill = defineButtonPersonality({
5108
5348
  type: "solid",
5109
5349
  colorToken: "primary"
5110
5350
  },
5111
- textColorToken: "primaryForeground",
5112
5351
  borderRadius: "rounded-full",
5113
5352
  shadow: {
5114
5353
  elevation: "low",
@@ -5131,13 +5370,12 @@ const softPill = defineButtonPersonality({
5131
5370
  name: "Secondary",
5132
5371
  enabled: true,
5133
5372
  priority: 2,
5134
- background: { type: "transparent" },
5135
- textColorToken: "primary",
5136
- borderRadius: "rounded-full",
5137
- border: {
5138
- widthClass: "border-2",
5139
- colorToken: "primary"
5373
+ background: {
5374
+ type: "surface",
5375
+ role: "link"
5140
5376
  },
5377
+ borderRadius: "rounded-full",
5378
+ border: { widthClass: "border-2" },
5141
5379
  effects: { hover: [{
5142
5380
  effectId: "background-on-hover",
5143
5381
  options: { colorToken: "surface" }
@@ -5148,13 +5386,12 @@ const softPill = defineButtonPersonality({
5148
5386
  name: "Outline",
5149
5387
  enabled: true,
5150
5388
  priority: 3,
5151
- background: { type: "transparent" },
5152
- textColorToken: "text",
5153
- borderRadius: "rounded-full",
5154
- border: {
5155
- widthClass: "border",
5156
- colorToken: "border"
5389
+ background: {
5390
+ type: "surface",
5391
+ role: "link"
5157
5392
  },
5393
+ borderRadius: "rounded-full",
5394
+ border: { widthClass: "border" },
5158
5395
  effects: { hover: [{
5159
5396
  effectId: "background-on-hover",
5160
5397
  options: { colorToken: "surface" }
@@ -5165,8 +5402,10 @@ const softPill = defineButtonPersonality({
5165
5402
  name: "Ghost",
5166
5403
  enabled: true,
5167
5404
  priority: 3,
5168
- background: { type: "transparent" },
5169
- textColorToken: "text",
5405
+ background: {
5406
+ type: "surface",
5407
+ role: "link"
5408
+ },
5170
5409
  borderRadius: "rounded-full",
5171
5410
  effects: { hover: [{
5172
5411
  effectId: "background-on-hover",
@@ -5185,9 +5424,8 @@ const solidSecondary = {
5185
5424
  priority: 2,
5186
5425
  background: {
5187
5426
  type: "solid",
5188
- colorToken: "secondary"
5427
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
5189
5428
  },
5190
- textColorToken: "onSecondary",
5191
5429
  borderRadius: "rounded-full",
5192
5430
  shadow: {
5193
5431
  elevation: "none",
@@ -5235,6 +5473,27 @@ const buttonPersonalities = [
5235
5473
  quietArrow
5236
5474
  ];
5237
5475
  new Map(buttonPersonalities.map((p) => [p.id, p]));
5476
+ buttonPersonalities.map((personality) => ({
5477
+ id: personality.id,
5478
+ name: personality.name,
5479
+ description: personality.description,
5480
+ category: presetCategory(personality),
5481
+ buttonSystem: personality.buttonSystem,
5482
+ compatibility: {
5483
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
5484
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
5485
+ }
5486
+ }));
5487
+ function presetCategory(personality) {
5488
+ switch (personality.tags.era) {
5489
+ case "retro": return "retro";
5490
+ case "editorial": return "minimal";
5491
+ case "organic": return "artistic";
5492
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
5493
+ case "technical": return "technical";
5494
+ case void 0: return "modern";
5495
+ }
5496
+ }
5238
5497
  //#endregion
5239
5498
  //#region ../theme-core/src/cards/types.ts
5240
5499
  const cardVariantRoleValues = ["default", "alternative"];
@@ -8711,6 +8970,241 @@ const originalJoyCardSystem = { variants: [{
8711
8970
  const serifDisplayQuote = { style: "serif-display" };
8712
8971
  /** Punchy quotation mark in the secondary accent colour. Bold / accent styles. */
8713
8972
  const accentGlyphQuote = { style: "accent-glyph" };
8973
+ /**
8974
+ * Curated library of gradient presets.
8975
+ * All gradients use theme color tokens, so they adapt to the site's palette.
8976
+ */
8977
+ const GRADIENT_PRESETS = [
8978
+ {
8979
+ id: "primary-secondary",
8980
+ name: "Primary to Secondary",
8981
+ description: "Blend your primary and secondary brand colors",
8982
+ type: "linear",
8983
+ angle: 135,
8984
+ stops: [{
8985
+ color: "primary-500",
8986
+ position: 0
8987
+ }, {
8988
+ color: "secondary-500",
8989
+ position: 100
8990
+ }]
8991
+ },
8992
+ {
8993
+ id: "primary-accent",
8994
+ name: "Primary to Accent",
8995
+ description: "Energetic gradient from primary to accent",
8996
+ type: "linear",
8997
+ angle: 135,
8998
+ stops: [{
8999
+ color: "primary-500",
9000
+ position: 0
9001
+ }, {
9002
+ color: "accent-500",
9003
+ position: 100
9004
+ }]
9005
+ },
9006
+ {
9007
+ id: "secondary-accent",
9008
+ name: "Secondary to Accent",
9009
+ description: "Vibrant secondary to accent blend",
9010
+ type: "linear",
9011
+ angle: 135,
9012
+ stops: [{
9013
+ color: "secondary-500",
9014
+ position: 0
9015
+ }, {
9016
+ color: "accent-500",
9017
+ position: 100
9018
+ }]
9019
+ },
9020
+ {
9021
+ id: "primary-light-dark",
9022
+ name: "Primary Light to Dark",
9023
+ description: "Subtle primary color fade",
9024
+ type: "linear",
9025
+ angle: 180,
9026
+ stops: [{
9027
+ color: "primary-500",
9028
+ position: 0
9029
+ }, {
9030
+ color: "primary-900",
9031
+ position: 100
9032
+ }]
9033
+ },
9034
+ {
9035
+ id: "primary-dark-light",
9036
+ name: "Primary Dark to Light",
9037
+ description: "Reverse primary fade",
9038
+ type: "linear",
9039
+ angle: 180,
9040
+ stops: [{
9041
+ color: "primary-900",
9042
+ position: 0
9043
+ }, {
9044
+ color: "primary-50",
9045
+ position: 100
9046
+ }]
9047
+ },
9048
+ {
9049
+ id: "secondary-light-dark",
9050
+ name: "Secondary Light to Dark",
9051
+ description: "Subtle secondary color fade",
9052
+ type: "linear",
9053
+ angle: 180,
9054
+ stops: [{
9055
+ color: "secondary-500",
9056
+ position: 0
9057
+ }, {
9058
+ color: "secondary-900",
9059
+ position: 100
9060
+ }]
9061
+ },
9062
+ {
9063
+ id: "accent-light-dark",
9064
+ name: "Accent Light to Dark",
9065
+ description: "Accent color depth fade",
9066
+ type: "linear",
9067
+ angle: 180,
9068
+ stops: [{
9069
+ color: "accent-500",
9070
+ position: 0
9071
+ }, {
9072
+ color: "accent-900",
9073
+ position: 100
9074
+ }]
9075
+ },
9076
+ {
9077
+ id: "background-surface",
9078
+ name: "Background to Surface",
9079
+ description: "Subtle depth using base colors",
9080
+ type: "linear",
9081
+ angle: 180,
9082
+ stops: [{
9083
+ color: "background",
9084
+ position: 0
9085
+ }, {
9086
+ color: "surface",
9087
+ position: 100
9088
+ }]
9089
+ },
9090
+ {
9091
+ id: "neutral-fade",
9092
+ name: "Neutral Gradient",
9093
+ description: "Elegant neutral color fade",
9094
+ type: "linear",
9095
+ angle: 180,
9096
+ stops: [{
9097
+ color: "neutral-900",
9098
+ position: 0
9099
+ }, {
9100
+ color: "neutral-50",
9101
+ position: 100
9102
+ }]
9103
+ },
9104
+ {
9105
+ id: "primary-glow",
9106
+ name: "Primary glow",
9107
+ description: "A soft top-centred glow using your primary palette",
9108
+ type: "radial",
9109
+ shape: "ellipse",
9110
+ position: "top center",
9111
+ stops: [{
9112
+ color: "primary-900",
9113
+ position: 0
9114
+ }, {
9115
+ color: "primary-950",
9116
+ position: 100
9117
+ }],
9118
+ foreground: {
9119
+ textColor: "onPrimary900",
9120
+ headingColor: "onPrimary900",
9121
+ linkColor: "onPrimary900",
9122
+ supportingColor: "onPrimary900"
9123
+ }
9124
+ },
9125
+ {
9126
+ id: "accent-glow",
9127
+ name: "Accent glow",
9128
+ description: "A soft top-centred glow using your accent palette",
9129
+ type: "radial",
9130
+ shape: "ellipse",
9131
+ position: "top center",
9132
+ stops: [{
9133
+ color: "accent-900",
9134
+ position: 0
9135
+ }, {
9136
+ color: "accent-950",
9137
+ position: 100
9138
+ }],
9139
+ foreground: {
9140
+ textColor: "onAccent900",
9141
+ headingColor: "onAccent900",
9142
+ linkColor: "onAccent900",
9143
+ supportingColor: "onAccent900"
9144
+ }
9145
+ },
9146
+ {
9147
+ id: "primary-secondary-accent",
9148
+ name: "Brand Trio",
9149
+ description: "All three brand colors in harmony",
9150
+ type: "linear",
9151
+ angle: 135,
9152
+ stops: [
9153
+ {
9154
+ color: "primary-500",
9155
+ position: 0
9156
+ },
9157
+ {
9158
+ color: "secondary-500",
9159
+ position: 50
9160
+ },
9161
+ {
9162
+ color: "accent-500",
9163
+ position: 100
9164
+ }
9165
+ ]
9166
+ }
9167
+ ].map((preset) => ({
9168
+ ...preset,
9169
+ id: preset.id,
9170
+ stops: preset.stops
9171
+ }));
9172
+ const GRADIENT_PRESET_IDS = GRADIENT_PRESETS.map((preset) => preset.id);
9173
+ const gradientPresetIdSet = new Set(GRADIENT_PRESET_IDS);
9174
+ const gradientPresetById = Object.fromEntries(GRADIENT_PRESETS.map((preset) => [preset.id, preset]));
9175
+ function parseGradientPresetId(value) {
9176
+ if (typeof value !== "string") return null;
9177
+ const normalized = value.trim();
9178
+ if (!gradientPresetIdSet.has(normalized)) return null;
9179
+ return normalized;
9180
+ }
9181
+ function getGradientPreset(id) {
9182
+ return gradientPresetById[id];
9183
+ }
9184
+ //#endregion
9185
+ //#region ../theme-core/src/gradients/utils.ts
9186
+ /**
9187
+ * Convert a GradientConfig to a CSS gradient string
9188
+ *
9189
+ * @param config - The gradient configuration using theme tokens
9190
+ * @param tokens - Map of theme color tokens to hex values
9191
+ * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
9192
+ */
9193
+ function gradientToCss(config, tokens) {
9194
+ const stops = config.stops.map((stop) => {
9195
+ return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
9196
+ }).join(", ");
9197
+ const type = config.type ?? "linear";
9198
+ if (type === "radial") {
9199
+ const position = config.position ?? "center";
9200
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
9201
+ }
9202
+ if (type === "conic") {
9203
+ const position = config.position ?? "center";
9204
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
9205
+ }
9206
+ return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
9207
+ }
8714
9208
  //#endregion
8715
9209
  //#region ../theme-core/src/site-styles/headerLooks.ts
8716
9210
  function asHeaderLookId(value) {
@@ -10754,6 +11248,19 @@ z$1.object({
10754
11248
  }).strict();
10755
11249
  //#endregion
10756
11250
  //#region ../theme-core/src/site-styles/runtimeCompiler.ts
11251
+ function defineSectionForegroundRuntimeTokens(input) {
11252
+ return {
11253
+ textColor: requireThemeColorToken(input.textColor),
11254
+ headingColor: requireThemeColorToken(input.headingColor),
11255
+ linkColor: requireThemeColorToken(input.linkColor),
11256
+ supportingColor: requireThemeColorToken(input.supportingColor)
11257
+ };
11258
+ }
11259
+ function requireThemeColorToken(value) {
11260
+ const token = parseThemeColorToken(value);
11261
+ if (!token) throw new Error(`Invalid section foreground Theme color token: ${String(value)}`);
11262
+ return token;
11263
+ }
10757
11264
  function defineDesignRuntimeRules(rules) {
10758
11265
  return rules;
10759
11266
  }
@@ -11024,24 +11531,24 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
11024
11531
  type: "color",
11025
11532
  color: "muted"
11026
11533
  },
11027
- foreground: {
11534
+ foreground: defineSectionForegroundRuntimeTokens({
11028
11535
  textColor: "text",
11029
11536
  headingColor: "primary",
11030
11537
  linkColor: "primary",
11031
11538
  supportingColor: "text"
11032
- }
11539
+ })
11033
11540
  },
11034
11541
  "brand-depth-band": {
11035
11542
  background: {
11036
11543
  type: "color",
11037
11544
  color: "primary-800"
11038
11545
  },
11039
- foreground: {
11546
+ foreground: defineSectionForegroundRuntimeTokens({
11040
11547
  textColor: "text",
11041
11548
  headingColor: "primary",
11042
11549
  linkColor: "primary",
11043
11550
  supportingColor: "text"
11044
- }
11551
+ })
11045
11552
  },
11046
11553
  "hero-image": {
11047
11554
  background: {
@@ -11049,12 +11556,32 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
11049
11556
  opacity: 1,
11050
11557
  position: "center center"
11051
11558
  },
11052
- foreground: {
11559
+ foreground: defineSectionForegroundRuntimeTokens({
11053
11560
  textColor: "text",
11054
11561
  headingColor: "primary",
11055
11562
  linkColor: "primary",
11056
11563
  supportingColor: "text"
11057
- }
11564
+ })
11565
+ }
11566
+ }
11567
+ });
11568
+ const primaryGlowGradientPresetId = parseGradientPresetId("primary-glow");
11569
+ if (!primaryGlowGradientPresetId) throw new Error("Expected primary-glow in the Theme Core gradient catalog");
11570
+ const fulcrumDesignRuntimeRules = defineDesignRuntimeRules({
11571
+ ...defaultDesignRuntimeRules,
11572
+ sectionSurfaces: {
11573
+ ...defaultDesignRuntimeRules.sectionSurfaces,
11574
+ "accent-band": {
11575
+ background: {
11576
+ type: "gradient",
11577
+ gradientPresetId: primaryGlowGradientPresetId
11578
+ },
11579
+ foreground: defineSectionForegroundRuntimeTokens({
11580
+ textColor: "primaryForeground",
11581
+ headingColor: "primaryForeground",
11582
+ linkColor: "primaryForeground",
11583
+ supportingColor: "primaryForeground"
11584
+ })
11058
11585
  }
11059
11586
  }
11060
11587
  });
@@ -12442,6 +12969,8 @@ const curatedSiteStyles = [
12442
12969
  },
12443
12970
  compositionBudget: quietBudget,
12444
12971
  typography: fulcrumTypography,
12972
+ designRuntimeRules: fulcrumDesignRuntimeRules,
12973
+ recommendedAppearancePresetIds: ["cta-accent-band"],
12445
12974
  themeOverrides: {
12446
12975
  shadow: { colorToken: "primary" },
12447
12976
  accordions: {
@@ -12814,213 +13343,6 @@ z$1.object({
12814
13343
  spacing: z$1.enum(themeTokenRecipeOptions.spacing),
12815
13344
  motion: z$1.enum(themeTokenRecipeOptions.motion)
12816
13345
  });
12817
- //#endregion
12818
- //#region ../theme-core/src/gradients/presets.ts
12819
- /**
12820
- * Curated library of gradient presets
12821
- * All gradients use theme color tokens, so they adapt to the site's palette
12822
- */
12823
- const GRADIENT_PRESETS = [
12824
- {
12825
- id: "primary-secondary",
12826
- name: "Primary to Secondary",
12827
- description: "Blend your primary and secondary brand colors",
12828
- type: "linear",
12829
- angle: 135,
12830
- stops: [{
12831
- color: "primary-500",
12832
- position: 0
12833
- }, {
12834
- color: "secondary-500",
12835
- position: 100
12836
- }]
12837
- },
12838
- {
12839
- id: "primary-accent",
12840
- name: "Primary to Accent",
12841
- description: "Energetic gradient from primary to accent",
12842
- type: "linear",
12843
- angle: 135,
12844
- stops: [{
12845
- color: "primary-500",
12846
- position: 0
12847
- }, {
12848
- color: "accent-500",
12849
- position: 100
12850
- }]
12851
- },
12852
- {
12853
- id: "secondary-accent",
12854
- name: "Secondary to Accent",
12855
- description: "Vibrant secondary to accent blend",
12856
- type: "linear",
12857
- angle: 135,
12858
- stops: [{
12859
- color: "secondary-500",
12860
- position: 0
12861
- }, {
12862
- color: "accent-500",
12863
- position: 100
12864
- }]
12865
- },
12866
- {
12867
- id: "primary-light-dark",
12868
- name: "Primary Light to Dark",
12869
- description: "Subtle primary color fade",
12870
- type: "linear",
12871
- angle: 180,
12872
- stops: [{
12873
- color: "primary-500",
12874
- position: 0
12875
- }, {
12876
- color: "primary-900",
12877
- position: 100
12878
- }]
12879
- },
12880
- {
12881
- id: "primary-dark-light",
12882
- name: "Primary Dark to Light",
12883
- description: "Reverse primary fade",
12884
- type: "linear",
12885
- angle: 180,
12886
- stops: [{
12887
- color: "primary-900",
12888
- position: 0
12889
- }, {
12890
- color: "primary-50",
12891
- position: 100
12892
- }]
12893
- },
12894
- {
12895
- id: "secondary-light-dark",
12896
- name: "Secondary Light to Dark",
12897
- description: "Subtle secondary color fade",
12898
- type: "linear",
12899
- angle: 180,
12900
- stops: [{
12901
- color: "secondary-500",
12902
- position: 0
12903
- }, {
12904
- color: "secondary-900",
12905
- position: 100
12906
- }]
12907
- },
12908
- {
12909
- id: "accent-light-dark",
12910
- name: "Accent Light to Dark",
12911
- description: "Accent color depth fade",
12912
- type: "linear",
12913
- angle: 180,
12914
- stops: [{
12915
- color: "accent-500",
12916
- position: 0
12917
- }, {
12918
- color: "accent-900",
12919
- position: 100
12920
- }]
12921
- },
12922
- {
12923
- id: "background-surface",
12924
- name: "Background to Surface",
12925
- description: "Subtle depth using base colors",
12926
- type: "linear",
12927
- angle: 180,
12928
- stops: [{
12929
- color: "background",
12930
- position: 0
12931
- }, {
12932
- color: "surface",
12933
- position: 100
12934
- }]
12935
- },
12936
- {
12937
- id: "neutral-fade",
12938
- name: "Neutral Gradient",
12939
- description: "Elegant neutral color fade",
12940
- type: "linear",
12941
- angle: 180,
12942
- stops: [{
12943
- color: "neutral-900",
12944
- position: 0
12945
- }, {
12946
- color: "neutral-50",
12947
- position: 100
12948
- }]
12949
- },
12950
- {
12951
- id: "primary-radial",
12952
- name: "Primary Spotlight",
12953
- description: "Radial primary gradient from center",
12954
- type: "radial",
12955
- position: "center",
12956
- stops: [{
12957
- color: "primary-500",
12958
- position: 0
12959
- }, {
12960
- color: "primary-900",
12961
- position: 100
12962
- }]
12963
- },
12964
- {
12965
- id: "accent-radial",
12966
- name: "Accent Spotlight",
12967
- description: "Radial accent gradient from center",
12968
- type: "radial",
12969
- position: "center",
12970
- stops: [{
12971
- color: "accent-500",
12972
- position: 0
12973
- }, {
12974
- color: "accent-900",
12975
- position: 100
12976
- }]
12977
- },
12978
- {
12979
- id: "primary-secondary-accent",
12980
- name: "Brand Trio",
12981
- description: "All three brand colors in harmony",
12982
- type: "linear",
12983
- angle: 135,
12984
- stops: [
12985
- {
12986
- color: "primary-500",
12987
- position: 0
12988
- },
12989
- {
12990
- color: "secondary-500",
12991
- position: 50
12992
- },
12993
- {
12994
- color: "accent-500",
12995
- position: 100
12996
- }
12997
- ]
12998
- }
12999
- ];
13000
- //#endregion
13001
- //#region ../theme-core/src/gradients/utils.ts
13002
- /**
13003
- * Convert a GradientConfig to a CSS gradient string
13004
- *
13005
- * @param config - The gradient configuration using theme tokens
13006
- * @param tokens - Map of theme color tokens to hex values
13007
- * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
13008
- */
13009
- function gradientToCss(config, tokens) {
13010
- const stops = config.stops.map((stop) => {
13011
- return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
13012
- }).join(", ");
13013
- const type = config.type ?? "linear";
13014
- if (type === "radial") {
13015
- const position = config.position ?? "center";
13016
- return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
13017
- }
13018
- if (type === "conic") {
13019
- const position = config.position ?? "center";
13020
- return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
13021
- }
13022
- return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
13023
- }
13024
13346
  const BREAKPOINT_LG = 1024;
13025
13347
  const BREAKPOINT_XL = 1280;
13026
13348
  const BREAKPOINT_LG_DOWN = BREAKPOINT_LG - 1;
@@ -13987,6 +14309,20 @@ const blockCategoryEnum = z$1.enum([
13987
14309
  "layout",
13988
14310
  "interactive"
13989
14311
  ]);
14312
+ const blockContentSourceSchema = z$1.object({
14313
+ kind: z$1.enum([
14314
+ "inline",
14315
+ "entries",
14316
+ "mixed"
14317
+ ]),
14318
+ contentType: z$1.string().min(1).optional()
14319
+ }).superRefine((value, ctx) => {
14320
+ if (value.kind === "inline" && value.contentType) ctx.addIssue({
14321
+ code: z$1.ZodIssueCode.custom,
14322
+ path: ["contentType"],
14323
+ message: "contentType is not allowed when contentSource.kind is \"inline\""
14324
+ });
14325
+ });
13990
14326
  z$1.object({
13991
14327
  name: z$1.string().min(1),
13992
14328
  version: z$1.string().min(1),
@@ -14017,6 +14353,12 @@ z$1.object({
14017
14353
  }).optional()).optional(),
14018
14354
  category: blockCategoryEnum.optional(),
14019
14355
  contentTypes: z$1.array(z$1.string()).optional(),
14356
+ /**
14357
+ * Explicit content-source classification (inline / entries / mixed). Optional at the
14358
+ * schema level for backward compatibility with SDK-defined custom blocks, but every
14359
+ * registered SYSTEM block must declare it (enforced by a registry-wide test).
14360
+ */
14361
+ contentSource: blockContentSourceSchema.optional(),
14020
14362
  tags: z$1.array(z$1.string()).optional(),
14021
14363
  icon: z$1.string().optional()
14022
14364
  });
@@ -17135,9 +17477,15 @@ function createButtonGroup(options = {}) {
17135
17477
  //#endregion
17136
17478
  //#region ../blocks/src/system/fields/ctas.ts
17137
17479
  function createCtasRepeater(options = {}) {
17138
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
17480
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
17481
+ const fieldId = id;
17482
+ const buttonField = createButtonGroup({
17483
+ showGroupLabel: false,
17484
+ ...button ?? {},
17485
+ flattenInRepeater: true
17486
+ });
17139
17487
  return {
17140
- id,
17488
+ id: fieldId,
17141
17489
  type: "repeater",
17142
17490
  label,
17143
17491
  itemLabel,
@@ -17146,11 +17494,8 @@ function createCtasRepeater(options = {}) {
17146
17494
  maxItems,
17147
17495
  required: false,
17148
17496
  allowConversion: true,
17149
- schema: { fields: [createButtonGroup({
17150
- showGroupLabel: false,
17151
- ...button ?? {},
17152
- flattenInRepeater: true
17153
- })] }
17497
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
17498
+ schema: { fields: [buttonField] }
17154
17499
  };
17155
17500
  }
17156
17501
  //#endregion
@@ -17200,6 +17545,7 @@ const heroCtaRowFragment = defineFragment({
17200
17545
  label: "Calls to action",
17201
17546
  itemLabel: "CTA",
17202
17547
  maxItems: 3,
17548
+ defaultValue: [],
17203
17549
  button: {
17204
17550
  variants: [
17205
17551
  {
@@ -17267,7 +17613,7 @@ const ctaCopyFragment = defineFragment({
17267
17613
  eyebrowPath: "content.eyebrow",
17268
17614
  titlePath: "content.title",
17269
17615
  className: "cta-heading"
17270
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
17616
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
17271
17617
  });
17272
17618
  //#endregion
17273
17619
  //#region ../blocks/src/system/fragments/library/testimonialsHeading.ts
@@ -18999,6 +19345,7 @@ function createBlockManifest(config) {
18999
19345
  previewCustomize: config.previewCustomize,
19000
19346
  category: config.category,
19001
19347
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
19348
+ contentSource: config.contentSource,
19002
19349
  tags: config.tags ? [...config.tags] : [],
19003
19350
  icon: config.icon ?? "Box",
19004
19351
  layout,
@@ -19144,6 +19491,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
19144
19491
  title: "Hero",
19145
19492
  titleSource: "headline",
19146
19493
  category: "layout",
19494
+ contentSource: { kind: "inline" },
19147
19495
  includeContainerStyles: true,
19148
19496
  promotedFields: ["_sectionStyles.background.image"],
19149
19497
  fragments: [
@@ -19417,6 +19765,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
19417
19765
  id: "block.intro",
19418
19766
  title: "Intro",
19419
19767
  category: "layout",
19768
+ contentSource: { kind: "inline" },
19420
19769
  includeContainerStyles: true,
19421
19770
  titleSource: "title",
19422
19771
  previewCustomize: { quickFieldPriority: [
@@ -19602,6 +19951,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
19602
19951
  title: "Body Text",
19603
19952
  titleSource: "heading",
19604
19953
  category: "content",
19954
+ contentSource: { kind: "inline" },
19605
19955
  fragments: [{
19606
19956
  fragment: bodyCopyFragment,
19607
19957
  fieldPriority: 0
@@ -19658,6 +20008,10 @@ const blogPostBlockDefinition = {
19658
20008
  description: "Highlights a single blog post with title, image, and excerpt.",
19659
20009
  category: "blog",
19660
20010
  contentTypes: ["post"],
20011
+ contentSource: {
20012
+ kind: "entries",
20013
+ contentType: "post"
20014
+ },
19661
20015
  tags: [
19662
20016
  "blog",
19663
20017
  "post",
@@ -19955,6 +20309,10 @@ const blogListingManifest = createBlockManifest({
19955
20309
  ],
19956
20310
  description: "Display a collection of blog posts in grid or stack layout.",
19957
20311
  contentTypes: ["post"],
20312
+ contentSource: {
20313
+ kind: "entries",
20314
+ contentType: "post"
20315
+ },
19958
20316
  tags: [
19959
20317
  "blog",
19960
20318
  "posts",
@@ -19997,6 +20355,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
19997
20355
  id: "block.cta-full",
19998
20356
  title: "Full-width CTA",
19999
20357
  category: "marketing",
20358
+ contentSource: { kind: "inline" },
20000
20359
  fragments: [{
20001
20360
  fragment: ctaCopyFragment,
20002
20361
  fieldPriority: 0
@@ -20030,6 +20389,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
20030
20389
  id: "block.single-button",
20031
20390
  title: "Single Button",
20032
20391
  category: "marketing",
20392
+ contentSource: { kind: "inline" },
20033
20393
  fragments: [{
20034
20394
  fragment: singleButtonFragment,
20035
20395
  fieldPriority: 0
@@ -20290,6 +20650,7 @@ const formManifest = createBlockManifest({
20290
20650
  paletteHidden: false
20291
20651
  },
20292
20652
  category: "interactive",
20653
+ contentSource: { kind: "inline" },
20293
20654
  tags: [
20294
20655
  "form",
20295
20656
  "contact",
@@ -20352,6 +20713,7 @@ const contactNewsletterBlockDefinition = {
20352
20713
  titleSource: "contactTitle",
20353
20714
  description: "Two-column newsletter signup and contact form section.",
20354
20715
  category: "interactive",
20716
+ contentSource: { kind: "inline" },
20355
20717
  layout: contactNewsletterLayout,
20356
20718
  defaultVariant: "default",
20357
20719
  variants: { default: contactNewsletterLayout },
@@ -20555,6 +20917,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
20555
20917
  title: "FAQ",
20556
20918
  titleSource: "title",
20557
20919
  category: "content",
20920
+ contentSource: { kind: "inline" },
20558
20921
  includeContainerStyles: true,
20559
20922
  fragments: [{
20560
20923
  fragment: faqHeadingFragment,
@@ -22198,6 +22561,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
22198
22561
  id: "block.site-header",
22199
22562
  title: "Site Header",
22200
22563
  category: "layout",
22564
+ contentSource: { kind: "inline" },
22201
22565
  additionalFields: [{
22202
22566
  id: "mode",
22203
22567
  type: "select",
@@ -22402,6 +22766,7 @@ const siteFooterBlockDefinition = { manifest: createBlockManifest({
22402
22766
  id: "block.site-footer",
22403
22767
  title: "Site Footer",
22404
22768
  category: "layout",
22769
+ contentSource: { kind: "inline" },
22405
22770
  skipSectionStyles: true,
22406
22771
  layout: section({
22407
22772
  background: "background",
@@ -22551,6 +22916,7 @@ const testimonialsBlockDefinition = {
22551
22916
  id: "block.testimonials",
22552
22917
  title: "Testimonials",
22553
22918
  category: "marketing",
22919
+ contentSource: { kind: "inline" },
22554
22920
  includeContainerStyles: true,
22555
22921
  previewCustomize: { quickFieldPriority: [
22556
22922
  "avatarLayout",
@@ -22709,6 +23075,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
22709
23075
  id: "block.columns",
22710
23076
  title: "Columns",
22711
23077
  category: "layout",
23078
+ contentSource: { kind: "inline" },
22712
23079
  additionalFields: [
22713
23080
  parseFieldDefinition({
22714
23081
  id: "equalHeight",
@@ -22942,6 +23309,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
22942
23309
  id: "block.collection",
22943
23310
  title: "Collection",
22944
23311
  category: "layout",
23312
+ contentSource: { kind: "inline" },
22945
23313
  additionalFields: [
22946
23314
  parseFieldDefinition({
22947
23315
  id: "layout",
@@ -23178,6 +23546,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
23178
23546
  id: "block.feature-cards",
23179
23547
  title: "Feature Cards",
23180
23548
  category: "layout",
23549
+ contentSource: { kind: "inline" },
23181
23550
  includeContainerStyles: true,
23182
23551
  titleSource: "title",
23183
23552
  additionalFields: [
@@ -23561,6 +23930,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
23561
23930
  id: "block.media-text",
23562
23931
  title: "Media and Text",
23563
23932
  category: "layout",
23933
+ contentSource: { kind: "inline" },
23564
23934
  includeContainerStyles: true,
23565
23935
  titleSource: "title",
23566
23936
  previewCustomize: { quickFieldPriority: [
@@ -23961,6 +24331,7 @@ const appointmentBookingBlockDefinition = {
23961
24331
  paletteHidden: false
23962
24332
  },
23963
24333
  category: "interactive",
24334
+ contentSource: { kind: "inline" },
23964
24335
  tags: [
23965
24336
  "booking",
23966
24337
  "appointment",
@@ -24125,6 +24496,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
24125
24496
  paletteHidden: false
24126
24497
  },
24127
24498
  category: "interactive",
24499
+ contentSource: { kind: "inline" },
24128
24500
  tags: [
24129
24501
  "booking",
24130
24502
  "appointment",
@@ -25689,6 +26061,7 @@ const eventRegistrationBlockDefinition = {
25689
26061
  titleSource: "heading",
25690
26062
  description: "Multi-step event registration form",
25691
26063
  category: "interactive",
26064
+ contentSource: { kind: "inline" },
25692
26065
  tags: [
25693
26066
  "events",
25694
26067
  "registration",
@@ -25795,15 +26168,9 @@ const eventRegistrationBlockDefinition = {
25795
26168
  defaultValue: "Complete Registration",
25796
26169
  maxLength: 40
25797
26170
  },
25798
- {
25799
- id: "buttonVariant",
25800
- type: "select",
25801
- label: "Button style",
26171
+ createButtonVariantField({
25802
26172
  description: "Choose a button style from your theme",
25803
- required: false,
25804
- multiple: false,
25805
- defaultValue: "primary",
25806
- options: [
26173
+ variants: [
25807
26174
  {
25808
26175
  value: "primary",
25809
26176
  label: "Primary"
@@ -25816,9 +26183,8 @@ const eventRegistrationBlockDefinition = {
25816
26183
  value: "outline",
25817
26184
  label: "Outline"
25818
26185
  }
25819
- ],
25820
- ui: { intent: "style" }
25821
- }
26186
+ ]
26187
+ })
25822
26188
  ],
25823
26189
  layout: [styledSection({
25824
26190
  baseClass: "",
@@ -26011,6 +26377,7 @@ const courseRegistrationBlockDefinition = {
26011
26377
  titleSource: "heading",
26012
26378
  description: "Enrollment form for multi-session courses",
26013
26379
  category: "interactive",
26380
+ contentSource: { kind: "inline" },
26014
26381
  tags: [
26015
26382
  "courses",
26016
26383
  "enrollment",
@@ -26124,15 +26491,9 @@ const courseRegistrationBlockDefinition = {
26124
26491
  defaultValue: "Sign up",
26125
26492
  maxLength: 40
26126
26493
  },
26127
- {
26128
- id: "buttonVariant",
26129
- type: "select",
26130
- label: "Button style",
26494
+ createButtonVariantField({
26131
26495
  description: "Choose a button style from your theme",
26132
- required: false,
26133
- multiple: false,
26134
- defaultValue: "primary",
26135
- options: [
26496
+ variants: [
26136
26497
  {
26137
26498
  value: "primary",
26138
26499
  label: "Primary"
@@ -26145,9 +26506,8 @@ const courseRegistrationBlockDefinition = {
26145
26506
  value: "outline",
26146
26507
  label: "Outline"
26147
26508
  }
26148
- ],
26149
- ui: { intent: "style" }
26150
- }
26509
+ ]
26510
+ })
26151
26511
  ],
26152
26512
  layout: [styledSection({
26153
26513
  baseClass: "",
@@ -26227,6 +26587,7 @@ const eventDetailsManifest = createBlockManifest({
26227
26587
  titleSource: "heading",
26228
26588
  description: "Date/time, venue, map, and other dates for an event",
26229
26589
  category: "content",
26590
+ contentSource: { kind: "entries" },
26230
26591
  tags: [
26231
26592
  "events",
26232
26593
  "venue",
@@ -26432,6 +26793,7 @@ const courseDetailsBlockDefinition = {
26432
26793
  titleSource: "heading",
26433
26794
  description: "Schedule, venue, price, and enrollment status for a course",
26434
26795
  category: "content",
26796
+ contentSource: { kind: "entries" },
26435
26797
  tags: [
26436
26798
  "courses",
26437
26799
  "schedule",
@@ -26723,6 +27085,7 @@ const eventSpotlightBlockDefinition = {
26723
27085
  paletteHidden: false
26724
27086
  },
26725
27087
  category: "content",
27088
+ contentSource: { kind: "entries" },
26726
27089
  tags: [
26727
27090
  "events",
26728
27091
  "featured",
@@ -27269,6 +27632,7 @@ const eventListingBlockDefinition = {
27269
27632
  paletteHidden: true
27270
27633
  },
27271
27634
  category: "interactive",
27635
+ contentSource: { kind: "entries" },
27272
27636
  tags: [
27273
27637
  "events",
27274
27638
  "listing",
@@ -28441,6 +28805,7 @@ const eventCalendarBlockDefinition = {
28441
28805
  paletteHidden: false
28442
28806
  },
28443
28807
  category: "interactive",
28808
+ contentSource: { kind: "entries" },
28444
28809
  tags: [
28445
28810
  "events",
28446
28811
  "calendar",
@@ -28838,6 +29203,7 @@ const recurringScheduleBlockDefinition = {
28838
29203
  titleSource: "heading",
28839
29204
  description: "A compact weekly schedule with one row per recurring series.",
28840
29205
  category: "interactive",
29206
+ contentSource: { kind: "entries" },
28841
29207
  icon: "CalendarDays",
28842
29208
  tags: [
28843
29209
  "schedule",
@@ -29255,7 +29621,10 @@ const offeringsPreviewFields = [
29255
29621
  label: "Link"
29256
29622
  }
29257
29623
  ],
29258
- ui: { intent: "display" }
29624
+ ui: {
29625
+ intent: "display",
29626
+ widget: "buttonVariant"
29627
+ }
29259
29628
  },
29260
29629
  {
29261
29630
  id: "buttonText",
@@ -29308,6 +29677,7 @@ const offeringsPreviewManifest = createBlockManifest({
29308
29677
  paletteHidden: false
29309
29678
  },
29310
29679
  category: "content",
29680
+ contentSource: { kind: "mixed" },
29311
29681
  tags: [
29312
29682
  "offerings",
29313
29683
  "events",
@@ -29476,6 +29846,7 @@ const embedManifest = createBlockManifest({
29476
29846
  id: "block.embed",
29477
29847
  title: "Embed Content",
29478
29848
  category: "content",
29849
+ contentSource: { kind: "entries" },
29479
29850
  titleSource: "heading",
29480
29851
  additionalFields: [
29481
29852
  parseFieldDefinition({
@@ -29963,6 +30334,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
29963
30334
  id: "block.image-gallery",
29964
30335
  title: "Image Gallery",
29965
30336
  category: "content",
30337
+ contentSource: { kind: "inline" },
29966
30338
  previewCustomize: { quickFieldPriority: [
29967
30339
  "aspectRatio",
29968
30340
  "slidesToShow",
@@ -30615,6 +30987,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
30615
30987
  id: "block.video-grid",
30616
30988
  title: "Video Grid",
30617
30989
  category: "media",
30990
+ contentSource: { kind: "inline" },
30618
30991
  skipSectionStyles: true,
30619
30992
  additionalFields: parseFieldDefinitions([
30620
30993
  {
@@ -30785,6 +31158,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
30785
31158
  title: "Audio Player",
30786
31159
  titleSource: "title",
30787
31160
  category: "media",
31161
+ contentSource: { kind: "inline" },
30788
31162
  description: "Add a branded audio player for a single track.",
30789
31163
  tags: [
30790
31164
  "audio",
@@ -30896,6 +31270,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
30896
31270
  title: "File Download",
30897
31271
  titleSource: ["title", "file.filename"],
30898
31272
  category: "media",
31273
+ contentSource: { kind: "inline" },
30899
31274
  description: "Add a simple public download link for a document, ZIP, or audio file.",
30900
31275
  tags: [
30901
31276
  "file",
@@ -31840,6 +32215,7 @@ const shopBlockDefinition = {
31840
32215
  paletteHidden: false
31841
32216
  },
31842
32217
  category: "interactive",
32218
+ contentSource: { kind: "entries" },
31843
32219
  tags: [
31844
32220
  "shop",
31845
32221
  "passes",
@@ -32039,6 +32415,7 @@ const productListBlockDefinition = {
32039
32415
  paletteHidden: false
32040
32416
  },
32041
32417
  category: "interactive",
32418
+ contentSource: { kind: "entries" },
32042
32419
  tags: [
32043
32420
  "shop",
32044
32421
  "products",
@@ -32180,6 +32557,7 @@ const productDetailBlockDefinition = {
32180
32557
  paletteHidden: false
32181
32558
  },
32182
32559
  category: "interactive",
32560
+ contentSource: { kind: "entries" },
32183
32561
  tags: [
32184
32562
  "shop",
32185
32563
  "product",
@@ -32296,6 +32674,7 @@ const cartBlockDefinition = {
32296
32674
  paletteHidden: false
32297
32675
  },
32298
32676
  category: "interactive",
32677
+ contentSource: { kind: "inline" },
32299
32678
  tags: [
32300
32679
  "shop",
32301
32680
  "cart",
@@ -32378,6 +32757,7 @@ const checkoutBlockDefinition = {
32378
32757
  paletteHidden: false
32379
32758
  },
32380
32759
  category: "interactive",
32760
+ contentSource: { kind: "inline" },
32381
32761
  tags: [
32382
32762
  "shop",
32383
32763
  "checkout",
@@ -32581,6 +32961,7 @@ const giftingBlockDefinition = {
32581
32961
  paletteHidden: false
32582
32962
  },
32583
32963
  category: "interactive",
32964
+ contentSource: { kind: "entries" },
32584
32965
  tags: [
32585
32966
  "gifting",
32586
32967
  "gift cards",
@@ -32924,6 +33305,7 @@ const newsletterSignupBlockDefinition = {
32924
33305
  titleSource: "title",
32925
33306
  description: "Newsletter subscription form with configurable field presets.",
32926
33307
  category: "interactive",
33308
+ contentSource: { kind: "inline" },
32927
33309
  fragments: [{
32928
33310
  fragment: newsletterCopyFragment,
32929
33311
  fieldPriority: 0
@@ -33105,6 +33487,7 @@ const teamMembersBlockDefinition = {
33105
33487
  id: "block.team-members",
33106
33488
  title: "Team Members",
33107
33489
  category: "content",
33490
+ contentSource: { kind: "mixed" },
33108
33491
  titleSource: "heading",
33109
33492
  additionalFields: [
33110
33493
  parseFieldDefinition({
@@ -33525,6 +33908,7 @@ const locationMapBlockDefinition = {
33525
33908
  titleSource: "heading",
33526
33909
  description: "Show a business location with an interactive map and directions link.",
33527
33910
  category: "content",
33911
+ contentSource: { kind: "inline" },
33528
33912
  tags: [
33529
33913
  "map",
33530
33914
  "location",
@@ -34640,9 +35024,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
34640
35024
  ].filter(Boolean).join(" ");
34641
35025
  }
34642
35026
  function gradientPresetCss(value) {
34643
- if (!isString(value)) return null;
34644
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
34645
- if (!preset) return null;
35027
+ const presetId = parseGradientPresetId(value);
35028
+ if (!presetId) return null;
35029
+ const preset = getGradientPreset(presetId);
34646
35030
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
34647
35031
  }
34648
35032
  const backgroundTransforms = [
@@ -35764,6 +36148,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
35764
36148
  "already_refunded",
35765
36149
  "idempotency_amount_mismatch",
35766
36150
  "idempotency_method_mismatch",
36151
+ "idempotency_receipt_mismatch",
35767
36152
  "refund_in_progress"
35768
36153
  ],
35769
36154
  "invalid_amount",
@@ -35776,7 +36161,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
35776
36161
  "payment_intent_not_found",
35777
36162
  "stripe_error",
35778
36163
  "stale_pending_missing_context",
35779
- "non_refundable_deposit_remaining"
36164
+ "non_refundable_deposit_remaining",
36165
+ "deposit_refund_override_required",
36166
+ "refund_revoke_requires_full_line_refund",
36167
+ "payment_receipt_not_found",
36168
+ "payment_receipt_not_refundable",
36169
+ "payment_receipt_attribution_required"
35780
36170
  ];
35781
36171
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
35782
36172
  //#endregion
@@ -35789,7 +36179,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
35789
36179
  "missing_credit_customer",
35790
36180
  "deposit_refund_override_required",
35791
36181
  "refund_revoke_requires_full_line_refund",
35792
- "unified_order_link_required"
36182
+ "unified_order_link_required",
36183
+ "payment_receipt_not_found",
36184
+ "payment_receipt_not_refundable",
36185
+ "payment_receipt_attribution_required"
35793
36186
  ];
35794
36187
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
35795
36188
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];