@riverbankcms/sdk 0.78.2 → 0.80.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 (230) hide show
  1. package/README.md +80 -0
  2. package/dist/PreviewEditorSidebar-QZG37QIF.mjs +2655 -0
  3. package/dist/{PreviewEditorUI-CS5P4N3P.mjs → PreviewEditorUI-AXIKSMZA.mjs} +27 -4
  4. package/dist/SdkPreviewModeRuntime-XE5M4UKM.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +56 -0
  6. package/dist/_dts/api/src/endpoints.d.ts +79 -0
  7. package/dist/_dts/api/src/index.d.ts +6 -4
  8. package/dist/_dts/api/src/media.d.ts +8 -1
  9. package/dist/_dts/api/src/navigation/dashboardSettingsNav.d.ts +1 -1
  10. package/dist/_dts/api/src/navigation/dashboardSiteNav.d.ts +8 -8
  11. package/dist/_dts/api/src/navigation/identity.d.ts +59 -0
  12. package/dist/_dts/api/src/navigation.d.ts +2 -0
  13. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +4 -0
  14. package/dist/_dts/api/src/sdkContracts.d.ts +1 -0
  15. package/dist/_dts/api/src/siteIcons.d.ts +128 -0
  16. package/dist/_dts/api/src/siteInfrastructure.d.ts +124 -0
  17. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +16 -0
  18. package/dist/_dts/api/src/siteOnboarding.d.ts +13 -0
  19. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +17 -1
  20. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -1
  21. package/dist/_dts/api/src/types.d.ts +1 -1
  22. package/dist/_dts/api/src/webhooks.d.ts +239 -0
  23. package/dist/_dts/block-form/src/client/index.d.ts +2 -0
  24. package/dist/_dts/block-form/src/index.d.ts +2 -0
  25. package/dist/_dts/block-form/src/utils/evaluateVisibility.d.ts +2 -1
  26. package/dist/_dts/blocks/src/client/header.d.ts +1 -1
  27. package/dist/_dts/blocks/src/client.d.ts +12 -12
  28. package/dist/_dts/blocks/src/index.d.ts +5 -1
  29. package/dist/_dts/blocks/src/system/blocks/appointment-booking.d.ts +288 -288
  30. package/dist/_dts/blocks/src/system/blocks/blog-listing.d.ts +288 -288
  31. package/dist/_dts/blocks/src/system/blocks/cart.d.ts +288 -288
  32. package/dist/_dts/blocks/src/system/blocks/checkout.d.ts +288 -288
  33. package/dist/_dts/blocks/src/system/blocks/collection.d.ts +288 -288
  34. package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +2 -2
  35. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -1
  36. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +4 -1
  37. package/dist/_dts/blocks/src/system/blocks/faq.d.ts +294 -289
  38. package/dist/_dts/blocks/src/system/blocks/feature-card-icons.d.ts +57 -0
  39. package/dist/_dts/blocks/src/system/blocks/feature-cards.d.ts +4 -0
  40. package/dist/_dts/blocks/src/system/blocks/gifting.d.ts +288 -288
  41. package/dist/_dts/blocks/src/system/blocks/index.d.ts +1 -0
  42. package/dist/_dts/blocks/src/system/blocks/location-map.d.ts +1 -1
  43. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +22 -22
  44. package/dist/_dts/blocks/src/system/blocks/product-detail.d.ts +288 -288
  45. package/dist/_dts/blocks/src/system/blocks/product-list.d.ts +288 -288
  46. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +288 -288
  47. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +13 -1
  48. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +179 -0
  49. package/dist/_dts/blocks/src/system/fields/boxStyles.d.ts +4 -2
  50. package/dist/_dts/blocks/src/system/fragments/library/faqHeading.d.ts +1 -0
  51. package/dist/_dts/blocks/src/system/fragments/library/testimonialsCarousel.d.ts +10 -0
  52. package/dist/_dts/blocks/src/system/helpers/resolveBackground.d.ts +3 -1
  53. package/dist/_dts/blocks/src/system/icons/ids.d.ts +13 -0
  54. package/dist/_dts/blocks/src/system/icons/index.d.ts +6 -0
  55. package/dist/_dts/blocks/src/system/icons/presets.d.ts +4 -0
  56. package/dist/_dts/blocks/src/system/icons/registry.d.ts +18 -0
  57. package/dist/_dts/blocks/src/system/icons/semantic.d.ts +239 -0
  58. package/dist/_dts/blocks/src/system/icons/value.d.ts +94 -0
  59. package/dist/_dts/blocks/src/system/index.d.ts +1 -0
  60. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +4 -1
  61. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +23 -0
  62. package/dist/_dts/blocks/src/system/node/fragments/headingDecoration.d.ts +1 -4
  63. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  64. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +7 -7
  65. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  66. package/dist/_dts/blocks/src/system/runtime/header/enhanceHeaderSection.d.ts +10 -2
  67. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.interactive.d.ts +5 -5
  68. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventListing.server.d.ts +2 -2
  69. package/dist/_dts/blocks/src/system/runtime/nodes/events/EventSpotlight.d.ts +2 -2
  70. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventCard.d.ts +2 -2
  71. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventDetailModal.d.ts +2 -2
  72. package/dist/_dts/blocks/src/system/runtime/nodes/events/shared/EventModals.d.ts +2 -2
  73. package/dist/_dts/blocks/src/system/runtime/nodes/feature-card-icon.d.ts +13 -0
  74. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +2 -2
  75. package/dist/_dts/blocks/src/system/transforms/registry/boxStyles.d.ts +3 -0
  76. package/dist/_dts/blocks/src/system/transforms/registry/layout.d.ts +9 -0
  77. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +14 -1
  78. package/dist/_dts/content-model/src/contentManifest.d.ts +3 -1
  79. package/dist/_dts/core/src/branded.d.ts +6 -0
  80. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +200 -3
  81. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +8 -1
  82. package/dist/_dts/editor-blocks/src/block-editor/BlockCardBody.d.ts +8 -1
  83. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +8 -2
  84. package/dist/_dts/editor-blocks/src/block-editor/FeatureCardIconsPanel.d.ts +17 -0
  85. package/dist/_dts/editor-blocks/src/block-editor/GeneratedIconSetDialog.d.ts +42 -0
  86. package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +7 -1
  87. package/dist/_dts/editor-blocks/src/block-editor/featureCardIconActions.d.ts +82 -0
  88. package/dist/_dts/editor-blocks/src/index.d.ts +2 -0
  89. package/dist/_dts/editor-blocks/src/widgets/icon-picker/IconPickerField.d.ts +1 -1
  90. package/dist/_dts/media-core/src/fileDomain.d.ts +8 -1
  91. package/dist/_dts/media-editor/src/MediaEditor.d.ts +3 -2
  92. package/dist/_dts/media-react/src/components/MediaLibrary.d.ts +2 -1
  93. package/dist/_dts/media-react/src/components/MediaPickerMini.d.ts +2 -1
  94. package/dist/_dts/preview-next/src/client/blocks/BlockToolbar.d.ts +5 -1
  95. package/dist/_dts/preview-next/src/client/blocks/previewCustomizeActions.d.ts +17 -0
  96. package/dist/_dts/preview-next/src/client/blocks/previewCustomizeControlPlan.d.ts +24 -0
  97. package/dist/_dts/preview-next/src/client/blocks/useBlockCustomizeControls.d.ts +34 -0
  98. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -5
  99. package/dist/_dts/preview-next/src/client/preview/PageDesignEditorStateContext.d.ts +8 -1
  100. package/dist/_dts/preview-next/src/client/preview/PreviewBlockCustomizeSelectionContext.d.ts +20 -0
  101. package/dist/_dts/preview-next/src/client/preview/PreviewOpenEditorButton.d.ts +2 -0
  102. package/dist/_dts/preview-next/src/client/preview/SelectedBlockCustomizePanel.d.ts +13 -0
  103. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +3 -2
  104. package/dist/_dts/preview-next/src/client/preview/previewCustomizeEditorDraftPatch.d.ts +13 -0
  105. package/dist/_dts/preview-next/src/client/preview/previewCustomizeHistory.d.ts +6 -0
  106. package/dist/_dts/preview-next/src/client/preview/previewCustomizeRuntimePatch.d.ts +2 -0
  107. package/dist/_dts/preview-next/src/client/preview/storeTypes.d.ts +4 -0
  108. package/dist/_dts/preview-next/src/client/widgets/widgetOverrides.d.ts +3 -1
  109. package/dist/_dts/sdk/src/cli/commands/webhooks.d.ts +44 -0
  110. package/dist/_dts/sdk/src/cli/navigationIdentity.d.ts +11 -0
  111. package/dist/_dts/sdk/src/cli/site-commands/navigationCommands.d.ts +4 -0
  112. package/dist/_dts/sdk/src/cli/site-commands/oneOffCommands.d.ts +1 -0
  113. package/dist/_dts/sdk/src/cli/sync/diff.d.ts +9 -0
  114. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  115. package/dist/_dts/sdk/src/client/management/types.d.ts +58 -0
  116. package/dist/_dts/sdk/src/client/management/webhooks.d.ts +3 -0
  117. package/dist/_dts/sdk/src/config/field-definitions.d.ts +3 -1
  118. package/dist/_dts/sdk/src/contracts/index.d.ts +1 -1
  119. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +24 -4
  120. package/dist/_dts/sdk/src/next/index.d.ts +1 -1
  121. package/dist/_dts/sdk/src/next/revalidate.d.ts +26 -5
  122. package/dist/_dts/sdk/src/next/static-params.d.ts +28 -3
  123. package/dist/_dts/sdk/src/public-api/contracts.d.ts +5 -1
  124. package/dist/_dts/sdk/src/public-api/runtime.d.ts +1 -1
  125. package/dist/_dts/sdk/src/version.d.ts +1 -1
  126. package/dist/_dts/sdk/src/webhooks/index.d.ts +1 -1
  127. package/dist/_dts/sdk/src/webhooks/verify.d.ts +6 -102
  128. package/dist/_dts/site-commands/src/commands.d.ts +3 -0
  129. package/dist/_dts/theme-core/src/accordions/siteStyleDefaults.d.ts +220 -0
  130. package/dist/_dts/theme-core/src/accordions/types.d.ts +45 -2
  131. package/dist/_dts/theme-core/src/blockOverrides.d.ts +8 -0
  132. package/dist/_dts/theme-core/src/blocks/types.d.ts +1 -1
  133. package/dist/_dts/theme-core/src/blocks/vars/testimonials.d.ts +4 -1
  134. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +1 -1
  135. package/dist/_dts/theme-core/src/cards/core.d.ts +20 -0
  136. package/dist/_dts/theme-core/src/cards/generateDefaultCardSystem.d.ts +6 -3
  137. package/dist/_dts/theme-core/src/cards/siteStyleDefaults.d.ts +105 -0
  138. package/dist/_dts/theme-core/src/cards/types.d.ts +177 -0
  139. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  140. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +159 -21
  141. package/dist/_dts/theme-core/src/palette/variants/index.d.ts +15 -0
  142. package/dist/_dts/theme-core/src/palette/variants/soft-natural.d.ts +16 -0
  143. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +1 -1
  144. package/dist/_dts/theme-core/src/schema.d.ts +451 -57
  145. package/dist/_dts/theme-core/src/site-styles/appearancePresetCatalog.d.ts +86 -17
  146. package/dist/_dts/theme-core/src/site-styles/appearancePresetTypes.d.ts +2 -3
  147. package/dist/_dts/theme-core/src/site-styles/blockAppearancePresets.d.ts +86 -17
  148. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +135 -3
  149. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +5 -5
  150. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +20 -1
  151. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +8 -2
  152. package/dist/_dts/theme-core/src/site-styles/headerLooks.d.ts +286 -6
  153. package/dist/_dts/theme-core/src/site-styles/index.d.ts +2 -0
  154. package/dist/_dts/theme-core/src/site-styles/logoBranding.d.ts +193 -0
  155. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +6 -12
  156. package/dist/_dts/theme-core/src/site-styles/rawStyleFields.d.ts +2 -0
  157. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +10 -7
  158. package/dist/_dts/theme-core/src/site-styles/siteStyleThemeCompiler.d.ts +11 -0
  159. package/dist/_dts/theme-core/src/site-styles/sourceCatalogs.d.ts +2 -2
  160. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +1 -1
  161. package/dist/_dts/theme-core/src/site-styles/testimonialQuotePresets.d.ts +15 -0
  162. package/dist/_dts/theme-core/src/site-styles/tokenRecipes.d.ts +1 -1
  163. package/dist/_dts/theme-core/src/site-styles/types.d.ts +7 -29
  164. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -0
  165. package/dist/_dts/ui/src/combobox.d.ts +1 -0
  166. package/dist/{PreviewEditorSidebar-4DXLYX2V.mjs → chunk-5NZGBSJF.mjs} +2215 -2566
  167. package/dist/{chunk-RGTOD4AJ.mjs → chunk-7PCYG6YV.mjs} +621 -108
  168. package/dist/{chunk-CR5HKAGU.mjs → chunk-BBLZSQEY.mjs} +79 -0
  169. package/dist/{chunk-MCRQMPET.mjs → chunk-GYXKAUFV.mjs} +4500 -912
  170. package/dist/{chunk-6HYXHRAI.mjs → chunk-HTB4BMKD.mjs} +267 -49
  171. package/dist/{chunk-OKMBEAXY.mjs → chunk-MPBNEVPB.mjs} +1 -1
  172. package/dist/cli/index.mjs +3255 -702
  173. package/dist/cli/init-docs/content/workflow-editor-workflows.md +2 -0
  174. package/dist/cli/init-docs/content/workflow-isr-revalidation.md +150 -0
  175. package/dist/client/{accordion-PLYNJIIM.mjs → accordion-QFZMNB7O.mjs} +1 -1
  176. package/dist/client/{bookingForm-BXAP6AO7.mjs → bookingForm-NCIXFWIG.mjs} +3 -3
  177. package/dist/client/bookings.mjs +1246 -323
  178. package/dist/client/{carousel-TRBXDHGF.mjs → carousel-EO4BJMWD.mjs} +2 -2
  179. package/dist/client/{cart-Z7H3HJRS.mjs → cart-FTYCLYUW.mjs} +5 -5
  180. package/dist/client/{checkout-WAFCUBIX.mjs → checkout-NFGLVCOX.mjs} +5 -5
  181. package/dist/client/{chunk-CWGTG37I.mjs → chunk-4W66ALYT.mjs} +1 -1
  182. package/dist/client/{chunk-JRDUHZCT.mjs → chunk-6GVVWSPU.mjs} +4 -4
  183. package/dist/client/{chunk-75OUS5MT.mjs → chunk-IWFZSQNZ.mjs} +1 -1
  184. package/dist/client/{chunk-JGXPTEI2.mjs → chunk-PUOELU4O.mjs} +95 -8
  185. package/dist/client/{chunk-FUXW6VW2.mjs → chunk-PYRBIURC.mjs} +4 -4
  186. package/dist/client/{chunk-ZI3LLBPZ.mjs → chunk-T6UIP6UZ.mjs} +1 -1
  187. package/dist/client/{chunk-DNRGY432.mjs → chunk-VDS5YFLX.mjs} +1 -1
  188. package/dist/client/{chunk-UVQEJJTN.mjs → chunk-Y37KDO7P.mjs} +1 -1
  189. package/dist/client/client.mjs +24277 -20796
  190. package/dist/client/{courseRegistration-AHFQHWIJ.mjs → courseRegistration-2EORROPS.mjs} +3 -3
  191. package/dist/client/{eventCalendar-LDXTV5R7.mjs → eventCalendar-WZI4VL6N.mjs} +5 -5
  192. package/dist/client/{eventCombined-A4JGTNJO.mjs → eventCombined-QCB2TCNL.mjs} +5 -5
  193. package/dist/client/{eventDetails-4YXTZ7EG.mjs → eventDetails-TFTATAPH.mjs} +5 -5
  194. package/dist/client/{eventListing-P72TPFFM.mjs → eventListing-A2CQEHEQ.mjs} +5 -5
  195. package/dist/client/{eventRegistration-LSYJHGMT.mjs → eventRegistration-OELPVLUY.mjs} +5 -5
  196. package/dist/client/{form-AOPYOKOW.mjs → form-NTIFD6WQ.mjs} +1 -1
  197. package/dist/client/{headerSection-5TFYDFVQ.mjs → headerSection-7TBNKCLA.mjs} +65 -24
  198. package/dist/client/hooks.mjs +3687 -2024
  199. package/dist/client/{locationMap-QSZ3ZVAZ.mjs → locationMap-LRLB5A3H.mjs} +1 -1
  200. package/dist/client/{newsletterForm-KTRHZY52.mjs → newsletterForm-XI52RZSN.mjs} +1 -1
  201. package/dist/client/{productDetail-N4E775RG.mjs → productDetail-GSNKBFLY.mjs} +5 -5
  202. package/dist/client/{productList-UGUQ2S45.mjs → productList-BGCGT4KZ.mjs} +5 -5
  203. package/dist/client/rendering/client.mjs +5274 -3030
  204. package/dist/client/rendering/islands.mjs +18 -18
  205. package/dist/client/rendering.mjs +6271 -2790
  206. package/dist/client/{shop-VHSZEEQ2.mjs → shop-RQHUCLNY.mjs} +5 -5
  207. package/dist/preview-next/before-render.mjs +79 -0
  208. package/dist/preview-next/client/runtime.mjs +5 -5
  209. package/dist/preview-next/middleware.mjs +79 -0
  210. package/dist/{sdk-runtime-WHPJEF5G.mjs → sdk-runtime-A4LHT2RS.mjs} +6 -6
  211. package/dist/server/components.mjs +6215 -3057
  212. package/dist/server/config-validation.mjs +3858 -2194
  213. package/dist/server/config.mjs +3858 -2194
  214. package/dist/server/data.mjs +3687 -2024
  215. package/dist/server/index.mjs +88 -1
  216. package/dist/server/next/revalidate.mjs +229 -34
  217. package/dist/server/next.mjs +6295 -3036
  218. package/dist/server/page-converter.mjs +3055 -1883
  219. package/dist/server/prebuild.mjs +1 -1
  220. package/dist/server/rendering/server.mjs +6220 -3062
  221. package/dist/server/rendering.mjs +6233 -3075
  222. package/dist/server/routing.mjs +4251 -2137
  223. package/dist/server/server.mjs +3705 -2042
  224. package/dist/server/theme-bridge.mjs +1617 -329
  225. package/dist/server/theme.mjs +411 -221
  226. package/dist/server/webhooks.mjs +129 -25
  227. package/dist/styles/index.css +355 -33
  228. package/package.json +2 -1
  229. package/dist/SdkPreviewModeRuntime-IJDHTW4W.mjs +0 -8
  230. package/dist/chunk-4QEGTLK6.mjs +0 -1175
