@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
@@ -205,19 +205,29 @@ function isRecord$7(value) {
205
205
  //#region ../core/src/booking-date-time.ts
206
206
  const DEFAULT_LOCALE = "en-US";
207
207
  const FALLBACK_TIMEZONE = "UTC";
208
+ const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
209
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
210
+ const timeZoneValidityCache = /* @__PURE__ */ new Map();
208
211
  function isValidTimeZone(timeZone) {
212
+ const cached = timeZoneValidityCache.get(timeZone);
213
+ if (cached !== void 0) return cached;
214
+ let isValid;
209
215
  try {
210
216
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
211
- return true;
217
+ isValid = true;
212
218
  } catch {
213
- return false;
219
+ isValid = false;
214
220
  }
221
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
222
+ timeZoneValidityCache.set(timeZone, isValid);
223
+ return isValid;
215
224
  }
216
225
  function getSafeTimeZone(timeZone) {
217
226
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
218
227
  return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
219
228
  }
220
229
  function parseStrictBookingTimeZone(timeZone) {
230
+ if (typeof timeZone !== "string") return null;
221
231
  const normalized = timeZone.trim();
222
232
  if (normalized.length === 0 || !isValidTimeZone(normalized)) return null;
223
233
  return normalized;
@@ -230,10 +240,19 @@ function formatParseError(error) {
230
240
  }
231
241
  }
232
242
  function formatToPartsLookup(date, locale, timeZone, format) {
233
- return new Map(new Intl.DateTimeFormat(locale, {
243
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
244
+ }
245
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
246
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
247
+ const cached = dateTimeFormatterCache.get(key);
248
+ if (cached !== void 0) return cached;
249
+ const formatter = new Intl.DateTimeFormat(locale, {
234
250
  ...format,
235
251
  timeZone
236
- }).formatToParts(date).map((part) => [part.type, part.value]));
252
+ });
253
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
254
+ dateTimeFormatterCache.set(key, formatter);
255
+ return formatter;
237
256
  }
