@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
@@ -249,19 +249,29 @@ function isRecord$7(value) {
249
249
  //#region ../core/src/booking-date-time.ts
250
250
  const DEFAULT_LOCALE = "en-US";
251
251
  const FALLBACK_TIMEZONE = "UTC";
252
+ const DATE_TIME_FORMATTER_CACHE_LIMIT = 100;
253
+ const dateTimeFormatterCache = /* @__PURE__ */ new Map();
254
+ const timeZoneValidityCache = /* @__PURE__ */ new Map();
252
255
  function isValidTimeZone(timeZone) {
256
+ const cached = timeZoneValidityCache.get(timeZone);
257
+ if (cached !== void 0) return cached;
258
+ let isValid;
253
259
  try {
254
260
  new Intl.DateTimeFormat(DEFAULT_LOCALE, { timeZone }).format(/* @__PURE__ */ new Date());
255
- return true;
261
+ isValid = true;
256
262
  } catch {
257
- return false;
263
+ isValid = false;
258
264
  }
265
+ if (timeZoneValidityCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) timeZoneValidityCache.clear();
266
+ timeZoneValidityCache.set(timeZone, isValid);
267
+ return isValid;
259
268
  }
260
269
  function getSafeTimeZone(timeZone) {
261
270
  const normalized = typeof timeZone === "string" ? timeZone.trim() : "";
262
271
  return normalized.length > 0 && isValidTimeZone(normalized) ? normalized : FALLBACK_TIMEZONE;
263
272
  }
264
273
  function parseStrictBookingTimeZone(timeZone) {
274
+ if (typeof timeZone !== "string") return null;
265
275
  const normalized = timeZone.trim();
266
276
  if (normalized.length === 0 || !isValidTimeZone(normalized)) return null;
267
277
  return normalized;
@@ -274,10 +284,19 @@ function formatParseError(error) {
274
284
  }
275
285
  }
276
286
  function formatToPartsLookup(date, locale, timeZone, format) {
277
- return new Map(new Intl.DateTimeFormat(locale, {
287
+ return new Map(getCachedDateTimeFormatter(locale, timeZone, format).formatToParts(date).map((part) => [part.type, part.value]));
288
+ }
289
+ function getCachedDateTimeFormatter(locale, timeZone, format) {
290
+ const key = `${locale}\u0000${timeZone}\u0000${JSON.stringify(Object.entries(format).sort(([left], [right]) => left.localeCompare(right)))}`;
291
+ const cached = dateTimeFormatterCache.get(key);
292
+ if (cached !== void 0) return cached;
293
+ const formatter = new Intl.DateTimeFormat(locale, {
278
294
  ...format,
279
295
  timeZone
280
- }).formatToParts(date).map((part) => [part.type, part.value]));
296
+ });
297
+ if (dateTimeFormatterCache.size >= DATE_TIME_FORMATTER_CACHE_LIMIT) dateTimeFormatterCache.clear();
298
+ dateTimeFormatterCache.set(key, formatter);
299
+ return formatter;
281
300
  }
282
301
  function getZonedDateTimeParts(date, timeZone) {
283
302
  const parts = formatToPartsLookup(date, "en-GB", timeZone, {
@@ -320,23 +339,9 @@ function toUtcIsoDateTimeString(value) {
320
339
  return parsed.value;
321
340
  }
322
341
  function parseScheduledBookingDateTime(input) {
342
+ let startsAt;
323
343
  try {
324
- const startsAt = toUtcIsoDateTimeString(input.startsAt);
325
- const timeZone = parseStrictBookingTimeZone(input.timeZone);
326
- if (timeZone === null) return {
327
- ok: false,
328
- field: "timeZone",
329
- reason: "invalid_time_zone",
330
- value: input.timeZone
331
- };
332
- return {
333
- ok: true,
334
- value: {
335
- startsAt,
336
- timeZone,
337
- locale: input.locale
338
- }
339
- };
344
+ startsAt = toUtcIsoDateTimeString(input.startsAt);
340
345
  } catch {
341
346
  return {
342
347
  ok: false,
@@ -345,6 +350,21 @@ function parseScheduledBookingDateTime(input) {
345
350
  value: input.startsAt
346
351
  };
347
352
  }
353
+ const timeZone = parseStrictBookingTimeZone(input.timeZone);
354
+ if (timeZone === null) return {
355
+ ok: false,
356
+ field: "timeZone",
357
+ reason: "invalid_time_zone",
358
+ value: typeof input.timeZone === "string" ? input.timeZone : ""
359
+ };
360
+ return {
361
+ ok: true,
362
+ value: {
363
+ startsAt,
364
+ timeZone,
365
+ locale: input.locale
366
+ }
367
+ };
348
368
  }
349
369
  function toScheduledBookingDateTime(input) {
350
370
  const result = parseScheduledBookingDateTime(input);
@@ -3474,6 +3494,111 @@ const mediaSchema$1 = z.object({
3474
3494
  transform: transformSchema$1.optional()
3475
3495
  });
3476
3496
  //#endregion
3497
+ //#region ../theme-core/src/buttons/effectClassification.ts
3498
+ /**
3499
+ * Exhaustive live policy for every registered effect id.
3500
+ *
3501
+ * The resolver consumes the transition payload directly, so adding an effect
3502
+ * cannot update classification without also defining its runtime behavior.
3503
+ */
3504
+ const BUTTON_EFFECT_POLICIES = {
3505
+ "darken-background": {
3506
+ classification: "colour-transition",
3507
+ transition: {
3508
+ kind: "adjust-shade",
3509
+ direction: "darker"
3510
+ }
3511
+ },
3512
+ "lighten-background": {
3513
+ classification: "colour-transition",
3514
+ transition: {
3515
+ kind: "adjust-shade",
3516
+ direction: "lighter"
3517
+ }
3518
+ },
3519
+ "background-on-hover": {
3520
+ classification: "colour-transition",
3521
+ transition: { kind: "replace-background" }
3522
+ },
3523
+ "background-on-hover-alpha": {
3524
+ classification: "unsupported-colour",
3525
+ reason: "alpha_requires_surface"
3526
+ },
3527
+ "fade-background": {
3528
+ classification: "unsupported-colour",
3529
+ reason: "changes_element_opacity"
3530
+ },
3531
+ "opacity-reduce": {
3532
+ classification: "unsupported-colour",
3533
+ reason: "changes_element_opacity"
3534
+ },
3535
+ "gradient-text": {
3536
+ classification: "unsupported-colour",
3537
+ reason: "changes_foreground"
3538
+ },
3539
+ "text-color-change": {
3540
+ classification: "unsupported-colour",
3541
+ reason: "changes_foreground"
3542
+ },
3543
+ "border-color-change": {
3544
+ classification: "unsupported-colour",
3545
+ reason: "changes_border"
3546
+ },
3547
+ "aurora-glow": {
3548
+ classification: "unsupported-background-overlay",
3549
+ reason: "unresolved_background_overlay"
3550
+ },
3551
+ "cosmic-stardust": {
3552
+ classification: "unsupported-background-overlay",
3553
+ reason: "unresolved_background_overlay"
3554
+ },
3555
+ "gradient-border-fill": {
3556
+ classification: "unsupported-background-overlay",
3557
+ reason: "unresolved_background_overlay"
3558
+ },
3559
+ "animated-gradient-border-fill": {
3560
+ classification: "unsupported-background-overlay",
3561
+ reason: "unresolved_background_overlay"
3562
+ },
3563
+ "nav-underline": {
3564
+ classification: "not-button",
3565
+ reason: "not_button_effect"
3566
+ },
3567
+ "nav-frosted-base": {
3568
+ classification: "not-button",
3569
+ reason: "not_button_effect"
3570
+ },
3571
+ "nav-frosted-hover": {
3572
+ classification: "not-button",
3573
+ reason: "not_button_effect"
3574
+ },
3575
+ "nav-frosted-active": {
3576
+ classification: "not-button",
3577
+ reason: "not_button_effect"
3578
+ },
3579
+ "animated-gradient": { classification: "non-colour" },
3580
+ "border-glow": { classification: "non-colour" },
3581
+ "drop-shadow": { classification: "non-colour" },
3582
+ "inner-shadow": { classification: "non-colour" },
3583
+ "neumorphic-shadow": { classification: "non-colour" },
3584
+ "outer-glow": { classification: "non-colour" },
3585
+ "retro-3d-shadow": { classification: "non-colour" },
3586
+ "scale-up": { classification: "non-colour" },
3587
+ "scale-down": { classification: "non-colour" },
3588
+ lift: { classification: "non-colour" },
3589
+ "press-down": { classification: "non-colour" },
3590
+ pop: { classification: "non-colour" },
3591
+ "border-bottom-grow": { classification: "non-colour" },
3592
+ "sketchy-border": { classification: "non-colour" },
3593
+ "pulse-animation": { classification: "non-colour" }
3594
+ };
3595
+ function getButtonEffectPolicy(effectId) {
3596
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
3597
+ }
3598
+ function classifyButtonEffectId(effectId) {
3599
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
3600
+ }
3601
+ //#endregion
3477
3602
  //#region ../theme-core/src/buttons/types.ts
3478
3603
  /**
3479
3604
  * Standard semantic variant roles a theme exposes.
@@ -3490,6 +3615,20 @@ const VARIANT_ROLES = [
3490
3615
  "tertiary",
3491
3616
  "accent"
3492
3617
  ];
3618
+ function parseOpaqueButtonColourToken(value) {
3619
+ const token = parseThemeColorToken(value);
3620
+ if (token === null) return null;
3621
+ const parts = parseColorTokenParts(token);
3622
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
3623
+ }
3624
+ function unsafeAsOpaqueButtonColourToken(value) {
3625
+ return value;
3626
+ }
3627
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
3628
+ const token = parseOpaqueButtonColourToken(value);
3629
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
3630
+ return token;
3631
+ });
3493
3632
  const cornerStyleSchema = z$1.enum([
3494
3633
  "square",
3495
3634
  "rounded",
@@ -3591,7 +3730,7 @@ const buttonSizesSchema = z$1.object({
3591
3730
  lg,
3592
3731
  xl: xl ?? lg
3593
3732
  }));
3594
- const buttonGlobalSettingsSchema = z$1.object({
3733
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
3595
3734
  cornerStyle: cornerStyleSchema,
3596
3735
  cornerRadius: z$1.number().min(0).max(24).optional(),
3597
3736
  /**
@@ -3622,11 +3761,12 @@ const buttonGlobalSettingsSchema = z$1.object({
3622
3761
  paddingPreset: buttonPaddingPresetSchema.optional(),
3623
3762
  hoverTransform: hoverTransformSchema,
3624
3763
  hoverColor: hoverColorSchema,
3625
- hoverColorToken: themeColorTokenSchema.optional(),
3764
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
3626
3765
  gradientStyle: gradientStyleSchema.optional(),
3627
3766
  gradientAngle: z$1.number().min(0).max(360).optional(),
3628
3767
  gradientSharpness: gradientSharpnessSchema.optional()
3629
3768
  });
3769
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
3630
3770
  const gradientDirectionSchema$1 = z$1.enum([
3631
3771
  "to-r",
3632
3772
  "to-l",
@@ -3640,27 +3780,33 @@ const gradientDirectionSchema$1 = z$1.enum([
3640
3780
  const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
3641
3781
  z$1.object({
3642
3782
  type: z$1.literal("solid"),
3643
- colorToken: themeColorTokenSchema
3783
+ colorToken: opaqueButtonColourTokenSchema
3644
3784
  }),
3645
3785
  z$1.object({
3646
3786
  type: z$1.literal("gradient"),
3647
- stops: z$1.array(themeColorTokenSchema).min(2),
3648
- direction: gradientDirectionSchema$1
3787
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
3788
+ const [first, second, ...rest] = stops;
3789
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
3790
+ return [
3791
+ first,
3792
+ second,
3793
+ ...rest
3794
+ ];
3795
+ }),
3796
+ direction: gradientDirectionSchema$1,
3797
+ foregroundToken: opaqueButtonColourTokenSchema
3649
3798
  }),
3650
- z$1.object({ type: z$1.literal("transparent") })
3799
+ z$1.object({
3800
+ type: z$1.literal("surface"),
3801
+ role: z$1.literal("link")
3802
+ })
3651
3803
  ]);
3652
3804
  const effectApplicationSchema$1 = z$1.object({
3653
3805
  effectId: z$1.string(),
3654
- options: z$1.record(z$1.string(), z$1.any()).optional()
3655
- });
3656
- const buttonBorderSchema = z$1.object({
3657
- widthClass: z$1.string(),
3658
- colorToken: themeColorTokenSchema
3659
- });
3660
- const buttonVariantAffordanceSchema = z$1.object({
3661
- iconId: z$1.string().min(1),
3662
- colorToken: themeColorTokenSchema.optional()
3806
+ options: z$1.record(z$1.string(), z$1.json()).optional()
3663
3807
  });
3808
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
3809
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
3664
3810
  const variantShadowSchema = z$1.object({
3665
3811
  elevation: z$1.enum([
3666
3812
  "none",
@@ -3701,27 +3847,170 @@ const variantSizeOverridesSchema = z$1.object({
3701
3847
  * default (e.g. link-style variants declaring zero horizontal padding at
3702
3848
  * every size).
3703
3849
  */
3704
- const buttonVariantSchema = z$1.object({
3850
+ const canonicalButtonVariantSchema = z$1.object({
3705
3851
  id: z$1.string(),
3706
3852
  name: z$1.string().min(1).max(20),
3707
3853
  enabled: z$1.boolean(),
3708
3854
  priority: prioritySchema,
3709
3855
  background: buttonBackgroundSchema,
3710
- textColorToken: themeColorTokenSchema,
3711
3856
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
3712
3857
  borderRadius: z$1.string().optional(),
3713
3858
  shadow: variantShadowSchema.optional(),
3714
3859
  border: buttonBorderSchema.optional(),
3715
- hoverBackgroundToken: z$1.string().optional(),
3860
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
3716
3861
  effects: variantEffectsSchema.optional(),
3717
3862
  sizes: variantSizeOverridesSchema.optional(),
3718
3863
  affordance: buttonVariantAffordanceSchema.optional()
3719
3864
  });
3865
+ /**
3866
+ * Temporary persisted-theme admission boundary for issue #1206.
3867
+ *
3868
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
3869
+ * `textColorToken`/border colour shape. New source and all downstream code use
3870
+ * only the canonical relationship. Delete this preprocessor after the reviewed
3871
+ * production rewrite reports zero legacy rows.
3872
+ */
3873
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
3720
3874
  const buttonSystemSchema = z$1.object({
3721
3875
  global: buttonGlobalSettingsSchema,
3722
3876
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
3723
3877
  sizes: buttonSizesSchema.optional()
3724
3878
  });
3879
+ function normalizeLegacyButtonVariantInput(input) {
3880
+ if (!isUnknownRecord(input)) return input;
3881
+ const background = input.background;
3882
+ if (!isUnknownRecord(background)) return input;
3883
+ 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;
3884
+ const { textColorToken, ...withoutLegacyText } = input;
3885
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
3886
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
3887
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
3888
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
3889
+ if (background.type === "transparent") return {
3890
+ ...withoutLegacyText,
3891
+ background: {
3892
+ type: "surface",
3893
+ role: "link"
3894
+ },
3895
+ border: normalizedBorder,
3896
+ affordance: normalizedAffordance,
3897
+ effects: normalizedEffects,
3898
+ hoverBackgroundToken
3899
+ };
3900
+ if (background.type === "gradient") {
3901
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
3902
+ return {
3903
+ ...withoutLegacyText,
3904
+ background: {
3905
+ ...background,
3906
+ stops,
3907
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
3908
+ },
3909
+ border: normalizedBorder,
3910
+ affordance: normalizedAffordance,
3911
+ effects: normalizedEffects,
3912
+ hoverBackgroundToken
3913
+ };
3914
+ }
3915
+ return {
3916
+ ...withoutLegacyText,
3917
+ background: background.type === "solid" ? {
3918
+ ...background,
3919
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
3920
+ } : background,
3921
+ border: normalizedBorder,
3922
+ affordance: normalizedAffordance,
3923
+ effects: normalizedEffects,
3924
+ hoverBackgroundToken
3925
+ };
3926
+ }
3927
+ function normalizeLegacyButtonGlobalInput(input) {
3928
+ if (!isUnknownRecord(input)) return input;
3929
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
3930
+ return hoverColorToken === input.hoverColorToken ? input : {
3931
+ ...input,
3932
+ hoverColorToken
3933
+ };
3934
+ }
3935
+ function hasLegacyAlphaToken(input, background) {
3936
+ const stops = isUnknownArray(background.stops) ? background.stops : [];
3937
+ return [
3938
+ input.hoverBackgroundToken,
3939
+ background.colorToken,
3940
+ background.foregroundToken,
3941
+ ...stops
3942
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
3943
+ }
3944
+ function stripLegacyTokenAlpha(value) {
3945
+ if (typeof value !== "string") return value;
3946
+ const slashIndex = value.indexOf("/");
3947
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
3948
+ }
3949
+ function hasLegacyButtonEffects(input) {
3950
+ if (!isUnknownRecord(input)) return false;
3951
+ return [
3952
+ "base",
3953
+ "hover",
3954
+ "active",
3955
+ "focus"
3956
+ ].some((state) => {
3957
+ const effects = input[state];
3958
+ return Array.isArray(effects) && effects.some((effect) => {
3959
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
3960
+ const classification = classifyButtonEffectId(effect.effectId);
3961
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
3962
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
3963
+ });
3964
+ });
3965
+ }
3966
+ function normalizeLegacyButtonEffects(input, backgroundType) {
3967
+ if (!isUnknownRecord(input)) return input;
3968
+ const normalized = {};
3969
+ for (const state of [
3970
+ "base",
3971
+ "hover",
3972
+ "active",
3973
+ "focus"
3974
+ ]) {
3975
+ const effects = input[state];
3976
+ if (!Array.isArray(effects)) continue;
3977
+ const safeEffects = effects.flatMap((effect) => {
3978
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
3979
+ const classification = classifyButtonEffectId(effect.effectId);
3980
+ if (classification === "non-colour") return [effect];
3981
+ if (classification !== "colour-transition") return [];
3982
+ if (effect.effectId === "background-on-hover") {
3983
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
3984
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
3985
+ return colorToken === null ? [] : [{
3986
+ ...effect,
3987
+ options: {
3988
+ ...options,
3989
+ colorToken
3990
+ }
3991
+ }];
3992
+ }
3993
+ if (backgroundType !== "solid") return [];
3994
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
3995
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
3996
+ return [{
3997
+ ...effect,
3998
+ options: {
3999
+ ...isUnknownRecord(effect.options) ? effect.options : {},
4000
+ amount
4001
+ }
4002
+ }];
4003
+ });
4004
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
4005
+ }
4006
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
4007
+ }
4008
+ function isUnknownRecord(value) {
4009
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4010
+ }
4011
+ function isUnknownArray(value) {
4012
+ return Array.isArray(value);
4013
+ }
3725
4014
  buttonSizeNameSchema.options;
3726
4015
  //#endregion
3727
4016
  //#region ../theme-core/src/buttons/personalities/types.ts
@@ -3748,7 +4037,7 @@ function defineButtonPersonality(input) {
3748
4037
  name: input.name,
3749
4038
  description: input.description,
3750
4039
  tags: input.tags,
3751
- buttonSystem: input.buttonSystem
4040
+ buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
3752
4041
  };
3753
4042
  }
3754
4043
  //#endregion
@@ -3801,19 +4090,15 @@ const brushedWash = defineButtonPersonality({
3801
4090
  background: {
3802
4091
  type: "gradient",
3803
4092
  stops: ["primary", "accent"],
3804
- direction: "to-r"
4093
+ direction: "to-r",
4094
+ foregroundToken: "primaryForeground"
3805
4095
  },
3806
- textColorToken: "primaryForeground",
3807
4096
  borderRadius: "rounded-lg",
3808
4097
  shadow: {
3809
4098
  elevation: "low",
3810
4099
  softness: "soft",
3811
4100
  position: "bottom"
3812
- },
3813
- effects: { hover: [{
3814
- effectId: "opacity-reduce",
3815
- options: { reduction: -15 }
3816
- }] }
4101
+ }
3817
4102
  },
3818
4103
  {
3819
4104
  id: "secondary",
@@ -3823,32 +4108,27 @@ const brushedWash = defineButtonPersonality({
3823
4108
  background: {
3824
4109
  type: "gradient",
3825
4110
  stops: ["secondary", "accent"],
3826
- direction: "to-br"
4111
+ direction: "to-br",
4112
+ foregroundToken: "primaryForeground"
3827
4113
  },
3828
- textColorToken: "primaryForeground",
3829
4114
  borderRadius: "rounded-lg",
3830
4115
  shadow: {
3831
4116
  elevation: "low",
3832
4117
  softness: "soft",
3833
4118
  position: "bottom"
3834
- },
3835
- effects: { hover: [{
3836
- effectId: "opacity-reduce",
3837
- options: { reduction: -15 }
3838
- }] }
4119
+ }
3839
4120
  },
3840
4121
  {
3841
4122
  id: "outline",
3842
4123
  name: "Outline",
3843
4124
  enabled: true,
3844
4125
  priority: 3,
3845
- background: { type: "transparent" },
3846
- textColorToken: "primary",
3847
- borderRadius: "rounded-lg",
3848
- border: {
3849
- widthClass: "border",
3850
- colorToken: "primary"
4126
+ background: {
4127
+ type: "surface",
4128
+ role: "link"
3851
4129
  },
4130
+ borderRadius: "rounded-lg",
4131
+ border: { widthClass: "border" },
3852
4132
  effects: { hover: [{
3853
4133
  effectId: "background-on-hover",
3854
4134
  options: { colorToken: "surface" }
@@ -3859,8 +4139,10 @@ const brushedWash = defineButtonPersonality({
3859
4139
  name: "Ghost",
3860
4140
  enabled: true,
3861
4141
  priority: 3,
3862
- background: { type: "transparent" },
3863
- textColorToken: "text",
4142
+ background: {
4143
+ type: "surface",
4144
+ role: "link"
4145
+ },
3864
4146
  borderRadius: "rounded-lg",
3865
4147
  effects: { hover: [{
3866
4148
  effectId: "background-on-hover",
@@ -3906,7 +4188,6 @@ const confidentChip = defineButtonPersonality({
3906
4188
  type: "solid",
3907
4189
  colorToken: "primary"
3908
4190
  },
3909
- textColorToken: "primaryForeground",
3910
4191
  borderRadius: "rounded-md",
3911
4192
  shadow: {
3912
4193
  elevation: "medium",
@@ -3916,7 +4197,7 @@ const confidentChip = defineButtonPersonality({
3916
4197
  effects: {
3917
4198
  hover: [{
3918
4199
  effectId: "darken-background",
3919
- options: { amount: 60 }
4200
+ options: { amount: 100 }
3920
4201
  }],
3921
4202
  active: [{
3922
4203
  effectId: "scale-down",
@@ -3933,12 +4214,8 @@ const confidentChip = defineButtonPersonality({
3933
4214
  type: "solid",
3934
4215
  colorToken: "surface"
3935
4216
  },
3936
- textColorToken: "text",
3937
4217
  borderRadius: "rounded-md",
3938
- border: {
3939
- widthClass: "border",
3940
- colorToken: "border"
3941
- },
4218
+ border: { widthClass: "border" },
3942
4219
  effects: { hover: [{
3943
4220
  effectId: "background-on-hover",
3944
4221
  options: { colorToken: "background" }
@@ -3949,13 +4226,12 @@ const confidentChip = defineButtonPersonality({
3949
4226
  name: "Outline",
3950
4227
  enabled: true,
3951
4228
  priority: 3,
3952
- background: { type: "transparent" },
3953
- textColorToken: "primary",
3954
- borderRadius: "rounded-md",
3955
- border: {
3956
- widthClass: "border",
3957
- colorToken: "primary"
4229
+ background: {
4230
+ type: "surface",
4231
+ role: "link"
3958
4232
  },
4233
+ borderRadius: "rounded-md",
4234
+ border: { widthClass: "border" },
3959
4235
  effects: { hover: [{
3960
4236
  effectId: "background-on-hover",
3961
4237
  options: { colorToken: "surface" }
@@ -3966,8 +4242,10 @@ const confidentChip = defineButtonPersonality({
3966
4242
  name: "Ghost",
3967
4243
  enabled: true,
3968
4244
  priority: 3,
3969
- background: { type: "transparent" },
3970
- textColorToken: "primary",
4245
+ background: {
4246
+ type: "surface",
4247
+ role: "link"
4248
+ },
3971
4249
  borderRadius: "rounded-md",
3972
4250
  effects: { hover: [{
3973
4251
  effectId: "background-on-hover",
@@ -4030,7 +4308,6 @@ const earthPill = defineButtonPersonality({
4030
4308
  type: "solid",
4031
4309
  colorToken: "primary"
4032
4310
  },
4033
- textColorToken: "primaryForeground",
4034
4311
  borderRadius: "rounded-full",
4035
4312
  shadow: {
4036
4313
  elevation: "low",
@@ -4056,13 +4333,12 @@ const earthPill = defineButtonPersonality({
4056
4333
  name: "Secondary",
4057
4334
  enabled: true,
4058
4335
  priority: 2,
4059
- background: { type: "transparent" },
4060
- textColorToken: "primary",
4061
- borderRadius: "rounded-full",
4062
- border: {
4063
- widthClass: "border",
4064
- colorToken: "primary"
4336
+ background: {
4337
+ type: "surface",
4338
+ role: "link"
4065
4339
  },
4340
+ borderRadius: "rounded-full",
4341
+ border: { widthClass: "border" },
4066
4342
  effects: { hover: [{
4067
4343
  effectId: "background-on-hover",
4068
4344
  options: { colorToken: "muted" }
@@ -4073,13 +4349,12 @@ const earthPill = defineButtonPersonality({
4073
4349
  name: "Outline",
4074
4350
  enabled: true,
4075
4351
  priority: 3,
4076
- background: { type: "transparent" },
4077
- textColorToken: "text",
4078
- borderRadius: "rounded-full",
4079
- border: {
4080
- widthClass: "border",
4081
- colorToken: "border"
4352
+ background: {
4353
+ type: "surface",
4354
+ role: "link"
4082
4355
  },
4356
+ borderRadius: "rounded-full",
4357
+ border: { widthClass: "border" },
4083
4358
  effects: { hover: [{
4084
4359
  effectId: "background-on-hover",
4085
4360
  options: { colorToken: "surfaceAlt" }
@@ -4090,8 +4365,10 @@ const earthPill = defineButtonPersonality({
4090
4365
  name: "Ghost",
4091
4366
  enabled: true,
4092
4367
  priority: 3,
4093
- background: { type: "transparent" },
4094
- textColorToken: "primary",
4368
+ background: {
4369
+ type: "surface",
4370
+ role: "link"
4371
+ },
4095
4372
  borderRadius: "rounded-full",
4096
4373
  shadow: {
4097
4374
  elevation: "none",
@@ -4112,11 +4389,7 @@ const earthPill = defineButtonPersonality({
4112
4389
  padding: "0.625rem 0",
4113
4390
  fontSize: "text-xl"
4114
4391
  }
4115
- },
4116
- effects: { hover: [{
4117
- effectId: "opacity-reduce",
4118
- options: { reduction: 25 }
4119
- }] }
4392
+ }
4120
4393
  }
4121
4394
  ]
4122
4395
  }
@@ -4152,8 +4425,10 @@ const editorialLink = defineButtonPersonality({
4152
4425
  name: "Primary",
4153
4426
  enabled: true,
4154
4427
  priority: 1,
4155
- background: { type: "transparent" },
4156
- textColorToken: "text",
4428
+ background: {
4429
+ type: "surface",
4430
+ role: "link"
4431
+ },
4157
4432
  borderRadius: "rounded-none",
4158
4433
  sizes: {
4159
4434
  sm: { padding: "0.25rem 0" },
@@ -4175,8 +4450,10 @@ const editorialLink = defineButtonPersonality({
4175
4450
  name: "Secondary",
4176
4451
  enabled: true,
4177
4452
  priority: 2,
4178
- background: { type: "transparent" },
4179
- textColorToken: "mutedText",
4453
+ background: {
4454
+ type: "surface",
4455
+ role: "link"
4456
+ },
4180
4457
  borderRadius: "rounded-none",
4181
4458
  sizes: {
4182
4459
  sm: { padding: "0.25rem 0" },
@@ -4198,8 +4475,10 @@ const editorialLink = defineButtonPersonality({
4198
4475
  name: "Outline",
4199
4476
  enabled: true,
4200
4477
  priority: 3,
4201
- background: { type: "transparent" },
4202
- textColorToken: "accent",
4478
+ background: {
4479
+ type: "surface",
4480
+ role: "link"
4481
+ },
4203
4482
  borderRadius: "rounded-none",
4204
4483
  sizes: {
4205
4484
  sm: { padding: "0.25rem 0" },
@@ -4221,19 +4500,17 @@ const editorialLink = defineButtonPersonality({
4221
4500
  name: "Ghost",
4222
4501
  enabled: true,
4223
4502
  priority: 3,
4224
- background: { type: "transparent" },
4225
- textColorToken: "mutedText",
4503
+ background: {
4504
+ type: "surface",
4505
+ role: "link"
4506
+ },
4226
4507
  borderRadius: "rounded-none",
4227
4508
  sizes: {
4228
4509
  sm: { padding: "0.25rem 0" },
4229
4510
  md: { padding: "0.5rem 0" },
4230
4511
  lg: { padding: "0.625rem 0" },
4231
4512
  xl: { padding: "0.75rem 0" }
4232
- },
4233
- effects: { hover: [{
4234
- effectId: "opacity-reduce",
4235
- options: { reduction: -20 }
4236
- }] }
4513
+ }
4237
4514
  }
4238
4515
  ]
4239
4516
  }
@@ -4295,12 +4572,8 @@ const flatInk = defineButtonPersonality({
4295
4572
  type: "solid",
4296
4573
  colorToken: "primary"
4297
4574
  },
4298
- textColorToken: "primaryForeground",
4299
4575
  borderRadius: "rounded-lg",
4300
- affordance: {
4301
- iconId: "ArrowRight",
4302
- colorToken: "accent"
4303
- },
4576
+ affordance: { iconId: "ArrowRight" },
4304
4577
  effects: { hover: [{
4305
4578
  effectId: "lift",
4306
4579
  options: { translateY: "-2px" }
@@ -4314,13 +4587,12 @@ const flatInk = defineButtonPersonality({
4314
4587
  name: "Secondary",
4315
4588
  enabled: true,
4316
4589
  priority: 2,
4317
- background: { type: "transparent" },
4318
- textColorToken: "primary",
4319
- borderRadius: "rounded-lg",
4320
- border: {
4321
- widthClass: "border",
4322
- colorToken: "border"
4590
+ background: {
4591
+ type: "surface",
4592
+ role: "link"
4323
4593
  },
4594
+ borderRadius: "rounded-lg",
4595
+ border: { widthClass: "border" },
4324
4596
  effects: { hover: [{
4325
4597
  effectId: "lift",
4326
4598
  options: { translateY: "-2px" }
@@ -4338,12 +4610,8 @@ const flatInk = defineButtonPersonality({
4338
4610
  type: "solid",
4339
4611
  colorToken: "accent"
4340
4612
  },
4341
- textColorToken: "accentForeground",
4342
4613
  borderRadius: "rounded-lg",
4343
- affordance: {
4344
- iconId: "ArrowRight",
4345
- colorToken: "accentForeground"
4346
- },
4614
+ affordance: { iconId: "ArrowRight" },
4347
4615
  effects: { hover: [{
4348
4616
  effectId: "lift",
4349
4617
  options: { translateY: "-2px" }
@@ -4406,7 +4674,6 @@ const inkStamp = defineButtonPersonality({
4406
4674
  type: "solid",
4407
4675
  colorToken: "primary"
4408
4676
  },
4409
- textColorToken: "primaryForeground",
4410
4677
  borderRadius: "rounded-md",
4411
4678
  effects: {
4412
4679
  hover: [{
@@ -4427,13 +4694,12 @@ const inkStamp = defineButtonPersonality({
4427
4694
  name: "Secondary",
4428
4695
  enabled: true,
4429
4696
  priority: 2,
4430
- background: { type: "transparent" },
4431
- textColorToken: "primary",
4432
- borderRadius: "rounded-md",
4433
- border: {
4434
- widthClass: "border-2",
4435
- colorToken: "primary"
4697
+ background: {
4698
+ type: "surface",
4699
+ role: "link"
4436
4700
  },
4701
+ borderRadius: "rounded-md",
4702
+ border: { widthClass: "border-2" },
4437
4703
  effects: { hover: [{
4438
4704
  effectId: "background-on-hover",
4439
4705
  options: { colorToken: "surface" }
@@ -4444,13 +4710,12 @@ const inkStamp = defineButtonPersonality({
4444
4710
  name: "Outline",
4445
4711
  enabled: true,
4446
4712
  priority: 3,
4447
- background: { type: "transparent" },
4448
- textColorToken: "text",
4449
- borderRadius: "rounded-md",
4450
- border: {
4451
- widthClass: "border-2",
4452
- colorToken: "border"
4713
+ background: {
4714
+ type: "surface",
4715
+ role: "link"
4453
4716
  },
4717
+ borderRadius: "rounded-md",
4718
+ border: { widthClass: "border-2" },
4454
4719
  effects: { hover: [{
4455
4720
  effectId: "background-on-hover",
4456
4721
  options: { colorToken: "surface" }
@@ -4461,8 +4726,10 @@ const inkStamp = defineButtonPersonality({
4461
4726
  name: "Ghost",
4462
4727
  enabled: true,
4463
4728
  priority: 3,
4464
- background: { type: "transparent" },
4465
- textColorToken: "accent",
4729
+ background: {
4730
+ type: "surface",
4731
+ role: "link"
4732
+ },
4466
4733
  borderRadius: "rounded-none",
4467
4734
  sizes: {
4468
4735
  sm: {
@@ -4555,7 +4822,6 @@ const joyStamp = defineButtonPersonality({
4555
4822
  type: "solid",
4556
4823
  colorToken: "primary"
4557
4824
  },
4558
- textColorToken: "primaryForeground",
4559
4825
  borderRadius: "rounded-full",
4560
4826
  shadow: {
4561
4827
  elevation: "high",
@@ -4569,13 +4835,12 @@ const joyStamp = defineButtonPersonality({
4569
4835
  name: "Secondary",
4570
4836
  enabled: true,
4571
4837
  priority: 2,
4572
- background: { type: "transparent" },
4573
- textColorToken: "text",
4574
- borderRadius: "rounded-full",
4575
- border: {
4576
- widthClass: "border-2",
4577
- colorToken: "text"
4838
+ background: {
4839
+ type: "surface",
4840
+ role: "link"
4578
4841
  },
4842
+ borderRadius: "rounded-full",
4843
+ border: { widthClass: "border-2" },
4579
4844
  shadow: {
4580
4845
  elevation: "high",
4581
4846
  softness: "hard",
@@ -4640,12 +4905,8 @@ const ornateRitual = defineButtonPersonality({
4640
4905
  type: "solid",
4641
4906
  colorToken: "primary"
4642
4907
  },
4643
- textColorToken: "primaryForeground",
4644
4908
  borderRadius: "rounded-md",
4645
- border: {
4646
- widthClass: "border",
4647
- colorToken: "primary"
4648
- },
4909
+ border: { widthClass: "border" },
4649
4910
  effects: {
4650
4911
  hover: [{
4651
4912
  effectId: "background-on-hover",
@@ -4666,12 +4927,8 @@ const ornateRitual = defineButtonPersonality({
4666
4927
  type: "solid",
4667
4928
  colorToken: "secondary"
4668
4929
  },
4669
- textColorToken: "primaryForeground",
4670
4930
  borderRadius: "rounded-md",
4671
- border: {
4672
- widthClass: "border",
4673
- colorToken: "primary"
4674
- },
4931
+ border: { widthClass: "border" },
4675
4932
  effects: { hover: [{
4676
4933
  effectId: "background-on-hover",
4677
4934
  options: { colorToken: "surface" }
@@ -4682,13 +4939,12 @@ const ornateRitual = defineButtonPersonality({
4682
4939
  name: "Outline",
4683
4940
  enabled: true,
4684
4941
  priority: 3,
4685
- background: { type: "transparent" },
4686
- textColorToken: "primary",
4687
- borderRadius: "rounded-md",
4688
- border: {
4689
- widthClass: "border",
4690
- colorToken: "primary"
4942
+ background: {
4943
+ type: "surface",
4944
+ role: "link"
4691
4945
  },
4946
+ borderRadius: "rounded-md",
4947
+ border: { widthClass: "border" },
4692
4948
  effects: { hover: [{
4693
4949
  effectId: "background-on-hover",
4694
4950
  options: { colorToken: "muted" }
@@ -4699,8 +4955,10 @@ const ornateRitual = defineButtonPersonality({
4699
4955
  name: "Ghost",
4700
4956
  enabled: true,
4701
4957
  priority: 3,
4702
- background: { type: "transparent" },
4703
- textColorToken: "accent",
4958
+ background: {
4959
+ type: "surface",
4960
+ role: "link"
4961
+ },
4704
4962
  borderRadius: "rounded-none",
4705
4963
  sizes: {
4706
4964
  sm: {
@@ -4782,14 +5040,10 @@ const pebble = defineButtonPersonality({
4782
5040
  type: "solid",
4783
5041
  colorToken: "primary"
4784
5042
  },
4785
- textColorToken: "primaryForeground",
4786
5043
  borderRadius: "rounded-full",
4787
5044
  effects: { hover: [{
4788
- effectId: "background-on-hover-alpha",
4789
- options: {
4790
- colorToken: "primary",
4791
- opacity: 88
4792
- }
5045
+ effectId: "darken-background",
5046
+ options: { amount: 100 }
4793
5047
  }] }
4794
5048
  },
4795
5049
  {
@@ -4797,13 +5051,12 @@ const pebble = defineButtonPersonality({
4797
5051
  name: "Secondary",
4798
5052
  enabled: true,
4799
5053
  priority: 2,
4800
- background: { type: "transparent" },
4801
- textColorToken: "primary",
4802
- borderRadius: "rounded-full",
4803
- border: {
4804
- widthClass: "border-2",
4805
- colorToken: "accent"
5054
+ background: {
5055
+ type: "surface",
5056
+ role: "link"
4806
5057
  },
5058
+ borderRadius: "rounded-full",
5059
+ border: { widthClass: "border-2" },
4807
5060
  effects: { hover: [{
4808
5061
  effectId: "background-on-hover",
4809
5062
  options: { colorToken: "accent" }
@@ -4814,13 +5067,12 @@ const pebble = defineButtonPersonality({
4814
5067
  name: "Outline",
4815
5068
  enabled: true,
4816
5069
  priority: 3,
4817
- background: { type: "transparent" },
4818
- textColorToken: "text",
4819
- borderRadius: "rounded-full",
4820
- border: {
4821
- widthClass: "border",
4822
- colorToken: "border"
5070
+ background: {
5071
+ type: "surface",
5072
+ role: "link"
4823
5073
  },
5074
+ borderRadius: "rounded-full",
5075
+ border: { widthClass: "border" },
4824
5076
  effects: { hover: [{
4825
5077
  effectId: "background-on-hover",
4826
5078
  options: { colorToken: "surface" }
@@ -4831,8 +5083,10 @@ const pebble = defineButtonPersonality({
4831
5083
  name: "Ghost",
4832
5084
  enabled: true,
4833
5085
  priority: 3,
4834
- background: { type: "transparent" },
4835
- textColorToken: "primary",
5086
+ background: {
5087
+ type: "surface",
5088
+ role: "link"
5089
+ },
4836
5090
  borderRadius: "rounded-full",
4837
5091
  sizes: {
4838
5092
  sm: {
@@ -4848,11 +5102,7 @@ const pebble = defineButtonPersonality({
4848
5102
  padding: "0.75rem 1.5rem",
4849
5103
  fontSize: "text-xl"
4850
5104
  }
4851
- },
4852
- effects: { hover: [{
4853
- effectId: "opacity-reduce",
4854
- options: { reduction: 30 }
4855
- }] }
5105
+ }
4856
5106
  }
4857
5107
  ]
4858
5108
  }
@@ -4914,15 +5164,11 @@ const quietArrow = defineButtonPersonality({
4914
5164
  type: "solid",
4915
5165
  colorToken: "primary"
4916
5166
  },
4917
- textColorToken: "primaryForeground",
4918
5167
  borderRadius: "rounded-xl",
4919
5168
  affordance: { iconId: "ArrowRight" },
4920
5169
  effects: { hover: [{
4921
- effectId: "background-on-hover-alpha",
4922
- options: {
4923
- colorToken: "primary",
4924
- opacity: 90
4925
- }
5170
+ effectId: "darken-background",
5171
+ options: { amount: 100 }
4926
5172
  }] }
4927
5173
  },
4928
5174
  {
@@ -4930,13 +5176,12 @@ const quietArrow = defineButtonPersonality({
4930
5176
  name: "Secondary",
4931
5177
  enabled: true,
4932
5178
  priority: 2,
4933
- background: { type: "transparent" },
4934
- textColorToken: "primary",
4935
- borderRadius: "rounded-xl",
4936
- border: {
4937
- widthClass: "border",
4938
- colorToken: "primary"
5179
+ background: {
5180
+ type: "surface",
5181
+ role: "link"
4939
5182
  },
5183
+ borderRadius: "rounded-xl",
5184
+ border: { widthClass: "border" },
4940
5185
  affordance: { iconId: "ArrowRight" },
4941
5186
  effects: { hover: [{
4942
5187
  effectId: "background-on-hover",
@@ -4948,21 +5193,22 @@ const quietArrow = defineButtonPersonality({
4948
5193
  name: "Outline",
4949
5194
  enabled: true,
4950
5195
  priority: 3,
4951
- background: { type: "transparent" },
4952
- textColorToken: "primary",
5196
+ background: {
5197
+ type: "surface",
5198
+ role: "link"
5199
+ },
4953
5200
  borderRadius: "rounded-xl",
4954
- border: {
4955
- widthClass: "border",
4956
- colorToken: "primary"
4957
- }
5201
+ border: { widthClass: "border" }
4958
5202
  },
4959
5203
  {
4960
5204
  id: "ghost",
4961
5205
  name: "Ghost",
4962
5206
  enabled: true,
4963
5207
  priority: 3,
4964
- background: { type: "transparent" },
4965
- textColorToken: "primary",
5208
+ background: {
5209
+ type: "surface",
5210
+ role: "link"
5211
+ },
4966
5212
  borderRadius: "rounded-xl"
4967
5213
  }
4968
5214
  ]
@@ -5026,7 +5272,6 @@ const showtimePill = defineButtonPersonality({
5026
5272
  type: "solid",
5027
5273
  colorToken: "primary"
5028
5274
  },
5029
- textColorToken: "background",
5030
5275
  borderRadius: "rounded-full",
5031
5276
  effects: { hover: [{ effectId: "pop" }] }
5032
5277
  },
@@ -5035,13 +5280,12 @@ const showtimePill = defineButtonPersonality({
5035
5280
  name: "Secondary",
5036
5281
  enabled: true,
5037
5282
  priority: 2,
5038
- background: { type: "transparent" },
5039
- textColorToken: "primary",
5040
- borderRadius: "rounded-full",
5041
- border: {
5042
- widthClass: "border-2",
5043
- colorToken: "primary"
5283
+ background: {
5284
+ type: "surface",
5285
+ role: "link"
5044
5286
  },
5287
+ borderRadius: "rounded-full",
5288
+ border: { widthClass: "border-2" },
5045
5289
  effects: { hover: [{ effectId: "pop" }] }
5046
5290
  },
5047
5291
  {
@@ -5053,7 +5297,6 @@ const showtimePill = defineButtonPersonality({
5053
5297
  type: "solid",
5054
5298
  colorToken: "secondary"
5055
5299
  },
5056
- textColorToken: "primary",
5057
5300
  borderRadius: "rounded-full",
5058
5301
  effects: { hover: [{ effectId: "pop" }] }
5059
5302
  },
@@ -5066,12 +5309,8 @@ const showtimePill = defineButtonPersonality({
5066
5309
  type: "solid",
5067
5310
  colorToken: "background"
5068
5311
  },
5069
- textColorToken: "primary",
5070
5312
  borderRadius: "rounded-full",
5071
- border: {
5072
- widthClass: "border-2",
5073
- colorToken: "primary"
5074
- },
5313
+ border: { widthClass: "border-2" },
5075
5314
  effects: { hover: [{
5076
5315
  effectId: "background-on-hover",
5077
5316
  options: { colorToken: "surface" }
@@ -5082,13 +5321,12 @@ const showtimePill = defineButtonPersonality({
5082
5321
  name: "Outline",
5083
5322
  enabled: true,
5084
5323
  priority: 3,
5085
- background: { type: "transparent" },
5086
- textColorToken: "primary",
5087
- borderRadius: "rounded-full",
5088
- border: {
5089
- widthClass: "border-2",
5090
- colorToken: "primary"
5324
+ background: {
5325
+ type: "surface",
5326
+ role: "link"
5091
5327
  },
5328
+ borderRadius: "rounded-full",
5329
+ border: { widthClass: "border-2" },
5092
5330
  effects: { hover: [{
5093
5331
  effectId: "background-on-hover",
5094
5332
  options: { colorToken: "background" }
@@ -5099,8 +5337,10 @@ const showtimePill = defineButtonPersonality({
5099
5337
  name: "Ghost",
5100
5338
  enabled: true,
5101
5339
  priority: 3,
5102
- background: { type: "transparent" },
5103
- textColorToken: "primary",
5340
+ background: {
5341
+ type: "surface",
5342
+ role: "link"
5343
+ },
5104
5344
  borderRadius: "rounded-full",
5105
5345
  effects: { hover: [{
5106
5346
  effectId: "background-on-hover",
@@ -5146,7 +5386,6 @@ const softPill = defineButtonPersonality({
5146
5386
  type: "solid",
5147
5387
  colorToken: "primary"
5148
5388
  },
5149
- textColorToken: "primaryForeground",
5150
5389
  borderRadius: "rounded-full",
5151
5390
  shadow: {
5152
5391
  elevation: "low",
@@ -5169,13 +5408,12 @@ const softPill = defineButtonPersonality({
5169
5408
  name: "Secondary",
5170
5409
  enabled: true,
5171
5410
  priority: 2,
5172
- background: { type: "transparent" },
5173
- textColorToken: "primary",
5174
- borderRadius: "rounded-full",
5175
- border: {
5176
- widthClass: "border-2",
5177
- colorToken: "primary"
5411
+ background: {
5412
+ type: "surface",
5413
+ role: "link"
5178
5414
  },
5415
+ borderRadius: "rounded-full",
5416
+ border: { widthClass: "border-2" },
5179
5417
  effects: { hover: [{
5180
5418
  effectId: "background-on-hover",
5181
5419
  options: { colorToken: "surface" }
@@ -5186,13 +5424,12 @@ const softPill = defineButtonPersonality({
5186
5424
  name: "Outline",
5187
5425
  enabled: true,
5188
5426
  priority: 3,
5189
- background: { type: "transparent" },
5190
- textColorToken: "text",
5191
- borderRadius: "rounded-full",
5192
- border: {
5193
- widthClass: "border",
5194
- colorToken: "border"
5427
+ background: {
5428
+ type: "surface",
5429
+ role: "link"
5195
5430
  },
5431
+ borderRadius: "rounded-full",
5432
+ border: { widthClass: "border" },
5196
5433
  effects: { hover: [{
5197
5434
  effectId: "background-on-hover",
5198
5435
  options: { colorToken: "surface" }
@@ -5203,8 +5440,10 @@ const softPill = defineButtonPersonality({
5203
5440
  name: "Ghost",
5204
5441
  enabled: true,
5205
5442
  priority: 3,
5206
- background: { type: "transparent" },
5207
- textColorToken: "text",
5443
+ background: {
5444
+ type: "surface",
5445
+ role: "link"
5446
+ },
5208
5447
  borderRadius: "rounded-full",
5209
5448
  effects: { hover: [{
5210
5449
  effectId: "background-on-hover",
@@ -5223,9 +5462,8 @@ const solidSecondary = {
5223
5462
  priority: 2,
5224
5463
  background: {
5225
5464
  type: "solid",
5226
- colorToken: "secondary"
5465
+ colorToken: unsafeAsOpaqueButtonColourToken("secondary")
5227
5466
  },
5228
- textColorToken: "onSecondary",
5229
5467
  borderRadius: "rounded-full",
5230
5468
  shadow: {
5231
5469
  elevation: "none",
@@ -5273,6 +5511,27 @@ const buttonPersonalities = [
5273
5511
  quietArrow
5274
5512
  ];
5275
5513
  new Map(buttonPersonalities.map((p) => [p.id, p]));
5514
+ buttonPersonalities.map((personality) => ({
5515
+ id: personality.id,
5516
+ name: personality.name,
5517
+ description: personality.description,
5518
+ category: presetCategory(personality),
5519
+ buttonSystem: personality.buttonSystem,
5520
+ compatibility: {
5521
+ ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
5522
+ ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
5523
+ }
5524
+ }));
5525
+ function presetCategory(personality) {
5526
+ switch (personality.tags.era) {
5527
+ case "retro": return "retro";
5528
+ case "editorial": return "minimal";
5529
+ case "organic": return "artistic";
5530
+ case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
5531
+ case "technical": return "technical";
5532
+ case void 0: return "modern";
5533
+ }
5534
+ }
5276
5535
  //#endregion
5277
5536
  //#region ../theme-core/src/cards/types.ts
5278
5537
  const cardVariantRoleValues = ["default", "alternative"];
@@ -8648,6 +8907,241 @@ const originalJoyCardSystem = { variants: [{
8648
8907
  const serifDisplayQuote = { style: "serif-display" };
8649
8908
  /** Punchy quotation mark in the secondary accent colour. Bold / accent styles. */
8650
8909
  const accentGlyphQuote = { style: "accent-glyph" };
8910
+ /**
8911
+ * Curated library of gradient presets.
8912
+ * All gradients use theme color tokens, so they adapt to the site's palette.
8913
+ */
8914
+ const GRADIENT_PRESETS = [
8915
+ {
8916
+ id: "primary-secondary",
8917
+ name: "Primary to Secondary",
8918
+ description: "Blend your primary and secondary brand colors",
8919
+ type: "linear",
8920
+ angle: 135,
8921
+ stops: [{
8922
+ color: "primary-500",
8923
+ position: 0
8924
+ }, {
8925
+ color: "secondary-500",
8926
+ position: 100
8927
+ }]
8928
+ },
8929
+ {
8930
+ id: "primary-accent",
8931
+ name: "Primary to Accent",
8932
+ description: "Energetic gradient from primary to accent",
8933
+ type: "linear",
8934
+ angle: 135,
8935
+ stops: [{
8936
+ color: "primary-500",
8937
+ position: 0
8938
+ }, {
8939
+ color: "accent-500",
8940
+ position: 100
8941
+ }]
8942
+ },
8943
+ {
8944
+ id: "secondary-accent",
8945
+ name: "Secondary to Accent",
8946
+ description: "Vibrant secondary to accent blend",
8947
+ type: "linear",
8948
+ angle: 135,
8949
+ stops: [{
8950
+ color: "secondary-500",
8951
+ position: 0
8952
+ }, {
8953
+ color: "accent-500",
8954
+ position: 100
8955
+ }]
8956
+ },
8957
+ {
8958
+ id: "primary-light-dark",
8959
+ name: "Primary Light to Dark",
8960
+ description: "Subtle primary color fade",
8961
+ type: "linear",
8962
+ angle: 180,
8963
+ stops: [{
8964
+ color: "primary-500",
8965
+ position: 0
8966
+ }, {
8967
+ color: "primary-900",
8968
+ position: 100
8969
+ }]
8970
+ },
8971
+ {
8972
+ id: "primary-dark-light",
8973
+ name: "Primary Dark to Light",
8974
+ description: "Reverse primary fade",
8975
+ type: "linear",
8976
+ angle: 180,
8977
+ stops: [{
8978
+ color: "primary-900",
8979
+ position: 0
8980
+ }, {
8981
+ color: "primary-50",
8982
+ position: 100
8983
+ }]
8984
+ },
8985
+ {
8986
+ id: "secondary-light-dark",
8987
+ name: "Secondary Light to Dark",
8988
+ description: "Subtle secondary color fade",
8989
+ type: "linear",
8990
+ angle: 180,
8991
+ stops: [{
8992
+ color: "secondary-500",
8993
+ position: 0
8994
+ }, {
8995
+ color: "secondary-900",
8996
+ position: 100
8997
+ }]
8998
+ },
8999
+ {
9000
+ id: "accent-light-dark",
9001
+ name: "Accent Light to Dark",
9002
+ description: "Accent color depth fade",
9003
+ type: "linear",
9004
+ angle: 180,
9005
+ stops: [{
9006
+ color: "accent-500",
9007
+ position: 0
9008
+ }, {
9009
+ color: "accent-900",
9010
+ position: 100
9011
+ }]
9012
+ },
9013
+ {
9014
+ id: "background-surface",
9015
+ name: "Background to Surface",
9016
+ description: "Subtle depth using base colors",
9017
+ type: "linear",
9018
+ angle: 180,
9019
+ stops: [{
9020
+ color: "background",
9021
+ position: 0
9022
+ }, {
9023
+ color: "surface",
9024
+ position: 100
9025
+ }]
9026
+ },
9027
+ {
9028
+ id: "neutral-fade",
9029
+ name: "Neutral Gradient",
9030
+ description: "Elegant neutral color fade",
9031
+ type: "linear",
9032
+ angle: 180,
9033
+ stops: [{
9034
+ color: "neutral-900",
9035
+ position: 0
9036
+ }, {
9037
+ color: "neutral-50",
9038
+ position: 100
9039
+ }]
9040
+ },
9041
+ {
9042
+ id: "primary-glow",
9043
+ name: "Primary glow",
9044
+ description: "A soft top-centred glow using your primary palette",
9045
+ type: "radial",
9046
+ shape: "ellipse",
9047
+ position: "top center",
9048
+ stops: [{
9049
+ color: "primary-900",
9050
+ position: 0
9051
+ }, {
9052
+ color: "primary-950",
9053
+ position: 100
9054
+ }],
9055
+ foreground: {
9056
+ textColor: "onPrimary900",
9057
+ headingColor: "onPrimary900",
9058
+ linkColor: "onPrimary900",
9059
+ supportingColor: "onPrimary900"
9060
+ }
9061
+ },
9062
+ {
9063
+ id: "accent-glow",
9064
+ name: "Accent glow",
9065
+ description: "A soft top-centred glow using your accent palette",
9066
+ type: "radial",
9067
+ shape: "ellipse",
9068
+ position: "top center",
9069
+ stops: [{
9070
+ color: "accent-900",
9071
+ position: 0
9072
+ }, {
9073
+ color: "accent-950",
9074
+ position: 100
9075
+ }],
9076
+ foreground: {
9077
+ textColor: "onAccent900",
9078
+ headingColor: "onAccent900",
9079
+ linkColor: "onAccent900",
9080
+ supportingColor: "onAccent900"
9081
+ }
9082
+ },
9083
+ {
9084
+ id: "primary-secondary-accent",
9085
+ name: "Brand Trio",
9086
+ description: "All three brand colors in harmony",
9087
+ type: "linear",
9088
+ angle: 135,
9089
+ stops: [
9090
+ {
9091
+ color: "primary-500",
9092
+ position: 0
9093
+ },
9094
+ {
9095
+ color: "secondary-500",
9096
+ position: 50
9097
+ },
9098
+ {
9099
+ color: "accent-500",
9100
+ position: 100
9101
+ }
9102
+ ]
9103
+ }
9104
+ ].map((preset) => ({
9105
+ ...preset,
9106
+ id: preset.id,
9107
+ stops: preset.stops
9108
+ }));
9109
+ const GRADIENT_PRESET_IDS = GRADIENT_PRESETS.map((preset) => preset.id);
9110
+ const gradientPresetIdSet = new Set(GRADIENT_PRESET_IDS);
9111
+ const gradientPresetById = Object.fromEntries(GRADIENT_PRESETS.map((preset) => [preset.id, preset]));
9112
+ function parseGradientPresetId(value) {
9113
+ if (typeof value !== "string") return null;
9114
+ const normalized = value.trim();
9115
+ if (!gradientPresetIdSet.has(normalized)) return null;
9116
+ return normalized;
9117
+ }
9118
+ function getGradientPreset(id) {
9119
+ return gradientPresetById[id];
9120
+ }
9121
+ //#endregion
9122
+ //#region ../theme-core/src/gradients/utils.ts
9123
+ /**
9124
+ * Convert a GradientConfig to a CSS gradient string
9125
+ *
9126
+ * @param config - The gradient configuration using theme tokens
9127
+ * @param tokens - Map of theme color tokens to hex values
9128
+ * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
9129
+ */
9130
+ function gradientToCss(config, tokens) {
9131
+ const stops = config.stops.map((stop) => {
9132
+ return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
9133
+ }).join(", ");
9134
+ const type = config.type ?? "linear";
9135
+ if (type === "radial") {
9136
+ const position = config.position ?? "center";
9137
+ return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
9138
+ }
9139
+ if (type === "conic") {
9140
+ const position = config.position ?? "center";
9141
+ return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
9142
+ }
9143
+ return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
9144
+ }
8651
9145
  //#endregion
8652
9146
  //#region ../theme-core/src/site-styles/headerLooks.ts
8653
9147
  function asHeaderLookId(value) {
@@ -10691,6 +11185,19 @@ z$1.object({
10691
11185
  }).strict();
10692
11186
  //#endregion
10693
11187
  //#region ../theme-core/src/site-styles/runtimeCompiler.ts
11188
+ function defineSectionForegroundRuntimeTokens(input) {
11189
+ return {
11190
+ textColor: requireThemeColorToken(input.textColor),
11191
+ headingColor: requireThemeColorToken(input.headingColor),
11192
+ linkColor: requireThemeColorToken(input.linkColor),
11193
+ supportingColor: requireThemeColorToken(input.supportingColor)
11194
+ };
11195
+ }
11196
+ function requireThemeColorToken(value) {
11197
+ const token = parseThemeColorToken(value);
11198
+ if (!token) throw new Error(`Invalid section foreground Theme color token: ${String(value)}`);
11199
+ return token;
11200
+ }
10694
11201
  function defineDesignRuntimeRules(rules) {
10695
11202
  return rules;
10696
11203
  }
@@ -10961,24 +11468,24 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
10961
11468
  type: "color",
10962
11469
  color: "muted"
10963
11470
  },
10964
- foreground: {
11471
+ foreground: defineSectionForegroundRuntimeTokens({
10965
11472
  textColor: "text",
10966
11473
  headingColor: "primary",
10967
11474
  linkColor: "primary",
10968
11475
  supportingColor: "text"
10969
- }
11476
+ })
10970
11477
  },
10971
11478
  "brand-depth-band": {
10972
11479
  background: {
10973
11480
  type: "color",
10974
11481
  color: "primary-800"
10975
11482
  },
10976
- foreground: {
11483
+ foreground: defineSectionForegroundRuntimeTokens({
10977
11484
  textColor: "text",
10978
11485
  headingColor: "primary",
10979
11486
  linkColor: "primary",
10980
11487
  supportingColor: "text"
10981
- }
11488
+ })
10982
11489
  },
10983
11490
  "hero-image": {
10984
11491
  background: {
@@ -10986,12 +11493,32 @@ const kirtanOrnateDesignRuntimeRules = defineDesignRuntimeRules({
10986
11493
  opacity: 1,
10987
11494
  position: "center center"
10988
11495
  },
10989
- foreground: {
11496
+ foreground: defineSectionForegroundRuntimeTokens({
10990
11497
  textColor: "text",
10991
11498
  headingColor: "primary",
10992
11499
  linkColor: "primary",
10993
11500
  supportingColor: "text"
10994
- }
11501
+ })
11502
+ }
11503
+ }
11504
+ });
11505
+ const primaryGlowGradientPresetId = parseGradientPresetId("primary-glow");
11506
+ if (!primaryGlowGradientPresetId) throw new Error("Expected primary-glow in the Theme Core gradient catalog");
11507
+ const fulcrumDesignRuntimeRules = defineDesignRuntimeRules({
11508
+ ...defaultDesignRuntimeRules,
11509
+ sectionSurfaces: {
11510
+ ...defaultDesignRuntimeRules.sectionSurfaces,
11511
+ "accent-band": {
11512
+ background: {
11513
+ type: "gradient",
11514
+ gradientPresetId: primaryGlowGradientPresetId
11515
+ },
11516
+ foreground: defineSectionForegroundRuntimeTokens({
11517
+ textColor: "primaryForeground",
11518
+ headingColor: "primaryForeground",
11519
+ linkColor: "primaryForeground",
11520
+ supportingColor: "primaryForeground"
11521
+ })
10995
11522
  }
10996
11523
  }
10997
11524
  });
@@ -12379,6 +12906,8 @@ const curatedSiteStyles = [
12379
12906
  },
12380
12907
  compositionBudget: quietBudget,
12381
12908
  typography: fulcrumTypography,
12909
+ designRuntimeRules: fulcrumDesignRuntimeRules,
12910
+ recommendedAppearancePresetIds: ["cta-accent-band"],
12382
12911
  themeOverrides: {
12383
12912
  shadow: { colorToken: "primary" },
12384
12913
  accordions: {
@@ -12751,213 +13280,6 @@ z$1.object({
12751
13280
  spacing: z$1.enum(themeTokenRecipeOptions.spacing),
12752
13281
  motion: z$1.enum(themeTokenRecipeOptions.motion)
12753
13282
  });
12754
- //#endregion
12755
- //#region ../theme-core/src/gradients/presets.ts
12756
- /**
12757
- * Curated library of gradient presets
12758
- * All gradients use theme color tokens, so they adapt to the site's palette
12759
- */
12760
- const GRADIENT_PRESETS = [
12761
- {
12762
- id: "primary-secondary",
12763
- name: "Primary to Secondary",
12764
- description: "Blend your primary and secondary brand colors",
12765
- type: "linear",
12766
- angle: 135,
12767
- stops: [{
12768
- color: "primary-500",
12769
- position: 0
12770
- }, {
12771
- color: "secondary-500",
12772
- position: 100
12773
- }]
12774
- },
12775
- {
12776
- id: "primary-accent",
12777
- name: "Primary to Accent",
12778
- description: "Energetic gradient from primary to accent",
12779
- type: "linear",
12780
- angle: 135,
12781
- stops: [{
12782
- color: "primary-500",
12783
- position: 0
12784
- }, {
12785
- color: "accent-500",
12786
- position: 100
12787
- }]
12788
- },
12789
- {
12790
- id: "secondary-accent",
12791
- name: "Secondary to Accent",
12792
- description: "Vibrant secondary to accent blend",
12793
- type: "linear",
12794
- angle: 135,
12795
- stops: [{
12796
- color: "secondary-500",
12797
- position: 0
12798
- }, {
12799
- color: "accent-500",
12800
- position: 100
12801
- }]
12802
- },
12803
- {
12804
- id: "primary-light-dark",
12805
- name: "Primary Light to Dark",
12806
- description: "Subtle primary color fade",
12807
- type: "linear",
12808
- angle: 180,
12809
- stops: [{
12810
- color: "primary-500",
12811
- position: 0
12812
- }, {
12813
- color: "primary-900",
12814
- position: 100
12815
- }]
12816
- },
12817
- {
12818
- id: "primary-dark-light",
12819
- name: "Primary Dark to Light",
12820
- description: "Reverse primary fade",
12821
- type: "linear",
12822
- angle: 180,
12823
- stops: [{
12824
- color: "primary-900",
12825
- position: 0
12826
- }, {
12827
- color: "primary-50",
12828
- position: 100
12829
- }]
12830
- },
12831
- {
12832
- id: "secondary-light-dark",
12833
- name: "Secondary Light to Dark",
12834
- description: "Subtle secondary color fade",
12835
- type: "linear",
12836
- angle: 180,
12837
- stops: [{
12838
- color: "secondary-500",
12839
- position: 0
12840
- }, {
12841
- color: "secondary-900",
12842
- position: 100
12843
- }]
12844
- },
12845
- {
12846
- id: "accent-light-dark",
12847
- name: "Accent Light to Dark",
12848
- description: "Accent color depth fade",
12849
- type: "linear",
12850
- angle: 180,
12851
- stops: [{
12852
- color: "accent-500",
12853
- position: 0
12854
- }, {
12855
- color: "accent-900",
12856
- position: 100
12857
- }]
12858
- },
12859
- {
12860
- id: "background-surface",
12861
- name: "Background to Surface",
12862
- description: "Subtle depth using base colors",
12863
- type: "linear",
12864
- angle: 180,
12865
- stops: [{
12866
- color: "background",
12867
- position: 0
12868
- }, {
12869
- color: "surface",
12870
- position: 100
12871
- }]
12872
- },
12873
- {
12874
- id: "neutral-fade",
12875
- name: "Neutral Gradient",
12876
- description: "Elegant neutral color fade",
12877
- type: "linear",
12878
- angle: 180,
12879
- stops: [{
12880
- color: "neutral-900",
12881
- position: 0
12882
- }, {
12883
- color: "neutral-50",
12884
- position: 100
12885
- }]
12886
- },
12887
- {
12888
- id: "primary-radial",
12889
- name: "Primary Spotlight",
12890
- description: "Radial primary gradient from center",
12891
- type: "radial",
12892
- position: "center",
12893
- stops: [{
12894
- color: "primary-500",
12895
- position: 0
12896
- }, {
12897
- color: "primary-900",
12898
- position: 100
12899
- }]
12900
- },
12901
- {
12902
- id: "accent-radial",
12903
- name: "Accent Spotlight",
12904
- description: "Radial accent gradient from center",
12905
- type: "radial",
12906
- position: "center",
12907
- stops: [{
12908
- color: "accent-500",
12909
- position: 0
12910
- }, {
12911
- color: "accent-900",
12912
- position: 100
12913
- }]
12914
- },
12915
- {
12916
- id: "primary-secondary-accent",
12917
- name: "Brand Trio",
12918
- description: "All three brand colors in harmony",
12919
- type: "linear",
12920
- angle: 135,
12921
- stops: [
12922
- {
12923
- color: "primary-500",
12924
- position: 0
12925
- },
12926
- {
12927
- color: "secondary-500",
12928
- position: 50
12929
- },
12930
- {
12931
- color: "accent-500",
12932
- position: 100
12933
- }
12934
- ]
12935
- }
12936
- ];
12937
- //#endregion
12938
- //#region ../theme-core/src/gradients/utils.ts
12939
- /**
12940
- * Convert a GradientConfig to a CSS gradient string
12941
- *
12942
- * @param config - The gradient configuration using theme tokens
12943
- * @param tokens - Map of theme color tokens to hex values
12944
- * @returns CSS gradient string (e.g., "linear-gradient(180deg, #3b82f6 0%, #f59e0b 100%)")
12945
- */
12946
- function gradientToCss(config, tokens) {
12947
- const stops = config.stops.map((stop) => {
12948
- return `${tokens[stop.color] ?? "#000000"} ${stop.position}%`;
12949
- }).join(", ");
12950
- const type = config.type ?? "linear";
12951
- if (type === "radial") {
12952
- const position = config.position ?? "center";
12953
- return `radial-gradient(${config.shape ?? "circle"} at ${position}, ${stops})`;
12954
- }
12955
- if (type === "conic") {
12956
- const position = config.position ?? "center";
12957
- return `conic-gradient(from ${config.angle ?? 0}deg at ${position}, ${stops})`;
12958
- }
12959
- return `linear-gradient(${config.angle ?? 180}deg, ${stops})`;
12960
- }
12961
13283
  const BREAKPOINT_LG = 1024;
12962
13284
  const BREAKPOINT_XL = 1280;
12963
13285
  const BREAKPOINT_LG_DOWN = BREAKPOINT_LG - 1;
@@ -14044,6 +14366,20 @@ const blockCategoryEnum = z$1.enum([
14044
14366
  "layout",
14045
14367
  "interactive"
14046
14368
  ]);
14369
+ const blockContentSourceSchema = z$1.object({
14370
+ kind: z$1.enum([
14371
+ "inline",
14372
+ "entries",
14373
+ "mixed"
14374
+ ]),
14375
+ contentType: z$1.string().min(1).optional()
14376
+ }).superRefine((value, ctx) => {
14377
+ if (value.kind === "inline" && value.contentType) ctx.addIssue({
14378
+ code: z$1.ZodIssueCode.custom,
14379
+ path: ["contentType"],
14380
+ message: "contentType is not allowed when contentSource.kind is \"inline\""
14381
+ });
14382
+ });
14047
14383
  z$1.object({
14048
14384
  name: z$1.string().min(1),
14049
14385
  version: z$1.string().min(1),
@@ -14074,6 +14410,12 @@ z$1.object({
14074
14410
  }).optional()).optional(),
14075
14411
  category: blockCategoryEnum.optional(),
14076
14412
  contentTypes: z$1.array(z$1.string()).optional(),
14413
+ /**
14414
+ * Explicit content-source classification (inline / entries / mixed). Optional at the
14415
+ * schema level for backward compatibility with SDK-defined custom blocks, but every
14416
+ * registered SYSTEM block must declare it (enforced by a registry-wide test).
14417
+ */
14418
+ contentSource: blockContentSourceSchema.optional(),
14077
14419
  tags: z$1.array(z$1.string()).optional(),
14078
14420
  icon: z$1.string().optional()
14079
14421
  });
@@ -17187,9 +17529,15 @@ function createButtonGroup(options = {}) {
17187
17529
  //#endregion
17188
17530
  //#region ../blocks/src/system/fields/ctas.ts
17189
17531
  function createCtasRepeater(options = {}) {
17190
- const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button } = options;
17532
+ const { id = "ctas", label = "Calls to action", itemLabel = "CTA", minItems = 0, maxItems, button, defaultValue } = options;
17533
+ const fieldId = id;
17534
+ const buttonField = createButtonGroup({
17535
+ showGroupLabel: false,
17536
+ ...button ?? {},
17537
+ flattenInRepeater: true
17538
+ });
17191
17539
  return {
17192
- id,
17540
+ id: fieldId,
17193
17541
  type: "repeater",
17194
17542
  label,
17195
17543
  itemLabel,
@@ -17198,11 +17546,8 @@ function createCtasRepeater(options = {}) {
17198
17546
  maxItems,
17199
17547
  required: false,
17200
17548
  allowConversion: true,
17201
- schema: { fields: [createButtonGroup({
17202
- showGroupLabel: false,
17203
- ...button ?? {},
17204
- flattenInRepeater: true
17205
- })] }
17549
+ ...defaultValue !== void 0 ? { defaultValue: [...defaultValue] } : {},
17550
+ schema: { fields: [buttonField] }
17206
17551
  };
17207
17552
  }
17208
17553
  //#endregion
@@ -17252,6 +17597,7 @@ const heroCtaRowFragment = defineFragment({
17252
17597
  label: "Calls to action",
17253
17598
  itemLabel: "CTA",
17254
17599
  maxItems: 3,
17600
+ defaultValue: [],
17255
17601
  button: {
17256
17602
  variants: [
17257
17603
  {
@@ -17319,7 +17665,7 @@ const ctaCopyFragment = defineFragment({
17319
17665
  eyebrowPath: "content.eyebrow",
17320
17666
  titlePath: "content.title",
17321
17667
  className: "cta-heading"
17322
- }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content.content"), bind("content.content"))]
17668
+ }), richText({ className: "cta-content rb-prose rb-mx-auto rb-max-w-none" }, when("content"), bind("content"))]
17323
17669
  });
17324
17670
  //#endregion
17325
17671
  //#region ../blocks/src/system/fragments/library/testimonialsHeading.ts
@@ -19051,6 +19397,7 @@ function createBlockManifest(config) {
19051
19397
  previewCustomize: config.previewCustomize,
19052
19398
  category: config.category,
19053
19399
  contentTypes: config.contentTypes ? [...config.contentTypes] : void 0,
19400
+ contentSource: config.contentSource,
19054
19401
  tags: config.tags ? [...config.tags] : [],
19055
19402
  icon: config.icon ?? "Box",
19056
19403
  layout,
@@ -19196,6 +19543,7 @@ const heroBlockDefinition = { manifest: createBlockManifest({
19196
19543
  title: "Hero",
19197
19544
  titleSource: "headline",
19198
19545
  category: "layout",
19546
+ contentSource: { kind: "inline" },
19199
19547
  includeContainerStyles: true,
19200
19548
  promotedFields: ["_sectionStyles.background.image"],
19201
19549
  fragments: [
@@ -19469,6 +19817,7 @@ const introBlockDefinition = { manifest: createBlockManifest({
19469
19817
  id: "block.intro",
19470
19818
  title: "Intro",
19471
19819
  category: "layout",
19820
+ contentSource: { kind: "inline" },
19472
19821
  includeContainerStyles: true,
19473
19822
  titleSource: "title",
19474
19823
  previewCustomize: { quickFieldPriority: [
@@ -19654,6 +20003,7 @@ const bodyTextBlockDefinition = { manifest: createBlockManifest({
19654
20003
  title: "Body Text",
19655
20004
  titleSource: "heading",
19656
20005
  category: "content",
20006
+ contentSource: { kind: "inline" },
19657
20007
  fragments: [{
19658
20008
  fragment: bodyCopyFragment,
19659
20009
  fieldPriority: 0
@@ -19710,6 +20060,10 @@ const blogPostBlockDefinition = {
19710
20060
  description: "Highlights a single blog post with title, image, and excerpt.",
19711
20061
  category: "blog",
19712
20062
  contentTypes: ["post"],
20063
+ contentSource: {
20064
+ kind: "entries",
20065
+ contentType: "post"
20066
+ },
19713
20067
  tags: [
19714
20068
  "blog",
19715
20069
  "post",
@@ -20007,6 +20361,10 @@ const blogListingManifest = createBlockManifest({
20007
20361
  ],
20008
20362
  description: "Display a collection of blog posts in grid or stack layout.",
20009
20363
  contentTypes: ["post"],
20364
+ contentSource: {
20365
+ kind: "entries",
20366
+ contentType: "post"
20367
+ },
20010
20368
  tags: [
20011
20369
  "blog",
20012
20370
  "posts",
@@ -20049,6 +20407,7 @@ const ctaFullBlockDefinition = { manifest: createBlockManifest({
20049
20407
  id: "block.cta-full",
20050
20408
  title: "Full-width CTA",
20051
20409
  category: "marketing",
20410
+ contentSource: { kind: "inline" },
20052
20411
  fragments: [{
20053
20412
  fragment: ctaCopyFragment,
20054
20413
  fieldPriority: 0
@@ -20082,6 +20441,7 @@ const singleButtonBlockDefinition = { manifest: createBlockManifest({
20082
20441
  id: "block.single-button",
20083
20442
  title: "Single Button",
20084
20443
  category: "marketing",
20444
+ contentSource: { kind: "inline" },
20085
20445
  fragments: [{
20086
20446
  fragment: singleButtonFragment,
20087
20447
  fieldPriority: 0
@@ -20342,6 +20702,7 @@ const formManifest = createBlockManifest({
20342
20702
  paletteHidden: false
20343
20703
  },
20344
20704
  category: "interactive",
20705
+ contentSource: { kind: "inline" },
20345
20706
  tags: [
20346
20707
  "form",
20347
20708
  "contact",
@@ -20404,6 +20765,7 @@ const contactNewsletterBlockDefinition = {
20404
20765
  titleSource: "contactTitle",
20405
20766
  description: "Two-column newsletter signup and contact form section.",
20406
20767
  category: "interactive",
20768
+ contentSource: { kind: "inline" },
20407
20769
  layout: contactNewsletterLayout,
20408
20770
  defaultVariant: "default",
20409
20771
  variants: { default: contactNewsletterLayout },
@@ -20607,6 +20969,7 @@ const faqBlockDefinition = { manifest: createBlockManifest({
20607
20969
  title: "FAQ",
20608
20970
  titleSource: "title",
20609
20971
  category: "content",
20972
+ contentSource: { kind: "inline" },
20610
20973
  includeContainerStyles: true,
20611
20974
  fragments: [{
20612
20975
  fragment: faqHeadingFragment,
@@ -22240,6 +22603,7 @@ const siteHeaderBlockDefinition = { manifest: createBlockManifest({
22240
22603
  id: "block.site-header",
22241
22604
  title: "Site Header",
22242
22605
  category: "layout",
22606
+ contentSource: { kind: "inline" },
22243
22607
  additionalFields: [{
22244
22608
  id: "mode",
22245
22609
  type: "select",
@@ -22444,6 +22808,7 @@ const siteFooterBlockDefinition = { manifest: createBlockManifest({
22444
22808
  id: "block.site-footer",
22445
22809
  title: "Site Footer",
22446
22810
  category: "layout",
22811
+ contentSource: { kind: "inline" },
22447
22812
  skipSectionStyles: true,
22448
22813
  layout: section({
22449
22814
  background: "background",
@@ -22593,6 +22958,7 @@ const testimonialsBlockDefinition = {
22593
22958
  id: "block.testimonials",
22594
22959
  title: "Testimonials",
22595
22960
  category: "marketing",
22961
+ contentSource: { kind: "inline" },
22596
22962
  includeContainerStyles: true,
22597
22963
  previewCustomize: { quickFieldPriority: [
22598
22964
  "avatarLayout",
@@ -22751,6 +23117,7 @@ const columnsBlockDefinition = { manifest: createBlockManifest({
22751
23117
  id: "block.columns",
22752
23118
  title: "Columns",
22753
23119
  category: "layout",
23120
+ contentSource: { kind: "inline" },
22754
23121
  additionalFields: [
22755
23122
  parseFieldDefinition({
22756
23123
  id: "equalHeight",
@@ -22984,6 +23351,7 @@ const collectionBlockDefinition = { manifest: createBlockManifest({
22984
23351
  id: "block.collection",
22985
23352
  title: "Collection",
22986
23353
  category: "layout",
23354
+ contentSource: { kind: "inline" },
22987
23355
  additionalFields: [
22988
23356
  parseFieldDefinition({
22989
23357
  id: "layout",
@@ -23220,6 +23588,7 @@ const featureCardsBlockDefinition = { manifest: createBlockManifest({
23220
23588
  id: "block.feature-cards",
23221
23589
  title: "Feature Cards",
23222
23590
  category: "layout",
23591
+ contentSource: { kind: "inline" },
23223
23592
  includeContainerStyles: true,
23224
23593
  titleSource: "title",
23225
23594
  additionalFields: [
@@ -23603,6 +23972,7 @@ const mediaTextBlockDefinition = { manifest: createBlockManifest({
23603
23972
  id: "block.media-text",
23604
23973
  title: "Media and Text",
23605
23974
  category: "layout",
23975
+ contentSource: { kind: "inline" },
23606
23976
  includeContainerStyles: true,
23607
23977
  titleSource: "title",
23608
23978
  previewCustomize: { quickFieldPriority: [
@@ -24003,6 +24373,7 @@ const appointmentBookingBlockDefinition = {
24003
24373
  paletteHidden: false
24004
24374
  },
24005
24375
  category: "interactive",
24376
+ contentSource: { kind: "inline" },
24006
24377
  tags: [
24007
24378
  "booking",
24008
24379
  "appointment",
@@ -24167,6 +24538,7 @@ const weeklySlotAvailabilityManifest = createBlockManifest({
24167
24538
  paletteHidden: false
24168
24539
  },
24169
24540
  category: "interactive",
24541
+ contentSource: { kind: "inline" },
24170
24542
  tags: [
24171
24543
  "booking",
24172
24544
  "appointment",
@@ -25731,6 +26103,7 @@ const eventRegistrationBlockDefinition = {
25731
26103
  titleSource: "heading",
25732
26104
  description: "Multi-step event registration form",
25733
26105
  category: "interactive",
26106
+ contentSource: { kind: "inline" },
25734
26107
  tags: [
25735
26108
  "events",
25736
26109
  "registration",
@@ -25837,15 +26210,9 @@ const eventRegistrationBlockDefinition = {
25837
26210
  defaultValue: "Complete Registration",
25838
26211
  maxLength: 40
25839
26212
  },
25840
- {
25841
- id: "buttonVariant",
25842
- type: "select",
25843
- label: "Button style",
26213
+ createButtonVariantField({
25844
26214
  description: "Choose a button style from your theme",
25845
- required: false,
25846
- multiple: false,
25847
- defaultValue: "primary",
25848
- options: [
26215
+ variants: [
25849
26216
  {
25850
26217
  value: "primary",
25851
26218
  label: "Primary"
@@ -25858,9 +26225,8 @@ const eventRegistrationBlockDefinition = {
25858
26225
  value: "outline",
25859
26226
  label: "Outline"
25860
26227
  }
25861
- ],
25862
- ui: { intent: "style" }
25863
- }
26228
+ ]
26229
+ })
25864
26230
  ],
25865
26231
  layout: [styledSection({
25866
26232
  baseClass: "",
@@ -26053,6 +26419,7 @@ const courseRegistrationBlockDefinition = {
26053
26419
  titleSource: "heading",
26054
26420
  description: "Enrollment form for multi-session courses",
26055
26421
  category: "interactive",
26422
+ contentSource: { kind: "inline" },
26056
26423
  tags: [
26057
26424
  "courses",
26058
26425
  "enrollment",
@@ -26166,15 +26533,9 @@ const courseRegistrationBlockDefinition = {
26166
26533
  defaultValue: "Sign up",
26167
26534
  maxLength: 40
26168
26535
  },
26169
- {
26170
- id: "buttonVariant",
26171
- type: "select",
26172
- label: "Button style",
26536
+ createButtonVariantField({
26173
26537
  description: "Choose a button style from your theme",
26174
- required: false,
26175
- multiple: false,
26176
- defaultValue: "primary",
26177
- options: [
26538
+ variants: [
26178
26539
  {
26179
26540
  value: "primary",
26180
26541
  label: "Primary"
@@ -26187,9 +26548,8 @@ const courseRegistrationBlockDefinition = {
26187
26548
  value: "outline",
26188
26549
  label: "Outline"
26189
26550
  }
26190
- ],
26191
- ui: { intent: "style" }
26192
- }
26551
+ ]
26552
+ })
26193
26553
  ],
26194
26554
  layout: [styledSection({
26195
26555
  baseClass: "",
@@ -26269,6 +26629,7 @@ const eventDetailsManifest = createBlockManifest({
26269
26629
  titleSource: "heading",
26270
26630
  description: "Date/time, venue, map, and other dates for an event",
26271
26631
  category: "content",
26632
+ contentSource: { kind: "entries" },
26272
26633
  tags: [
26273
26634
  "events",
26274
26635
  "venue",
@@ -26474,6 +26835,7 @@ const courseDetailsBlockDefinition = {
26474
26835
  titleSource: "heading",
26475
26836
  description: "Schedule, venue, price, and enrollment status for a course",
26476
26837
  category: "content",
26838
+ contentSource: { kind: "entries" },
26477
26839
  tags: [
26478
26840
  "courses",
26479
26841
  "schedule",
@@ -26765,6 +27127,7 @@ const eventSpotlightBlockDefinition = {
26765
27127
  paletteHidden: false
26766
27128
  },
26767
27129
  category: "content",
27130
+ contentSource: { kind: "entries" },
26768
27131
  tags: [
26769
27132
  "events",
26770
27133
  "featured",
@@ -27311,6 +27674,7 @@ const eventListingBlockDefinition = {
27311
27674
  paletteHidden: true
27312
27675
  },
27313
27676
  category: "interactive",
27677
+ contentSource: { kind: "entries" },
27314
27678
  tags: [
27315
27679
  "events",
27316
27680
  "listing",
@@ -28483,6 +28847,7 @@ const eventCalendarBlockDefinition = {
28483
28847
  paletteHidden: false
28484
28848
  },
28485
28849
  category: "interactive",
28850
+ contentSource: { kind: "entries" },
28486
28851
  tags: [
28487
28852
  "events",
28488
28853
  "calendar",
@@ -28656,6 +29021,7 @@ const recurringScheduleBlockDefinition = {
28656
29021
  titleSource: "heading",
28657
29022
  description: "A compact weekly schedule with one row per recurring series.",
28658
29023
  category: "interactive",
29024
+ contentSource: { kind: "entries" },
28659
29025
  icon: "CalendarDays",
28660
29026
  tags: [
28661
29027
  "schedule",
@@ -29073,7 +29439,10 @@ const offeringsPreviewFields = [
29073
29439
  label: "Link"
29074
29440
  }
29075
29441
  ],
29076
- ui: { intent: "display" }
29442
+ ui: {
29443
+ intent: "display",
29444
+ widget: "buttonVariant"
29445
+ }
29077
29446
  },
29078
29447
  {
29079
29448
  id: "buttonText",
@@ -29126,6 +29495,7 @@ const offeringsPreviewManifest = createBlockManifest({
29126
29495
  paletteHidden: false
29127
29496
  },
29128
29497
  category: "content",
29498
+ contentSource: { kind: "mixed" },
29129
29499
  tags: [
29130
29500
  "offerings",
29131
29501
  "events",
@@ -29294,6 +29664,7 @@ const embedManifest = createBlockManifest({
29294
29664
  id: "block.embed",
29295
29665
  title: "Embed Content",
29296
29666
  category: "content",
29667
+ contentSource: { kind: "entries" },
29297
29668
  titleSource: "heading",
29298
29669
  additionalFields: [
29299
29670
  parseFieldDefinition({
@@ -29781,6 +30152,7 @@ const imageGalleryBlockDefinition = { manifest: createBlockManifest({
29781
30152
  id: "block.image-gallery",
29782
30153
  title: "Image Gallery",
29783
30154
  category: "content",
30155
+ contentSource: { kind: "inline" },
29784
30156
  previewCustomize: { quickFieldPriority: [
29785
30157
  "aspectRatio",
29786
30158
  "slidesToShow",
@@ -30433,6 +30805,7 @@ const videoGridBlockDefinition = { manifest: createBlockManifest({
30433
30805
  id: "block.video-grid",
30434
30806
  title: "Video Grid",
30435
30807
  category: "media",
30808
+ contentSource: { kind: "inline" },
30436
30809
  skipSectionStyles: true,
30437
30810
  additionalFields: parseFieldDefinitions([
30438
30811
  {
@@ -30603,6 +30976,7 @@ const audioPlayerBlockDefinition = { manifest: createBlockManifest({
30603
30976
  title: "Audio Player",
30604
30977
  titleSource: "title",
30605
30978
  category: "media",
30979
+ contentSource: { kind: "inline" },
30606
30980
  description: "Add a branded audio player for a single track.",
30607
30981
  tags: [
30608
30982
  "audio",
@@ -30714,6 +31088,7 @@ const fileDownloadBlockDefinition = { manifest: createBlockManifest({
30714
31088
  title: "File Download",
30715
31089
  titleSource: ["title", "file.filename"],
30716
31090
  category: "media",
31091
+ contentSource: { kind: "inline" },
30717
31092
  description: "Add a simple public download link for a document, ZIP, or audio file.",
30718
31093
  tags: [
30719
31094
  "file",
@@ -31658,6 +32033,7 @@ const shopBlockDefinition = {
31658
32033
  paletteHidden: false
31659
32034
  },
31660
32035
  category: "interactive",
32036
+ contentSource: { kind: "entries" },
31661
32037
  tags: [
31662
32038
  "shop",
31663
32039
  "passes",
@@ -31857,6 +32233,7 @@ const productListBlockDefinition = {
31857
32233
  paletteHidden: false
31858
32234
  },
31859
32235
  category: "interactive",
32236
+ contentSource: { kind: "entries" },
31860
32237
  tags: [
31861
32238
  "shop",
31862
32239
  "products",
@@ -31998,6 +32375,7 @@ const productDetailBlockDefinition = {
31998
32375
  paletteHidden: false
31999
32376
  },
32000
32377
  category: "interactive",
32378
+ contentSource: { kind: "entries" },
32001
32379
  tags: [
32002
32380
  "shop",
32003
32381
  "product",
@@ -32114,6 +32492,7 @@ const cartBlockDefinition = {
32114
32492
  paletteHidden: false
32115
32493
  },
32116
32494
  category: "interactive",
32495
+ contentSource: { kind: "inline" },
32117
32496
  tags: [
32118
32497
  "shop",
32119
32498
  "cart",
@@ -32196,6 +32575,7 @@ const checkoutBlockDefinition = {
32196
32575
  paletteHidden: false
32197
32576
  },
32198
32577
  category: "interactive",
32578
+ contentSource: { kind: "inline" },
32199
32579
  tags: [
32200
32580
  "shop",
32201
32581
  "checkout",
@@ -32399,6 +32779,7 @@ const giftingBlockDefinition = {
32399
32779
  paletteHidden: false
32400
32780
  },
32401
32781
  category: "interactive",
32782
+ contentSource: { kind: "entries" },
32402
32783
  tags: [
32403
32784
  "gifting",
32404
32785
  "gift cards",
@@ -32742,6 +33123,7 @@ const newsletterSignupBlockDefinition = {
32742
33123
  titleSource: "title",
32743
33124
  description: "Newsletter subscription form with configurable field presets.",
32744
33125
  category: "interactive",
33126
+ contentSource: { kind: "inline" },
32745
33127
  fragments: [{
32746
33128
  fragment: newsletterCopyFragment,
32747
33129
  fieldPriority: 0
@@ -32923,6 +33305,7 @@ const teamMembersBlockDefinition = {
32923
33305
  id: "block.team-members",
32924
33306
  title: "Team Members",
32925
33307
  category: "content",
33308
+ contentSource: { kind: "mixed" },
32926
33309
  titleSource: "heading",
32927
33310
  additionalFields: [
32928
33311
  parseFieldDefinition({
@@ -33343,6 +33726,7 @@ const locationMapBlockDefinition = {
33343
33726
  titleSource: "heading",
33344
33727
  description: "Show a business location with an interactive map and directions link.",
33345
33728
  category: "content",
33729
+ contentSource: { kind: "inline" },
33346
33730
  tags: [
33347
33731
  "map",
33348
33732
  "location",
@@ -34458,9 +34842,9 @@ function appendBackgroundMediaClasses(baseClassName, input) {
34458
34842
  ].filter(Boolean).join(" ");
34459
34843
  }
34460
34844
  function gradientPresetCss(value) {
34461
- if (!isString(value)) return null;
34462
- const preset = GRADIENT_PRESETS.find((candidate) => candidate.id === value.trim());
34463
- if (!preset) return null;
34845
+ const presetId = parseGradientPresetId(value);
34846
+ if (!presetId) return null;
34847
+ const preset = getGradientPreset(presetId);
34464
34848
  return gradientToCss(preset, Object.fromEntries(preset.stops.map((stop) => [stop.color, `rgb(var(--tb-${stop.color}))`])));
34465
34849
  }
34466
34850
  const backgroundTransforms = [
@@ -35134,6 +35518,7 @@ const CANONICAL_REFUND_PLANNER_ERROR_CODES = [
35134
35518
  "already_refunded",
35135
35519
  "idempotency_amount_mismatch",
35136
35520
  "idempotency_method_mismatch",
35521
+ "idempotency_receipt_mismatch",
35137
35522
  "refund_in_progress"
35138
35523
  ],
35139
35524
  "invalid_amount",
@@ -35146,7 +35531,12 @@ const CANONICAL_ADMIN_REFUND_FAILURE_CODES = [
35146
35531
  "payment_intent_not_found",
35147
35532
  "stripe_error",
35148
35533
  "stale_pending_missing_context",
35149
- "non_refundable_deposit_remaining"
35534
+ "non_refundable_deposit_remaining",
35535
+ "deposit_refund_override_required",
35536
+ "refund_revoke_requires_full_line_refund",
35537
+ "payment_receipt_not_found",
35538
+ "payment_receipt_not_refundable",
35539
+ "payment_receipt_attribution_required"
35150
35540
  ];
35151
35541
  [...CANONICAL_REFUND_PLANNER_ERROR_CODES];
35152
35542
  //#endregion
@@ -35159,7 +35549,10 @@ const STANDARD_LINE_ITEM_REFUND_INVALID_CODES = [
35159
35549
  "missing_credit_customer",
35160
35550
  "deposit_refund_override_required",
35161
35551
  "refund_revoke_requires_full_line_refund",
35162
- "unified_order_link_required"
35552
+ "unified_order_link_required",
35553
+ "payment_receipt_not_found",
35554
+ "payment_receipt_not_refundable",
35555
+ "payment_receipt_attribution_required"
35163
35556
  ];
35164
35557
  const EVENT_ATTENDEE_REFUND_INVALID_CODES = ["manual_booking_not_refundable", ...STANDARD_LINE_ITEM_REFUND_INVALID_CODES];
35165
35558
  [...CANONICAL_ADMIN_REFUND_FAILURE_CODES];