@@ -1,53 +1,151 @@
1
1
  // src/webhooks/verify.ts
2
2
  import crypto from "crypto";
3
+
4
+ // ../api/src/webhooks.ts
3
5
  import { z } from "zod";
4
- var WebhookEventSchema = z.enum([
6
+ var RIVERBANK_SIGNATURE_PREFIX = "sha256=";
7
+ var SUPPORTED_WEBHOOK_EVENTS = [
5
8
  "page.published",
9
+ "page.unpublished",
10
+ "page.deleted",
11
+ "page.path_changed",
6
12
  "entry.published",
13
+ "entry.unpublished",
14
+ "entry.deleted",
15
+ "entry.path_changed",
7
16
  "navigation.updated",
8
17
  "theme.updated",
9
18
  "site.settings_updated"
10
- ]);
19
+ ];
20
+ var WebhookEventSchema = z.enum(SUPPORTED_WEBHOOK_EVENTS);
21
+ function asRevalidationPath(path) {
22
+ return path;
23
+ }
24
+ function parseRevalidationPath(input) {
25
+ const trimmed = input.trim();
26
+ if (!trimmed) {
27
+ return { success: false, error: { tag: "EMPTY_PATH", input } };
28
+ }
29
+ if (/^[a-z][a-z\d+.-]*:/i.test(trimmed) || trimmed.startsWith("//") || !trimmed.startsWith("/")) {
30
+ return { success: false, error: { tag: "ABSOLUTE_OR_PROTOCOL_PATH", input } };
31
+ }
32
+ if (/[\u0000-\u001F\u007F]/.test(trimmed) || trimmed.includes("\\") || trimmed.includes("?") || trimmed.includes("#")) {
33
+ return { success: false, error: { tag: "MALFORMED_PATH", input } };
34
+ }
35
+ const collapsed = trimmed.replace(/\/{2,}/g, "/");
36
+ const normalized = collapsed === "/" ? "/" : collapsed.replace(/\/+$/g, "");
37
+ return { success: true, path: asRevalidationPath(normalized) };
38
+ }
39
+ function normalizeRevalidationPath(input) {
40
+ const result = parseRevalidationPath(input);
41
+ return result.success ? result.path : null;
42
+ }
43
+ function unwrapRevalidationPath(path) {
44
+ return path;
45
+ }
11
46
  var PagePublishedDataSchema = z.object({
12
47
  pageId: z.string(),
13
48
  path: z.string(),
14
49
  slug: z.string().optional()
15
- });
50
+ }).strict();
51
+ var PageRemovedDataSchema = z.object({
52
+ pageId: z.string(),
53
+ path: z.string(),
54
+ slug: z.string().optional()
55
+ }).strict();
56
+ var PagePathChangedDataSchema = z.object({
57
+ pageId: z.string(),
58
+ previousPath: z.string(),
59
+ path: z.string(),
60
+ slug: z.string().optional()
61
+ }).strict();
16
62
  var EntryPublishedDataSchema = z.object({
17
63
  entryId: z.string(),
18
64
  path: z.string(),
19
65
  contentType: z.string()
20
- });
66
+ }).strict();
67
+ var EntryRemovedDataSchema = z.object({
68
+ entryId: z.string(),
69
+ path: z.string(),
70
+ contentType: z.string()
71
+ }).strict();
72
+ var EntryPathChangedDataSchema = z.object({
73
+ entryId: z.string(),
74
+ previousPath: z.string(),
75
+ path: z.string(),
76
+ contentType: z.string()
77
+ }).strict();
21
78
  var NavigationUpdatedDataSchema = z.object({
22
79
  menuId: z.string().optional()
23
- });
24
- var EmptyDataSchema = z.object({});
25
- var WebhookDataSchema = z.union([
26
- PagePublishedDataSchema,
27
- EntryPublishedDataSchema,
28
- NavigationUpdatedDataSchema,
29
- EmptyDataSchema
30
- ]);
31
- var WebhookPayloadSchema = z.object({
32
- /** Event type */
33
- event: WebhookEventSchema,
34
- /** ISO timestamp of when the event occurred */
80
+ }).strict();
81
+ var EmptyWebhookDataSchema = z.object({}).strict();
82
+ var WebhookPayloadBaseSchema = z.object({
35
83
  timestamp: z.string(),
36
- /** Site ID that triggered the event */
84
+ dispatchId: z.string().optional(),
37
85
  siteId: z.string(),
38
- /** Event-specific data (shape depends on event type) */
39
- data: z.record(z.string(), z.unknown()),
40
- /** Cache invalidation tags (for tag-based revalidation) */
41
- tags: z.array(z.string()).optional()
86
+ tags: z.array(z.string()).optional(),
87
+ paths: z.array(z.string()).optional()
42
88
  });