238
257
  function getZonedDateTimeParts(date, timeZone) {
239
258
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -276,23 +295,9 @@ function toUtcIsoDateTimeString(value) {
276
295
  return parsed.value;
277
296
  }
278
297
  function parseScheduledBookingDateTime(input) {
298
+ let startsAt;
279
299
  try {
280
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
281
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
282
- if (timeZone === null) return {
283
- ok: false,
284
- field: "timeZone",
285
- reason: "invalid_time_zone",
286
- value: input.timeZone
287
- };
288
- return {
289
- ok: true,
290
- value: {
291
- startsAt,
292
- timeZone,
293
- locale: input.locale
294
- }
295
- };
300
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
296
301
  } catch {
297
302
  return {
298
303
  ok: false,
@@ -301,6 +306,21 @@ function parseScheduledBookingDateTime(input) {
301
306
  value: input.startsAt
302
307
  };
303
308
  }
309
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
310
+ if (timeZone === null) return {
311
+ ok: false,
312
+ field: "timeZone",
313
+ reason: "invalid_time_zone",
314
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
315
+ };
316
+ return {
317
+ ok: true,
318
+ value: {
319
+ startsAt,
320
+ timeZone,
321
+ locale: input.locale
322
+ }
323
+ };
304
324
  }
305
325
  function toScheduledBookingDateTime(input) {
306
326
  const result = parseScheduledBookingDateTime(input);
@@ -3430,6 +3450,111 @@ const mediaSchema$1 = z.object({
3430
3450
  transform: transformSchema$1.optional()
3431
3451
  });
3432
3452
  //#endregion
3453
+ //#region ../theme-core/src/buttons/effectClassification.ts
3454
+ /**
3455
+ * Exhaustive live policy for every registered effect id.
3456
+ *
3457
+ * The resolver consumes the transition payload directly, so adding an effect
3458
+ * cannot update classification without also defining its runtime behavior.
3459
+ */
3460
+ const BUTTON_EFFECT_POLICIES = {
3461
+ "darken-background": {
3462
+ classification: "colour-transition",
3463
+ transition: {
3464
+ kind: "adjust-shade",
3465
+ direction: "darker"
3466
+ }
3467
+ },
3468
+ "lighten-background": {
3469
+ classification: "colour-transition",
3470
+ transition: {
3471
+ kind: "adjust-shade",
3472
+ direction: "lighter"
3473
+ }
3474
+ },
3475
+ "background-on-hover": {
3476
+ classification: "colour-transition",
3477
+ transition: { kind: "replace-background" }
3478
+ },
3479
+ "background-on-hover-alpha": {
3480
+ classification: "unsupported-colour",
3481
+ reason: "alpha_requires_surface"
3482
+ },
3483
+ "fade-background": {
3484
+ classification: "unsupported-colour",
3485
+ reason: "changes_element_opacity"
3486
+ },
3487
+ "opacity-reduce": {
3488
+ classification: "unsupported-colour",
3489
+ reason: "changes_element_opacity"
3490
+ },
3491
+ "gradient-text": {
3492
+ classification: "unsupported-colour",
3493
+ reason: "changes_foreground"
3494
+ },
3495
+ "text-color-change": {
3496
+ classification: "unsupported-colour",
3497
+ reason: "changes_foreground"
3498
+ },
3499
+ "border-color-change": {
3500
+ classification: "unsupported-colour",
3501
+ reason: "changes_border"
3502
+ },
3503
+ "aurora-glow": {
3504
+ classification: "unsupported-background-overlay",
3505
+ reason: "unresolved_background_overlay"
3506
+ },
3507
+ "cosmic-stardust": {
3508
+ classification: "unsupported-background-overlay",
3509
+ reason: "unresolved_background_overlay"
3510
+ },
3511
+ "gradient-border-fill": {
3512
+ classification: "unsupported-background-overlay",
3513
+ reason: "unresolved_background_overlay"
3514
+ },
3515
+ "animated-gradient-border-fill": {
3516
+ classification: "unsupported-background-overlay",
3517
+ reason: "unresolved_background_overlay"
3518
+ },
3519
+ "nav-underline": {
3520
+ classification: "not-button",
3521
+ reason: "not_button_effect"
3522
+ },
3523
+ "nav-frosted-base": {
3524
+ classification: "not-button",
3525
+ reason: "not_button_effect"
3526
+ },
3527
+ "nav-frosted-hover": {
3528
+ classification: "not-button",
3529
+ reason: "not_button_effect"
3530
+ },
3531
+ "nav-frosted-active": {
3532
+ classification: "not-button",
3533
+ reason: "not_button_effect"
3534
+ },
3535
+ "animated-gradient": { classification: "non-colour" },
3536
+ "border-glow": { classification: "non-colour" },
3537
+ "drop-shadow": { classification: "non-colour" },
3538
+ "inner-shadow": { classification: "non-colour" },
3539
+ "neumorphic-shadow": { classification: "non-colour" },
3540
+ "outer-glow": { classification: "non-colour" },
3541
+ "retro-3d-shadow": { classification: "non-colour" },
3542
+ "scale-up": { classification: "non-colour" },
3543
+ "scale-down": { classification: "non-colour" },
3544
+ lift: { classification: "non-colour" },
3545
+ "press-down": { classification: "non-colour" },
3546
+ pop: { classification: "non-colour" },
3547
+ "border-bottom-grow": { classification: "non-colour" },
3548
+ "sketchy-border": { classification: "non-colour" },
3549
+ "pulse-animation": { classification: "non-colour" }
3550
+ };
3551
+ function getButtonEffectPolicy(effectId) {
3552
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
3553
+ }
3554
+ function classifyButtonEffectId(effectId) {
3555
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
3556
+ }
3557
+ //#endregion
3433
3558
  //#region ../theme-core/src/buttons/types.ts
3434
3559
  /**
3435
3560
  * Standard semantic variant roles a theme exposes.
@@ -3446,6 +3571,20 @@ const VARIANT_ROLES = [
3446
3571
  "tertiary",
3447
3572
  "accent"
3448
3573
  ];
3574
+ function parseOpaqueButtonColourToken(value) {
3575
+ const token = parseThemeColorToken(value);
3576
+ if (token === null) return null;
3577
+ const parts = parseColorTokenParts(token);
3578
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
3579
+ }
3580
+ function unsafeAsOpaqueButtonColourToken(value) {
3581
+ return value;
3582
+ }
3583
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
3584
+ const token = parseOpaqueButtonColourToken(value);
3585
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
3586
+ return token;
3587
+ });
3449
3588
  const cornerStyleSchema = z$1.enum([
3450
3589
  "square",
3451
3590
  "rounded",
@@ -3547,7 +3686,7 @@ const buttonSizesSchema = z$1.object({
3547
3686
  lg,
3548
3687
  xl: xl ?? lg
3549
3688
  }));
3550
- const buttonGlobalSettingsSchema = z$1.object({
3689
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
3551
3690
  cornerStyle: cornerStyleSchema,
3552
3691
  cornerRadius: z$1.number().min(0).max(24).optional(),
3553
3692
  /**
@@ -3578,11 +3717,12 @@ const buttonGlobalSettingsSchema = z$1.object({
3578
3717
  paddingPreset: buttonPaddingPresetSchema.optional(),
3579
3718
  hoverTransform: hoverTransformSchema,
3580
3719
  hoverColor: hoverColorSchema,
3581
- hoverColorToken: themeColorTokenSchema.optional(),
3720
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
3582
3721
  gradientStyle: gradientStyleSchema.optional(),
3583
3722
  gradientAngle: z$1.number().min(0).max(360).optional(),
3584
3723
  gradientSharpness: gradientSharpnessSchema.optional()
3585
3724
  });
3725
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
3586
3726
  const gradientDirectionSchema$1 = z$1.enum([
3587
3727
  "to-r",
3588
3728
  "to-l",
@@ -3596,27 +3736,33 @@ const gradientDirectionSchema$1 = z$1.enum([
3596
3736
  const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
3597
3737
  z$1.object({
3598
3738
  type: z$1.literal("solid"),
3599
- colorToken: themeColorTokenSchema
3739
+ colorToken: opaqueButtonColourTokenSchema
3600
3740
  }),
3601
3741
  z$1.object({
3602
3742
  type: z$1.literal("gradient"),
3603
- stops: z$1.array(themeColorTokenSchema).min(2),
3604
- direction: gradientDirectionSchema$1
3743
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
3744
+ const [first, second, ...rest] = stops;
3745
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
3746
+ return [
3747
+ first,
3748
+ second,
3749
+ ...rest
3750
+ ];
3751
+ }),
3752
+ direction: gradientDirectionSchema$1,
3753
+ foregroundToken: opaqueButtonColourTokenSchema
3605
3754
  }),
3606
- z$1.object({ type: z$1.literal("transparent") })
3755
+ z$1.object({
3756
+ type: z$1.literal("surface"),
3757
+ role: z$1.literal("link")
3758
+ })
3607
3759
  ]);
3608
3760
  const effectApplicationSchema$1 = z$1.object({
3609
3761
  effectId: z$1.string(),
3610
- options: z$1.record(z$1.string(), z$1.any()).optional()
3611
- });
3612
- const buttonBorderSchema = z$1.object({
3613
- widthClass: z$1.string(),
3614
- colorToken: themeColorTokenSchema
3615
- });
3616
- const buttonVariantAffordanceSchema = z$1.object({
3617
- iconId: z$1.string().min(1),
3618
- colorToken: themeColorTokenSchema.optional()
3762
+ options: z$1.record(z$1.string(), z$1.json()).optional()
3619
3763
  });
3764
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
3765
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
3620
3766
  const variantShadowSchema = z$1.object({
3621
3767
  elevation: z$1.enum([
3622
3768
  "none",
@@ -3657,27 +3803,170 @@ const variantSizeOverridesSchema = z$1.object({
3657
3803
  * default (e.g. link-style variants declaring zero horizontal padding at
3658
3804
  * every size).
3659
3805
  */
3660
- const buttonVariantSchema = z$1.object({
3806
+ const canonicalButtonVariantSchema = z$1.object({
3661
3807
  id: z$1.string(),
3662
3808
  name: z$1.string().min(1).max(20),
3663
3809
  enabled: z$1.boolean(),
3664
3810
  priority: prioritySchema,
3665
3811
  background: buttonBackgroundSchema,
3666
- textColorToken: themeColorTokenSchema,
3667
3812
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
3668
3813
  borderRadius: z$1.string().optional(),
3669
3814
  shadow: variantShadowSchema.optional(),
3670
3815
  border: buttonBorderSchema.optional(),
3671
- hoverBackgroundToken: z$1.string().optional(),
3816
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
3672
3817
  effects: variantEffectsSchema.optional(),
3673
3818
  sizes: variantSizeOverridesSchema.optional(),
3674
3819
  affordance: buttonVariantAffordanceSchema.optional()
3675
3820
  });
3821
+ /**
3822
+ * Temporary persisted-theme admission boundary for issue #1206.
3823
+ *
3824
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
3825
+ * `textColorToken`/border colour shape. New source and all downstream code use
3826
+ * only the canonical relationship. Delete this preprocessor after the reviewed
3827
+ * production rewrite reports zero legacy rows.
3828
+ */
3829
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
3676
3830
  const buttonSystemSchema = z$1.object({
3677
3831
  global: buttonGlobalSettingsSchema,
3678
3832
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
3679
3833
  sizes: buttonSizesSchema.optional()
3680
3834
  });
3835
+ function normalizeLegacyButtonVariantInput(input) {
3836
+ if (!isUnknownRecord(input)) return input;
3837
+ const background = input.background;
3838
+ if (!isUnknownRecord(background)) return input;
3839
+ 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;
3840
+ const { textColorToken, ...withoutLegacyText } = input;
3841
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
3842
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
3843
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
3844
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
3845
+ if (background.type === "transparent") return {
3846
+ ...withoutLegacyText,
3847
+ background: {
3848
+ type: "surface",
3849
+ role: "link"
3850
+ },
3851
+ border: normalizedBorder,
3852
+ affordance: normalizedAffordance,
3853
+ effects: normalizedEffects,
3854
+ hoverBackgroundToken
3855
+ };
3856
+ if (background.type === "gradient") {
3857
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
3858
+ return {
3859
+ ...withoutLegacyText,
3860
+ background: {
3861
+ ...background,
3862
+ stops,
3863
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
3864
+ },
3865
+ border: normalizedBorder,
3866
+ affordance: normalizedAffordance,
3867
+ effects: normalizedEffects,
3868
+ hoverBackgroundToken
3869
+ };
3870
+ }
3871
+ return {
3872
+ ...withoutLegacyText,
3873
+ background: background.type === "solid" ? {
3874
+ ...background,
3875
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
3876
+ } : background,
3877
+ border: normalizedBorder,
3878
+ affordance: normalizedAffordance,
3879
+ effects: normalizedEffects,
3880
+ hoverBackgroundToken
3881
+ };
3882
+ }
3883
+ function normalizeLegacyButtonGlobalInput(input) {
3884
+ if (!isUnknownRecord(input)) return input;
3885
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
3886
+ return hoverColorToken === input.hoverColorToken ? input : {
3887
+ ...input,
3888
+ hoverColorToken
3889
+ };
3890
+ }
3891
+ function hasLegacyAlphaToken(input, background) {
3892
+ const stops = isUnknownArray(background.stops) ? background.stops : [];
3893
+ return [
3894
+ input.hoverBackgroundToken,
3895
+ background.colorToken,
3896
+ background.foregroundToken,
3897
+ ...stops
3898
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
3899
+ }
3900
+ function stripLegacyTokenAlpha(value) {
3901
+ if (typeof value !== "string") return value;
3902
+ const slashIndex = value.indexOf("/");
3903
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
3904
+ }
3905
+ function hasLegacyButtonEffects(input) {
3906
+ if (!isUnknownRecord(input)) return false;
3907
+ return [
3908
+ "base",
3909
+ "hover",
3910
+ "active",
3911
+ "focus"
3912
+ ].some((state) => {
3913
+ const effects = input[state];
3914
+ return Array.isArray(effects) && effects.some((effect) => {
3915
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
3916
+ const classification = classifyButtonEffectId(effect.effectId);
3917
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
3918
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
3919
+ });
3920
+ });
3921
+ }
3922
+ function normalizeLegacyButtonEffects(input, backgroundType) {
3923
+ if (!isUnknownRecord(input)) return input;
3924
+ const normalized = {};
3925
+ for (const state of [
3926
+ "base",
3927
+ "hover",
3928
+ "active",
3929
+ "focus"
3930
+ ]) {
3931
+ const effects = input[state];
3932
+ if (!Array.isArray(effects)) continue;
3933
+ const safeEffects = effects.flatMap((effect) => {
3934
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
3935
+ const classification = classifyButtonEffectId(effect.effectId);
3936
+ if (classification === "non-colour") return [effect];
3937
+ if (classification !== "colour-transition") return [];
3938
+ if (effect.effectId === "background-on-hover") {
3939
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
3940
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
3941
+ return colorToken === null ? [] : [{
3942
+ ...effect,
3943
+ options: {
3944
+ ...options,
3945
+ colorToken
3946
+ }
3947
+ }];
3948
+ }
3949
+ if (backgroundType !== "solid") return [];
3950
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
3951
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
3952
+ return [{
3953
+ ...effect,
3954
+ options: {
3955
+ ...isUnknownRecord(effect.options) ? effect.options : {},
3956
+ amount
3957
+ }
3958
+ }];
3959
+ });
3960
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
3961
+ }
3962
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
3963
+ }
3964
+ function isUnknownRecord(value) {
3965
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3966
+ }
3967
+ function isUnknownArray(value) {
3968
+ return Array.isArray(value);
3969
+ }
3681
3970
  buttonSizeNameSchema.options;
3682
3971
  //#endregion
3683
3972
  //#region ../theme-core/src/buttons/personalities/types.ts
@@ -3704,7 +3993,7 @@ function defineButtonPersonality(input) {
3704
3993
  name: input.name,
3705
3994
  description: input.description,
3706
3995
  tags: input.tags,
3707
- buttonSystem: input.buttonSystem
3996
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
3708
3997
  };
3709
3998
  }
3710
3999
  //#endregion
@@ -3757,19 +4046,15 @@ const brushedWash = defineButtonPersonality({
3757
4046
  background: {
3758
4047
  type: "gradient",
3759
4048
  stops: ["primary", "accent"],
3760
- direction: "to-r"
4049
+ direction: "to-r",
4050
+ foregroundToken: "primaryForeground"
3761
4051
  },
3762
- textColorToken: "primaryForeground",
3763
4052
  borderRadius: "rounded-lg",
3764
4053
  shadow: {
3765
4054
  elevation: "low",
3766
4055
  softness: "soft",
3767
4056
  position: "bottom"
3768
- },
3769
- effects: { hover: [{
3770
- effectId: "opacity-reduce",
3771
- options: { reduction: -15 }
3772
- }] }
4057
+ }
3773
4058
  },
3774
4059
  {
3775
4060
  id: "secondary",
@@ -3779,32 +4064,27 @@ const brushedWash = defineButtonPersonality({
3779
4064
  background: {
3780
4065
  type: "gradient",
3781
4066
  stops: ["secondary", "accent"],
3782
- direction: "to-br"
4067
+ direction: "to-br",
4068
+ foregroundToken: "primaryForeground"
3783
4069
  },
3784
- textColorToken: "primaryForeground",
3785
4070
  borderRadius: "rounded-lg",
3786
4071
  shadow: {
3787
4072
  elevation: "low",
3788
4073
  softness: "soft",
3789
4074
  position: "bottom"
3790
- },
3791
- effects: { hover: [{
3792
- effectId: "opacity-reduce",
3793
- options: { reduction: -15 }
3794
- }] }
4075
+ }
3795
4076
  },
3796
4077
  {
3797
4078
  id: "outline",
3798
4079
  name: "Outline",
3799
4080
  enabled: true,
3800
4081
  priority: 3,
3801
- background: { type: "transparent" },
3802
- textColorToken: "primary",
3803
- borderRadius: "rounded-lg",
3804
- border: {
3805
- widthClass: "border",
3806
- colorToken: "primary"
4082
+ background: {
4083
+ type: "surface",
4084
+ role: "link"
3807
4085
  },
4086
+ borderRadius: "rounded-lg",
4087
+ border: { widthClass: "border" },
3808
4088
  effects: { hover: [{
3809
4089
  effectId: "background-on-hover",
3810
4090
  options: { colorToken: "surface" }
@@ -3815,8 +4095,10 @@ const brushedWash = defineButtonPersonality({
3815
4095
  name: "Ghost",
3816
4096
  enabled: true,
3817
4097
  priority: 3,
3818
- background: { type: "transparent" },
3819
- textColorToken: "text",
4098
+ background: {
4099
+ type: "surface",
4100
+ role: "link"
4101
+ },
3820
4102
  borderRadius: "rounded-lg",
3821
4103
  effects: { hover: [{
3822
4104
  effectId: "background-on-hover",
@@ -3862,7 +4144,6 @@ const confidentChip = defineButtonPersonality({
3862
4144
  type: "solid",
3863
4145
  colorToken: "primary"
3864
4146
  },
3865
- textColorToken: "primaryForeground",
3866
4147
  borderRadius: "rounded-md",
3867
4148
  shadow: {
3868
4149
  elevation: "medium",
@@ -3872,7 +4153,7 @@ const confidentChip = defineButtonPersonality({
3872
4153
  effects: {
3873
4154
  hover: [{
3874
4155
  effectId: "darken-background",
3875
- options: { amount: 60 }
4156
+ options: { amount: 100 }
3876
4157
  }],
3877
4158
  active: [{
3878
4159
  effectId: "scale-down",
@@ -3889,12 +4170,8 @@ const confidentChip = defineButtonPersonality({
3889
4170
  type: "solid",
3890
4171
  colorToken: "surface"
3891
4172
  },
3892
- textColorToken: "text",
3893
4173
  borderRadius: "rounded-md",
3894
- border: {
3895
- widthClass: "border",
3896
- colorToken: "border"
3897
- },
4174
+ border: { widthClass: "border" },
3898
4175
  effects: { hover: [{
3899
4176
  effectId: "background-on-hover",
3900
4177
  options: { colorToken: "background" }
@@ -3905,13 +4182,12 @@ const confidentChip = defineButtonPersonality({
3905
4182
  name: "Outline",
3906
4183
  enabled: true,
3907
4184
  priority: 3,
3908
- background: { type: "transparent" },
3909
- textColorToken: "primary",
3910
- borderRadius: "rounded-md",
3911
- border: {
3912
- widthClass: "border",
3913
- colorToken: "primary"
4185
+ background: {
4186
+ type: "surface",
4187
+ role: "link"
3914
4188
  },
4189
+ borderRadius: "rounded-md",
4190
+ border: { widthClass: "border" },
3915
4191
  effects: { hover: [{
3916
4192
  effectId: "background-on-hover",
3917
4193
  options: { colorToken: "surface" }
@@ -3922,8 +4198,10 @@ const confidentChip = defineButtonPersonality({
3922
4198
  name: "Ghost",
3923
4199
  enabled: true,
3924
4200
  priority: 3,
3925
- background: { type: "transparent" },
3926
- textColorToken: "primary",
4201
+ background: {
4202
+ type: "surface",
4203
+ role: "link"
4204
+ },
3927
4205
  borderRadius: "rounded-md",
3928
4206
  effects: { hover: [{
3929
4207
  effectId: "background-on-hover",
@@ -3986,7 +4264,6 @@ const earthPill = defineButtonPersonality({
3986
4264
  type: "solid",
3987
4265
  colorToken: "primary"
3988
4266
  },
3989
- textColorToken: "primaryForeground",
3990
4267
  borderRadius: "rounded-full",
3991
4268
  shadow: {
3992
4269
  elevation: "low",
@@ -4012,13 +4289,12 @@ const earthPill = defineButtonPersonality({
4012
4289
  name: "Secondary",
4013
4290
  enabled: true,
4014
4291
  priority: 2,
4015
- background: { type: "transparent" },
4016
- textColorToken: "primary",
4017
- borderRadius: "rounded-full",
4018
- border: {
4019
- widthClass: "border",
4020
- colorToken: "primary"
4292
+ background: {
4293
+ type: "surface",
4294
+ role: "link"
4021
4295
  },
4296
+ borderRadius: "rounded-full",
4297
+ border: { widthClass: "border" },
4022
4298
  effects: { hover: [{
4023
4299
  effectId: "background-on-hover",
4024
4300
  options: { colorToken: "muted" }
@@ -4029,13 +4305,12 @@ const earthPill = defineButtonPersonality({
4029
4305
  name: "Outline",
4030
4306
  enabled: true,
4031
4307
  priority: 3,
4032
- background: { type: "transparent" },
4033
- textColorToken: "text",
4034
- borderRadius: "rounded-full",
4035
- border: {
4036
- widthClass: "border",
4037
- colorToken: "border"
4308
+ background: {
4309
+ type: "surface",
4310
+ role: "link"
4038
4311
  },
4312
+ borderRadius: "rounded-full",
4313
+ border: { widthClass: "border" },
4039
4314
  effects: { hover: [{
4040
4315
  effectId: "background-on-hover",
4041
4316
  options: { colorToken: "surfaceAlt" }
@@ -4046,8 +4321,10 @@ const earthPill = defineButtonPersonality({
4046
4321
  name: "Ghost",
4047
4322
  enabled: true,
4048
4323
  priority: 3,
4049
- background: { type: "transparent" },
4050
- textColorToken: "primary",
4324
+ background: {
4325
+ type: "surface",
4326
+ role: "link"
4327
+ },
4051
4328
  borderRadius: "rounded-full",
4052
4329
  shadow: {
4053
4330
  elevation: "none",
@@ -4068,11 +4345,7 @@ const earthPill = defineButtonPersonality({
4068
4345
  padding: "0.625rem 0",
4069
4346
  fontSize: "text-xl"
4070
4347
  }
4071
- },
4072
- effects: { hover: [{
4073
- effectId: "opacity-reduce",
4074
- options: { reduction: 25 }
4075
- }] }
4348
+ }
4076
4349
  }
4077
4350
  ]
4078
4351
  }
@@ -4108,8 +4381,10 @@ const editorialLink = defineButtonPersonality({
4108
4381
  name: "Primary",
4109
4382
  enabled: true,
4110
4383
  priority: 1,
4111
- background: { type: "transparent" },
4112
- textColorToken: "text",
4384
+ background: {
4385
+ type: "surface",
4386
+ role: "link"
4387
+ },
4113
4388
  borderRadius: "rounded-none",
4114
4389
  sizes: {
4115
4390
  sm: { padding: "0.25rem 0" },
@@ -4131,8 +4406,10 @@ const editorialLink = defineButtonPersonality({
4131
4406
  name: "Secondary",
4132
4407
  enabled: true,
4133
4408
  priority: 2,
4134
- background: { type: "transparent" },
4135
- textColorToken: "mutedText",
4409
+ background: {
4410
+ type: "surface",
4411
+ role: "link"
4412
+ },
4136
4413
  borderRadius: "rounded-none",
4137
4414
  sizes: {
4138
4415
  sm: { padding: "0.25rem 0" },
@@ -4154,8 +4431,10 @@ const editorialLink = defineButtonPersonality({
4154
4431
  name: "Outline",
4155
4432
  enabled: true,
4156
4433
  priority: 3,
4157
- background: { type: "transparent" },
4158
- textColorToken: "accent",
4434
+ background: {
4435
+ type: "surface",
4436
+ role: "link"
4437
+ },
4159
4438
  borderRadius: "rounded-none",
4160
4439
  sizes: {
4161
4440
  sm: { padding: "0.25rem 0" },
@@ -4177,19 +4456,17 @@ const editorialLink = defineButtonPersonality({
4177
4456
  name: "Ghost",
4178
4457
  enabled: true,
4179
4458
  priority: 3,
4180
- background: { type: "transparent" },
4181
- textColorToken: "mutedText",
4459
+ background: {
4460
+ type: "surface",
4461
+ role: "link"
4462
+ },
4182
4463
  borderRadius: "rounded-none",
4183
4464
  sizes: {
4184
4465
  sm: { padding: "0.25rem 0" },
4185
4466
  md: { padding: "0.5rem 0" },
4186
4467
  lg: { padding: "0.625rem 0" },
4187
4468
  xl: { padding: "0.75rem 0" }
4188
- },
4189
- effects: { hover: [{
4190
- effectId: "opacity-reduce",
4191
- options: { reduction: -20 }
4192
- }] }
4469
+ }
4193
4470
  }
4194
4471
  ]
4195
4472
  }
@@ -4251,12 +4528,8 @@ const flatInk = defineButtonPersonality({
4251
4528
  type: "solid",
4252
4529
  colorToken: "primary"
4253
4530
  },
4254
- textColorToken: "primaryForeground",
4255
4531
  borderRadius: "rounded-lg",
4256
- affordance: {
4257
- iconId: "ArrowRight",
4258
- colorToken: "accent"
4259
- },
4532
+ affordance: { iconId: "ArrowRight" },
4260
4533
  effects: { hover: [{
4261
4534
  effectId: "lift",
4262
4535
  options: { translateY: "-2px" }
@@ -4270,13 +4543,12 @@ const flatInk = defineButtonPersonality({
4270
4543
  name: "Secondary",
4271
4544
  enabled: true,
4272
4545
  priority: 2,
4273
- background: { type: "transparent" },
4274
- textColorToken: "primary",
4275
- borderRadius: "rounded-lg",
4276
- border: {
4277
- widthClass: "border",
4278
- colorToken: "border"
4546
+ background: {
4547
+ type: "surface",
4548
+ role: "link"
4279
4549
  },
4550
+ borderRadius: "rounded-lg",
4551
+ border: { widthClass: "border" },
4280
4552
  effects: { hover: [{
4281
4553
  effectId: "lift",
4282
4554
  options: { translateY: "-2px" }
@@ -4294,12 +4566,8 @@ const flatInk = defineButtonPersonality({
4294
4566
  type: "solid",
4295
4567
  colorToken: "accent"
4296
4568
  },
4297
- textColorToken: "accentForeground",
4298
4569
  borderRadius: "rounded-lg",
4299
- affordance: {
4300
- iconId: "ArrowRight",
4301
- colorToken: "accentForeground"
4302
- },
4570
+ affordance: { iconId: "ArrowRight" },
4303
4571
  effects: { hover: [{
4304
4572
  effectId: "lift",
4305
4573
  options: { translateY: "-2px" }
@@ -4362,7 +4630,6 @@ const inkStamp = defineButtonPersonality({
4362
4630
  type: "solid",
4363
4631
  colorToken: "primary"
4364
4632
  },
4365
- textColorToken: "primaryForeground",
4366
4633
  borderRadius: "rounded-md",
4367
4634
  effects: {
4368
4635
  hover: [{
@@ -4383,13 +4650,12 @@ const inkStamp = defineButtonPersonality({
4383
4650
  name: "Secondary",
4384
4651
  enabled: true,
4385
4652
  priority: 2,
4386
- background: { type: "transparent" },
4387
- textColorToken: "primary",
4388
- borderRadius: "rounded-md",
4389
- border: {
4390
- widthClass: "border-2",
4391
- colorToken: "primary"
4653
+ background: {
4654
+ type: "surface",
4655
+ role: "link"
4392
4656
  },
4657
+ borderRadius: "rounded-md",
4658
+ border: { widthClass: "border-2" },
4393
4659
  effects: { hover: [{
4394
4660
  effectId: "background-on-hover",
4395
4661
  options: { colorToken: "surface" }
@@ -4400,13 +4666,12 @@ const inkStamp = defineButtonPersonality({
4400
4666
  name: "Outline",
4401
4667
  enabled: true,
4402
4668
  priority: 3,
4403
- background: { type: "transparent" },
4404
- textColorToken: "text",
4405
- borderRadius: "rounded-md",
4406
- border: {
4407
- widthClass: "border-2",
4408
- colorToken: "border"
4669
+ background: {
4670
+ type: "surface",
4671
+ role: "link"
4409
4672
  },
4673
+ borderRadius: "rounded-md",
4674
+ border: { widthClass: "border-2" },
4410
4675
  effects: { hover: [{
4411
4676
  effectId: "background-on-hover",
4412
4677
  options: { colorToken: "surface" }
@@ -4417,8 +4682,10 @@ const inkStamp = defineButtonPersonality({
4417
4682
  name: "Ghost",
4418
4683
  enabled: true,
4419
4684
  priority: 3,
4420
- background: { type: "transparent" },
4421
- textColorToken: "accent",
4685
+ background: {
4686
+ type: "surface",
4687
+ role: "link"
4688
+ },
4422
4689
  borderRadius: "rounded-none",
4423
4690
  sizes: {
4424
4691
  sm: {
@@ -4511,7 +4778,6 @@ const joyStamp = defineButtonPersonality({
4511
4778
  type: "solid",
4512
4779
  colorToken: "primary"
4513
4780
  },
4514
- textColorToken: "primaryForeground",
4515
4781
  borderRadius: "rounded-full",
4516
4782
  shadow: {
4517
4783
  elevation: "high",
@@ -4525,13 +4791,12 @@ const joyStamp = defineButtonPersonality({
4525
4791
  name: "Secondary",
4526
4792
  enabled: true,
4527
4793
  priority: 2,
4528
- background: { type: "transparent" },
4529
- textColorToken: "text",
4530
- borderRadius: "rounded-full",
4531
- border: {
4532
- widthClass: "border-2",
4533
- colorToken: "text"
4794
+ background: {
4795
+ type: "surface",
4796
+ role: "link"
4534
4797
  },
4798
+ borderRadius: "rounded-full",
4799
+ border: { widthClass: "border-2" },
4535
4800
  shadow: {
4536
4801
  elevation: "high",
4537
4802
  softness: "hard",
@@ -4596,12 +4861,8 @@ const ornateRitual = defineButtonPersonality({
4596
4861
  type: "solid",
4597
4862
  colorToken: "primary"
4598
4863
  },
4599
- textColorToken: "primaryForeground",
4600
4864
  borderRadius: "rounded-md",
4601
- border: {
4602
- widthClass: "border",
4603
- colorToken: "primary"
4604
- },
4865
+ border: { widthClass: "border" },
4605
4866
  effects: {
4606
4867
  hover: [{
4607
4868
  effectId: "background-on-hover",
@@ -4622,12 +4883,8 @@ const ornateRitual = defineButtonPersonality({
4622
4883
  type: "solid",
4623
4884
  colorToken: "secondary"
4624
4885
  },
4625
- textColorToken: "primaryForeground",
4626
4886
  borderRadius: "rounded-md",
4627
- border: {
4628
- widthClass: "border",
4629
- colorToken: "primary"
4630
- },
4887
+ border: { widthClass: "border" },
4631
4888
  effects: { hover: [{
4632
4889
  effectId: "background-on-hover",
4633
4890
  options: { colorToken: "surface" }
@@ -4638,13 +4895,12 @@ const ornateRitual = defineButtonPersonality({
4638
4895
  name: "Outline",
4639
4896
  enabled: true,
4640
4897
  priority: 3,
4641
- background: { type: "transparent" },
4642
- textColorToken: "primary",
4643
- borderRadius: "rounded-md",
4644
- border: {
4645
- widthClass: "border",
4646
- colorToken: "primary"
4898
+ background: {
4899
+ type: "surface",
4900
+ role: "link"
4647
4901
  },
4902
+ borderRadius: "rounded-md",
4903
+ border: { widthClass: "border" },
4648
4904
  effects: { hover: [{
4649
4905
  effectId: "background-on-hover",
4650
4906
  options: { colorToken: "muted" }
@@ -4655,8 +4911,10 @@ const ornateRitual = defineButtonPersonality({
4655
4911
  name: "Ghost",
4656
4912
  enabled: true,
4657
4913
  priority: 3,
4658
- background: { type: "transparent" },
4659
- textColorToken: "accent",
4914
+ background: {
4915
+ type: "surface",
4916
+ role: "link"
4917
+ },
4660
4918
  borderRadius: "rounded-none",
4661
4919
  sizes: {
4662
4920
  sm: {
@@ -4738,14 +4996,10 @@ const pebble = defineButtonPersonality({
4738
4996
  type: "solid",
4739
4997
  colorToken: "primary"
4740
4998
  },
4741
- textColorToken: "primaryForeground",
4742
4999
  borderRadius: "rounded-full",
4743
5000
  effects: { hover: [{
4744
- effectId: "background-on-hover-alpha",
4745
- options: {
4746
- colorToken: "primary",
4747
- opacity: 88
4748
- }
5001
+ effectId: "darken-background",
5002
+ options: { amount: 100 }
4749
5003
  }] }
4750
5004
  },
4751
5005
  {
@@ -4753,13 +5007,12 @@ const pebble = defineButtonPersonality({
4753
5007
  name: "Secondary",
4754
5008
  enabled: true,
4755
5009
  priority: 2,
4756
- background: { type: "transparent" },
4757
- textColorToken: "primary",
4758
- borderRadius: "rounded-full",
4759
- border: {
4760
- widthClass: "border-2",
4761
- colorToken: "accent"
5010
+ background: {
5011
+ type: "surface",
5012
+ role: "link"
4762
5013
  },
5014
+ borderRadius: "rounded-full",
5015
+ border: { widthClass: "border-2" },
4763
5016
  effects: { hover: [{
4764
5017
  effectId: "background-on-hover",
4765
5018
  options: { colorToken: "accent" }
@@ -4770,13 +5023,12 @@ const pebble = defineButtonPersonality({
4770
5023
  name: "Outline",
4771
5024
  enabled: true,
4772
5025
  priority: 3,
4773
- background: { type: "transparent" },
4774
- textColorToken: "text",
4775
- borderRadius: "rounded-full",
4776
- border: {
4777
- widthClass: "border",
4778
- colorToken: "border"
5026
+ background: {
5027
+ type: "surface",
5028
+ role: "link"
4779
5029
  },
5030
+ borderRadius: "rounded-full",
5031
+ border: { widthClass: "border" },
4780
5032
  effects: { hover: [{
4781
5033
  effectId: "background-on-hover",
4782
5034
  options: { colorToken: "surface" }
@@ -4787,8 +5039,10 @@ const pebble = defineButtonPersonality({
4787
5039
  name: "Ghost",
4788
5040
  enabled: true,
4789
5041
  priority: 3,
4790
- background: { type: "transparent" },
4791
- textColorToken: "primary",
5042
+ background: {
5043
+ type: "surface",
5044
+ role: "link"
5045
+ },
4792
5046
  borderRadius: "rounded-full",
4793
5047
  sizes: {
4794
5048
  sm: {
@@ -4804,11 +5058,7 @@ const pebble = defineButtonPersonality({
4804
5058
  padding: "0.75rem 1.5rem",
4805
5059
  fontSize: "text-xl"
4806
5060
  }
4807
- },
4808
- effects: { hover: [{
4809
- effectId: "opacity-reduce",
4810
- options: { reduction: 30 }
4811
- }] }
5061
+ }
4812
5062
  }
4813
5063
  ]
4814
5064
  }
@@ -4870,15 +5120,11 @@ const quietArrow = defineButtonPersonality({
4870
5120
  type: "solid",
4871
5121
  colorToken: "primary"
4872
5122
  },
4873
- textColorToken: "primaryForeground",
4874
5123
  borderRadius: "rounded-xl",
4875
5124
  affordance: { iconId: "ArrowRight" },
4876
5125
  effects: { hover: [{
4877
- effectId: "background-on-hover-alpha",
4878
- options: {
4879
- colorToken: "primary",
4880
- opacity: 90
4881
- }
5126
+ effectId: "darken-background",
5127
+ options: { amount: 100 }
4882
5128
  }] }
4883
5129
  },
4884
5130
  {
@@ -4886,13 +5132,12 @@ const quietArrow = defineButtonPersonality({
4886
5132
  name: "Secondary",
4887
5133
  enabled: true,
4888
5134
  priority: 2,
4889
- background: { type: "transparent" },
4890
- textColorToken: "primary",
4891
- borderRadius: "rounded-xl",
4892
- border: {
4893
- widthClass: "border",
4894
- colorToken: "primary"
5135
+ background: {
5136
+ type: "surface",
5137
+ role: "link"
4895
5138
  },
5139
+ borderRadius: "rounded-xl",
5140
+ border: { widthClass: "border" },
4896
5141
  affordance: { iconId: "ArrowRight" },
4897
5142
  effects: { hover: [{
4898
5143
  effectId: "background-on-hover",
@@ -4904,21 +5149,22 @@ const quietArrow = defineButtonPersonality({
4904
5149
  name: "Outline",
4905
5150
  enabled: true,
4906
5151
  priority: 3,
4907
- background: { type: "transparent" },
4908
- textColorToken: "primary",
5152
+ background: {
5153
+ type: "surface",
5154
+ role: "link"
5155
+ },
4909
5156
  borderRadius: "rounded-xl",
4910
- border: {
4911
- widthClass: "border",
4912
- colorToken: "primary"
4913
- }
5157
+ border: { widthClass: "border" }
4914
5158
  },
4915
5159
  {
4916
5160
  id: "ghost",
4917
5161
  name: "Ghost",
4918
5162
  enabled: true,
4919
5163
  priority: 3,
4920
- background: { type: "transparent" },
4921
- textColorToken: "primary",
5164
+ background: {
5165
+ type: "surface",
5166
+ role: "link"
5167
+ },
4922
5168
  borderRadius: "rounded-xl"
4923
5169
  }
4924
5170
  ]
@@ -4982,7 +5228,6 @@ const showtimePill = defineButtonPersonality({
4982
5228
  type: "solid",
4983
5229
  colorToken: "primary"
4984
5230
  },
4985
- textColorToken: "background",
4986
5231
  borderRadius: "rounded-full",
4987
5232
  effects: { hover: [{ effectId: "pop" }] }
4988
5233
  },
@@ -4991,13 +5236,12 @@ const showtimePill = defineButtonPersonality({
4991
5236
  name: "Secondary",
4992
5237
  enabled: true,
4993
5238
  priority: 2,
4994
- background: { type: "transparent" },
4995
- textColorToken: "primary",
4996
- borderRadius: "rounded-full",
4997
- border: {
4998
- widthClass: "border-2",
4999
- colorToken: "primary"
5239
+ background: {
5240
+ type: "surface",
5241
+ role: "link"
5000
5242
  },
5243
+ borderRadius: "rounded-full",
5244
+ border: { widthClass: "border-2" },
5001
5245
  effects: { hover: [{ effectId: "pop" }] }
5002
5246
  },
5003
5247
  {
@@ -5009,7 +5253,6 @@ const showtimePill = defineButtonPersonality({
5009
5253
  type: "solid",
5010
5254
  colorToken: "secondary"
5011
5255
  },
5012
- textColorToken: "primary",
5013
5256
  borderRadius: "rounded-full",
5014
5257
  effects: { hover: [{ effectId: "pop" }] }
5015
5258
  },
@@ -5022,12 +5265,8 @@ const showtimePill = defineButtonPersonality({
5022
5265
  type: "solid",
5023
5266
  colorToken: "background"
5024
5267
  },
5025
- textColorToken: "primary",
5026
5268
  borderRadius: "rounded-full",
5027
- border: {
5028
- widthClass: "border-2",
5029
- colorToken: "primary"
5030
- },
5269
+ border: { widthClass: "border-2" },
5031
5270
  effects: { hover: [{
5032
5271
  effectId: "background-on-hover",
5033
5272
  options: { colorToken: "surface" }
@@ -5038,13 +5277,12 @@ const showtimePill = defineButtonPersonality({
5038
5277
  name: "Outline",
5039
5278
  enabled: true,
5040
5279
  priority: 3,
5041
- background: { type: "transparent" },
5042
- textColorToken: "primary",
5043
- borderRadius: "rounded-full",
5044
- border: {
5045
- widthClass: "border-2",
5046
- colorToken: "primary"
5280
+ background: {
5281
+ type: "surface",
5282
+ role: "link"
5047
5283
  },
5284
+ borderRadius: "rounded-full",
5285
+ border: { widthClass: "border-2" },
5048
5286
  effects: { hover: [{
5049
5287
  effectId: "background-on-hover",
5050
5288
  options: { colorToken: "background" }
@@ -5055,8 +5293,10 @@ const showtimePill = defineButtonPersonality({
5055
5293
  name: "Ghost",
5056
5294
  enabled: true,
5057
5295
  priority: 3,
5058
- background: { type: "transparent" },
5059
- textColorToken: "primary",
5296
+ background: {
5297
+ type: "surface",
5298
+ role: "link"
5299
+ },
5060
5300
  borderRadius: "rounded-full",
5061
5301
  effects: { hover: [{
5062
5302
  effectId: "background-on-hover",
@@ -5102,7 +5342,6 @@ const softPill = defineButtonPersonality({
5102
5342
  type: "solid",
5103
5343
  colorToken: "primary"
5104
5344
  },
5105
- textColorToken: "primaryForeground",
5106
5345
  borderRadius: "rounded-full",
5107
5346
  shadow: {
5108
5347
  elevation: "low",
@@ -5125,13 +5364,12 @@ const softPill = defineButtonPersonality({
5125
5364
  name: "Secondary",
5126
5365
  enabled: true,
5127
5366
  priority: 2,
5128
- background: { type: "transparent" },
5129
- textColorToken: "primary",
5130
- borderRadius: "rounded-full",
5131
- border: {
5132
- widthClass: "border-2",
5133
- colorToken: "primary"
5367
+ background: {
5368
+ type: "surface",
5369
+ role: "link"
5134
5370
  },
5371
+ borderRadius: "rounded-full",
5372
+ border: { widthClass: "border-2" },
5135
5373
  effects: { hover: [{
5136
5374
  effectId: "background-on-hover",
5137
5375
  options: { colorToken: "surface" }
@@ -5142,13 +5380,12 @@ const softPill = defineButtonPersonality({
5142
5380
  name: "Outline",
5143
5381
  enabled: true,
5144
5382
  priority: 3,
5145
- background: { type: "transparent" },
5146
- textColorToken: "text",
5147
- borderRadius: "rounded-full",
5148
- border: {
5149
- widthClass: "border",
5150
- colorToken: "border"
5383
+ background: {
5384
+ type: "surface",
5385
+ role: "link"
5151
5386
  },
5387
+ borderRadius: "rounded-full",
5388
+ border: { widthClass: "border" },
5152
5389
  effects: { hover: [{
5153
5390
  effectId: "background-on-hover",
5154
5391
  options: { colorToken: "surface" }
@@ -5159,8 +5396,10 @@ const softPill = defineButtonPersonality({
5159
5396
  name: "Ghost",
5160
5397
  enabled: true,
5161
5398
  priority: 3,
5162
- background: { type: "transparent" },
5163
- textColorToken: "text",
5399
+ background: {
5400
+ type: "surface",
5401
+ role: "link"
5402
+ },
5164
5403
  borderRadius: "rounded-full",
5165
5404
  effects: { hover: [{
5166
5405
  effectId: "background-on-hover",
@@ -5179,9 +5418,8 @@ const solidSecondary = {
5179
5418
  priority: 2,
5180
5419
  background: {
5181
5420
  type: "solid",
5182
- colorToken: "secondary"
5421
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
5183
5422
  },
5184
- textColorToken: "onSecondary",
5185
5423
  borderRadius: "rounded-full",
5186
5424
  shadow: {
5187
5425
  elevation: "none",
@@ -5229,6 +5467,27 @@ const buttonPersonalities = [
5229
5467
  quietArrow
5230
5468
  ];
5231
5469
  new Map(buttonPersonalities.map((p) => [p.id, p]));
5470
+ buttonPersonalities.map((personality) => ({
5471
+ id: personality.id,
5472
+ name: personality.name,
5473
+ description: personality.description,
5474
+ category: presetCategory(personality),
5475
+ buttonSystem: personality.buttonSystem,
5476
+ compatibility: {
5477
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
5478
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
5479
+ }
5480
+ }));
5481
+ function presetCategory(personality) {
5482
+ switch (personality.tags.era) {
5483
+ case "retro": return "retro";
5484
+ case "editorial": return "minimal";
5485
+ case "organic": return "artistic";
5486
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
5487
+ case "technical": return "technical";
5488
+ case void 0: return "modern";
5489
+ }
5490
+ }
5232
5491
  //#endregion
5233
5492
  //#region ../theme-core/src/cards/types.ts
5234
5493
  const cardVariantRoleValues = ["default", "alternative"];
@@ -8604,6 +8863,241 @@ const originalJoyCardSystem = { variants: [{
8604
8863
  const serifDisplayQuote = { style: "serif-display" };
8605
8864
  /** Punchy quotation mark in the secondary accent colour. Bold / accent styles. */
8606
8865
  const accentGlyphQuote = { style: "accent-glyph" };
8866
+ /**
8867
+ * Curated library of gradient presets.
8868
+ * All gradients use theme color tokens, so they adapt to the site's palette.
8869
+ */
8870
+ const GRADIENT_PRESETS = [
8871
+ {
8872
+ id: "primary-secondary",
8873
+ name: "Primary to Secondary",
8874
+ description: "Blend your primary and secondary brand colors",
8875
+ type: "linear",
8876
+ angle: 135,
8877
+ stops: [{
8878
+ color: "primary-500",
8879
+ position: 0
8880
+ }, {
8881
+ color: "secondary-500",
8882
+ position: 100
8883
+ }]
8884
+ },
8885
+ {
8886
+ id: "primary-accent",
8887
+ name: "Primary to Accent",
8888
+ description: "Energetic gradient from primary to accent",
8889
+ type: "linear",
8890
+ angle: 135,
8891
+ stops: [{
8892
+ color: "primary-500",
8893
+ position: 0
8894
+ }, {
8895
+ color: "accent-500",
8896
+ position: 100
8897
+ }]
8898
+ },
8899
+ {
8900
+ id: "secondary-accent",
8901
+ name: "Secondary to Accent",
8902
+ description: "Vibrant secondary to accent blend",
8903
+ type: "linear",
8904
+ angle: 135,
8905
+ stops: [{
8906
+ color: "secondary-500",
8907
+ position: 0
8908
+ }, {
8909
+ color: "accent-500",
8910
+ position: 100
8911
+ }]
8912
+ },
8913
+ {
8914
+ id: "primary-light-dark",
8915
+ name: "Primary Light to Dark",
8916
+ description: "Subtle primary color fade",
8917
+ type: "linear",
8918
+ angle: 180,
8919
+ stops: [{
8920
+ color: "primary-500",
8921
+ position: 0
8922
+ }, {
8923
+ color: "primary-900",
8924
+ position: 100
8925
+ }]
8926
+ },
8927
+ {
8928
+ id: "primary-dark-light",
8929
+ name: "Primary Dark to Light",
8930
+ description: "Reverse primary fade",
8931
+ type: "linear",
8932
+ angle: 180,
8933
+ stops: [{
8934
+ color: "primary-900",
8935
+ position: 0
8936
+ }, {
8937
+ color: "primary-50",
8938
+ position: 100
8939
+ }]
8940
+ },
8941
+ {
8942
+ id: "secondary-light-dark",
8943
+ name: "Secondary Light to Dark",
8944
+ description: "Subtle secondary color fade",
8945
+ type: "linear",
8946
+ angle: 180,
8947
+ stops: [{
8948
+ color: "secondary-500",
8949
+ position: 0
8950
+ }, {
8951
+ color: "secondary-900",
8952
+ position: 100
8953
+ }]
8954
+ },
8955
+ {
8956
+ id: "accent-light-dark",
8957
+ name: "Accent Light to Dark",
8958
+ description: "Accent color depth fade",
8959
+ type: "linear",
8960
+ angle: 180,
8961
+ stops: [{
8962
+ color: "accent-500",
8963
+ position: 0
8964
+ }, {
8965
+ color: "accent-900",
8966
+ position: 100
8967
+ }]
8968
+ },
8969
+ {
8970
+ id: "background-surface",
8971
+ name: "Background to Surface",
8972
+ description: "Subtle depth using base colors",
8973
+ type: "linear",
8974
+ angle: 180,
8975
+ stops: [{
8976
+ color: "background",
8977
+ position: 0
8978
+ }, {
8979
+ color: "surface",
8980
+ position: 100
8981
+ }]
8982
+ },
8983
+ {
8984
+ id: "neutral-fade",
8985
+ name: "Neutral Gradient",
8986
+ description: "Elegant neutral color fade",
8987
+ type: "linear",
8988
+ angle: 180,
8989
+ stops: [{
8990
+ color: "neutral-900",
8991
+ position: 0
8992
+ }, {
8993
+ color: "neutral-50",
8994
+ position: 100
8995
+ }]
8996
+ },
8997
+ {
8998
+ id: "primary-glow",
8999
+ name: "Primary glow",
9000
+ description: "A soft top-centred glow using your primary palette",
9001
+ type: "radial",
9002
+ shape: "ellipse",
9003
+ position: "top center",
9004
+ stops: [{
9005
+ color: "primary-900",
9006
+ position: 0
9007
+ }, {
9008
+ color: "primary-950",
9009
+ position: 100
9010
+ }],
9011
+ foreground: {
9012
+ textColor: "onPrimary900",
9013
+ headingColor: "onPrimary900",
9014
+ linkColor: "onPrimary900",
9015
+ supportingColor: "onPrimary900"
9016
+ }
9017
+ },
9018
+ {
9019
+ id: "accent-glow",
9020
+ name: "Accent glow",
9021
+ description: "A soft top-centred glow using your accent palette",
9022
+ type: "radial",
9023
+ shape: "ellipse",
9024
+ position: "top center",
9025
+ stops: [{
9026
+ color: "accent-900",
9027
+ position: 0
9028
+ }, {
9029
+ color: "accent-950",
9030
+ position: 100
9031
+ }],
9032
+ foreground: {
9033
+ textColor: "onAccent900",
9034
+ headingColor: "onAccent900",
9035
+ linkColor: "onAccent900",
9036
+ supportingColor: "onAccent900"
9037
+ }
9038
+ },
9039
+ {
9040
+ id: "primary-secondary-accent",
9041
+ name: "Brand Trio",
9042
+ description: "All three brand colors in harmony",
9043
+ type: "linear",
9044
+ angle: 135,
9045
+ stops: [
9046
+ {
9047
+ color: "primary-500",
9048
+ position: 0
9049
+ },
9050
+ {
9051
+ color: "secondary-500",
9052
+ position: 50
9053
+ },
9054
+ {
9055
+ color: "accent-500",
9056
+ position: 100
9057
+ }
9058
+ ]
9059
+ }
9060
+ ].map((preset) => ({
9061
+ ...preset,
9062
+ id: preset.id,
9063
+ stops: preset.stops
9064
+ }));
9065
+ const GRADIENT_PRESET_IDS = GRADIENT_PRESETS.map((preset) => preset.id);
9066
+ const gradientPresetIdSet = new Set(GRADIENT_PRESET_IDS);
9067
+ const gradientPresetById = Object.fromEntries(GRADIENT_PRESETS.map((preset) => [preset.id, preset]));
9068
+ function parseGradientPresetId(value) {
9069
+ if (typeof value !== "string") return null;
9070
+ const normalized = value.trim();
9071
+ if (!gradientPresetIdSet.has(normalized)) return null;
9072
+ return normalized;
9073
+ }
9074
+ function getGradientPreset(id) {
9075
+ return gradientPresetById[id];
9076
+ }
9077
+ //#endregion
9078
+ //#region ../theme-core/src/gradients/utils.ts
9079
+ /**
9080
+ * Convert a GradientConfig to a CSS gradient string
9081
+ *
9082
+ * @param config - The gradient configuration using theme tokens
9083
+ * @param tokens - Map of theme color tokens to hex values
9084
+ * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
9085
+ */
9086
+ function gradientToCss(config, tokens) {
9087
+ const stops = config.stops.map((stop) => {
9088
+ return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
9089
+ }).join(", ");
9090
+ const type = config.type ?? "linear";
9091
+ if (type === "radial") {
9092
+ const position = config.position ?? "center";
9093
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
9094
+ }
9095
+ if (type === "conic") {
9096
+ const position = config.position ?? "center";
9097
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
9098
+ }
9099
+ return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
9100
+ }
8607
9101
  //#endregion
8608
9102
  //#region ../theme-core/src/site-styles/headerLooks.ts
8609
9103
  function asHeaderLookId(value) {
@@ -10647,6 +11141,19 @@ z$1.object({
10647
11141
  }).strict();
10648
11142
  //#endregion
10649
11143
  //#region ../theme-core/src/site-styles/runtimeCompiler.ts
11144
+ function defineSectionForegroundRuntimeTokens(input) {
11145
+ return {
11146
+ textColor: requireThemeColorToken(input.textColor),
11147
+ headingColor: requireThemeColorToken(input.headingColor),
11148
+ linkColor: requireThemeColorToken(input.linkColor),
11149
+ supportingColor: requireThemeColorToken(input.supportingColor)
11150
+ };
11151
+ }
11152
+ function requireThemeColorToken(value) {
11153
+ const token = parseThemeColorToken(value);
11154
+ if (!token) throw new Error(`Invalid section foreground Theme color token: ${String(value)}`);
11155
+ return token;
11156
+ }
10650
11157
  function defineDesignRuntimeRules(rules) {
10651
11158
  return rules;
10652
11159
  }
@@ -10917,24 +11424,24 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
10917
11424
  type: "color",
10918
11425
  color: "muted"
10919
11426
  },
10920
- foreground: {
11427
+ foreground: defineSectionForegroundRuntimeTokens({
10921
11428
  textColor: "text",
10922
11429
  headingColor: "primary",
10923
11430
  linkColor: "primary",
10924
11431
  supportingColor: "text"
10925
- }
11432
+ })
10926
11433
  },
10927
11434
  "brand-depth-band": {
10928
11435
  background: {
10929
11436
  type: "color",
10930
11437
  color: "primary-800"
10931
11438
  },
10932
- foreground: {
11439
+ foreground: defineSectionForegroundRuntimeTokens({
10933
11440
  textColor: "text",
10934
11441
  headingColor: "primary",
10935
11442
  linkColor: "primary",
10936
11443
  supportingColor: "text"
10937
- }
11444
+ })
10938
11445
  },
10939
11446
  "hero-image": {
10940
11447
  background: {
@@ -10942,12 +11449,32 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
10942
11449
  opacity: 1,
10943
11450
  position: "center center"
10944
11451
  },
10945
- foreground: {
11452
+ foreground: defineSectionForegroundRuntimeTokens({
10946
11453
  textColor: "text",
10947
11454
  headingColor: "primary",
10948
11455
  linkColor: "primary",
10949
11456
  supportingColor: "text"
10950
- }
11457
+ })
11458
+ }
11459
+ }
11460
+ });
11461
+ const primaryGlowGradientPresetId = parseGradientPresetId("primary-glow");
11462
+ if (!primaryGlowGradientPresetId) throw new Error("Expected primary-glow in the Theme Core gradient catalog");
11463
+ const fulcrumDesignRuntimeRules = defineDesignRuntimeRules({
11464
+ ...defaultDesignRuntimeRules,
11465
+ sectionSurfaces: {
11466
+ ...defaultDesignRuntimeRules.sectionSurfaces,
11467
+ "accent-band": {
11468
+ background: {
11469
+ type: "gradient",
11470
+ gradientPresetId: primaryGlowGradientPresetId
11471
+ },
11472
+ foreground: defineSectionForegroundRuntimeTokens({
11473
+ textColor: "primaryForeground",
11474
+ headingColor: "primaryForeground",
11475
+ linkColor: "primaryForeground",
11476
+ supportingColor: "primaryForeground"
11477
+ })
10951
11478
  }
10952
11479
  }
10953
11480
  });
@@ -12335,6 +12862,8 @@ const curatedSiteStyles = [
12335
12862
  },
12336
12863
  compositionBudget: quietBudget,
12337
12864
  typography: fulcrumTypography,
12865
+ designRuntimeRules: fulcrumDesignRuntimeRules,
12866
+ recommendedAppearancePresetIds: ["cta-accent-band"],
12338
12867
  themeOverrides: {
12339
12868
  shadow: { colorToken: "primary" },
12340
12869
  accordions: {
@@ -12707,213 +13236,6 @@ z$1.object({
12707
13236
  spacing: z$1.enum(themeTokenRecipeOptions.spacing),
12708
13237
  motion: z$1.enum(themeTokenRecipeOptions.motion)
12709
13238
  });
12710
- //#endregion
12711
- //#region ../theme-core/src/gradients/presets.ts
12712
- /**
12713
- * Curated library of gradient presets
12714
- * All gradients use theme color tokens, so they adapt to the site's palette
12715
- */
12716
- const GRADIENT_PRESETS = [
12717
- {
12718
- id: "primary-secondary",
12719
- name: "Primary to Secondary",
12720
- description: "Blend your primary and secondary brand colors",
12721
- type: "linear",
12722
- angle: 135,
12723
- stops: [{
12724
- color: "primary-500",
12725
- position: 0
12726
- }, {
12727
- color: "secondary-500",
12728
- position: 100
12729
- }]
12730
- },
12731
- {
12732
- id: "primary-accent",
12733
- name: "Primary to Accent",
12734
- description: "Energetic gradient from primary to accent",
12735
- type: "linear",
12736
- angle: 135,
12737
- stops: [{
12738
- color: "primary-500",
12739
- position: 0
12740
- }, {
12741
- color: "accent-500",
12742
- position: 100
12743
- }]
12744
- },
12745
- {
12746
- id: "secondary-accent",
12747
- name: "Secondary to Accent",
12748
- description: "Vibrant secondary to accent blend",
12749
- type: "linear",
12750
- angle: 135,
12751
- stops: [{
12752
- color: "secondary-500",
12753
- position: 0
12754
- }, {
12755
- color: "accent-500",
12756
- position: 100
12757
- }]
12758
- },
12759
- {
12760
- id: "primary-light-dark",
12761
- name: "Primary Light to Dark",
12762
- description: "Subtle primary color fade",
12763
- type: "linear",
12764
- angle: 180,
12765
- stops: [{
12766
- color: "primary-500",
12767
- position: 0
12768
- }, {
12769
- color: "primary-900",
12770
- position: 100
12771
- }]
12772
- },
12773
- {
12774
- id: "primary-dark-light",
12775
- name: "Primary Dark to Light",
12776
- description: "Reverse primary fade",
12777
- type: "linear",
12778
- angle: 180,
12779
- stops: [{
12780
- color: "primary-900",
12781
- position: 0
12782
- }, {
12783
- color: "primary-50",
12784
- position: 100
12785
- }]
12786
- },
12787
- {
12788
- id: "secondary-light-dark",
12789
- name: "Secondary Light to Dark",
12790
- description: "Subtle secondary color fade",
12791
- type: "linear",
12792
- angle: 180,
12793
- stops: [{
12794
- color: "secondary-500",
12795
- position: 0
12796
- }, {
12797
- color: "secondary-900",
12798
- position: 100
12799
- }]
12800
- },
12801
- {
12802
- id: "accent-light-dark",
12803
- name: "Accent Light to Dark",
12804
- description: "Accent color depth fade",
12805
- type: "linear",
12806
- angle: 180,
12807
- stops: [{
12808
- color: "accent-500",
12809
- position: 0
12810
- }, {
12811
- color: "accent-900",
12812
- position: 100
12813
- }]
12814
- },
12815
- {
12816
- id: "background-surface",
12817
- name: "Background to Surface",
12818
- description: "Subtle depth using base colors",
12819
- type: "linear",
12820
- angle: 180,
12821
- stops: [{
12822
- color: "background",
12823
- position: 0
12824
- }, {
12825
- color: "surface",
12826
- position: 100
12827
- }]
12828
- },
12829
- {
12830
- id: "neutral-fade",
12831
- name: "Neutral Gradient",
12832
- description: "Elegant neutral color fade",
12833
- type: "linear",
12834
- angle: 180,
12835
- stops: [{
12836
- color: "neutral-900",
12837
- position: 0
12838
- }, {
12839
- color: "neutral-50",
12840
- position: 100
12841
- }]
12842
- },
12843
- {
12844
- id: "primary-radial",
12845
- name: "Primary Spotlight",
12846
- description: "Radial primary gradient from center",
12847
- type: "radial",
12848
- position: "center",
12849
- stops: [{
12850
- color: "primary-500",
12851
- position: 0
12852
- }, {
12853
- color: "primary-900",
12854
- position: 100
12855
- }]
12856
- },
12857
- {
12858
- id: "accent-radial",
12859
- name: "Accent Spotlight",
12860
- description: "Radial accent gradient from center",
12861
- type: "radial",
12862
- position: "center",
12863
- stops: [{
12864
- color: "accent-500",
12865
- position: 0
12866
- }, {
12867
- color: "accent-900",
12868
- position: 100
12869
- }]
12870
- },
12871
- {
12872
- id: "primary-secondary-accent",
12873
- name: "Brand Trio",
12874
- description: "All three brand colors in harmony",
12875
- type: "linear",
12876
- angle: 135,
12877
- stops: [
12878
- {
12879
- color: "primary-500",
12880
- position: 0
12881
- },
12882
- {
12883
- color: "secondary-500",
12884
- position: 50
12885
- },
12886
- {
12887
- color: "accent-500",
12888
- position: 100
12889
- }
12890
- ]
12891
- }
12892
- ];
12893
- //#endregion
12894
- //#region ../theme-core/src/gradients/utils.ts
12895
- /**
12896
- * Convert a GradientConfig to a CSS gradient string
12897
- *
12898
- * @param config - The gradient configuration using theme tokens
12899
- * @param tokens - Map of theme color tokens to hex values
12900
- * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
12901
- */
12902
- function gradientToCss(config, tokens) {
12903
- const stops = config.stops.map((stop) => {
12904
- return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
12905
- }).join(", ");
12906
- const type = config.type ?? "linear";
12907
- if (type === "radial") {
12908
- const position = config.position ?? "center";
12909
- return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
12910
- }
12911
- if (type === "conic") {
12912
- const position = config.position ?? "center";
12913
- return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
12914
- }
12915
- return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
12916
- }
12917
13239
  const BREAKPOINT_LG = 1024;
12918
13240
  const BREAKPOINT_XL = 1280;
12919
13241
  const BREAKPOINT_LG_DOWN = BREAKPOINT_LG - 1;
@@ -14000,6 +14322,20 @@ const blockCategoryEnum = z$1.enum([
14000
14322
  "layout",
14001
14323
  "interactive"
14002
14324
  ]);
14325
+ const blockContentSourceSchema = z$1.object({
14326
+ kind: z$1.enum([
14327
+ "inline",
14328
+ "entries",
14329
+ "mixed"
14330
+ ]),
14331
+ contentType: z$1.string().min(1).optional()
14332
+ }).superRefine((value, ctx) => {
14333
+ if (value.kind === "inline" && value.contentType) ctx.addIssue({
14334
+ code: z$1.ZodIssueCode.custom,
14335
+ path: ["contentType"],
14336
+ message: "contentType is not allowed when contentSource.kind is \"inline\""
14337
+ });
14338
+ });
14003
14339
  z$1.object({
14004
14340
  name: z$1.string().min(1),
14005
14341
  version: z$1.string().min(1),
@@ -14030,6 +14366,12 @@ z$1.object({
14030
14366
  }).optional()).optional(),
14031
14367
  category: blockCategoryEnum.optional(),
14032
14368
  contentTypes: z$1.array(z$1.string()).optional(),
14369
+ /**
14370
+ * Explicit content-source classification (inline / entries / mixed). Optional at the
14371
+ * schema level for backward compatibility with SDK-defined custom blocks, but every
14372
+ * registered SYSTEM block must declare it (enforced by a registry-wide test).
14373
+ */
14374
+ contentSource: blockContentSourceSchema.optional(),
14033
14375
  tags: z$1.array(z$1.string()).optional(),
14034
14376
  icon: z$1.string().optional()
14035
14377
  });
@@ -17143,9 +17485,15 @@ function createButtonGroup(options = {}) {
17143
17485
  //#endregion
17144
17486
  //#region ../blocks/src/system/fields/ctas.ts
17145
17487
  function createCtasRepeater(options = {}) {
17146
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
17488
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
17489
+ const fieldId = id;
17490
+ const buttonField = createButtonGroup({
17491
+ showGroupLabel: false,
17492
+ ...button ?? {},
17493
+ flattenInRepeater: true
17494
+ });
17147
17495
  return {
17148
- id,
17496
+ id: fieldId,
17149
17497
  type: "repeater",
17150
17498
  label,
17151
17499
  itemLabel,
@@ -17154,11 +17502,8 @@ function createCtasRepeater(options = {}) {
17154
17502
  maxItems,
17155
17503
  required: false,
17156
17504
  allowConversion: true,
17157
- schema: { fields: [createButtonGroup({
17158
- showGroupLabel: false,
17159
- ...button ?? {},
17160
- flattenInRepeater: true
17161
- })] }
17505
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
17506
+ schema: { fields: [buttonField] }
17162
17507
  };
17163
17508
  }
17164
17509
  //#endregion
@@ -17208,6 +17553,7 @@ const heroCtaRowFragment = defineFragment({
17208
17553
  label: "Calls to action",
17209
17554
  itemLabel: "CTA",
17210
17555
  maxItems: 3,
17556
+ defaultValue: [],
17211
17557
  button: {
17212
17558
  variants: [
17213
17559
  {
@@ -17275,7 +17621,7 @@ const ctaCopyFragment = defineFragment({
17275
17621
  eyebrowPath: "content.eyebrow",
17276
17622
  titlePath: "content.title",
17277
17623
  className: "cta-heading"
17278
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
17624
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
17279
17625
  });
17280
17626
  //#endregion
17281
17627
  //#region ../blocks/src/system/fragments/library/testimonialsHeading.ts
@@ -19007,6 +19353,7 @@ function createBlockManifest(config) {
19007
19353
  previewCustomize: config.previewCustomize,
19008
19354
  category: config.category,
19009
19355
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
19356
+ contentSource: config.contentSource,
19010
19357
  tags: config.tags ? [...config.tags] : [],
19011
19358
  icon: config.icon ?? "Box",
19012
19359
  layout,
@@ -19152,6 +19499,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
19152
19499
  title: "Hero",
19153
19500
  titleSource: "headline",
19154
19501
  category: "layout",
19502
+ contentSource: { kind: "inline" },
19155
19503
  includeContainerStyles: true,
19156
19504
  promotedFields: ["_sectionStyles.background.image"],
19157
19505
  fragments: [
@@ -19425,6 +19773,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
19425
19773
  id: "block.intro",
19426
19774
  title: "Intro",
19427
19775
  category: "layout",
19776
+ contentSource: { kind: "inline" },
19428
19777
  includeContainerStyles: true,
19429
19778
  titleSource: "title",
19430
19779
  previewCustomize: { quickFieldPriority: [
@@ -19610,6 +19959,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
19610
19959
  title: "Body Text",
19611
19960
  titleSource: "heading",
19612
19961
  category: "content",
19962
+ contentSource: { kind: "inline" },
19613
19963
  fragments: [{
19614
19964
  fragment: bodyCopyFragment,
19615
19965
  fieldPriority: 0
@@ -19666,6 +20016,10 @@ const blogPostBlockDefinition = {
19666
20016
  description: "Highlights a single blog post with title, image, and excerpt.",
19667
20017
  category: "blog",
19668
20018
  contentTypes: ["post"],
20019
+ contentSource: {
20020
+ kind: "entries",
20021
+ contentType: "post"
20022
+ },
19669
20023
  tags: [
19670
20024
  "blog",
19671
20025
  "post",
@@ -19963,6 +20317,10 @@ const blogListingManifest = createBlockManifest({
19963
20317
  ],
19964
20318
  description: "Display a collection of blog posts in grid or stack layout.",
19965
20319
  contentTypes: ["post"],
20320
+ contentSource: {
20321
+ kind: "entries",
20322
+ contentType: "post"
20323
+ },
19966
20324
  tags: [
19967
20325
  "blog",
19968
20326
  "posts",
@@ -20005,6 +20363,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
20005
20363
  id: "block.cta-full",
20006
20364
  title: "Full-width CTA",
20007
20365
  category: "marketing",
20366
+ contentSource: { kind: "inline" },
20008
20367
  fragments: [{
20009
20368
  fragment: ctaCopyFragment,
20010
20369
  fieldPriority: 0
@@ -20038,6 +20397,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
20038
20397
  id: "block.single-button",
20039
20398
  title: "Single Button",
20040
20399
  category: "marketing",
20400
+ contentSource: { kind: "inline" },
20041
20401
  fragments: [{
20042
20402
  fragment: singleButtonFragment,
20043
20403
  fieldPriority: 0
@@ -20298,6 +20658,7 @@ const formManifest = createBlockManifest({
20298
20658
  paletteHidden: false
20299
20659
  },
20300
20660
  category: "interactive",
20661
+ contentSource: { kind: "inline" },
20301
20662
  tags: [
20302
20663
  "form",
20303
20664
  "contact",
@@ -20360,6 +20721,7 @@ const contactNewsletterBlockDefinition = {
20360
20721
  titleSource: "contactTitle",
20361
20722
  description: "Two-column newsletter signup and contact form section.",
20362
20723
  category: "interactive",
20724
+ contentSource: { kind: "inline" },
20363
20725
  layout: contactNewsletterLayout,
20364
20726
  defaultVariant: "default",
20365
20727
  variants: { default: contactNewsletterLayout },
@@ -20563,6 +20925,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
20563
20925
  title: "FAQ",
20564
20926
  titleSource: "title",
20565
20927
  category: "content",
20928
+ contentSource: { kind: "inline" },
20566
20929
  includeContainerStyles: true,
20567
20930
  fragments: [{
20568
20931
  fragment: faqHeadingFragment,
@@ -22196,6 +22559,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
22196
22559
  id: "block.site-header",
22197
22560
  title: "Site Header",
22198
22561
  category: "layout",
22562
+ contentSource: { kind: "inline" },
22199
22563
  additionalFields: [{
22200
22564
  id: "mode",
22201
22565
  type: "select",
@@ -22400,6 +22764,7 @@ const siteFooterBlockDefinition = { manifest: createBlockManifest({
22400
22764
  id: "block.site-footer",
22401
22765
  title: "Site Footer",
22402
22766
  category: "layout",
22767
+ contentSource: { kind: "inline" },
22403
22768
  skipSectionStyles: true,
22404
22769
  layout: section({
22405
22770
  background: "background",
@@ -22549,6 +22914,7 @@ const testimonialsBlockDefinition = {
22549
22914
  id: "block.testimonials",
22550
22915
  title: "Testimonials",
22551
22916
  category: "marketing",
22917
+ contentSource: { kind: "inline" },
22552
22918
  includeContainerStyles: true,
22553
22919
  previewCustomize: { quickFieldPriority: [
22554
22920
  "avatarLayout",
@@ -22707,6 +23073,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
22707
23073
  id: "block.columns",
22708
23074
  title: "Columns",
22709
23075
  category: "layout",
23076
+ contentSource: { kind: "inline" },
22710
23077
  additionalFields: [
22711
23078
  parseFieldDefinition({
22712
23079
  id: "equalHeight",
@@ -22940,6 +23307,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
22940
23307
  id: "block.collection",
22941
23308
  title: "Collection",
22942
23309
  category: "layout",
23310
+ contentSource: { kind: "inline" },
22943
23311
  additionalFields: [
22944
23312
  parseFieldDefinition({
22945
23313
  id: "layout",
@@ -23176,6 +23544,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
23176
23544
  id: "block.feature-cards",
23177
23545
  title: "Feature Cards",
23178
23546
  category: "layout",
23547
+ contentSource: { kind: "inline" },
23179
23548
  includeContainerStyles: true,
23180
23549
  titleSource: "title",
23181
23550
  additionalFields: [
@@ -23559,6 +23928,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
23559
23928
  id: "block.media-text",
23560
23929
  title: "Media and Text",
23561
23930
  category: "layout",
23931
+ contentSource: { kind: "inline" },
23562
23932
  includeContainerStyles: true,
23563
23933
  titleSource: "title",
23564
23934
  previewCustomize: { quickFieldPriority: [
@@ -23959,6 +24329,7 @@ const appointmentBookingBlockDefinition = {
23959
24329
  paletteHidden: false
23960
24330
  },
23961
24331
  category: "interactive",
24332
+ contentSource: { kind: "inline" },
23962
24333
  tags: [
23963
24334
  "booking",
23964
24335
  "appointment",
@@ -24123,6 +24494,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
24123
24494
  paletteHidden: false
24124
24495
  },
24125
24496
  category: "interactive",
24497
+ contentSource: { kind: "inline" },
24126
24498
  tags: [
24127
24499
  "booking",
24128
24500
  "appointment",
@@ -25687,6 +26059,7 @@ const eventRegistrationBlockDefinition = {
25687
26059
  titleSource: "heading",
25688
26060
  description: "Multi-step event registration form",
25689
26061
  category: "interactive",
26062
+ contentSource: { kind: "inline" },
25690
26063
  tags: [
25691
26064
  "events",
25692
26065
  "registration",
@@ -25793,15 +26166,9 @@ const eventRegistrationBlockDefinition = {
25793
26166
  defaultValue: "Complete Registration",
25794
26167
  maxLength: 40
25795
26168
  },
25796
- {
25797
- id: "buttonVariant",
25798
- type: "select",
25799
- label: "Button style",
26169
+ createButtonVariantField({
25800
26170
  description: "Choose a button style from your theme",
25801
- required: false,
25802
- multiple: false,
25803
- defaultValue: "primary",
25804
- options: [
26171
+ variants: [
25805
26172
  {
25806
26173
  value: "primary",
25807
26174
  label: "Primary"
@@ -25814,9 +26181,8 @@ const eventRegistrationBlockDefinition = {
25814
26181
  value: "outline",
25815
26182
  label: "Outline"
25816
26183
  }
25817
- ],
25818
- ui: { intent: "style" }
25819
- }
26184
+ ]
26185
+ })
25820
26186
  ],
25821
26187
  layout: [styledSection({
25822
26188
  baseClass: "",
@@ -26009,6 +26375,7 @@ const courseRegistrationBlockDefinition = {
26009
26375
  titleSource: "heading",
26010
26376
  description: "Enrollment form for multi-session courses",
26011
26377
  category: "interactive",
26378
+ contentSource: { kind: "inline" },
26012
26379
  tags: [
26013
26380
  "courses",
26014
26381
  "enrollment",
@@ -26122,15 +26489,9 @@ const courseRegistrationBlockDefinition = {
26122
26489
  defaultValue: "Sign up",
26123
26490
  maxLength: 40
26124
26491
  },
26125
- {
26126
- id: "buttonVariant",
26127
- type: "select",
26128
- label: "Button style",
26492
+ createButtonVariantField({
26129
26493
  description: "Choose a button style from your theme",
26130
- required: false,
26131
- multiple: false,
26132
- defaultValue: "primary",
26133
- options: [
26494
+ variants: [
26134
26495
  {
26135
26496
  value: "primary",
26136
26497
  label: "Primary"
@@ -26143,9 +26504,8 @@ const courseRegistrationBlockDefinition = {
26143
26504
  value: "outline",
26144
26505
  label: "Outline"
26145
26506
  }
26146
- ],
26147
- ui: { intent: "style" }
26148
- }
26507
+ ]
26508
+ })
26149
26509
  ],
26150
26510
  layout: [styledSection({
26151
26511
  baseClass: "",
@@ -26225,6 +26585,7 @@ const eventDetailsManifest = createBlockManifest({
26225
26585
  titleSource: "heading",
26226
26586
  description: "Date/time, venue, map, and other dates for an event",
26227
26587
  category: "content",
26588
+ contentSource: { kind: "entries" },
26228
26589
  tags: [
26229
26590
  "events",
26230
26591
  "venue",
@@ -26430,6 +26791,7 @@ const courseDetailsBlockDefinition = {
26430
26791
  titleSource: "heading",
26431
26792
  description: "Schedule, venue, price, and enrollment status for a course",
26432
26793
  category: "content",
26794
+ contentSource: { kind: "entries" },
26433
26795
  tags: [
26434
26796
  "courses",
26435
26797
  "schedule",
@@ -26721,6 +27083,7 @@ const eventSpotlightBlockDefinition = {
26721
27083
  paletteHidden: false
26722
27084
  },
26723
27085
  category: "content",
27086
+ contentSource: { kind: "entries" },
26724
27087
  tags: [
26725
27088
  "events",
26726
27089
  "featured",
@@ -27267,6 +27630,7 @@ const eventListingBlockDefinition = {
27267
27630
  paletteHidden: true
27268
27631
  },
27269
27632
  category: "interactive",
27633
+ contentSource: { kind: "entries" },
27270
27634
  tags: [
27271
27635
  "events",
27272
27636
  "listing",
@@ -28439,6 +28803,7 @@ const eventCalendarBlockDefinition = {
28439
28803
  paletteHidden: false
28440
28804
  },
28441
28805
  category: "interactive",
28806
+ contentSource: { kind: "entries" },
28442
28807
  tags: [
28443
28808
  "events",
28444
28809
  "calendar",
@@ -28612,6 +28977,7 @@ const recurringScheduleBlockDefinition = {
28612
28977
  titleSource: "heading",
28613
28978
  description: "A compact weekly schedule with one row per recurring series.",
28614
28979
  category: "interactive",
28980
+ contentSource: { kind: "entries" },
28615
28981
  icon: "CalendarDays",
28616
28982
  tags: [
28617
28983
  "schedule",
@@ -29029,7 +29395,10 @@ const offeringsPreviewFields = [
29029
29395
  label: "Link"
29030
29396
  }
29031
29397
  ],
29032
- ui: { intent: "display" }
29398
+ ui: {
29399
+ intent: "display",
29400
+ widget: "buttonVariant"
29401
+ }
29033
29402
  },
29034
29403
  {
29035
29404
  id: "buttonText",
@@ -29082,6 +29451,7 @@ const offeringsPreviewManifest = createBlockManifest({
29082
29451
  paletteHidden: false
29083
29452
  },
29084
29453
  category: "content",
29454
+ contentSource: { kind: "mixed" },
29085
29455
  tags: [
29086
29456
  "offerings",
29087
29457
  "events",
@@ -29250,6 +29620,7 @@ const embedManifest = createBlockManifest({
29250
29620
  id: "block.embed",
29251
29621
  title: "Embed Content",
29252
29622
  category: "content",
29623
+ contentSource: { kind: "entries" },
29253
29624
  titleSource: "heading",
29254
29625
  additionalFields: [
29255
29626
  parseFieldDefinition({
@@ -29737,6 +30108,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
29737
30108
  id: "block.image-gallery",
29738
30109
  title: "Image Gallery",
29739
30110
  category: "content",
30111
+ contentSource: { kind: "inline" },
29740
30112
  previewCustomize: { quickFieldPriority: [
29741
30113
  "aspectRatio",
29742
30114
  "slidesToShow",
@@ -30389,6 +30761,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
30389
30761
  id: "block.video-grid",
30390
30762
  title: "Video Grid",
30391
30763
  category: "media",
30764
+ contentSource: { kind: "inline" },
30392
30765
  skipSectionStyles: true,
30393
30766
  additionalFields: parseFieldDefinitions([
30394
30767
  {
@@ -30559,6 +30932,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
30559
30932
  title: "Audio Player",
30560
30933
  titleSource: "title",
30561
30934
  category: "media",
30935
+ contentSource: { kind: "inline" },
30562
30936
  description: "Add a branded audio player for a single track.",
30563
30937
  tags: [
30564
30938
  "audio",
@@ -30670,6 +31044,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
30670
31044
  title: "File Download",
30671
31045
  titleSource: ["title", "file.filename"],
30672
31046
  category: "media",
31047
+ contentSource: { kind: "inline" },
30673
31048
  description: "Add a simple public download link for a document, ZIP, or audio file.",
30674
31049
  tags: [
30675
31050
  "file",
@@ -31614,6 +31989,7 @@ const shopBlockDefinition = {
31614
31989
  paletteHidden: false
31615
31990
  },
31616
31991
  category: "interactive",
31992
+ contentSource: { kind: "entries" },
31617
31993
  tags: [
31618
31994
  "shop",
31619
31995
  "passes",
@@ -31813,6 +32189,7 @@ const productListBlockDefinition = {
31813
32189
  paletteHidden: false
31814
32190
  },
31815
32191
  category: "interactive",
32192
+ contentSource: { kind: "entries" },
31816
32193
  tags: [
31817
32194
  "shop",
31818
32195
  "products",
@@ -31954,6 +32331,7 @@ const productDetailBlockDefinition = {
31954
32331
  paletteHidden: false
31955
32332
  },
31956
32333
  category: "interactive",
32334
+ contentSource: { kind: "entries" },
31957
32335
  tags: [
31958
32336
  "shop",
31959
32337
  "product",
@@ -32070,6 +32448,7 @@ const cartBlockDefinition = {
32070
32448
  paletteHidden: false
32071
32449
  },
32072
32450
  category: "interactive",
32451
+ contentSource: { kind: "inline" },
32073
32452
  tags: [
32074
32453
  "shop",
32075
32454
  "cart",
@@ -32152,6 +32531,7 @@ const checkoutBlockDefinition = {
32152
32531
  paletteHidden: false
32153
32532
  },
32154
32533
  category: "interactive",
32534
+ contentSource: { kind: "inline" },
32155
32535
  tags: [
32156
32536
  "shop",
32157
32537
  "checkout",
@@ -32355,6 +32735,7 @@ const giftingBlockDefinition = {
32355
32735
  paletteHidden: false
32356
32736
  },
32357
32737
  category: "interactive",
32738
+ contentSource: { kind: "entries" },
32358
32739
  tags: [
32359
32740
  "gifting",
32360
32741
  "gift cards",
@@ -32698,6 +33079,7 @@ const newsletterSignupBlockDefinition = {
32698
33079
  titleSource: "title",
32699
33080
  description: "Newsletter subscription form with configurable field presets.",
32700
33081
  category: "interactive",
33082
+ contentSource: { kind: "inline" },
32701
33083
  fragments: [{
32702
33084
  fragment: newsletterCopyFragment,
32703
33085
  fieldPriority: 0
@@ -32879,6 +33261,7 @@ const teamMembersBlockDefinition = {
32879
33261
  id: "block.team-members",
32880
33262
  title: "Team Members",
32881
33263
  category: "content",
33264
+ contentSource: { kind: "mixed" },
32882
33265
  titleSource: "heading",
32883
33266
  additionalFields: [
32884
33267
  parseFieldDefinition({
@@ -33299,6 +33682,7 @@ const locationMapBlockDefinition = {
33299
33682
  titleSource: "heading",
33300
33683
  description: "Show a business location with an interactive map and directions link.",
33301
33684
  category: "content",
33685
+ contentSource: { kind: "inline" },
33302
33686
  tags: [
33303
33687
  "map",
33304
33688
  "location",
@@ -34414,9 +34798,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
34414
34798
  ].filter(Boolean).join(" ");
34415
34799
  }
34416
34800
  function gradientPresetCss(value) {
34417
- if (!isString(value)) return null;
34418
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
34419
- if (!preset) return null;
34801
+ const presetId = parseGradientPresetId(value);
34802
+ if (!presetId) return null;
34803
+ const preset = getGradientPreset(presetId);
34420
34804
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
34421
34805
  }
34422
34806
  const backgroundTransforms = [
@@ -35090,6 +35474,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
35090
35474
  "already_refunded",
35091
35475
  "idempotency_amount_mismatch",
35092
35476
  "idempotency_method_mismatch",
35477
+ "idempotency_receipt_mismatch",
35093
35478
  "refund_in_progress"
35094
35479
  ],
35095
35480
  "invalid_amount",
@@ -35102,7 +35487,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
35102
35487
  "payment_intent_not_found",
35103
35488
  "stripe_error",
35104
35489
  "stale_pending_missing_context",
35105
- "non_refundable_deposit_remaining"
35490
+ "non_refundable_deposit_remaining",
35491
+ "deposit_refund_override_required",
35492
+ "refund_revoke_requires_full_line_refund",
35493
+ "payment_receipt_not_found",
35494
+ "payment_receipt_not_refundable",
35495
+ "payment_receipt_attribution_required"
35106
35496
  ];
35107
35497
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
35108
35498
  //#endregion
@@ -35115,7 +35505,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
35115
35505
  "missing_credit_customer",
35116
35506
  "deposit_refund_override_required",
35117
35507
  "refund_revoke_requires_full_line_refund",
35118
- "unified_order_link_required"
35508
+ "unified_order_link_required",
35509
+ "payment_receipt_not_found",
35510
+ "payment_receipt_not_refundable",
35511
+ "payment_receipt_attribution_required"
35119
35512
  ];
35120
35513
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
35121
35514
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];