@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
@@ -210,19 +210,29 @@ function isRecord$9(value) {
210
210
  //#region ../core/src/booking-date-time.ts
211
211
  const DEFAULT_LOCALE = "en-US";
212
212
  const FALLBACK_TIMEZONE = "UTC";
213
+ const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
214
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
215
+ const timeZoneValidityCache = /* @__PURE__ */ new Map();
213
216
  function isValidTimeZone(timeZone) {
217
+ const cached = timeZoneValidityCache.get(timeZone);
218
+ if (cached !== void 0) return cached;
219
+ let isValid;
214
220
  try {
215
221
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
216
- return true;
222
+ isValid = true;
217
223
  } catch {
218
- return false;
224
+ isValid = false;
219
225
  }
226
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
227
+ timeZoneValidityCache.set(timeZone, isValid);
228
+ return isValid;
220
229
  }
221
230
  function getSafeTimeZone(timeZone) {
222
231
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
223
232
  return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
224
233
  }
225
234
  function parseStrictBookingTimeZone(timeZone) {
235
+ if (typeof timeZone !== "string") return null;
226
236
  const normalized = timeZone.trim();
227
237
  if (normalized.length === 0 || !isValidTimeZone(normalized)) return null;
228
238
  return normalized;
@@ -235,10 +245,19 @@ function formatParseError(error) {
235
245
  }
236
246
  }
237
247
  function formatToPartsLookup(date, locale, timeZone, format) {
238
- return new Map(new Intl.DateTimeFormat(locale, {
248
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
249
+ }
250
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
251
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
252
+ const cached = dateTimeFormatterCache.get(key);
253
+ if (cached !== void 0) return cached;
254
+ const formatter = new Intl.DateTimeFormat(locale, {
239
255
  ...format,
240
256
  timeZone
241
- }).formatToParts(date).map((part) => [part.type, part.value]));
257
+ });
258
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
259
+ dateTimeFormatterCache.set(key, formatter);
260
+ return formatter;
242
261
  }