89
+ var WebhookPayloadSchema = z.discriminatedUnion("event", [
90
+ WebhookPayloadBaseSchema.extend({
91
+ event: z.literal("page.published"),
92
+ data: PagePublishedDataSchema
93
+ }),
94
+ WebhookPayloadBaseSchema.extend({
95
+ event: z.literal("page.unpublished"),
96
+ data: PageRemovedDataSchema
97
+ }),
98
+ WebhookPayloadBaseSchema.extend({
99
+ event: z.literal("page.deleted"),
100
+ data: PageRemovedDataSchema
101
+ }),
102
+ WebhookPayloadBaseSchema.extend({
103
+ event: z.literal("page.path_changed"),
104
+ data: PagePathChangedDataSchema
105
+ }),
106
+ WebhookPayloadBaseSchema.extend({
107
+ event: z.literal("entry.published"),
108
+ data: EntryPublishedDataSchema
109
+ }),
110
+ WebhookPayloadBaseSchema.extend({
111
+ event: z.literal("entry.unpublished"),
112
+ data: EntryRemovedDataSchema
113
+ }),
114
+ WebhookPayloadBaseSchema.extend({
115
+ event: z.literal("entry.deleted"),
116
+ data: EntryRemovedDataSchema
117
+ }),
118
+ WebhookPayloadBaseSchema.extend({
119
+ event: z.literal("entry.path_changed"),
120
+ data: EntryPathChangedDataSchema
121
+ }),
122
+ WebhookPayloadBaseSchema.extend({
123
+ event: z.literal("navigation.updated"),
124
+ data: NavigationUpdatedDataSchema
125
+ }),
126
+ WebhookPayloadBaseSchema.extend({
127
+ event: z.literal("theme.updated"),
128
+ data: EmptyWebhookDataSchema
129
+ }),
130
+ WebhookPayloadBaseSchema.extend({
131
+ event: z.literal("site.settings_updated"),
132
+ data: EmptyWebhookDataSchema
133
+ })
134
+ ]);
135
+
136
+ // src/webhooks/verify.ts
43
137
  function verifyWebhookSignature(payload, signature, secret) {
44
- const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
45
- if (signature.length !== expectedSignature.length) {
138
+ if (!signature.startsWith(RIVERBANK_SIGNATURE_PREFIX)) {
46
139
  return false;
47
140
  }
141
+ const signatureDigest = signature.slice(RIVERBANK_SIGNATURE_PREFIX.length);
142
+ if (!/^[a-f0-9]{64}$/.test(signatureDigest)) {
143
+ return false;
144
+ }
145
+ const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
48
146
  return crypto.timingSafeEqual(
49
- Buffer.from(signature),
50
- Buffer.from(expectedSignature)
147
+ Buffer.from(signatureDigest, "hex"),
148
+ Buffer.from(expectedSignature, "hex")
51
149
  );
52
150
  }
53
151
  function parseWebhookPayload(body) {
@@ -64,7 +162,13 @@ function parseWebhookPayload(body) {
64
162
  return { success: true, payload: result.data };
65
163
  }
66
164
  export {
165
+ RIVERBANK_SIGNATURE_PREFIX,
166
+ SUPPORTED_WEBHOOK_EVENTS,
167
+ WebhookEventSchema,
67
168
  WebhookPayloadSchema,
169
+ normalizeRevalidationPath,
170
+ parseRevalidationPath,
68
171
  parseWebhookPayload,
172
+ unwrapRevalidationPath,
69
173
  verifyWebhookSignature
70
174
  };
@@ -1576,40 +1576,51 @@
1576
1576
  }
1577
1577
 
1578
1578
  .rb-container-pad-none {
1579
- padding: 0;
1579
+ --rb-card-pad: 0rem;
1580
+ padding: var(--rb-card-pad);
1580
1581
  }
1581
1582
  .rb-container-pad-compact {
1582
- padding: 1rem;
1583
+ --rb-card-pad: 1rem;
1584
+ padding: var(--rb-card-pad);
1583
1585
  }
1584
1586
  .rb-container-pad-cozy {
1585
- padding: 1.5rem;
1587
+ --rb-card-pad: 1.5rem;
1588
+ padding: var(--rb-card-pad);
1586
1589
  }
1587
1590
  .rb-container-pad-medium {
1588
- padding: 1.5rem;
1591
+ --rb-card-pad: 1.5rem;
1592
+ padding: var(--rb-card-pad);
1589
1593
  }
1590
1594
  .rb-container-pad-comfortable {
1591
- padding: 2rem;
1595
+ --rb-card-pad: 2rem;
1596
+ padding: var(--rb-card-pad);
1592
1597
  }
1593
1598
  .rb-container-pad-spacious {
1594
- padding: 2.5rem;
1599
+ --rb-card-pad: 2.5rem;
1600
+ padding: var(--rb-card-pad);
1595
1601
  }
1596
1602
 
1597
1603
  @media (min-width: 640px) {
1598
1604
  @scope ([data-rb-responsive-mode="viewport"]) to (:scope [data-rb-responsive-mode]) {
1599
1605
  .rb-container-pad-compact {
1600
- padding: 1.5rem;
1606
+ --rb-card-pad: 1.5rem;
1607
+ padding: var(--rb-card-pad);
1601
1608
  }
1602
1609
  .rb-container-pad-cozy {
1603
- padding: 2rem;
1610
+ --rb-card-pad: 2rem;
1611
+ padding: var(--rb-card-pad);
1604
1612
  }
1605
1613
  .rb-container-pad-medium {
1606
- padding: 2rem;
1614
+ --rb-card-pad: 2rem;
1615
+ padding: var(--rb-card-pad);
1607
1616
  }
1608
1617
  .rb-container-pad-comfortable {
1609
- padding: 2.5rem;
1618
+ --rb-card-pad: 2.5rem;
1619
+ padding: var(--rb-card-pad);
1610
1620
  }
1611
1621
  .rb-container-pad-spacious {
1612
- padding: 3.5rem;
1622
+ --rb-card-pad: 3.5rem;
1623
+ padding: var(--rb-card-pad);
1613
1624
  }
1614
1625
  }
1615
1626
  }
@@ -1782,8 +1793,15 @@
1782
1793
  /* Shared: Site document overlay header clearance */
1783
1794
  /* -------------------------------------------------------------------------- */
1784
1795
 
1785
- :where(.theme-scope) :where([data-site-document-overlay-content='true']) :where([data-block]):first-of-type > :where([data-slot='section']) > :where(.rb-container) {
1786
- padding-top: calc(var(--site-overlay-header-clearance, 0px) + var(--site-overlay-opening-content-extra-pad, 0px));
1796
+ :where(.theme-scope)
1797
+ :where([data-site-document-overlay-content='true'])
1798
+ :where([data-block]):first-of-type
1799
+ > :where([data-slot='section'])
1800
+ > :where(.rb-container) {
1801
+ padding-top: calc(
1802
+ var(--site-overlay-header-clearance, 0px) +
1803
+ var(--site-overlay-opening-content-extra-pad, 0px)
1804
+ );
1787
1805
  }
1788
1806
 
1789
1807
  /* -------------------------------------------------------------------------- */
@@ -1869,6 +1887,22 @@
1869
1887
  }
1870
1888
  }
1871
1889
 
1890
+ /* -------------------------------------------------------------------------- */
1891
+ /* Header: Mobile floating/glass backing */
1892
+ /* -------------------------------------------------------------------------- */
1893
+
1894
+ :where(.theme-scope) .header-variant-floating .header-mobile-bar {
1895
+ align-items: flex-start;
1896
+ margin-top: 0.75rem;
1897
+ }
1898
+
1899
+ :where(.theme-scope) .header-variant-floating .nav-mobile-toggle {
1900
+ border: 1px solid rgb(var(--tb-border) / 0.82);
1901
+ background: rgb(var(--tb-surface) / 0.96);
1902
+ color: rgb(var(--tb-text));
1903
+ box-shadow: 0 10px 28px rgb(var(--tb-neutral-950) / 0.12);
1904
+ }
1905
+
1872
1906
  /*
1873
1907
  * Theme Scope Styles
1874
1908
  *
@@ -2797,6 +2831,56 @@
2797
2831
  transition: height 300ms var(--motion-ease, ease);
2798
2832
  }
2799
2833
 
2834
+ :where(.theme-scope) .header-logo-size-compact.rb-header-logo-sm {
2835
+ height: 2rem;
2836
+ }
2837
+ :where(.theme-scope) .header-logo-size-compact.rb-header-logo-lg {
2838
+ height: 2.5rem;
2839
+ }
2840
+ :where(.theme-scope) .header-logo-size-standard.rb-header-logo-sm {
2841
+ height: 2.5rem;
2842
+ }
2843
+ :where(.theme-scope) .header-logo-size-standard.rb-header-logo-lg {
2844
+ height: 3rem;
2845
+ }
2846
+ :where(.theme-scope) .header-logo-size-generous.rb-header-logo-sm {
2847
+ height: 3.5rem;
2848
+ }
2849
+ :where(.theme-scope) .header-logo-size-generous.rb-header-logo-lg {
2850
+ height: 4.5rem;
2851
+ }
2852
+ :where(.theme-scope) .header-logo-size-display.rb-header-logo-sm {
2853
+ height: 7.5rem;
2854
+ }
2855
+ :where(.theme-scope) .header-logo-size-display.rb-header-logo-lg {
2856
+ height: 8rem;
2857
+ }
2858
+
2859
+ :where(.theme-scope) .header-logo-accommodation-plate,
2860
+ :where(.theme-scope) .header-logo-accommodation-centered-badge,
2861
+ :where(.theme-scope) .header-logo-accommodation-popout-badge,
2862
+ :where(.theme-scope) .header-logo-accommodation-centered-masthead {
2863
+ border-radius: var(--radius-md, 0.5rem);
2864
+ background: var(--color-surface, #fff);
2865
+ box-shadow: var(--shadow-sm, 0 1px 2px rgb(0 0 0 / 0.08));
2866
+ padding: 0.5rem;
2867
+ }
2868
+
2869
+ :where(.theme-scope) .header-logo-accommodation-popout-badge {
2870
+ position: relative;
2871
+ z-index: 1;
2872
+ margin-block: -0.35rem -0.9rem;
2873
+ }
2874
+
2875
+ :where(.theme-scope)
2876
+ .header-logo-size-display.header-logo-accommodation-popout-badge {
2877
+ margin-block: -0.75rem -2rem;
2878
+ }
2879
+
2880
+ :where(.theme-scope) .header-logo-accommodation-centered-masthead {
2881
+ padding: 0.75rem 1rem;
2882
+ }
2883
+
2800
2884
  /* Site title base font size (replaces rb-text-lg / rb-text-xl utilities) */