243
262
  function getZonedDateTimeParts(date, timeZone) {
244
263
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -281,23 +300,9 @@ function toUtcIsoDateTimeString(value) {
281
300
  return parsed.value;
282
301
  }
283
302
  function parseScheduledBookingDateTime(input) {
303
+ let startsAt;
284
304
  try {
285
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
286
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
287
- if (timeZone === null) return {
288
- ok: false,
289
- field: "timeZone",
290
- reason: "invalid_time_zone",
291
- value: input.timeZone
292
- };
293
- return {
294
- ok: true,
295
- value: {
296
- startsAt,
297
- timeZone,
298
- locale: input.locale
299
- }
300
- };
305
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
301
306
  } catch {
302
307
  return {
303
308
  ok: false,
@@ -306,6 +311,21 @@ function parseScheduledBookingDateTime(input) {
306
311
  value: input.startsAt
307
312
  };
308
313
  }
314
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
315
+ if (timeZone === null) return {
316
+ ok: false,
317
+ field: "timeZone",
318
+ reason: "invalid_time_zone",
319
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
320
+ };
321
+ return {
322
+ ok: true,
323
+ value: {
324
+ startsAt,
325
+ timeZone,
326
+ locale: input.locale
327
+ }
328
+ };
309
329
  }
310
330
  function toScheduledBookingDateTime(input) {
311
331
  const result = parseScheduledBookingDateTime(input);
@@ -3435,6 +3455,111 @@ const mediaSchema$1 = z.object({
3435
3455
  transform: transformSchema$1.optional()
3436
3456
  });
3437
3457
  //#endregion
3458
+ //#region ../theme-core/src/buttons/effectClassification.ts
3459
+ /**
3460
+ * Exhaustive live policy for every registered effect id.
3461
+ *
3462
+ * The resolver consumes the transition payload directly, so adding an effect
3463
+ * cannot update classification without also defining its runtime behavior.
3464
+ */
3465
+ const BUTTON_EFFECT_POLICIES = {
3466
+ "darken-background": {
3467
+ classification: "colour-transition",
3468
+ transition: {
3469
+ kind: "adjust-shade",
3470
+ direction: "darker"
3471
+ }
3472
+ },
3473
+ "lighten-background": {
3474
+ classification: "colour-transition",
3475
+ transition: {
3476
+ kind: "adjust-shade",
3477
+ direction: "lighter"
3478
+ }
3479
+ },
3480
+ "background-on-hover": {
3481
+ classification: "colour-transition",
3482
+ transition: { kind: "replace-background" }
3483
+ },
3484
+ "background-on-hover-alpha": {
3485
+ classification: "unsupported-colour",
3486
+ reason: "alpha_requires_surface"
3487
+ },
3488
+ "fade-background": {
3489
+ classification: "unsupported-colour",
3490
+ reason: "changes_element_opacity"
3491
+ },
3492
+ "opacity-reduce": {
3493
+ classification: "unsupported-colour",
3494
+ reason: "changes_element_opacity"
3495
+ },
3496
+ "gradient-text": {
3497
+ classification: "unsupported-colour",
3498
+ reason: "changes_foreground"
3499
+ },
3500
+ "text-color-change": {
3501
+ classification: "unsupported-colour",
3502
+ reason: "changes_foreground"
3503
+ },
3504
+ "border-color-change": {
3505
+ classification: "unsupported-colour",
3506
+ reason: "changes_border"
3507
+ },
3508
+ "aurora-glow": {
3509
+ classification: "unsupported-background-overlay",
3510
+ reason: "unresolved_background_overlay"
3511
+ },
3512
+ "cosmic-stardust": {
3513
+ classification: "unsupported-background-overlay",
3514
+ reason: "unresolved_background_overlay"
3515
+ },
3516
+ "gradient-border-fill": {
3517
+ classification: "unsupported-background-overlay",
3518
+ reason: "unresolved_background_overlay"
3519
+ },
3520
+ "animated-gradient-border-fill": {
3521
+ classification: "unsupported-background-overlay",
3522
+ reason: "unresolved_background_overlay"
3523
+ },
3524
+ "nav-underline": {
3525
+ classification: "not-button",
3526
+ reason: "not_button_effect"
3527
+ },
3528
+ "nav-frosted-base": {
3529
+ classification: "not-button",
3530
+ reason: "not_button_effect"
3531
+ },
3532
+ "nav-frosted-hover": {
3533
+ classification: "not-button",
3534
+ reason: "not_button_effect"
3535
+ },
3536
+ "nav-frosted-active": {
3537
+ classification: "not-button",
3538
+ reason: "not_button_effect"
3539
+ },
3540
+ "animated-gradient": { classification: "non-colour" },
3541
+ "border-glow": { classification: "non-colour" },
3542
+ "drop-shadow": { classification: "non-colour" },
3543
+ "inner-shadow": { classification: "non-colour" },
3544
+ "neumorphic-shadow": { classification: "non-colour" },
3545
+ "outer-glow": { classification: "non-colour" },
3546
+ "retro-3d-shadow": { classification: "non-colour" },
3547
+ "scale-up": { classification: "non-colour" },
3548
+ "scale-down": { classification: "non-colour" },
3549
+ lift: { classification: "non-colour" },
3550
+ "press-down": { classification: "non-colour" },
3551
+ pop: { classification: "non-colour" },
3552
+ "border-bottom-grow": { classification: "non-colour" },
3553
+ "sketchy-border": { classification: "non-colour" },
3554
+ "pulse-animation": { classification: "non-colour" }
3555
+ };
3556
+ function getButtonEffectPolicy(effectId) {
3557
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
3558
+ }
3559
+ function classifyButtonEffectId(effectId) {
3560
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
3561
+ }
3562
+ //#endregion
3438
3563
  //#region ../theme-core/src/buttons/types.ts
3439
3564
  /**
3440
3565
  * Standard semantic variant roles a theme exposes.
@@ -3451,6 +3576,20 @@ const VARIANT_ROLES = [
3451
3576
  "tertiary",
3452
3577
  "accent"
3453
3578
  ];
3579
+ function parseOpaqueButtonColourToken(value) {
3580
+ const token = parseThemeColorToken(value);
3581
+ if (token === null) return null;
3582
+ const parts = parseColorTokenParts(token);
3583
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
3584
+ }
3585
+ function unsafeAsOpaqueButtonColourToken(value) {
3586
+ return value;
3587
+ }
3588
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
3589
+ const token = parseOpaqueButtonColourToken(value);
3590
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
3591
+ return token;
3592
+ });
3454
3593
  const cornerStyleSchema = z$1.enum([
3455
3594
  "square",
3456
3595
  "rounded",
@@ -3552,7 +3691,7 @@ const buttonSizesSchema = z$1.object({
3552
3691
  lg,
3553
3692
  xl: xl ?? lg
3554
3693
  }));
3555
- const buttonGlobalSettingsSchema = z$1.object({
3694
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
3556
3695
  cornerStyle: cornerStyleSchema,
3557
3696
  cornerRadius: z$1.number().min(0).max(24).optional(),
3558
3697
  /**
@@ -3583,11 +3722,12 @@ const buttonGlobalSettingsSchema = z$1.object({
3583
3722
  paddingPreset: buttonPaddingPresetSchema.optional(),
3584
3723
  hoverTransform: hoverTransformSchema,
3585
3724
  hoverColor: hoverColorSchema,
3586
- hoverColorToken: themeColorTokenSchema.optional(),
3725
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
3587
3726
  gradientStyle: gradientStyleSchema.optional(),
3588
3727
  gradientAngle: z$1.number().min(0).max(360).optional(),
3589
3728
  gradientSharpness: gradientSharpnessSchema.optional()
3590
3729
  });
3730
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
3591
3731
  const gradientDirectionSchema$1 = z$1.enum([
3592
3732
  "to-r",
3593
3733
  "to-l",
@@ -3601,27 +3741,33 @@ const gradientDirectionSchema$1 = z$1.enum([
3601
3741
  const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
3602
3742
  z$1.object({
3603
3743
  type: z$1.literal("solid"),
3604
- colorToken: themeColorTokenSchema
3744
+ colorToken: opaqueButtonColourTokenSchema
3605
3745
  }),
3606
3746
  z$1.object({
3607
3747
  type: z$1.literal("gradient"),
3608
- stops: z$1.array(themeColorTokenSchema).min(2),
3609
- direction: gradientDirectionSchema$1
3748
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
3749
+ const [first, second, ...rest] = stops;
3750
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
3751
+ return [
3752
+ first,
3753
+ second,
3754
+ ...rest
3755
+ ];
3756
+ }),
3757
+ direction: gradientDirectionSchema$1,
3758
+ foregroundToken: opaqueButtonColourTokenSchema
3610
3759
  }),
3611
- z$1.object({ type: z$1.literal("transparent") })
3760
+ z$1.object({
3761
+ type: z$1.literal("surface"),
3762
+ role: z$1.literal("link")
3763
+ })
3612
3764
  ]);
3613
3765
  const effectApplicationSchema$1 = z$1.object({
3614
3766
  effectId: z$1.string(),
3615
- options: z$1.record(z$1.string(), z$1.any()).optional()
3616
- });
3617
- const buttonBorderSchema = z$1.object({
3618
- widthClass: z$1.string(),
3619
- colorToken: themeColorTokenSchema
3620
- });
3621
- const buttonVariantAffordanceSchema = z$1.object({
3622
- iconId: z$1.string().min(1),
3623
- colorToken: themeColorTokenSchema.optional()
3767
+ options: z$1.record(z$1.string(), z$1.json()).optional()
3624
3768
  });
3769
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
3770
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
3625
3771
  const variantShadowSchema = z$1.object({
3626
3772
  elevation: z$1.enum([
3627
3773
  "none",
@@ -3662,27 +3808,170 @@ const variantSizeOverridesSchema = z$1.object({
3662
3808
  * default (e.g. link-style variants declaring zero horizontal padding at
3663
3809
  * every size).
3664
3810
  */
3665
- const buttonVariantSchema = z$1.object({
3811
+ const canonicalButtonVariantSchema = z$1.object({
3666
3812
  id: z$1.string(),
3667
3813
  name: z$1.string().min(1).max(20),
3668
3814
  enabled: z$1.boolean(),
3669
3815
  priority: prioritySchema,
3670
3816
  background: buttonBackgroundSchema,
3671
- textColorToken: themeColorTokenSchema,
3672
3817
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
3673
3818
  borderRadius: z$1.string().optional(),
3674
3819
  shadow: variantShadowSchema.optional(),
3675
3820
  border: buttonBorderSchema.optional(),
3676
- hoverBackgroundToken: z$1.string().optional(),
3821
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
3677
3822
  effects: variantEffectsSchema.optional(),
3678
3823
  sizes: variantSizeOverridesSchema.optional(),
3679
3824
  affordance: buttonVariantAffordanceSchema.optional()
3680
3825
  });
3826
+ /**
3827
+ * Temporary persisted-theme admission boundary for issue #1206.
3828
+ *
3829
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
3830
+ * `textColorToken`/border colour shape. New source and all downstream code use
3831
+ * only the canonical relationship. Delete this preprocessor after the reviewed
3832
+ * production rewrite reports zero legacy rows.
3833
+ */
3834
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
3681
3835
  const buttonSystemSchema = z$1.object({
3682
3836
  global: buttonGlobalSettingsSchema,
3683
3837
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
3684
3838
  sizes: buttonSizesSchema.optional()
3685
3839
  });
3840
+ function normalizeLegacyButtonVariantInput(input) {
3841
+ if (!isUnknownRecord(input)) return input;
3842
+ const background = input.background;
3843
+ if (!isUnknownRecord(background)) return input;
3844
+ 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;
3845
+ const { textColorToken, ...withoutLegacyText } = input;
3846
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
3847
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
3848
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
3849
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
3850
+ if (background.type === "transparent") return {
3851
+ ...withoutLegacyText,
3852
+ background: {
3853
+ type: "surface",
3854
+ role: "link"
3855
+ },
3856
+ border: normalizedBorder,
3857
+ affordance: normalizedAffordance,
3858
+ effects: normalizedEffects,
3859
+ hoverBackgroundToken
3860
+ };
3861
+ if (background.type === "gradient") {
3862
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
3863
+ return {
3864
+ ...withoutLegacyText,
3865
+ background: {
3866
+ ...background,
3867
+ stops,
3868
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
3869
+ },
3870
+ border: normalizedBorder,
3871
+ affordance: normalizedAffordance,
3872
+ effects: normalizedEffects,
3873
+ hoverBackgroundToken
3874
+ };
3875
+ }
3876
+ return {
3877
+ ...withoutLegacyText,
3878
+ background: background.type === "solid" ? {
3879
+ ...background,
3880
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
3881
+ } : background,
3882
+ border: normalizedBorder,
3883
+ affordance: normalizedAffordance,
3884
+ effects: normalizedEffects,
3885
+ hoverBackgroundToken
3886
+ };
3887
+ }
3888
+ function normalizeLegacyButtonGlobalInput(input) {
3889
+ if (!isUnknownRecord(input)) return input;
3890
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
3891
+ return hoverColorToken === input.hoverColorToken ? input : {
3892
+ ...input,
3893
+ hoverColorToken
3894
+ };
3895
+ }
3896
+ function hasLegacyAlphaToken(input, background) {
3897
+ const stops = isUnknownArray(background.stops) ? background.stops : [];
3898
+ return [
3899
+ input.hoverBackgroundToken,
3900
+ background.colorToken,
3901
+ background.foregroundToken,
3902
+ ...stops
3903
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
3904
+ }
3905
+ function stripLegacyTokenAlpha(value) {
3906
+ if (typeof value !== "string") return value;
3907
+ const slashIndex = value.indexOf("/");
3908
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
3909
+ }
3910
+ function hasLegacyButtonEffects(input) {
3911
+ if (!isUnknownRecord(input)) return false;
3912
+ return [
3913
+ "base",
3914
+ "hover",
3915
+ "active",
3916
+ "focus"
3917
+ ].some((state) => {
3918
+ const effects = input[state];
3919
+ return Array.isArray(effects) && effects.some((effect) => {
3920
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
3921
+ const classification = classifyButtonEffectId(effect.effectId);
3922
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
3923
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
3924
+ });
3925
+ });
3926
+ }
3927
+ function normalizeLegacyButtonEffects(input, backgroundType) {
3928
+ if (!isUnknownRecord(input)) return input;
3929
+ const normalized = {};
3930
+ for (const state of [
3931
+ "base",
3932
+ "hover",
3933
+ "active",
3934
+ "focus"
3935
+ ]) {
3936
+ const effects = input[state];
3937
+ if (!Array.isArray(effects)) continue;
3938
+ const safeEffects = effects.flatMap((effect) => {
3939
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
3940
+ const classification = classifyButtonEffectId(effect.effectId);
3941
+ if (classification === "non-colour") return [effect];
3942
+ if (classification !== "colour-transition") return [];
3943
+ if (effect.effectId === "background-on-hover") {
3944
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
3945
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
3946
+ return colorToken === null ? [] : [{
3947
+ ...effect,
3948
+ options: {
3949
+ ...options,
3950
+ colorToken
3951
+ }
3952
+ }];
3953
+ }
3954
+ if (backgroundType !== "solid") return [];
3955
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
3956
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
3957
+ return [{
3958
+ ...effect,
3959
+ options: {
3960
+ ...isUnknownRecord(effect.options) ? effect.options : {},
3961
+ amount
3962
+ }
3963
+ }];
3964
+ });
3965
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
3966
+ }
3967
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
3968
+ }
3969
+ function isUnknownRecord(value) {
3970
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3971
+ }
3972
+ function isUnknownArray(value) {
3973
+ return Array.isArray(value);
3974
+ }
3686
3975
  buttonSizeNameSchema.options;
3687
3976
  //#endregion
3688
3977
  //#region ../theme-core/src/buttons/personalities/types.ts
@@ -3709,7 +3998,7 @@ function defineButtonPersonality(input) {
3709
3998
  name: input.name,
3710
3999
  description: input.description,
3711
4000
  tags: input.tags,
3712
- buttonSystem: input.buttonSystem
4001
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
3713
4002
  };
3714
4003
  }
3715
4004
  //#endregion
@@ -3762,19 +4051,15 @@ const brushedWash = defineButtonPersonality({
3762
4051
  background: {
3763
4052
  type: "gradient",
3764
4053
  stops: ["primary", "accent"],
3765
- direction: "to-r"
4054
+ direction: "to-r",
4055
+ foregroundToken: "primaryForeground"
3766
4056
  },
3767
- textColorToken: "primaryForeground",
3768
4057
  borderRadius: "rounded-lg",
3769
4058
  shadow: {
3770
4059
  elevation: "low",
3771
4060
  softness: "soft",
3772
4061
  position: "bottom"
3773
- },
3774
- effects: { hover: [{
3775
- effectId: "opacity-reduce",
3776
- options: { reduction: -15 }
3777
- }] }
4062
+ }
3778
4063
  },
3779
4064
  {
3780
4065
  id: "secondary",
@@ -3784,32 +4069,27 @@ const brushedWash = defineButtonPersonality({
3784
4069
  background: {
3785
4070
  type: "gradient",
3786
4071
  stops: ["secondary", "accent"],
3787
- direction: "to-br"
4072
+ direction: "to-br",
4073
+ foregroundToken: "primaryForeground"
3788
4074
  },
3789
- textColorToken: "primaryForeground",
3790
4075
  borderRadius: "rounded-lg",
3791
4076
  shadow: {
3792
4077
  elevation: "low",
3793
4078
  softness: "soft",
3794
4079
  position: "bottom"
3795
- },
3796
- effects: { hover: [{
3797
- effectId: "opacity-reduce",
3798
- options: { reduction: -15 }
3799
- }] }
4080
+ }
3800
4081
  },
3801
4082
  {
3802
4083
  id: "outline",
3803
4084
  name: "Outline",
3804
4085
  enabled: true,
3805
4086
  priority: 3,
3806
- background: { type: "transparent" },
3807
- textColorToken: "primary",
3808
- borderRadius: "rounded-lg",
3809
- border: {
3810
- widthClass: "border",
3811
- colorToken: "primary"
4087
+ background: {
4088
+ type: "surface",
4089
+ role: "link"
3812
4090
  },
4091
+ borderRadius: "rounded-lg",
4092
+ border: { widthClass: "border" },
3813
4093
  effects: { hover: [{
3814
4094
  effectId: "background-on-hover",
3815
4095
  options: { colorToken: "surface" }
@@ -3820,8 +4100,10 @@ const brushedWash = defineButtonPersonality({
3820
4100
  name: "Ghost",
3821
4101
  enabled: true,
3822
4102
  priority: 3,
3823
- background: { type: "transparent" },
3824
- textColorToken: "text",
4103
+ background: {
4104
+ type: "surface",
4105
+ role: "link"
4106
+ },
3825
4107
  borderRadius: "rounded-lg",
3826
4108
  effects: { hover: [{
3827
4109
  effectId: "background-on-hover",
@@ -3867,7 +4149,6 @@ const confidentChip = defineButtonPersonality({
3867
4149
  type: "solid",
3868
4150
  colorToken: "primary"
3869
4151
  },
3870
- textColorToken: "primaryForeground",
3871
4152
  borderRadius: "rounded-md",
3872
4153
  shadow: {
3873
4154
  elevation: "medium",
@@ -3877,7 +4158,7 @@ const confidentChip = defineButtonPersonality({
3877
4158
  effects: {
3878
4159
  hover: [{
3879
4160
  effectId: "darken-background",
3880
- options: { amount: 60 }
4161
+ options: { amount: 100 }
3881
4162
  }],
3882
4163
  active: [{
3883
4164
  effectId: "scale-down",
@@ -3894,12 +4175,8 @@ const confidentChip = defineButtonPersonality({
3894
4175
  type: "solid",
3895
4176
  colorToken: "surface"
3896
4177
  },
3897
- textColorToken: "text",
3898
4178
  borderRadius: "rounded-md",
3899
- border: {
3900
- widthClass: "border",
3901
- colorToken: "border"
3902
- },
4179
+ border: { widthClass: "border" },
3903
4180
  effects: { hover: [{
3904
4181
  effectId: "background-on-hover",
3905
4182
  options: { colorToken: "background" }
@@ -3910,13 +4187,12 @@ const confidentChip = defineButtonPersonality({
3910
4187
  name: "Outline",
3911
4188
  enabled: true,
3912
4189
  priority: 3,
3913
- background: { type: "transparent" },
3914
- textColorToken: "primary",
3915
- borderRadius: "rounded-md",
3916
- border: {
3917
- widthClass: "border",
3918
- colorToken: "primary"
4190
+ background: {
4191
+ type: "surface",
4192
+ role: "link"
3919
4193
  },
4194
+ borderRadius: "rounded-md",
4195
+ border: { widthClass: "border" },
3920
4196
  effects: { hover: [{
3921
4197
  effectId: "background-on-hover",
3922
4198
  options: { colorToken: "surface" }
@@ -3927,8 +4203,10 @@ const confidentChip = defineButtonPersonality({
3927
4203
  name: "Ghost",
3928
4204
  enabled: true,
3929
4205
  priority: 3,
3930
- background: { type: "transparent" },
3931
- textColorToken: "primary",
4206
+ background: {
4207
+ type: "surface",
4208
+ role: "link"
4209
+ },
3932
4210
  borderRadius: "rounded-md",
3933
4211
  effects: { hover: [{
3934
4212
  effectId: "background-on-hover",
@@ -3991,7 +4269,6 @@ const earthPill = defineButtonPersonality({
3991
4269
  type: "solid",
3992
4270
  colorToken: "primary"
3993
4271
  },
3994
- textColorToken: "primaryForeground",
3995
4272
  borderRadius: "rounded-full",
3996
4273
  shadow: {
3997
4274
  elevation: "low",
@@ -4017,13 +4294,12 @@ const earthPill = defineButtonPersonality({
4017
4294
  name: "Secondary",
4018
4295
  enabled: true,
4019
4296
  priority: 2,
4020
- background: { type: "transparent" },
4021
- textColorToken: "primary",
4022
- borderRadius: "rounded-full",
4023
- border: {
4024
- widthClass: "border",
4025
- colorToken: "primary"
4297
+ background: {
4298
+ type: "surface",
4299
+ role: "link"
4026
4300
  },
4301
+ borderRadius: "rounded-full",
4302
+ border: { widthClass: "border" },
4027
4303
  effects: { hover: [{
4028
4304
  effectId: "background-on-hover",
4029
4305
  options: { colorToken: "muted" }
@@ -4034,13 +4310,12 @@ const earthPill = defineButtonPersonality({
4034
4310
  name: "Outline",
4035
4311
  enabled: true,
4036
4312
  priority: 3,
4037
- background: { type: "transparent" },
4038
- textColorToken: "text",
4039
- borderRadius: "rounded-full",
4040
- border: {
4041
- widthClass: "border",
4042
- colorToken: "border"
4313
+ background: {
4314
+ type: "surface",
4315
+ role: "link"
4043
4316
  },
4317
+ borderRadius: "rounded-full",
4318
+ border: { widthClass: "border" },
4044
4319
  effects: { hover: [{
4045
4320
  effectId: "background-on-hover",
4046
4321
  options: { colorToken: "surfaceAlt" }
@@ -4051,8 +4326,10 @@ const earthPill = defineButtonPersonality({
4051
4326
  name: "Ghost",
4052
4327
  enabled: true,
4053
4328
  priority: 3,
4054
- background: { type: "transparent" },
4055
- textColorToken: "primary",
4329
+ background: {
4330
+ type: "surface",
4331
+ role: "link"
4332
+ },
4056
4333
  borderRadius: "rounded-full",
4057
4334
  shadow: {
4058
4335
  elevation: "none",
@@ -4073,11 +4350,7 @@ const earthPill = defineButtonPersonality({
4073
4350
  padding: "0.625rem 0",
4074
4351
  fontSize: "text-xl"
4075
4352
  }
4076
- },
4077
- effects: { hover: [{
4078
- effectId: "opacity-reduce",
4079
- options: { reduction: 25 }
4080
- }] }
4353
+ }
4081
4354
  }
4082
4355
  ]
4083
4356
  }
@@ -4113,8 +4386,10 @@ const editorialLink = defineButtonPersonality({
4113
4386
  name: "Primary",
4114
4387
  enabled: true,
4115
4388
  priority: 1,
4116
- background: { type: "transparent" },
4117
- textColorToken: "text",
4389
+ background: {
4390
+ type: "surface",
4391
+ role: "link"
4392
+ },
4118
4393
  borderRadius: "rounded-none",
4119
4394
  sizes: {
4120
4395
  sm: { padding: "0.25rem 0" },
@@ -4136,8 +4411,10 @@ const editorialLink = defineButtonPersonality({
4136
4411
  name: "Secondary",
4137
4412
  enabled: true,
4138
4413
  priority: 2,
4139
- background: { type: "transparent" },
4140
- textColorToken: "mutedText",
4414
+ background: {
4415
+ type: "surface",
4416
+ role: "link"
4417
+ },
4141
4418
  borderRadius: "rounded-none",
4142
4419
  sizes: {
4143
4420
  sm: { padding: "0.25rem 0" },
@@ -4159,8 +4436,10 @@ const editorialLink = defineButtonPersonality({
4159
4436
  name: "Outline",
4160
4437
  enabled: true,
4161
4438
  priority: 3,
4162
- background: { type: "transparent" },
4163
- textColorToken: "accent",
4439
+ background: {
4440
+ type: "surface",
4441
+ role: "link"
4442
+ },
4164
4443
  borderRadius: "rounded-none",
4165
4444
  sizes: {
4166
4445
  sm: { padding: "0.25rem 0" },
@@ -4182,19 +4461,17 @@ const editorialLink = defineButtonPersonality({
4182
4461
  name: "Ghost",
4183
4462
  enabled: true,
4184
4463
  priority: 3,
4185
- background: { type: "transparent" },
4186
- textColorToken: "mutedText",
4464
+ background: {
4465
+ type: "surface",
4466
+ role: "link"
4467
+ },
4187
4468
  borderRadius: "rounded-none",
4188
4469
  sizes: {
4189
4470
  sm: { padding: "0.25rem 0" },
4190
4471
  md: { padding: "0.5rem 0" },
4191
4472
  lg: { padding: "0.625rem 0" },
4192
4473
  xl: { padding: "0.75rem 0" }
4193
- },
4194
- effects: { hover: [{
4195
- effectId: "opacity-reduce",
4196
- options: { reduction: -20 }
4197
- }] }
4474
+ }
4198
4475
  }
4199
4476
  ]
4200
4477
  }
@@ -4256,12 +4533,8 @@ const flatInk = defineButtonPersonality({
4256
4533
  type: "solid",
4257
4534
  colorToken: "primary"
4258
4535
  },
4259
- textColorToken: "primaryForeground",
4260
4536
  borderRadius: "rounded-lg",
4261
- affordance: {
4262
- iconId: "ArrowRight",
4263
- colorToken: "accent"
4264
- },
4537
+ affordance: { iconId: "ArrowRight" },
4265
4538
  effects: { hover: [{
4266
4539
  effectId: "lift",
4267
4540
  options: { translateY: "-2px" }
@@ -4275,13 +4548,12 @@ const flatInk = defineButtonPersonality({
4275
4548
  name: "Secondary",
4276
4549
  enabled: true,
4277
4550
  priority: 2,
4278
- background: { type: "transparent" },
4279
- textColorToken: "primary",
4280
- borderRadius: "rounded-lg",
4281
- border: {
4282
- widthClass: "border",
4283
- colorToken: "border"
4551
+ background: {
4552
+ type: "surface",
4553
+ role: "link"
4284
4554
  },
4555
+ borderRadius: "rounded-lg",
4556
+ border: { widthClass: "border" },
4285
4557
  effects: { hover: [{
4286
4558
  effectId: "lift",
4287
4559
  options: { translateY: "-2px" }
@@ -4299,12 +4571,8 @@ const flatInk = defineButtonPersonality({
4299
4571
  type: "solid",
4300
4572
  colorToken: "accent"
4301
4573
  },
4302
- textColorToken: "accentForeground",
4303
4574
  borderRadius: "rounded-lg",
4304
- affordance: {
4305
- iconId: "ArrowRight",
4306
- colorToken: "accentForeground"
4307
- },
4575
+ affordance: { iconId: "ArrowRight" },
4308
4576
  effects: { hover: [{
4309
4577
  effectId: "lift",
4310
4578
  options: { translateY: "-2px" }
@@ -4367,7 +4635,6 @@ const inkStamp = defineButtonPersonality({
4367
4635
  type: "solid",
4368
4636
  colorToken: "primary"
4369
4637
  },
4370
- textColorToken: "primaryForeground",
4371
4638
  borderRadius: "rounded-md",
4372
4639
  effects: {
4373
4640
  hover: [{
@@ -4388,13 +4655,12 @@ const inkStamp = defineButtonPersonality({
4388
4655
  name: "Secondary",
4389
4656
  enabled: true,
4390
4657
  priority: 2,
4391
- background: { type: "transparent" },
4392
- textColorToken: "primary",
4393
- borderRadius: "rounded-md",
4394
- border: {
4395
- widthClass: "border-2",
4396
- colorToken: "primary"
4658
+ background: {
4659
+ type: "surface",
4660
+ role: "link"
4397
4661
  },
4662
+ borderRadius: "rounded-md",
4663
+ border: { widthClass: "border-2" },
4398
4664
  effects: { hover: [{
4399
4665
  effectId: "background-on-hover",
4400
4666
  options: { colorToken: "surface" }
@@ -4405,13 +4671,12 @@ const inkStamp = defineButtonPersonality({
4405
4671
  name: "Outline",
4406
4672
  enabled: true,
4407
4673
  priority: 3,
4408
- background: { type: "transparent" },
4409
- textColorToken: "text",
4410
- borderRadius: "rounded-md",
4411
- border: {
4412
- widthClass: "border-2",
4413
- colorToken: "border"
4674
+ background: {
4675
+ type: "surface",
4676
+ role: "link"
4414
4677
  },
4678
+ borderRadius: "rounded-md",
4679
+ border: { widthClass: "border-2" },
4415
4680
  effects: { hover: [{
4416
4681
  effectId: "background-on-hover",
4417
4682
  options: { colorToken: "surface" }
@@ -4422,8 +4687,10 @@ const inkStamp = defineButtonPersonality({
4422
4687
  name: "Ghost",
4423
4688
  enabled: true,
4424
4689
  priority: 3,
4425
- background: { type: "transparent" },
4426
- textColorToken: "accent",
4690
+ background: {
4691
+ type: "surface",
4692
+ role: "link"
4693
+ },
4427
4694
  borderRadius: "rounded-none",
4428
4695
  sizes: {
4429
4696
  sm: {
@@ -4516,7 +4783,6 @@ const joyStamp = defineButtonPersonality({
4516
4783
  type: "solid",
4517
4784
  colorToken: "primary"
4518
4785
  },
4519
- textColorToken: "primaryForeground",
4520
4786
  borderRadius: "rounded-full",
4521
4787
  shadow: {
4522
4788
  elevation: "high",
@@ -4530,13 +4796,12 @@ const joyStamp = defineButtonPersonality({
4530
4796
  name: "Secondary",
4531
4797
  enabled: true,
4532
4798
  priority: 2,
4533
- background: { type: "transparent" },
4534
- textColorToken: "text",
4535
- borderRadius: "rounded-full",
4536
- border: {
4537
- widthClass: "border-2",
4538
- colorToken: "text"
4799
+ background: {
4800
+ type: "surface",
4801
+ role: "link"
4539
4802
  },
4803
+ borderRadius: "rounded-full",
4804
+ border: { widthClass: "border-2" },
4540
4805
  shadow: {
4541
4806
  elevation: "high",
4542
4807
  softness: "hard",
@@ -4601,12 +4866,8 @@ const ornateRitual = defineButtonPersonality({
4601
4866
  type: "solid",
4602
4867
  colorToken: "primary"
4603
4868
  },
4604
- textColorToken: "primaryForeground",
4605
4869
  borderRadius: "rounded-md",
4606
- border: {
4607
- widthClass: "border",
4608
- colorToken: "primary"
4609
- },
4870
+ border: { widthClass: "border" },
4610
4871
  effects: {
4611
4872
  hover: [{
4612
4873
  effectId: "background-on-hover",
@@ -4627,12 +4888,8 @@ const ornateRitual = defineButtonPersonality({
4627
4888
  type: "solid",
4628
4889
  colorToken: "secondary"
4629
4890
  },
4630
- textColorToken: "primaryForeground",
4631
4891
  borderRadius: "rounded-md",
4632
- border: {
4633
- widthClass: "border",
4634
- colorToken: "primary"
4635
- },
4892
+ border: { widthClass: "border" },
4636
4893
  effects: { hover: [{
4637
4894
  effectId: "background-on-hover",
4638
4895
  options: { colorToken: "surface" }
@@ -4643,13 +4900,12 @@ const ornateRitual = defineButtonPersonality({
4643
4900
  name: "Outline",
4644
4901
  enabled: true,
4645
4902
  priority: 3,
4646
- background: { type: "transparent" },
4647
- textColorToken: "primary",
4648
- borderRadius: "rounded-md",
4649
- border: {
4650
- widthClass: "border",
4651
- colorToken: "primary"
4903
+ background: {
4904
+ type: "surface",
4905
+ role: "link"
4652
4906
  },
4907
+ borderRadius: "rounded-md",
4908
+ border: { widthClass: "border" },
4653
4909
  effects: { hover: [{
4654
4910
  effectId: "background-on-hover",
4655
4911
  options: { colorToken: "muted" }
@@ -4660,8 +4916,10 @@ const ornateRitual = defineButtonPersonality({
4660
4916
  name: "Ghost",
4661
4917
  enabled: true,
4662
4918
  priority: 3,
4663
- background: { type: "transparent" },
4664
- textColorToken: "accent",
4919
+ background: {
4920
+ type: "surface",
4921
+ role: "link"
4922
+ },
4665
4923
  borderRadius: "rounded-none",
4666
4924
  sizes: {
4667
4925
  sm: {
@@ -4743,14 +5001,10 @@ const pebble = defineButtonPersonality({
4743
5001
  type: "solid",
4744
5002
  colorToken: "primary"
4745
5003
  },
4746
- textColorToken: "primaryForeground",
4747
5004
  borderRadius: "rounded-full",
4748
5005
  effects: { hover: [{
4749
- effectId: "background-on-hover-alpha",
4750
- options: {
4751
- colorToken: "primary",
4752
- opacity: 88
4753
- }
5006
+ effectId: "darken-background",
5007
+ options: { amount: 100 }
4754
5008
  }] }
4755
5009
  },
4756
5010
  {
@@ -4758,13 +5012,12 @@ const pebble = defineButtonPersonality({
4758
5012
  name: "Secondary",
4759
5013
  enabled: true,
4760
5014
  priority: 2,
4761
- background: { type: "transparent" },
4762
- textColorToken: "primary",
4763
- borderRadius: "rounded-full",
4764
- border: {
4765
- widthClass: "border-2",
4766
- colorToken: "accent"
5015
+ background: {
5016
+ type: "surface",
5017
+ role: "link"
4767
5018
  },
5019
+ borderRadius: "rounded-full",
5020
+ border: { widthClass: "border-2" },
4768
5021
  effects: { hover: [{
4769
5022
  effectId: "background-on-hover",
4770
5023
  options: { colorToken: "accent" }
@@ -4775,13 +5028,12 @@ const pebble = defineButtonPersonality({
4775
5028
  name: "Outline",
4776
5029
  enabled: true,
4777
5030
  priority: 3,
4778
- background: { type: "transparent" },
4779
- textColorToken: "text",
4780
- borderRadius: "rounded-full",
4781
- border: {
4782
- widthClass: "border",
4783
- colorToken: "border"
5031
+ background: {
5032
+ type: "surface",
5033
+ role: "link"
4784
5034
  },
5035
+ borderRadius: "rounded-full",
5036
+ border: { widthClass: "border" },
4785
5037
  effects: { hover: [{
4786
5038
  effectId: "background-on-hover",
4787
5039
  options: { colorToken: "surface" }
@@ -4792,8 +5044,10 @@ const pebble = defineButtonPersonality({
4792
5044
  name: "Ghost",
4793
5045
  enabled: true,
4794
5046
  priority: 3,
4795
- background: { type: "transparent" },
4796
- textColorToken: "primary",
5047
+ background: {
5048
+ type: "surface",
5049
+ role: "link"
5050
+ },
4797
5051
  borderRadius: "rounded-full",
4798
5052
  sizes: {
4799
5053
  sm: {
@@ -4809,11 +5063,7 @@ const pebble = defineButtonPersonality({
4809
5063
  padding: "0.75rem 1.5rem",
4810
5064
  fontSize: "text-xl"
4811
5065
  }
4812
- },
4813
- effects: { hover: [{
4814
- effectId: "opacity-reduce",
4815
- options: { reduction: 30 }
4816
- }] }
5066
+ }
4817
5067
  }
4818
5068
  ]
4819
5069
  }
@@ -4875,15 +5125,11 @@ const quietArrow = defineButtonPersonality({
4875
5125
  type: "solid",
4876
5126
  colorToken: "primary"
4877
5127
  },
4878
- textColorToken: "primaryForeground",
4879
5128
  borderRadius: "rounded-xl",
4880
5129
  affordance: { iconId: "ArrowRight" },
4881
5130
  effects: { hover: [{
4882
- effectId: "background-on-hover-alpha",
4883
- options: {
4884
- colorToken: "primary",
4885
- opacity: 90
4886
- }
5131
+ effectId: "darken-background",
5132
+ options: { amount: 100 }
4887
5133
  }] }
4888
5134
  },
4889
5135
  {
@@ -4891,13 +5137,12 @@ const quietArrow = defineButtonPersonality({
4891
5137
  name: "Secondary",
4892
5138
  enabled: true,
4893
5139
  priority: 2,
4894
- background: { type: "transparent" },
4895
- textColorToken: "primary",
4896
- borderRadius: "rounded-xl",
4897
- border: {
4898
- widthClass: "border",
4899
- colorToken: "primary"
5140
+ background: {
5141
+ type: "surface",
5142
+ role: "link"
4900
5143
  },
5144
+ borderRadius: "rounded-xl",
5145
+ border: { widthClass: "border" },
4901
5146
  affordance: { iconId: "ArrowRight" },
4902
5147
  effects: { hover: [{
4903
5148
  effectId: "background-on-hover",
@@ -4909,21 +5154,22 @@ const quietArrow = defineButtonPersonality({
4909
5154
  name: "Outline",
4910
5155
  enabled: true,
4911
5156
  priority: 3,
4912
- background: { type: "transparent" },
4913
- textColorToken: "primary",
5157
+ background: {
5158
+ type: "surface",
5159
+ role: "link"
5160
+ },
4914
5161
  borderRadius: "rounded-xl",
4915
- border: {
4916
- widthClass: "border",
4917
- colorToken: "primary"
4918
- }
5162
+ border: { widthClass: "border" }
4919
5163
  },
4920
5164
  {
4921
5165
  id: "ghost",
4922
5166
  name: "Ghost",
4923
5167
  enabled: true,
4924
5168
  priority: 3,
4925
- background: { type: "transparent" },
4926
- textColorToken: "primary",
5169
+ background: {
5170
+ type: "surface",
5171
+ role: "link"
5172
+ },
4927
5173
  borderRadius: "rounded-xl"
4928
5174
  }
4929
5175
  ]
@@ -4987,7 +5233,6 @@ const showtimePill = defineButtonPersonality({
4987
5233
  type: "solid",
4988
5234
  colorToken: "primary"
4989
5235
  },
4990
- textColorToken: "background",
4991
5236
  borderRadius: "rounded-full",
4992
5237
  effects: { hover: [{ effectId: "pop" }] }
4993
5238
  },
@@ -4996,13 +5241,12 @@ const showtimePill = defineButtonPersonality({
4996
5241
  name: "Secondary",
4997
5242
  enabled: true,
4998
5243
  priority: 2,
4999
- background: { type: "transparent" },
5000
- textColorToken: "primary",
5001
- borderRadius: "rounded-full",
5002
- border: {
5003
- widthClass: "border-2",
5004
- colorToken: "primary"
5244
+ background: {
5245
+ type: "surface",
5246
+ role: "link"
5005
5247
  },
5248
+ borderRadius: "rounded-full",
5249
+ border: { widthClass: "border-2" },
5006
5250
  effects: { hover: [{ effectId: "pop" }] }
5007
5251
  },
5008
5252
  {
@@ -5014,7 +5258,6 @@ const showtimePill = defineButtonPersonality({
5014
5258
  type: "solid",
5015
5259
  colorToken: "secondary"
5016
5260
  },
5017
- textColorToken: "primary",
5018
5261
  borderRadius: "rounded-full",
5019
5262
  effects: { hover: [{ effectId: "pop" }] }
5020
5263
  },
@@ -5027,12 +5270,8 @@ const showtimePill = defineButtonPersonality({
5027
5270
  type: "solid",
5028
5271
  colorToken: "background"
5029
5272
  },
5030
- textColorToken: "primary",
5031
5273
  borderRadius: "rounded-full",
5032
- border: {
5033
- widthClass: "border-2",
5034
- colorToken: "primary"
5035
- },
5274
+ border: { widthClass: "border-2" },
5036
5275
  effects: { hover: [{
5037
5276
  effectId: "background-on-hover",
5038
5277
  options: { colorToken: "surface" }
@@ -5043,13 +5282,12 @@ const showtimePill = defineButtonPersonality({
5043
5282
  name: "Outline",
5044
5283
  enabled: true,
5045
5284
  priority: 3,
5046
- background: { type: "transparent" },
5047
- textColorToken: "primary",
5048
- borderRadius: "rounded-full",
5049
- border: {
5050
- widthClass: "border-2",
5051
- colorToken: "primary"
5285
+ background: {
5286
+ type: "surface",
5287
+ role: "link"
5052
5288
  },
5289
+ borderRadius: "rounded-full",
5290
+ border: { widthClass: "border-2" },
5053
5291
  effects: { hover: [{
5054
5292
  effectId: "background-on-hover",
5055
5293
  options: { colorToken: "background" }
@@ -5060,8 +5298,10 @@ const showtimePill = defineButtonPersonality({
5060
5298
  name: "Ghost",
5061
5299
  enabled: true,
5062
5300
  priority: 3,
5063
- background: { type: "transparent" },
5064
- textColorToken: "primary",
5301
+ background: {
5302
+ type: "surface",
5303
+ role: "link"
5304
+ },
5065
5305
  borderRadius: "rounded-full",
5066
5306
  effects: { hover: [{
5067
5307
  effectId: "background-on-hover",
@@ -5107,7 +5347,6 @@ const softPill = defineButtonPersonality({
5107
5347
  type: "solid",
5108
5348
  colorToken: "primary"
5109
5349
  },
5110
- textColorToken: "primaryForeground",
5111
5350
  borderRadius: "rounded-full",
5112
5351
  shadow: {
5113
5352
  elevation: "low",
@@ -5130,13 +5369,12 @@ const softPill = defineButtonPersonality({
5130
5369
  name: "Secondary",
5131
5370
  enabled: true,
5132
5371
  priority: 2,
5133
- background: { type: "transparent" },
5134
- textColorToken: "primary",
5135
- borderRadius: "rounded-full",
5136
- border: {
5137
- widthClass: "border-2",
5138
- colorToken: "primary"
5372
+ background: {
5373
+ type: "surface",
5374
+ role: "link"
5139
5375
  },
5376
+ borderRadius: "rounded-full",
5377
+ border: { widthClass: "border-2" },
5140
5378
  effects: { hover: [{
5141
5379
  effectId: "background-on-hover",
5142
5380
  options: { colorToken: "surface" }
@@ -5147,13 +5385,12 @@ const softPill = defineButtonPersonality({
5147
5385
  name: "Outline",
5148
5386
  enabled: true,
5149
5387
  priority: 3,
5150
- background: { type: "transparent" },
5151
- textColorToken: "text",
5152
- borderRadius: "rounded-full",
5153
- border: {
5154
- widthClass: "border",
5155
- colorToken: "border"
5388
+ background: {
5389
+ type: "surface",
5390
+ role: "link"
5156
5391
  },
5392
+ borderRadius: "rounded-full",
5393
+ border: { widthClass: "border" },
5157
5394
  effects: { hover: [{
5158
5395
  effectId: "background-on-hover",
5159
5396
  options: { colorToken: "surface" }
@@ -5164,8 +5401,10 @@ const softPill = defineButtonPersonality({
5164
5401
  name: "Ghost",
5165
5402
  enabled: true,
5166
5403
  priority: 3,
5167
- background: { type: "transparent" },
5168
- textColorToken: "text",
5404
+ background: {
5405
+ type: "surface",
5406
+ role: "link"
5407
+ },
5169
5408
  borderRadius: "rounded-full",
5170
5409
  effects: { hover: [{
5171
5410
  effectId: "background-on-hover",
@@ -5184,9 +5423,8 @@ const solidSecondary = {
5184
5423
  priority: 2,
5185
5424
  background: {
5186
5425
  type: "solid",
5187
- colorToken: "secondary"
5426
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
5188
5427
  },
5189
- textColorToken: "onSecondary",
5190
5428
  borderRadius: "rounded-full",
5191
5429
  shadow: {
5192
5430
  elevation: "none",
@@ -5234,6 +5472,27 @@ const buttonPersonalities = [
5234
5472
  quietArrow
5235
5473
  ];
5236
5474
  new Map(buttonPersonalities.map((p) => [p.id, p]));
5475
+ buttonPersonalities.map((personality) => ({
5476
+ id: personality.id,
5477
+ name: personality.name,
5478
+ description: personality.description,
5479
+ category: presetCategory(personality),
5480
+ buttonSystem: personality.buttonSystem,
5481
+ compatibility: {
5482
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
5483
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
5484
+ }
5485
+ }));
5486
+ function presetCategory(personality) {
5487
+ switch (personality.tags.era) {
5488
+ case "retro": return "retro";
5489
+ case "editorial": return "minimal";
5490
+ case "organic": return "artistic";
5491
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
5492
+ case "technical": return "technical";
5493
+ case void 0: return "modern";
5494
+ }
5495
+ }
5237
5496
  //#endregion
5238
5497
  //#region ../theme-core/src/cards/types.ts
5239
5498
  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
  });
@@ -17139,9 +17481,15 @@ function createButtonGroup(options = {}) {
17139
17481
  //#endregion
17140
17482
  //#region ../blocks/src/system/fields/ctas.ts
17141
17483
  function createCtasRepeater(options = {}) {
17142
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
17484
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
17485
+ const fieldId = id;
17486
+ const buttonField = createButtonGroup({
17487
+ showGroupLabel: false,
17488
+ ...button ?? {},
17489
+ flattenInRepeater: true
17490
+ });
17143
17491
  return {
17144
- id,
17492
+ id: fieldId,
17145
17493
  type: "repeater",
17146
17494
  label,
17147
17495
  itemLabel,
@@ -17150,11 +17498,8 @@ function createCtasRepeater(options = {}) {
17150
17498
  maxItems,
17151
17499
  required: false,
17152
17500
  allowConversion: true,
17153
- schema: { fields: [createButtonGroup({
17154
- showGroupLabel: false,
17155
- ...button ?? {},
17156
- flattenInRepeater: true
17157
- })] }
17501
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
17502
+ schema: { fields: [buttonField] }
17158
17503
  };
17159
17504
  }
17160
17505
  //#endregion
@@ -17204,6 +17549,7 @@ const heroCtaRowFragment = defineFragment({
17204
17549
  label: "Calls to action",
17205
17550
  itemLabel: "CTA",
17206
17551
  maxItems: 3,
17552
+ defaultValue: [],
17207
17553
  button: {
17208
17554
  variants: [
17209
17555
  {
@@ -17271,7 +17617,7 @@ const ctaCopyFragment = defineFragment({
17271
17617
  eyebrowPath: "content.eyebrow",
17272
17618
  titlePath: "content.title",
17273
17619
  className: "cta-heading"
17274
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
17620
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
17275
17621
  });
17276
17622
  //#endregion
17277
17623
  //#region ../blocks/src/system/fragments/library/testimonialsHeading.ts
@@ -19003,6 +19349,7 @@ function createBlockManifest(config) {
19003
19349
  previewCustomize: config.previewCustomize,
19004
19350
  category: config.category,
19005
19351
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
19352
+ contentSource: config.contentSource,
19006
19353
  tags: config.tags ? [...config.tags] : [],
19007
19354
  icon: config.icon ?? "Box",
19008
19355
  layout,
@@ -19148,6 +19495,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
19148
19495
  title: "Hero",
19149
19496
  titleSource: "headline",
19150
19497
  category: "layout",
19498
+ contentSource: { kind: "inline" },
19151
19499
  includeContainerStyles: true,
19152
19500
  promotedFields: ["_sectionStyles.background.image"],
19153
19501
  fragments: [
@@ -19421,6 +19769,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
19421
19769
  id: "block.intro",
19422
19770
  title: "Intro",
19423
19771
  category: "layout",
19772
+ contentSource: { kind: "inline" },
19424
19773
  includeContainerStyles: true,
19425
19774
  titleSource: "title",
19426
19775
  previewCustomize: { quickFieldPriority: [
@@ -19606,6 +19955,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
19606
19955
  title: "Body Text",
19607
19956
  titleSource: "heading",
19608
19957
  category: "content",
19958
+ contentSource: { kind: "inline" },
19609
19959
  fragments: [{
19610
19960
  fragment: bodyCopyFragment,
19611
19961
  fieldPriority: 0
@@ -19662,6 +20012,10 @@ const blogPostBlockDefinition = {
19662
20012
  description: "Highlights a single blog post with title, image, and excerpt.",
19663
20013
  category: "blog",
19664
20014
  contentTypes: ["post"],
20015
+ contentSource: {
20016
+ kind: "entries",
20017
+ contentType: "post"
20018
+ },
19665
20019
  tags: [
19666
20020
  "blog",
19667
20021
  "post",
@@ -19959,6 +20313,10 @@ const blogListingManifest = createBlockManifest({
19959
20313
  ],
19960
20314
  description: "Display a collection of blog posts in grid or stack layout.",
19961
20315
  contentTypes: ["post"],
20316
+ contentSource: {
20317
+ kind: "entries",
20318
+ contentType: "post"
20319
+ },
19962
20320
  tags: [
19963
20321
  "blog",
19964
20322
  "posts",
@@ -20001,6 +20359,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
20001
20359
  id: "block.cta-full",
20002
20360
  title: "Full-width CTA",
20003
20361
  category: "marketing",
20362
+ contentSource: { kind: "inline" },
20004
20363
  fragments: [{
20005
20364
  fragment: ctaCopyFragment,
20006
20365
  fieldPriority: 0
@@ -20034,6 +20393,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
20034
20393
  id: "block.single-button",
20035
20394
  title: "Single Button",
20036
20395
  category: "marketing",
20396
+ contentSource: { kind: "inline" },
20037
20397
  fragments: [{
20038
20398
  fragment: singleButtonFragment,
20039
20399
  fieldPriority: 0
@@ -20294,6 +20654,7 @@ const formManifest = createBlockManifest({
20294
20654
  paletteHidden: false
20295
20655
  },
20296
20656
  category: "interactive",
20657
+ contentSource: { kind: "inline" },
20297
20658
  tags: [
20298
20659
  "form",
20299
20660
  "contact",
@@ -20356,6 +20717,7 @@ const contactNewsletterBlockDefinition = {
20356
20717
  titleSource: "contactTitle",
20357
20718
  description: "Two-column newsletter signup and contact form section.",
20358
20719
  category: "interactive",
20720
+ contentSource: { kind: "inline" },
20359
20721
  layout: contactNewsletterLayout,
20360
20722
  defaultVariant: "default",
20361
20723
  variants: { default: contactNewsletterLayout },
@@ -20559,6 +20921,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
20559
20921
  title: "FAQ",
20560
20922
  titleSource: "title",
20561
20923
  category: "content",
20924
+ contentSource: { kind: "inline" },
20562
20925
  includeContainerStyles: true,
20563
20926
  fragments: [{
20564
20927
  fragment: faqHeadingFragment,
@@ -22202,6 +22565,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
22202
22565
  id: "block.site-header",
22203
22566
  title: "Site Header",
22204
22567
  category: "layout",
22568
+ contentSource: { kind: "inline" },
22205
22569
  additionalFields: [{
22206
22570
  id: "mode",
22207
22571
  type: "select",
@@ -22406,6 +22770,7 @@ const siteFooterBlockDefinition = { manifest: createBlockManifest({
22406
22770
  id: "block.site-footer",
22407
22771
  title: "Site Footer",
22408
22772
  category: "layout",
22773
+ contentSource: { kind: "inline" },
22409
22774
  skipSectionStyles: true,
22410
22775
  layout: section({
22411
22776
  background: "background",
@@ -22555,6 +22920,7 @@ const testimonialsBlockDefinition = {
22555
22920
  id: "block.testimonials",
22556
22921
  title: "Testimonials",
22557
22922
  category: "marketing",
22923
+ contentSource: { kind: "inline" },
22558
22924
  includeContainerStyles: true,
22559
22925
  previewCustomize: { quickFieldPriority: [
22560
22926
  "avatarLayout",
@@ -22713,6 +23079,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
22713
23079
  id: "block.columns",
22714
23080
  title: "Columns",
22715
23081
  category: "layout",
23082
+ contentSource: { kind: "inline" },
22716
23083
  additionalFields: [
22717
23084
  parseFieldDefinition({
22718
23085
  id: "equalHeight",
@@ -22946,6 +23313,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
22946
23313
  id: "block.collection",
22947
23314
  title: "Collection",
22948
23315
  category: "layout",
23316
+ contentSource: { kind: "inline" },
22949
23317
  additionalFields: [
22950
23318
  parseFieldDefinition({
22951
23319
  id: "layout",
@@ -23182,6 +23550,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
23182
23550
  id: "block.feature-cards",
23183
23551
  title: "Feature Cards",
23184
23552
  category: "layout",
23553
+ contentSource: { kind: "inline" },
23185
23554
  includeContainerStyles: true,
23186
23555
  titleSource: "title",
23187
23556
  additionalFields: [
@@ -23565,6 +23934,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
23565
23934
  id: "block.media-text",
23566
23935
  title: "Media and Text",
23567
23936
  category: "layout",
23937
+ contentSource: { kind: "inline" },
23568
23938
  includeContainerStyles: true,
23569
23939
  titleSource: "title",
23570
23940
  previewCustomize: { quickFieldPriority: [
@@ -23965,6 +24335,7 @@ const appointmentBookingBlockDefinition = {
23965
24335
  paletteHidden: false
23966
24336
  },
23967
24337
  category: "interactive",
24338
+ contentSource: { kind: "inline" },
23968
24339
  tags: [
23969
24340
  "booking",
23970
24341
  "appointment",
@@ -24129,6 +24500,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
24129
24500
  paletteHidden: false
24130
24501
  },
24131
24502
  category: "interactive",
24503
+ contentSource: { kind: "inline" },
24132
24504
  tags: [
24133
24505
  "booking",
24134
24506
  "appointment",
@@ -25693,6 +26065,7 @@ const eventRegistrationBlockDefinition = {
25693
26065
  titleSource: "heading",
25694
26066
  description: "Multi-step event registration form",
25695
26067
  category: "interactive",
26068
+ contentSource: { kind: "inline" },
25696
26069
  tags: [
25697
26070
  "events",
25698
26071
  "registration",
@@ -25799,15 +26172,9 @@ const eventRegistrationBlockDefinition = {
25799
26172
  defaultValue: "Complete Registration",
25800
26173
  maxLength: 40
25801
26174
  },
25802
- {
25803
- id: "buttonVariant",
25804
- type: "select",
25805
- label: "Button style",
26175
+ createButtonVariantField({
25806
26176
  description: "Choose a button style from your theme",
25807
- required: false,
25808
- multiple: false,
25809
- defaultValue: "primary",
25810
- options: [
26177
+ variants: [
25811
26178
  {
25812
26179
  value: "primary",
25813
26180
  label: "Primary"
@@ -25820,9 +26187,8 @@ const eventRegistrationBlockDefinition = {
25820
26187
  value: "outline",
25821
26188
  label: "Outline"
25822
26189
  }
25823
- ],
25824
- ui: { intent: "style" }
25825
- }
26190
+ ]
26191
+ })
25826
26192
  ],
25827
26193
  layout: [styledSection({
25828
26194
  baseClass: "",
@@ -26015,6 +26381,7 @@ const courseRegistrationBlockDefinition = {
26015
26381
  titleSource: "heading",
26016
26382
  description: "Enrollment form for multi-session courses",
26017
26383
  category: "interactive",
26384
+ contentSource: { kind: "inline" },
26018
26385
  tags: [
26019
26386
  "courses",
26020
26387
  "enrollment",
@@ -26128,15 +26495,9 @@ const courseRegistrationBlockDefinition = {
26128
26495
  defaultValue: "Sign up",
26129
26496
  maxLength: 40
26130
26497
  },
26131
- {
26132
- id: "buttonVariant",
26133
- type: "select",
26134
- label: "Button style",
26498
+ createButtonVariantField({
26135
26499
  description: "Choose a button style from your theme",
26136
- required: false,
26137
- multiple: false,
26138
- defaultValue: "primary",
26139
- options: [
26500
+ variants: [
26140
26501
  {
26141
26502
  value: "primary",
26142
26503
  label: "Primary"
@@ -26149,9 +26510,8 @@ const courseRegistrationBlockDefinition = {
26149
26510
  value: "outline",
26150
26511
  label: "Outline"
26151
26512
  }
26152
- ],
26153
- ui: { intent: "style" }
26154
- }
26513
+ ]
26514
+ })
26155
26515
  ],
26156
26516
  layout: [styledSection({
26157
26517
  baseClass: "",
@@ -26231,6 +26591,7 @@ const eventDetailsManifest = createBlockManifest({
26231
26591
  titleSource: "heading",
26232
26592
  description: "Date/time, venue, map, and other dates for an event",
26233
26593
  category: "content",
26594
+ contentSource: { kind: "entries" },
26234
26595
  tags: [
26235
26596
  "events",
26236
26597
  "venue",
@@ -26436,6 +26797,7 @@ const courseDetailsBlockDefinition = {
26436
26797
  titleSource: "heading",
26437
26798
  description: "Schedule, venue, price, and enrollment status for a course",
26438
26799
  category: "content",
26800
+ contentSource: { kind: "entries" },
26439
26801
  tags: [
26440
26802
  "courses",
26441
26803
  "schedule",
@@ -26727,6 +27089,7 @@ const eventSpotlightBlockDefinition = {
26727
27089
  paletteHidden: false
26728
27090
  },
26729
27091
  category: "content",
27092
+ contentSource: { kind: "entries" },
26730
27093
  tags: [
26731
27094
  "events",
26732
27095
  "featured",
@@ -27273,6 +27636,7 @@ const eventListingBlockDefinition = {
27273
27636
  paletteHidden: true
27274
27637
  },
27275
27638
  category: "interactive",
27639
+ contentSource: { kind: "entries" },
27276
27640
  tags: [
27277
27641
  "events",
27278
27642
  "listing",
@@ -28445,6 +28809,7 @@ const eventCalendarBlockDefinition = {
28445
28809
  paletteHidden: false
28446
28810
  },
28447
28811
  category: "interactive",
28812
+ contentSource: { kind: "entries" },
28448
28813
  tags: [
28449
28814
  "events",
28450
28815
  "calendar",
@@ -28842,6 +29207,7 @@ const recurringScheduleBlockDefinition = {
28842
29207
  titleSource: "heading",
28843
29208
  description: "A compact weekly schedule with one row per recurring series.",
28844
29209
  category: "interactive",
29210
+ contentSource: { kind: "entries" },
28845
29211
  icon: "CalendarDays",
28846
29212
  tags: [
28847
29213
  "schedule",
@@ -29259,7 +29625,10 @@ const offeringsPreviewFields = [
29259
29625
  label: "Link"
29260
29626
  }
29261
29627
  ],
29262
- ui: { intent: "display" }
29628
+ ui: {
29629
+ intent: "display",
29630
+ widget: "buttonVariant"
29631
+ }
29263
29632
  },
29264
29633
  {
29265
29634
  id: "buttonText",
@@ -29312,6 +29681,7 @@ const offeringsPreviewManifest = createBlockManifest({
29312
29681
  paletteHidden: false
29313
29682
  },
29314
29683
  category: "content",
29684
+ contentSource: { kind: "mixed" },
29315
29685
  tags: [
29316
29686
  "offerings",
29317
29687
  "events",
@@ -29480,6 +29850,7 @@ const embedManifest = createBlockManifest({
29480
29850
  id: "block.embed",
29481
29851
  title: "Embed Content",
29482
29852
  category: "content",
29853
+ contentSource: { kind: "entries" },
29483
29854
  titleSource: "heading",
29484
29855
  additionalFields: [
29485
29856
  parseFieldDefinition({
@@ -29967,6 +30338,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
29967
30338
  id: "block.image-gallery",
29968
30339
  title: "Image Gallery",
29969
30340
  category: "content",
30341
+ contentSource: { kind: "inline" },
29970
30342
  previewCustomize: { quickFieldPriority: [
29971
30343
  "aspectRatio",
29972
30344
  "slidesToShow",
@@ -30619,6 +30991,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
30619
30991
  id: "block.video-grid",
30620
30992
  title: "Video Grid",
30621
30993
  category: "media",
30994
+ contentSource: { kind: "inline" },
30622
30995
  skipSectionStyles: true,
30623
30996
  additionalFields: parseFieldDefinitions([
30624
30997
  {
@@ -30789,6 +31162,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
30789
31162
  title: "Audio Player",
30790
31163
  titleSource: "title",
30791
31164
  category: "media",
31165
+ contentSource: { kind: "inline" },
30792
31166
  description: "Add a branded audio player for a single track.",
30793
31167
  tags: [
30794
31168
  "audio",
@@ -30900,6 +31274,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
30900
31274
  title: "File Download",
30901
31275
  titleSource: ["title", "file.filename"],
30902
31276
  category: "media",
31277
+ contentSource: { kind: "inline" },
30903
31278
  description: "Add a simple public download link for a document, ZIP, or audio file.",
30904
31279
  tags: [
30905
31280
  "file",
@@ -31844,6 +32219,7 @@ const shopBlockDefinition = {
31844
32219
  paletteHidden: false
31845
32220
  },
31846
32221
  category: "interactive",
32222
+ contentSource: { kind: "entries" },
31847
32223
  tags: [
31848
32224
  "shop",
31849
32225
  "passes",
@@ -32043,6 +32419,7 @@ const productListBlockDefinition = {
32043
32419
  paletteHidden: false
32044
32420
  },
32045
32421
  category: "interactive",
32422
+ contentSource: { kind: "entries" },
32046
32423
  tags: [
32047
32424
  "shop",
32048
32425
  "products",
@@ -32184,6 +32561,7 @@ const productDetailBlockDefinition = {
32184
32561
  paletteHidden: false
32185
32562
  },
32186
32563
  category: "interactive",
32564
+ contentSource: { kind: "entries" },
32187
32565
  tags: [
32188
32566
  "shop",
32189
32567
  "product",
@@ -32300,6 +32678,7 @@ const cartBlockDefinition = {
32300
32678
  paletteHidden: false
32301
32679
  },
32302
32680
  category: "interactive",
32681
+ contentSource: { kind: "inline" },
32303
32682
  tags: [
32304
32683
  "shop",
32305
32684
  "cart",
@@ -32382,6 +32761,7 @@ const checkoutBlockDefinition = {
32382
32761
  paletteHidden: false
32383
32762
  },
32384
32763
  category: "interactive",
32764
+ contentSource: { kind: "inline" },
32385
32765
  tags: [
32386
32766
  "shop",
32387
32767
  "checkout",
@@ -32585,6 +32965,7 @@ const giftingBlockDefinition = {
32585
32965
  paletteHidden: false
32586
32966
  },
32587
32967
  category: "interactive",
32968
+ contentSource: { kind: "entries" },
32588
32969
  tags: [
32589
32970
  "gifting",
32590
32971
  "gift cards",
@@ -32928,6 +33309,7 @@ const newsletterSignupBlockDefinition = {
32928
33309
  titleSource: "title",
32929
33310
  description: "Newsletter subscription form with configurable field presets.",
32930
33311
  category: "interactive",
33312
+ contentSource: { kind: "inline" },
32931
33313
  fragments: [{
32932
33314
  fragment: newsletterCopyFragment,
32933
33315
  fieldPriority: 0
@@ -33109,6 +33491,7 @@ const teamMembersBlockDefinition = {
33109
33491
  id: "block.team-members",
33110
33492
  title: "Team Members",
33111
33493
  category: "content",
33494
+ contentSource: { kind: "mixed" },
33112
33495
  titleSource: "heading",
33113
33496
  additionalFields: [
33114
33497
  parseFieldDefinition({
@@ -33529,6 +33912,7 @@ const locationMapBlockDefinition = {
33529
33912
  titleSource: "heading",
33530
33913
  description: "Show a business location with an interactive map and directions link.",
33531
33914
  category: "content",
33915
+ contentSource: { kind: "inline" },
33532
33916
  tags: [
33533
33917
  "map",
33534
33918
  "location",
@@ -34644,9 +35028,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
34644
35028
  ].filter(Boolean).join(" ");
34645
35029
  }
34646
35030
  function gradientPresetCss(value) {
34647
- if (!isString(value)) return null;
34648
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
34649
- if (!preset) return null;
35031
+ const presetId = parseGradientPresetId(value);
35032
+ if (!presetId) return null;
35033
+ const preset = getGradientPreset(presetId);
34650
35034
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
34651
35035
  }
34652
35036
  const backgroundTransforms = [
@@ -35768,6 +36152,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
35768
36152
  "already_refunded",
35769
36153
  "idempotency_amount_mismatch",
35770
36154
  "idempotency_method_mismatch",
36155
+ "idempotency_receipt_mismatch",
35771
36156
  "refund_in_progress"
35772
36157
  ],
35773
36158
  "invalid_amount",
@@ -35780,7 +36165,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
35780
36165
  "payment_intent_not_found",
35781
36166
  "stripe_error",
35782
36167
  "stale_pending_missing_context",
35783
- "non_refundable_deposit_remaining"
36168
+ "non_refundable_deposit_remaining",
36169
+ "deposit_refund_override_required",
36170
+ "refund_revoke_requires_full_line_refund",
36171
+ "payment_receipt_not_found",
36172
+ "payment_receipt_not_refundable",
36173
+ "payment_receipt_attribution_required"
35784
36174
  ];
35785
36175
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
35786
36176
  //#endregion
@@ -35793,7 +36183,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
35793
36183
  "missing_credit_customer",
35794
36184
  "deposit_refund_override_required",
35795
36185
  "refund_revoke_requires_full_line_refund",
35796
- "unified_order_link_required"
36186
+ "unified_order_link_required",
36187
+ "payment_receipt_not_found",
36188
+ "payment_receipt_not_refundable",
36189
+ "payment_receipt_attribution_required"
35797
36190
  ];
35798
36191
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
35799
36192
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];