2801
2885
  :where(.theme-scope) .header-logo-text {
2802
2886
  font-size: 1.125rem; /* matches rb-text-lg */
@@ -2833,11 +2917,43 @@
2833
2917
  :where(.theme-scope) .rb-header-shrink.header-scrolled .rb-header-logo-lg {
2834
2918
  height: 2.5rem;
2835
2919
  }
2920
+ :where(.theme-scope)
2921
+ .rb-header-shrink.header-scrolled
2922
+ .header-logo-size-generous.rb-header-logo-sm {
2923
+ height: 2.75rem;
2924
+ }
2925
+ :where(.theme-scope)
2926
+ .rb-header-shrink.header-scrolled
2927
+ .header-logo-size-generous.rb-header-logo-lg {
2928
+ height: 3.25rem;
2929
+ }
2930
+ :where(.theme-scope)
2931
+ .rb-header-shrink.header-scrolled
2932
+ .header-logo-size-display.rb-header-logo-sm,
2933
+ :where(.theme-scope)
2934
+ .rb-header-shrink.header-scrolled
2935
+ .header-logo-size-display.rb-header-logo-lg {
2936
+ height: 5rem;
2937
+ }
2836
2938
  :where(.theme-scope) .rb-header-shrink.header-scrolled .header-logo-text {
2837
2939
  font-size: 0.875rem;
2838
2940
  }
2839
2941
 
2840
2942
  @media (max-width: 767px) {
2943
+ :where(.theme-scope) .header-logo-size-generous.rb-header-logo-sm,
2944
+ :where(.theme-scope) .header-logo-size-generous.rb-header-logo-lg {
2945
+ height: 3rem;
2946
+ }
2947
+
2948
+ :where(.theme-scope) .header-logo-size-display.rb-header-logo-sm,
2949
+ :where(.theme-scope) .header-logo-size-display.rb-header-logo-lg {
2950
+ height: 5.5rem;
2951
+ }
2952
+
2953
+ :where(.theme-scope) .header-logo-accommodation-popout-badge {
2954
+ margin-block: 0;
2955
+ }
2956
+
2841
2957
  :where(.theme-scope) .rb-header-shrink.header-scrolled .header-logo-text {
2842
2958
  font-size: 0.75rem;
2843
2959
  }
@@ -7611,11 +7727,13 @@
7611
7727
  }
7612
7728
 
7613
7729
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonial-quote {
7730
+ display: var(--rb-testimonial-quote-display, block);
7731
+ font-family: var(--rb-testimonial-quote-font, inherit);
7614
7732
  font-size: var(--rb-testimonial-quote-size);
7615
7733
  line-height: 1;
7616
- font-weight: 700;
7734
+ font-weight: var(--rb-testimonial-quote-weight, 700);
7617
7735
  opacity: var(--rb-testimonial-quote-opacity);
7618
- color: rgb(var(--tb-primary));
7736
+ color: var(--rb-testimonial-quote-color, rgb(var(--tb-primary)));
7619
7737
  }
7620
7738
 
7621
7739
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-accent-quote .rb-testimonial-quote {
@@ -7624,6 +7742,59 @@
7624
7742
  opacity: 1;
7625
7743
  }
7626
7744
 
7745
+ /* Open editorial testimonial card: boxless, with a hairline rule before the
7746
+ * attribution, an accent ring on the avatar, and comfortable prose. The quote
7747
+ * mark itself is owned by the site-style quote treatment (see the
7748
+ * --rb-testimonial-quote-* vars), not by these rules.
7749
+ *
7750
+ * `editorial-open` is the current non-carded look; `editorial-serif-quote` is
7751
+ * retained for content saved before the decomposition. */
7752
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonial-card.rb-card-treatment-editorial-open,
7753
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonial-card.rb-card-treatment-editorial-serif-quote {
7754
+ background: transparent;
7755
+ border: 0;
7756
+ border-radius: 0;
7757
+ padding: 0.25rem clamp(0.5rem, 1.5vw, 1.5rem);
7758
+ }
7759
+
7760
+ /* styledCard always renders an inner white rb-bg-surface fill layer; a boxless
7761
+ * card must clear it so the section band shows through (otherwise: white box). */
7762
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-open > .rb-bg-surface,
7763
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-serif-quote > .rb-bg-surface {
7764
+ background: transparent;
7765
+ }
7766
+
7767
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-open .rb-prose,
7768
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-serif-quote .rb-prose {
7769
+ font-size: 1.0625rem;
7770
+ line-height: 1.7;
7771
+ }
7772
+
7773
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-open .rb-testimonial-attribution,
7774
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-serif-quote .rb-testimonial-attribution {
7775
+ margin-top: 1.25rem;
7776
+ padding-top: 1.25rem;
7777
+ border-top: 1px solid rgba(var(--tb-border), 0.75);
7778
+ }
7779
+
7780
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-open .rb-testimonial-avatar,
7781
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-card-treatment-editorial-serif-quote .rb-testimonial-avatar {
7782
+ box-shadow:
7783
+ 0 0 0 2px rgb(var(--tb-surface)),
7784
+ 0 0 0 4px rgba(var(--tb-primary), 0.3);
7785
+ }
7786
+
7787
+
7788
+ /* Split grid: title column + cards. On desktop the title takes one quarter and
7789
+ * the cards fill the remaining three quarters (so title + 3 cards each read as
7790
+ * a quarter). Stacks on mobile. */
7791
+ @media (min-width: 1024px) {
7792
+ :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-split-grid {
7793
+ grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
7794
+ align-items: start;
7795
+ }
7796
+ }
7797
+
7627
7798
 
7628
7799
  /* Testimonials carousel tweaks: arrow styling + gutters + equal-height cards */
7629
7800
  :where(.theme-scope) :where([data-block="testimonials"]) .rb-testimonials-carousel.carousel-root .carousel-nav-btn {
@@ -9103,10 +9274,10 @@
9103
9274
 
9104
9275
  :where(.theme-scope) .event-compact-row {
9105
9276
  display: grid;
9106
- grid-template-columns: clamp(5.5rem, 8vw, 8rem) minmax(0, 1fr) clamp(15rem, 24vw, 21rem);
9277
+ grid-template-columns: clamp(5rem, 7vw, 7rem) minmax(0, 1fr) clamp(15rem, 24vw, 21rem);
9107
9278
  align-items: center;
9108
- min-height: 8.75rem;
9109
- padding: 1.55rem clamp(1.5rem, 3vw, 2.6rem);
9279
+ min-height: 6.75rem;
9280
+ padding: 1.35rem clamp(1.5rem, 3vw, 2.6rem);
9110
9281
  border-bottom: 1px solid var(--event-compact-divider-color);
9111
9282
  transition: background-color 150ms ease;
9112
9283
  }
@@ -9145,10 +9316,10 @@
9145
9316
  :where(.theme-scope) .event-compact-row-date-day {
9146
9317
  display: grid;
9147
9318
  place-items: center;
9148
- min-block-size: clamp(2.7rem, 4.5vw, 3.7rem);
9319
+ min-block-size: clamp(2rem, 3vw, 2.6rem);
9149
9320
  color: rgb(var(--tb-text, 17 24 39));
9150
9321
  font-family: var(--font-heading, var(--font-body, inherit));
9151
- font-size: clamp(2.3rem, 4.2vw, 3.35rem);
9322
+ font-size: clamp(1.7rem, 1.35rem + 1.1vw, 2.35rem);
9152
9323
  font-weight: 400;
9153
9324
  line-height: 1;
9154
9325
  }
@@ -9168,9 +9339,10 @@
9168
9339
  margin: 0;
9169
9340
  color: rgb(var(--tb-text, 17 24 39));
9170
9341
  font-family: var(--font-heading, var(--font-body, inherit));
9171
- font-size: clamp(1.55rem, 2.6vw, 2.4rem);
9342
+ /* Row titles sit at the theme's h3 scale so section headings stay dominant */
9343
+ font-size: var(--fs-h3-fluid, clamp(1.1rem, 1rem + 0.7vw, 1.5rem));
9172
9344
  font-weight: 400;
9173
- line-height: 1.05;
9345
+ line-height: 1.2;
9174
9346
  overflow: hidden;
9175
9347
  text-overflow: ellipsis;
9176
9348
  white-space: nowrap;
@@ -9282,7 +9454,7 @@
9282
9454
  }
9283
9455
 
9284
9456
  :where(.theme-scope) .event-compact-row-date-day {
9285
- font-size: 2.35rem;
9457
+ font-size: 1.85rem;
9286
9458
  }
9287
9459
 
9288
9460
  :where(.theme-scope) .event-compact-row-content {
@@ -9292,7 +9464,7 @@
9292
9464
  }
9293
9465
 
9294
9466
  :where(.theme-scope) .event-compact-row-title {
9295
- font-size: clamp(1.35rem, 8vw, 1.9rem);
9467
+ font-size: clamp(1.15rem, 5vw, 1.35rem);
9296
9468
  white-space: normal;
9297
9469
  }
9298
9470
 
@@ -9375,19 +9547,23 @@
9375
9547
  * =============================================================================
9376
9548
  */
9377
9549
 
9378
- :where(.theme-scope) .rb-heading-decoration {
9550
+ /*
9551
+ * The mark sits inside a full-width block row so it inherits the heading group's
9552
+ * `text-align`: a centred heading centres the mark, a left-aligned heading keeps
9553
+ * it at the start. The heading stacks are flexbox, where `text-align` positions
9554
+ * inline content but not flex items — so the row (a stretched block flex item)
9555
+ * is what carries the alignment, and the inline-block mark follows it. Alignment
9556
+ * is never configured directly; it follows the heading.
9557
+ */
9558
+ :where(.theme-scope) .rb-heading-decoration-row {
9379
9559
  display: block;
9380
- flex: 0 0 auto;
9381
- pointer-events: none;
9382
- }
9383
-
9384
- :where(.theme-scope) .rb-heading-decoration-placement-after-heading {
9560
+ width: 100%;
9385
9561
  margin-top: 0.35rem;
9562
+ pointer-events: none;
9386
9563
  }
9387
9564
 
9388
- :where(.theme-scope) .rb-heading-decoration-placement-under-centered-heading {
9389
- margin-left: auto;
9390
- margin-right: auto;
9565
+ :where(.theme-scope) .rb-heading-decoration {
9566
+ display: inline-block;
9391
9567
  }
9392
9568
 
9393
9569
  :where(.theme-scope) .rb-heading-decoration-organic-squiggle {
@@ -9432,3 +9608,149 @@
9432
9608
  }
9433
9609
 
9434
9610
 
9611
+ /* =============================================================================
9612
+ * Block: Feature Card Icons
9613
+ * =============================================================================
9614
+ */
9615
+
9616
+ :where(.theme-scope) .rb-feature-card-icon-zone {
9617
+ display: inline-flex;
9618
+ align-items: center;
9619
+ justify-content: center;
9620
+ flex: 0 0 auto;
9621
+ margin-bottom: 0.125rem;
9622
+ color: rgb(var(--tb-primary));
9623
+ }
9624
+
9625
+ :where(.theme-scope) .rb-feature-card-icon-zone--empty {
9626
+ visibility: hidden;
9627
+ }
9628
+
9629
+ :where(.theme-scope) .rb-feature-card-icon-zone--plain {
9630
+ width: 1.5rem;
9631
+ height: 1.5rem;
9632
+ }
9633
+
9634
+ :where(.theme-scope) .rb-feature-card-icon-zone--soft-badge,
9635
+ :where(.theme-scope) .rb-feature-card-icon-zone--utility-badge {
9636
+ width: 2.5rem;
9637
+ height: 2.5rem;
9638
+ border-radius: var(--rb-block-radius, 0.75rem);
9639
+ }
9640
+
9641
+ :where(.theme-scope) .rb-feature-card-icon-zone--soft-badge {
9642
+ background-color: rgb(var(--tb-primary) / 10%);
9643
+ }
9644
+
9645
+ :where(.theme-scope) .rb-feature-card-icon-zone--utility-badge {
9646
+ background-color: rgb(var(--tb-surface));
9647
+ border: 1px solid rgb(var(--tb-border));
9648
+ box-shadow: 0 1px 2px rgba(var(--tb-shadow), 0.08);
9649
+ }
9650
+
9651
+ :where(.theme-scope) .rb-feature-card-icon {
9652
+ width: 1.25rem;
9653
+ height: 1.25rem;
9654
+ }
9655
+
9656
+ :where(.theme-scope) .rb-feature-card-icon--generated {
9657
+ object-fit: contain;
9658
+ }
9659
+
9660
+ :where(.theme-scope) .rb-feature-card-icon-zone--plain .rb-feature-card-icon {
9661
+ width: 1.5rem;
9662
+ height: 1.5rem;
9663
+ }
9664
+
9665
+
9666
+ /* =============================================================================
9667
+ * Shared: Card treatments
9668
+ *
9669
+ * Visual treatments referenced from `_cardStyles.treatment` (see
9670
+ * cardStylesOverrideSchema). Class names are emitted by the boxStyles
9671
+ * transform in @riverbankcms/blocks.
9672
+ *
9673
+ * Also contains feature-card media/padding behaviour shared by all looks:
9674
+ * - card images bleed to the card edges (flush photo tops)
9675
+ * - card-level padding replaces the content stack's fallback padding so the
9676
+ * two never stack up
9677
+ * ============================================================================= */
9678
+
9679
+ /* --- Feature card media + padding behaviour (all looks) -------------------- */
9680
+
9681
+ /*
9682
+ * When a look gives the card real padding (rb-container-pad-*), the image
9683
+ * bleeds to the card edges and the inner content stack drops its fallback
9684
+ * padding so insets don't double up.
9685
+ */
9686
+ :where(.theme-scope) .rb-feature-card[class*="rb-container-pad-"]:not(.rb-container-pad-none) > .rb-feature-card-media {
9687
+ width: calc(100% + 2 * var(--rb-card-pad, 0rem));
9688
+ max-width: none;
9689
+ margin: calc(-1 * var(--rb-card-pad, 0rem)) calc(-1 * var(--rb-card-pad, 0rem)) 0;
9690
+ }
9691
+
9692
+ :where(.theme-scope) .rb-feature-card[class*="rb-container-pad-"]:not(.rb-container-pad-none) > .rb-feature-card-media + .rb-feature-card-content {
9693
+ margin-top: 1.4rem;
9694
+ }
9695
+
9696
+ :where(.theme-scope) .rb-feature-card[class*="rb-container-pad-"]:not(.rb-container-pad-none) > .rb-feature-card-content {
9697
+ padding: 0;
9698
+ }
9699
+
9700
+ /* --- Soft panel ------------------------------------------------------------ */
9701
+
9702
+ :where(.theme-scope) .rb-card-treatment-soft-panel {
9703
+ transition: transform 250ms ease, box-shadow 250ms ease;
9704
+ }
9705
+
9706
+ @media (prefers-reduced-motion: no-preference) {
9707
+ :where(.theme-scope) .rb-card-treatment-soft-panel:hover {
9708
+ transform: translateY(-3px);
9709
+ box-shadow: 0 0.875rem 1.875rem rgba(var(--tb-shadow, 0 0 0), 0.1);
9710
+ }
9711
+ }
9712
+
9713
+ :where(.theme-scope) .rb-card-treatment-soft-panel .cta-row .button-ghost {
9714
+ padding-inline: 0;
9715
+ }
9716
+
9717
+ /* --- Editorial rule --------------------------------------------------------- */
9718
+
9719
+ /*
9720
+ * Boxless open column: no background, no border box, a short brand rule
9721
+ * sitting on a full-width hairline at the top of the column.
9722
+ */
9723
+ :where(.theme-scope) .rb-card-treatment-editorial-rule {
9724
+ margin-top: 1rem;
9725
+ border-top: 1px solid
9726
+ color-mix(in oklab, rgb(var(--tb-border, 229 231 235)), transparent 25%);
9727
+ }
9728
+
9729
+ :where(.theme-scope) .rb-card-treatment-editorial-rule > .rb-bg-surface {
9730
+ background: transparent;
9731
+ }
9732
+
9733
+ :where(.theme-scope) .rb-card-treatment-editorial-rule::before {
9734
+ content: "";
9735
+ position: absolute;
9736
+ top: 0;
9737
+ left: 0;
9738
+ width: 2.75rem;
9739
+ height: 2px;
9740
+ background: rgb(var(--tb-primary, 0 0 0));
9741
+ }
9742
+
9743
+ :where(.theme-scope) .rb-card-treatment-editorial-rule > .rb-feature-card-media {
9744
+ margin-top: 1.6rem;
9745
+ border-radius: calc(var(--rb-block-radius, 0.75rem) * 0.5);
9746
+ }
9747
+
9748
+ :where(.theme-scope) .rb-card-treatment-editorial-rule > .rb-feature-card-content {
9749
+ padding: 1.6rem 0 0.25rem;
9750
+ }
9751
+
9752
+ :where(.theme-scope) .rb-card-treatment-editorial-rule .cta-row .button-ghost {
9753
+ padding-inline: 0;
9754
+ }
9755
+
9756
+