@riverbankcms/sdk 0.64.0 → 0.67.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 (78) hide show
  1. package/dist/_dts/api/src/aiPlayground.d.ts +18 -11
  2. package/dist/_dts/api/src/apiEndpointTypes.d.ts +12 -0
  3. package/dist/_dts/api/src/bookingOperations.d.ts +1 -1
  4. package/dist/_dts/api/src/endpoints.d.ts +25 -0
  5. package/dist/_dts/api/src/sdkConfig/contracts.d.ts +0 -40
  6. package/dist/_dts/api/src/sdkContracts.d.ts +1 -1
  7. package/dist/_dts/api/src/siteMembers.d.ts +1 -1
  8. package/dist/_dts/api/src/siteOperations.d.ts +1 -1
  9. package/dist/_dts/billing/src/plans/types.d.ts +1 -1
  10. package/dist/_dts/blocks/src/bindings/index.d.ts +1 -1
  11. package/dist/_dts/blocks/src/system/node/validation-constants.d.ts +1 -1
  12. package/dist/_dts/blocks/src/system/transforms/registry/formatting.d.ts +1 -0
  13. package/dist/_dts/blocks/src/system/transforms/typed.d.ts +2 -1
  14. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +81 -0
  15. package/dist/_dts/preview-next/src/client/blocks/pageDesignRuntimePreview.d.ts +7 -3
  16. package/dist/_dts/preview-next/src/client/blocks/previewProjection/runtimeContentDecoration.d.ts +2 -2
  17. package/dist/_dts/sdk/src/cli/commands/push/execute/footer.d.ts +33 -0
  18. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +2 -1
  19. package/dist/_dts/sdk/src/cli/env.d.ts +2 -1
  20. package/dist/_dts/sdk/src/cli/merge-remote/entryMergePush.d.ts +2 -1
  21. package/dist/_dts/sdk/src/cli/site-commands/commandKeys.d.ts +13 -0
  22. package/dist/_dts/sdk/src/cli/site-commands/commandRuntime.d.ts +114 -0
  23. package/dist/_dts/sdk/src/cli/site-commands/entryCommands.d.ts +26 -48
  24. package/dist/_dts/sdk/src/cli/site-commands/footerCommands.d.ts +50 -0
  25. package/dist/_dts/sdk/src/cli/site-commands/formCommands.d.ts +57 -0
  26. package/dist/_dts/sdk/src/cli/site-commands/index.d.ts +5 -0
  27. package/dist/_dts/sdk/src/cli/site-commands/navigationCommands.d.ts +57 -0
  28. package/dist/_dts/sdk/src/cli/site-commands/pageCommands.d.ts +83 -0
  29. package/dist/_dts/sdk/src/cli/site-commands/pushExecution.d.ts +67 -14
  30. package/dist/_dts/sdk/src/cli/sync/executor.d.ts +10 -28
  31. package/dist/_dts/sdk/src/cli/sync/index.d.ts +1 -1
  32. package/dist/_dts/sdk/src/config/dashboard-validation.d.ts +0 -48
  33. package/dist/_dts/sdk/src/config/types.d.ts +1 -1
  34. package/dist/_dts/sdk/src/version.d.ts +1 -1
  35. package/dist/_dts/site-commands/src/adapter.d.ts +2 -2
  36. package/dist/_dts/site-commands/src/commands.d.ts +410 -13
  37. package/dist/_dts/site-commands/src/domain.d.ts +3 -3
  38. package/dist/_dts/site-commands/src/exposure.d.ts +41 -0
  39. package/dist/_dts/site-commands/src/index.d.ts +1 -0
  40. package/dist/_dts/site-commands/src/metadata.d.ts +93 -2
  41. package/dist/_dts/site-commands/src/planner.d.ts +13 -6
  42. package/dist/_dts/site-commands/src/refs.d.ts +13 -1
  43. package/dist/_dts/theme-core/src/palette/utils/index.d.ts +1 -0
  44. package/dist/_dts/theme-core/src/palette/utils/onColor.d.ts +2 -0
  45. package/dist/_dts/theme-core/src/site-styles/accessibleSurfaces.d.ts +83 -0
  46. package/dist/_dts/theme-core/src/site-styles/contentTemplateRuntimeCompiler.d.ts +2 -1
  47. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +89 -12
  48. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +8 -2
  49. package/dist/_dts/theme-core/src/site-styles/index.d.ts +1 -0
  50. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +3 -2
  51. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +9 -6
  52. package/dist/_dts/ui/src/callout.d.ts +1 -1
  53. package/dist/cli/index.mjs +4290 -2513
  54. package/dist/client/client.mjs +598 -372
  55. package/dist/client/hooks.mjs +311 -123
  56. package/dist/client/rendering/client.mjs +209 -68
  57. package/dist/client/rendering/islands.mjs +281 -150
  58. package/dist/client/rendering.mjs +416 -190
  59. package/dist/preview-next/before-render.mjs +61 -13
  60. package/dist/preview-next/client/runtime.mjs +930 -376
  61. package/dist/preview-next/middleware.mjs +61 -13
  62. package/dist/server/components.mjs +526 -325
  63. package/dist/server/config-validation.mjs +313 -125
  64. package/dist/server/config.mjs +313 -125
  65. package/dist/server/data.mjs +311 -123
  66. package/dist/server/index.mjs +78 -16
  67. package/dist/server/next.mjs +527 -326
  68. package/dist/server/page-converter.mjs +159 -41
  69. package/dist/server/prebuild.mjs +1 -1
  70. package/dist/server/rendering/server.mjs +526 -325
  71. package/dist/server/rendering.mjs +526 -325
  72. package/dist/server/routing.mjs +392 -131
  73. package/dist/server/server.mjs +312 -124
  74. package/dist/server/theme-bridge.mjs +155 -48
  75. package/package.json +1 -1
  76. package/dist/_dts/path-utils/src/index.d.ts +0 -8
  77. package/dist/_dts/path-utils/src/redirectPaths.d.ts +0 -26
  78. package/dist/_dts/path-utils/src/safeAppPath.d.ts +0 -26
@@ -1992,6 +1992,144 @@ function resolveVariantKey(manifest, content) {
1992
1992
  return null;
1993
1993
  }
1994
1994
 
1995
+ // ../theme-core/src/palette/utils/colorConversion.ts
1996
+ var clamp01 = (x) => Math.max(0, Math.min(1, x));
1997
+ var mod = (a, n) => (a % n + n) % n;
1998
+ var deg = (x) => mod(x, 360);
1999
+ function hexToRgb(hex) {
2000
+ const h = hex.replace(/^#/, "");
2001
+ const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
2002
+ if (m.length !== 6) throw new Error("Bad hex");
2003
+ const int = parseInt(m, 16);
2004
+ return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
2005
+ }
2006
+ function rgbToHex(r2, g, b) {
2007
+ const to = (n) => Math.round(n).toString(16).padStart(2, "0");
2008
+ return `#${to(r2)}${to(g)}${to(b)}`;
2009
+ }
2010
+ function srgbToLinear(u) {
2011
+ const x = u / 255;
2012
+ return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
2013
+ }
2014
+ function linearToSrgb(x) {
2015
+ const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
2016
+ return clamp01(y) * 255;
2017
+ }
2018
+ function rgbToHsl(r2, g, b) {
2019
+ const R = r2 / 255, G = g / 255, B = b / 255;
2020
+ const max = Math.max(R, G, B), min = Math.min(R, G, B);
2021
+ const d = max - min;
2022
+ let h = 0;
2023
+ if (d !== 0) {
2024
+ switch (max) {
2025
+ case R:
2026
+ h = (G - B) / d + (G < B ? 6 : 0);
2027
+ break;
2028
+ case G:
2029
+ h = (B - R) / d + 2;
2030
+ break;
2031
+ case B:
2032
+ h = (R - G) / d + 4;
2033
+ break;
2034
+ }
2035
+ h *= 60;
2036
+ }
2037
+ const l = (max + min) / 2;
2038
+ const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
2039
+ return { h, s, l };
2040
+ }
2041
+ function srgbToOklab(r2, g, b) {
2042
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
2043
+ const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
2044
+ const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
2045
+ const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
2046
+ const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
2047
+ const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
2048
+ const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
2049
+ const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
2050
+ return { L, a, b: b2 };
2051
+ }
2052
+ function oklabToSrgb(L, a, b) {
2053
+ const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
2054
+ const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
2055
+ const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
2056
+ const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
2057
+ const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
2058
+ const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
2059
+ return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
2060
+ }
2061
+ function oklabToOklch(L, a, b) {
2062
+ const C = Math.sqrt(a * a + b * b);
2063
+ const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
2064
+ return { L, C, h };
2065
+ }
2066
+ function oklchToOklab(L, C, h) {
2067
+ const hr = h * Math.PI / 180;
2068
+ const a = C * Math.cos(hr);
2069
+ const b = C * Math.sin(hr);
2070
+ return { L, a, b };
2071
+ }
2072
+ function inSRGB(r2, g, b) {
2073
+ return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
2074
+ }
2075
+ function oklchToHexGamut(L, C, h) {
2076
+ let lo = 0, hi = C, best = 0;
2077
+ for (let i = 0; i < 18; i++) {
2078
+ const mid = (lo + hi) / 2;
2079
+ const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
2080
+ const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
2081
+ if (inSRGB(r3, g2, bb2)) {
2082
+ best = mid;
2083
+ lo = mid;
2084
+ } else {
2085
+ hi = mid;
2086
+ }
2087
+ }
2088
+ const { a, b } = oklchToOklab(L, best, h);
2089
+ const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
2090
+ return rgbToHex(r2, g, bb);
2091
+ }
2092
+ function featuresFromHex(hex) {
2093
+ const { r: r2, g, b } = hexToRgb(hex);
2094
+ const { h, s, l } = rgbToHsl(r2, g, b);
2095
+ const { L, a, b: b2 } = srgbToOklab(r2, g, b);
2096
+ const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
2097
+ const max = Math.max(r2, g, b);
2098
+ const v = max / 255;
2099
+ const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
2100
+ const chroma = s;
2101
+ return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
2102
+ }
2103
+
2104
+ // ../theme-core/src/palette/utils/contrast.ts
2105
+ function relativeLuminance(r2, g, b) {
2106
+ const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
2107
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
2108
+ }
2109
+
2110
+ // ../theme-core/src/palette/utils/onColor.ts
2111
+ var BACKGROUND_ROLE_NAMES = /* @__PURE__ */ new Set([
2112
+ "primary",
2113
+ "secondary",
2114
+ "accent",
2115
+ "success",
2116
+ "warning",
2117
+ "destructive",
2118
+ "info",
2119
+ "background",
2120
+ "surface",
2121
+ "surfaceAlt",
2122
+ "muted",
2123
+ "neutral"
2124
+ ]);
2125
+ function onColorTokenName(backgroundToken) {
2126
+ return `on${backgroundToken.split("-").filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("")}`;
2127
+ }
2128
+ function isOnColorBackgroundCandidateToken(token) {
2129
+ const role = token.match(/^(.*?)(?:-\d{2,3})?$/)?.[1] ?? token;
2130
+ return BACKGROUND_ROLE_NAMES.has(role);
2131
+ }
2132
+
1995
2133
  // ../theme-core/src/site-styles/appearancePresetResolution.ts
1996
2134
  function assertValidOptionGroups(preset2) {
1997
2135
  preset2.optionGroups?.forEach((group) => {
@@ -7613,6 +7751,9 @@ var curatedSiteStyleIdValues = [
7613
7751
  "site-style:bright-community",
7614
7752
  "site-style:quiet-luxury",
7615
7753
  "site-style:practical-services",
7754
+ "site-style:quiet-practice",
7755
+ "site-style:personal-retreat-journal",
7756
+ "site-style:tactile-workshop",
7616
7757
  "site-style:modern-wellness",
7617
7758
  "site-style:bold-launch",
7618
7759
  "site-style:south-west-twerk-school"
@@ -7695,7 +7836,8 @@ function defineCuratedSiteStyle(input) {
7695
7836
  name: input.name,
7696
7837
  description: input.description,
7697
7838
  generationBrief: input.generationBrief,
7698
- selectionKeywords: input.selectionKeywords ?? [],
7839
+ selectionKeywordRules: input.selectionKeywordRules ?? [],
7840
+ siteCreatorSelection: input.siteCreatorSelection ?? { kind: "explicit_only" },
7699
7841
  template: {
7700
7842
  id: asDesignSystemTemplateId(`template:${input.id.replace("site-style:", "")}`),
7701
7843
  name: input.name,
@@ -7839,12 +7981,13 @@ var curatedSiteStyles = [
7839
7981
  name: "Quiet Luxury",
7840
7982
  description: "Minimal, confident, and refined for premium experiences and private services.",
7841
7983
  generationBrief: "Use fewer claims, more specificity, and restrained sensory detail. Favor elegant media and low repetition over dense panels.",
7842
- selectionKeywords: [
7843
- "luxury",
7844
- "premium",
7845
- "boutique",
7846
- "bespoke",
7847
- "exclusive"
7984
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 20 },
7985
+ selectionKeywordRules: [
7986
+ { kind: "word", value: "luxury" },
7987
+ { kind: "word", value: "premium" },
7988
+ { kind: "word", value: "boutique" },
7989
+ { kind: "word", value: "bespoke" },
7990
+ { kind: "word", value: "exclusive" }
7848
7991
  ],
7849
7992
  tokenRecipes: {
7850
7993
  palette: "high-contrast",
@@ -7873,13 +8016,14 @@ var curatedSiteStyles = [
7873
8016
  name: "Practical Services",
7874
8017
  description: "Efficient, plainspoken, and conversion-focused for trades and everyday services.",
7875
8018
  generationBrief: "Make services, location, trust signals, and contact paths obvious. Keep copy brief and avoid ornate visual treatments.",
7876
- selectionKeywords: [
7877
- "repair",
7878
- "plumb",
7879
- "electric",
7880
- "cleaning",
7881
- "landscap",
7882
- "contractor"
8019
+ siteCreatorSelection: { kind: "primary_goal_support" },
8020
+ selectionKeywordRules: [
8021
+ { kind: "word", value: "repair" },
8022
+ { kind: "substring", value: "plumb" },
8023
+ { kind: "substring", value: "electric" },
8024
+ { kind: "word", value: "cleaning" },
8025
+ { kind: "substring", value: "landscap" },
8026
+ { kind: "substring", value: "contractor" }
7883
8027
  ],
7884
8028
  tokenRecipes: {
7885
8029
  palette: "brand-led",
@@ -7930,18 +8074,134 @@ var curatedSiteStyles = [
7930
8074
  paletteChoice("warm-neutral-forest")
7931
8075
  ]
7932
8076
  }),
8077
+ defineCuratedSiteStyle({
8078
+ id: "site-style:quiet-practice",
8079
+ name: "Quiet Practice",
8080
+ description: "Grounded, calm, and practical for small appointment-first practices.",
8081
+ generationBrief: "Make services, practitioner trust, preparation notes, and booking routes easy to scan. Keep the tone warm and specific, with quiet confidence rather than spa cliches or medical claims.",
8082
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 30 },
8083
+ selectionKeywordRules: [
8084
+ { kind: "substring", value: "massage" },
8085
+ { kind: "word", value: "bodywork" },
8086
+ { kind: "phrase", value: "appointment practice" },
8087
+ { kind: "phrase", value: "appointment-first" },
8088
+ { kind: "substring", value: "practitioner" },
8089
+ { kind: "substring", value: "therap" },
8090
+ { kind: "substring", value: "clinic" },
8091
+ { kind: "phrase", value: "wellness practice" }
8092
+ ],
8093
+ tokenRecipes: {
8094
+ palette: "soft-natural",
8095
+ contrast: "standard",
8096
+ radius: "soft",
8097
+ shadow: "subtle",
8098
+ typography: "clean-sans",
8099
+ spacing: "regular",
8100
+ motion: "subtle"
8101
+ },
8102
+ compositionBudget: quietBudget,
8103
+ recommendedHeaderLookIds: ["practical-utility", "clean-base", "centered-calm"],
8104
+ buttonPersonalityChoices: [
8105
+ buttonChoice("pebble"),
8106
+ buttonChoice("soft-pill"),
8107
+ buttonChoice("editorial-link")
8108
+ ],
8109
+ paletteVariantChoices: [
8110
+ paletteChoice("soft-natural-stone"),
8111
+ paletteChoice("soft-natural-sage"),
8112
+ paletteChoice("warm-neutral-clay")
8113
+ ]
8114
+ }),
8115
+ defineCuratedSiteStyle({
8116
+ id: "site-style:personal-retreat-journal",
8117
+ name: "Personal Retreat Journal",
8118
+ description: "Warm, story-led, and readable for solo practitioners with mixed offers.",
8119
+ generationBrief: "Center the practitioner as the guide, then make private sessions, classes, retreats, and resources feel like clear pathways. Keep retreat copy grounded and practical, with enough editorial warmth for longer reading.",
8120
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 40 },
8121
+ selectionKeywordRules: [
8122
+ { kind: "substring", value: "retreat" },
8123
+ { kind: "phrase", value: "solo practitioner" },
8124
+ { kind: "phrase", value: "personal brand" },
8125
+ { kind: "substring", value: "teacher" },
8126
+ { kind: "substring", value: "coach" },
8127
+ { kind: "phrase", value: "retreat resources" },
8128
+ { kind: "substring", value: "journal" }
8129
+ ],
8130
+ tokenRecipes: {
8131
+ palette: "warm-neutral",
8132
+ contrast: "standard",
8133
+ radius: "soft",
8134
+ shadow: "subtle",
8135
+ typography: "serif-editorial",
8136
+ spacing: "airy",
8137
+ motion: "subtle"
8138
+ },
8139
+ compositionBudget: balancedBudget,
8140
+ recommendedHeaderLookIds: ["editorial-line", "centered-calm", "minimal-transparent"],
8141
+ buttonPersonalityChoices: [
8142
+ buttonChoice("editorial-link"),
8143
+ buttonChoice("soft-pill"),
8144
+ buttonChoice("brushed-wash")
8145
+ ],
8146
+ paletteVariantChoices: [
8147
+ paletteChoice("warm-neutral-forest"),
8148
+ paletteChoice("warm-neutral-clay"),
8149
+ paletteChoice("soft-natural-stone")
8150
+ ]
8151
+ }),
8152
+ defineCuratedSiteStyle({
8153
+ id: "site-style:tactile-workshop",
8154
+ name: "Tactile Workshop",
8155
+ description: "Bright, hands-on, and image-led for maker studios, workshops, and creative classes.",
8156
+ generationBrief: "Lead with objects, materials, studio process, and practical booking detail. Keep the tone warm and direct, with useful mess, clear dates, and enough gallery rhythm to feel like a real creative studio.",
8157
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 50 },
8158
+ selectionKeywordRules: [
8159
+ { kind: "substring", value: "ceramic" },
8160
+ { kind: "word", value: "pottery" },
8161
+ { kind: "phrase", value: "maker studio" },
8162
+ { kind: "phrase", value: "craft class" },
8163
+ { kind: "phrase", value: "craft workshop" },
8164
+ { kind: "word", value: "clay" },
8165
+ { kind: "word", value: "kiln" }
8166
+ ],
8167
+ tokenRecipes: {
8168
+ palette: "brand-led",
8169
+ contrast: "standard",
8170
+ radius: "soft",
8171
+ shadow: "subtle",
8172
+ typography: "friendly-sans",
8173
+ spacing: "regular",
8174
+ motion: "subtle"
8175
+ },
8176
+ compositionBudget: balancedBudget,
8177
+ recommendedHeaderLookIds: ["brand-solid", "practical-utility", "clean-base"],
8178
+ recommendedFooterLookIds: ["site-footer-brand-two-band", "footer-muted-grounding"],
8179
+ buttonPersonalityChoices: [
8180
+ buttonChoice("pebble"),
8181
+ buttonChoice("confident-chip"),
8182
+ buttonChoice("ink-stamp"),
8183
+ buttonChoice("editorial-link")
8184
+ ],
8185
+ paletteVariantChoices: [
8186
+ paletteChoice("brand-led-warm"),
8187
+ paletteChoice("brand-led-cool"),
8188
+ paletteChoice("soft-natural-watercolor"),
8189
+ paletteChoice("warm-neutral-clay")
8190
+ ]
8191
+ }),
7933
8192
  defineCuratedSiteStyle({
7934
8193
  id: "site-style:bold-launch",
7935
8194
  name: "Bold Launch",
7936
8195
  description: "High-energy and punchy for launches, campaigns, and creative offers.",
7937
8196
  generationBrief: "Use crisp positioning, bold hero structure, strong calls to action, and confident visual rhythm. Keep it precise, not shouty.",
7938
- selectionKeywords: [
7939
- "launch",
7940
- "campaign",
7941
- "preorder",
7942
- "pre-order",
7943
- "waitlist",
7944
- "drop"
8197
+ siteCreatorSelection: { kind: "site_creator_keyword_heuristic", priority: 10 },
8198
+ selectionKeywordRules: [
8199
+ { kind: "substring", value: "launch" },
8200
+ { kind: "substring", value: "campaign" },
8201
+ { kind: "word", value: "preorder" },
8202
+ { kind: "phrase", value: "pre-order" },
8203
+ { kind: "substring", value: "waitlist" },
8204
+ { kind: "word", value: "drop" }
7945
8205
  ],
7946
8206
  tokenRecipes: {
7947
8207
  palette: "high-contrast",
@@ -7972,15 +8232,6 @@ var curatedSiteStyles = [
7972
8232
  name: "South West Twerk School",
7973
8233
  description: "Energetic, editorial, and high-contrast for a branded dance school presence.",
7974
8234
  generationBrief: "Use confident rhythm, bold burgundy-and-gold accents, large editorial intro copy, strong booking routes, and dark feature sections where proof or forms need emphasis.",
7975
- selectionKeywords: [
7976
- "dance",
7977
- "classes",
7978
- "workshop",
7979
- "school",
7980
- "movement",
7981
- "performance",
7982
- "community"
7983
- ],
7984
8235
  tokenRecipes: {
7985
8236
  palette: "brand-led",
7986
8237
  contrast: "maximum",
@@ -8223,6 +8474,148 @@ var modernMinimalTheme = {
8223
8474
  }
8224
8475
  };
8225
8476
 
8477
+ // ../theme-core/src/palette/generateShades.ts
8478
+ function generateShades(hexColor, name) {
8479
+ const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
8480
+ const base = featuresFromHex(hexColor);
8481
+ const hue = base.okH;
8482
+ const baseChroma = base.okC;
8483
+ const toneMap = {
8484
+ 50: 0.975,
8485
+ 100: 0.945,
8486
+ 200: 0.89,
8487
+ 300: 0.82,
8488
+ 400: 0.74,
8489
+ 500: 0.66,
8490
+ 600: 0.58,
8491
+ 700: 0.49,
8492
+ 800: 0.4,
8493
+ 900: 0.28,
8494
+ 950: 0.16
8495
+ };
8496
+ const shadeDefs = shadeSteps.map((step, idx) => {
8497
+ const t = idx / (shadeSteps.length - 1);
8498
+ const L = toneMap[step];
8499
+ const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
8500
+ const C = baseChroma * chromaFactor;
8501
+ return {
8502
+ name: `${name}-${step}`,
8503
+ hex: oklchToHexGamut(L, C, hue)
8504
+ };
8505
+ });
8506
+ shadeDefs.push({ name, hex: hexColor });
8507
+ return shadeDefs;
8508
+ }
8509
+
8510
+ // ../theme-core/src/palette/neutralScale.ts
8511
+ function generateNeutralScale({
8512
+ background,
8513
+ steps = 11,
8514
+ warm = false
8515
+ }) {
8516
+ const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
8517
+ const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
8518
+ const count = Math.min(steps, shadeNames.length);
8519
+ const scale = [];
8520
+ for (let i = 0; i < count; i++) {
8521
+ const t = i / (count - 1);
8522
+ const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
8523
+ const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
8524
+ const name = `neutral-${shadeNames[i]}`;
8525
+ scale.push({ name, hex });
8526
+ }
8527
+ return scale;
8528
+ }
8529
+ function mix(a, b, t) {
8530
+ return a + (b - a) * Math.max(0, Math.min(1, t));
8531
+ }
8532
+
8533
+ // ../theme-core/src/palette/utils/textColor.ts
8534
+ function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
8535
+ const { r: r2, g, b } = parseColorToRgb(background);
8536
+ const luminance = relativeLuminance(r2, g, b);
8537
+ const blackContrast = (luminance + 0.05) / 0.05;
8538
+ const whiteContrast = 1.05 / (luminance + 0.05);
8539
+ if (blackContrast >= minContrast && whiteContrast < minContrast) {
8540
+ return "#000000";
8541
+ }
8542
+ if (whiteContrast >= minContrast && blackContrast < minContrast) {
8543
+ return "#FFFFFF";
8544
+ }
8545
+ return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
8546
+ }
8547
+ function getTextColorForBackground(background) {
8548
+ return pickBlackOrWhiteTextColor(background);
8549
+ }
8550
+ function parseColorToRgb(input) {
8551
+ const trimmed = input.trim();
8552
+ if (trimmed.startsWith("#")) {
8553
+ return hexToRgb(trimmed);
8554
+ }
8555
+ const rgbMatch = trimmed.match(
8556
+ /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
8557
+ );
8558
+ if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
8559
+ return {
8560
+ r: clamp255(Number(rgbMatch[1])),
8561
+ g: clamp255(Number(rgbMatch[2])),
8562
+ b: clamp255(Number(rgbMatch[3]))
8563
+ };
8564
+ }
8565
+ throw new Error("Unsupported color format");
8566
+ }
8567
+ function clamp255(value) {
8568
+ if (Number.isNaN(value)) return 0;
8569
+ return Math.max(0, Math.min(255, value));
8570
+ }
8571
+
8572
+ // ../theme-core/src/palette/expandPalette.ts
8573
+ function colorsToMap(palette) {
8574
+ const map = {};
8575
+ for (const c of palette.colors) {
8576
+ map[c.name] = c.hex;
8577
+ }
8578
+ return map;
8579
+ }
8580
+ function isBackgroundDark(hex) {
8581
+ try {
8582
+ return featuresFromHex(hex).Y < 0.5;
8583
+ } catch {
8584
+ return false;
8585
+ }
8586
+ }
8587
+ function expandPalette(palette) {
8588
+ const base = colorsToMap(palette);
8589
+ const expanded = { ...base };
8590
+ const background = base.background || base.surface || "#ffffff";
8591
+ const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
8592
+ neutral2.forEach((n) => {
8593
+ expanded[n.name] = n.hex;
8594
+ });
8595
+ for (const [name, hex] of Object.entries(base)) {
8596
+ if (hex) {
8597
+ const shades = generateShades(hex, name);
8598
+ shades.forEach((shade) => {
8599
+ expanded[shade.name] = shade.hex;
8600
+ });
8601
+ }
8602
+ }
8603
+ if (base.text) expanded.body = base.text;
8604
+ if (base.danger && !base.destructive) {
8605
+ expanded.destructive = base.danger;
8606
+ }
8607
+ const isDark = base.background ? isBackgroundDark(base.background) : false;
8608
+ const isDarkMode = palette.meta?.mode === "dark" || isDark;
8609
+ expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
8610
+ for (const [token, hex] of Object.entries({ ...expanded })) {
8611
+ if (!hex || !isOnColorBackgroundCandidateToken(token)) continue;
8612
+ const onToken = onColorTokenName(token);
8613
+ if (expanded[onToken]) continue;
8614
+ expanded[onToken] = getTextColorForBackground(hex);
8615
+ }
8616
+ return expanded;
8617
+ }
8618
+
8226
8619
  // ../theme-core/src/site-styles/designState.ts
8227
8620
  import { z as z24 } from "zod";
8228
8621
 
@@ -8391,25 +8784,19 @@ var defaultDesignRuntimeRules = defineDesignRuntimeRules({
8391
8784
  "muted-band": {
8392
8785
  background: {
8393
8786
  type: "color",
8394
- color: "muted",
8395
- textColor: "text",
8396
- headingColor: "text"
8787
+ color: "muted"
8397
8788
  }
8398
8789
  },
8399
8790
  "accent-band": {
8400
8791
  background: {
8401
8792
  type: "color",
8402
- color: "primary",
8403
- textColor: "primaryForeground",
8404
- headingColor: "primaryForeground"
8793
+ color: "primary"
8405
8794
  }
8406
8795
  },
8407
8796
  "brand-depth-band": {
8408
8797
  background: {
8409
8798
  type: "color",
8410
- color: "primary-800",
8411
- textColor: "primaryForeground",
8412
- headingColor: "primaryForeground"
8799
+ color: "primary-800"
8413
8800
  }
8414
8801
  },
8415
8802
  "hero-image": {
@@ -14631,6 +15018,16 @@ var jsonArrayTransform = {
14631
15018
  return "";
14632
15019
  }
14633
15020
  };
15021
+ var csvTransform = {
15022
+ id: "value.csv",
15023
+ kind: "formatter",
15024
+ summary: "Normalize a string or array of strings into a comma-separated list",
15025
+ run: (value) => {
15026
+ const rawValues = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
15027
+ const normalized = rawValues.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
15028
+ return normalized.length > 0 ? Array.from(new Set(normalized)).join(",") : "";
15029
+ }
15030
+ };
14634
15031
  var marqueeLoopOptionsSchema = z33.object({
14635
15032
  minItems: z33.number().int().min(1).default(10)
14636
15033
  });
@@ -14656,6 +15053,7 @@ var formattingTransforms = [
14656
15053
  dateFormatShort,
14657
15054
  arrayLengthTransform,
14658
15055
  jsonArrayTransform,
15056
+ csvTransform,
14659
15057
  marqueeLoopTransform
14660
15058
  ];
14661
15059
 
@@ -15139,117 +15537,6 @@ var uiTransforms = [
15139
15537
 
15140
15538
  // ../blocks/src/system/transforms/registry/layout.ts
15141
15539
  import { z as z35 } from "zod";
15142
-
15143
- // ../theme-core/src/palette/utils/colorConversion.ts
15144
- var clamp01 = (x) => Math.max(0, Math.min(1, x));
15145
- var mod = (a, n) => (a % n + n) % n;
15146
- var deg = (x) => mod(x, 360);
15147
- function hexToRgb(hex) {
15148
- const h = hex.replace(/^#/, "");
15149
- const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
15150
- if (m.length !== 6) throw new Error("Bad hex");
15151
- const int = parseInt(m, 16);
15152
- return { r: int >> 16 & 255, g: int >> 8 & 255, b: int & 255 };
15153
- }
15154
- function rgbToHex(r2, g, b) {
15155
- const to = (n) => Math.round(n).toString(16).padStart(2, "0");
15156
- return `#${to(r2)}${to(g)}${to(b)}`;
15157
- }
15158
- function srgbToLinear(u) {
15159
- const x = u / 255;
15160
- return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
15161
- }
15162
- function linearToSrgb(x) {
15163
- const y = x <= 31308e-7 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055;
15164
- return clamp01(y) * 255;
15165
- }
15166
- function rgbToHsl(r2, g, b) {
15167
- const R = r2 / 255, G = g / 255, B = b / 255;
15168
- const max = Math.max(R, G, B), min = Math.min(R, G, B);
15169
- const d = max - min;
15170
- let h = 0;
15171
- if (d !== 0) {
15172
- switch (max) {
15173
- case R:
15174
- h = (G - B) / d + (G < B ? 6 : 0);
15175
- break;
15176
- case G:
15177
- h = (B - R) / d + 2;
15178
- break;
15179
- case B:
15180
- h = (R - G) / d + 4;
15181
- break;
15182
- }
15183
- h *= 60;
15184
- }
15185
- const l = (max + min) / 2;
15186
- const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
15187
- return { h, s, l };
15188
- }
15189
- function srgbToOklab(r2, g, b) {
15190
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
15191
- const l = 0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B;
15192
- const m = 0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B;
15193
- const s = 0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B;
15194
- const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
15195
- const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
15196
- const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
15197
- const b2 = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
15198
- return { L, a, b: b2 };
15199
- }
15200
- function oklabToSrgb(L, a, b) {
15201
- const l_ = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
15202
- const m_ = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
15203
- const s_ = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
15204
- const R = 4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
15205
- const G = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
15206
- const B = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.707614701 * s_;
15207
- return { r: linearToSrgb(R), g: linearToSrgb(G), b: linearToSrgb(B) };
15208
- }
15209
- function oklabToOklch(L, a, b) {
15210
- const C = Math.sqrt(a * a + b * b);
15211
- const h = C < 1e-7 ? 0 : deg(Math.atan2(b, a) * 180 / Math.PI);
15212
- return { L, C, h };
15213
- }
15214
- function oklchToOklab(L, C, h) {
15215
- const hr = h * Math.PI / 180;
15216
- const a = C * Math.cos(hr);
15217
- const b = C * Math.sin(hr);
15218
- return { L, a, b };
15219
- }
15220
- function inSRGB(r2, g, b) {
15221
- return r2 >= 0 && r2 <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
15222
- }
15223
- function oklchToHexGamut(L, C, h) {
15224
- let lo = 0, hi = C, best = 0;
15225
- for (let i = 0; i < 18; i++) {
15226
- const mid = (lo + hi) / 2;
15227
- const { a: a2, b: b2 } = oklchToOklab(L, mid, h);
15228
- const { r: r3, g: g2, b: bb2 } = oklabToSrgb(L, a2, b2);
15229
- if (inSRGB(r3, g2, bb2)) {
15230
- best = mid;
15231
- lo = mid;
15232
- } else {
15233
- hi = mid;
15234
- }
15235
- }
15236
- const { a, b } = oklchToOklab(L, best, h);
15237
- const { r: r2, g, b: bb } = oklabToSrgb(L, a, b);
15238
- return rgbToHex(r2, g, bb);
15239
- }
15240
- function featuresFromHex(hex) {
15241
- const { r: r2, g, b } = hexToRgb(hex);
15242
- const { h, s, l } = rgbToHsl(r2, g, b);
15243
- const { L, a, b: b2 } = srgbToOklab(r2, g, b);
15244
- const { L: okL, C: okC, h: okH } = oklabToOklch(L, a, b2);
15245
- const max = Math.max(r2, g, b);
15246
- const v = max / 255;
15247
- const Y = 0.2126 * srgbToLinear(r2) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
15248
- const chroma = s;
15249
- return { r: r2, g, b, h, s, l, v, Y, chroma, okL, okC, okH, hex };
15250
- }
15251
-
15252
- // ../blocks/src/system/transforms/registry/layout.ts
15253
15540
  var joinClasses4 = (parts) => parts.filter(
15254
15541
  (part) => typeof part === "string" && part.trim().length > 0
15255
15542
  ).join(" ").replace(/\s+/g, " ").trim();
@@ -20198,51 +20485,6 @@ function resolveEventCta(event, buttonText) {
20198
20485
  return { label, href: event.path, hidden: false };
20199
20486
  }
20200
20487
 
20201
- // ../theme-core/src/palette/utils/contrast.ts
20202
- function relativeLuminance(r2, g, b) {
20203
- const R = srgbToLinear(r2), G = srgbToLinear(g), B = srgbToLinear(b);
20204
- return 0.2126 * R + 0.7152 * G + 0.0722 * B;
20205
- }
20206
-
20207
- // ../theme-core/src/palette/utils/textColor.ts
20208
- function pickBlackOrWhiteTextColor(background, minContrast = 4.5) {
20209
- const { r: r2, g, b } = parseColorToRgb(background);
20210
- const luminance = relativeLuminance(r2, g, b);
20211
- const blackContrast = (luminance + 0.05) / 0.05;
20212
- const whiteContrast = 1.05 / (luminance + 0.05);
20213
- if (blackContrast >= minContrast && whiteContrast < minContrast) {
20214
- return "#000000";
20215
- }
20216
- if (whiteContrast >= minContrast && blackContrast < minContrast) {
20217
- return "#FFFFFF";
20218
- }
20219
- return blackContrast >= whiteContrast ? "#000000" : "#FFFFFF";
20220
- }
20221
- function getTextColorForBackground(background) {
20222
- return pickBlackOrWhiteTextColor(background);
20223
- }
20224
- function parseColorToRgb(input) {
20225
- const trimmed = input.trim();
20226
- if (trimmed.startsWith("#")) {
20227
- return hexToRgb(trimmed);
20228
- }
20229
- const rgbMatch = trimmed.match(
20230
- /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\)$/i
20231
- );
20232
- if (rgbMatch?.[1] && rgbMatch[2] && rgbMatch[3]) {
20233
- return {
20234
- r: clamp255(Number(rgbMatch[1])),
20235
- g: clamp255(Number(rgbMatch[2])),
20236
- b: clamp255(Number(rgbMatch[3]))
20237
- };
20238
- }
20239
- throw new Error("Unsupported color format");
20240
- }
20241
- function clamp255(value) {
20242
- if (Number.isNaN(value)) return 0;
20243
- return Math.max(0, Math.min(255, value));
20244
- }
20245
-
20246
20488
  // ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
20247
20489
  function r(e) {
20248
20490
  var t, f, n = "";
@@ -22169,7 +22411,12 @@ var eventListingBlockDefinition = {
22169
22411
  detailLevel: "listing",
22170
22412
  kind: { $bind: { from: "content.kind" } },
22171
22413
  eventSurface: { $bind: { from: "content.eventSurface" } },
22172
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
22414
+ eventPresets: {
22415
+ $bind: {
22416
+ from: "content.filterEventPresets",
22417
+ transforms: [{ id: "value.csv" }]
22418
+ }
22419
+ },
22173
22420
  scheduleScope: { $bind: { from: "content.scheduleScope" } }
22174
22421
  },
22175
22422
  mode: "server"
@@ -22954,7 +23201,12 @@ var eventCalendarBlockDefinition = {
22954
23201
  // Pass filter params if configured
22955
23202
  kind: { $bind: { from: "content.kind" } },
22956
23203
  eventSurface: { $bind: { from: "content.eventSurface" } },
22957
- eventPresets: { $bind: { from: "content.filterEventPresets" } },
23204
+ eventPresets: {
23205
+ $bind: {
23206
+ from: "content.filterEventPresets",
23207
+ transforms: [{ id: "value.csv" }]
23208
+ }
23209
+ },
22958
23210
  scheduleScope: { $bind: { from: "content.scheduleScope" } },
22959
23211
  categoryIds: { $bind: { from: "content.filterCategoryIds" } },
22960
23212
  staffMemberId: { $bind: { from: "content.filterStaffMemberId" } },
@@ -33416,119 +33668,6 @@ function renderBlock(manifest, content, options = {}) {
33416
33668
  );
33417
33669
  }
33418
33670
 
33419
- // ../theme-core/src/palette/generateShades.ts
33420
- function generateShades(hexColor, name) {
33421
- const shadeSteps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
33422
- const base = featuresFromHex(hexColor);
33423
- const hue = base.okH;
33424
- const baseChroma = base.okC;
33425
- const toneMap = {
33426
- 50: 0.975,
33427
- 100: 0.945,
33428
- 200: 0.89,
33429
- 300: 0.82,
33430
- 400: 0.74,
33431
- 500: 0.66,
33432
- 600: 0.58,
33433
- 700: 0.49,
33434
- 800: 0.4,
33435
- 900: 0.28,
33436
- 950: 0.16
33437
- };
33438
- const shadeDefs = shadeSteps.map((step, idx) => {
33439
- const t = idx / (shadeSteps.length - 1);
33440
- const L = toneMap[step];
33441
- const chromaFactor = 0.06 + 0.94 * Math.sin(Math.PI * t);
33442
- const C = baseChroma * chromaFactor;
33443
- return {
33444
- name: `${name}-${step}`,
33445
- hex: oklchToHexGamut(L, C, hue)
33446
- };
33447
- });
33448
- shadeDefs.push({ name, hex: hexColor });
33449
- return shadeDefs;
33450
- }
33451
-
33452
- // ../theme-core/src/palette/neutralScale.ts
33453
- function generateNeutralScale({
33454
- background,
33455
- steps = 11,
33456
- warm = false
33457
- }) {
33458
- const isDark = background === "#000000" || background.startsWith("#0") || background.startsWith("#1");
33459
- const shadeNames = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
33460
- const count = Math.min(steps, shadeNames.length);
33461
- const scale = [];
33462
- for (let i = 0; i < count; i++) {
33463
- const t = i / (count - 1);
33464
- const tone = isDark ? mix(0.06, 0.92, t) : mix(0.98, 0.1, t);
33465
- const hex = oklchToHexGamut(tone, 0.02, warm ? 85 : 250);
33466
- const name = `neutral-${shadeNames[i]}`;
33467
- scale.push({ name, hex });
33468
- }
33469
- return scale;
33470
- }
33471
- function mix(a, b, t) {
33472
- return a + (b - a) * Math.max(0, Math.min(1, t));
33473
- }
33474
-
33475
- // ../theme-core/src/palette/expandPalette.ts
33476
- function colorsToMap(palette) {
33477
- const map = {};
33478
- for (const c of palette.colors) {
33479
- map[c.name] = c.hex;
33480
- }
33481
- return map;
33482
- }
33483
- function isBackgroundDark(hex) {
33484
- try {
33485
- return featuresFromHex(hex).Y < 0.5;
33486
- } catch {
33487
- return false;
33488
- }
33489
- }
33490
- function expandPalette(palette) {
33491
- const base = colorsToMap(palette);
33492
- const expanded = { ...base };
33493
- const background = base.background || base.surface || "#ffffff";
33494
- const neutral2 = generateNeutralScale({ background, steps: 11, warm: false });
33495
- neutral2.forEach((n) => {
33496
- expanded[n.name] = n.hex;
33497
- });
33498
- for (const [name, hex] of Object.entries(base)) {
33499
- if (hex) {
33500
- const shades = generateShades(hex, name);
33501
- shades.forEach((shade) => {
33502
- expanded[shade.name] = shade.hex;
33503
- });
33504
- }
33505
- }
33506
- if (base.text) expanded.body = base.text;
33507
- if (base.danger && !base.destructive) {
33508
- expanded.destructive = base.danger;
33509
- }
33510
- const isDark = base.background ? isBackgroundDark(base.background) : false;
33511
- const isDarkMode = palette.meta?.mode === "dark" || isDark;
33512
- expanded.mutedText = isDarkMode ? expanded["neutral-600"] ?? "#666" : expanded["neutral-500"] ?? "#888";
33513
- const onRoles = [
33514
- { role: "primary", on: "onPrimary" },
33515
- { role: "secondary", on: "onSecondary" },
33516
- { role: "accent", on: "onAccent" },
33517
- { role: "success", on: "onSuccess" },
33518
- { role: "warning", on: "onWarning" },
33519
- { role: "destructive", on: "onDestructive" },
33520
- { role: "info", on: "onInfo" },
33521
- { role: "surface", on: "onSurface" }
33522
- ];
33523
- for (const { role, on } of onRoles) {
33524
- const bg = base[role];
33525
- if (!bg) continue;
33526
- if (expanded[on]) continue;
33527
- expanded[on] = getTextColorForBackground(bg);
33528
- }
33529
- return expanded;
33530
- }
33531
-
33532
33671
  // ../theme-core/src/runtime/fontFamily.ts
33533
33672
  var GENERIC_CSS_FAMILIES = [
33534
33673
  "serif",
@@ -48993,6 +49132,17 @@ function normalizeLoaderParams(endpoint, params, context) {
48993
49132
  return out;
48994
49133
  }
48995
49134
 
49135
+ // ../api/src/apiEndpointTypes.ts
49136
+ function blockedDemoMutationPolicy(classification, publicMessage) {
49137
+ if (publicMessage.trim() === "") {
49138
+ throw new Error(`Demo mutation policy ${classification} requires publicMessage.`);
49139
+ }
49140
+ return {
49141
+ classification,
49142
+ publicMessage
49143
+ };
49144
+ }
49145
+
48996
49146
  // ../api/src/cache-tags.ts
48997
49147
  var TAG_TEMPLATES = {
48998
49148
  siteCollection: "riverbank:site",
@@ -49023,6 +49173,18 @@ var TAG_TEMPLATES = {
49023
49173
  };
49024
49174
 
49025
49175
  // ../api/src/endpoints.ts
49176
+ var DEMO_MUTATION_BLOCKED_HIDDEN = blockedDemoMutationPolicy(
49177
+ "blocked-hidden",
49178
+ "This action is not available in demo sites."
49179
+ );
49180
+ var DEMO_MUTATION_BLOCKED_DISABLED = blockedDemoMutationPolicy(
49181
+ "blocked-disabled",
49182
+ "This setting is disabled in demo sites."
49183
+ );
49184
+ var DEMO_MUTATION_INTERNAL_ONLY = blockedDemoMutationPolicy(
49185
+ "internal-only",
49186
+ "This internal operation is not available in demo sites."
49187
+ );
49026
49188
  var ENDPOINT_DEFINITIONS = {
49027
49189
  // AI endpoints - no cache due to dynamic nature
49028
49190
  aiContentUpdateChat: {
@@ -49139,7 +49301,8 @@ var ENDPOINT_DEFINITIONS = {
49139
49301
  path: "/sites/{siteId}/ai/generate",
49140
49302
  method: "POST",
49141
49303
  auth: "user",
49142
- responseKind: "json"
49304
+ responseKind: "json",
49305
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49143
49306
  },
49144
49307
  getOnboardingPreviewStatus: {
49145
49308
  path: "/public/sites/{siteId}/onboarding/preview-status",
@@ -49160,7 +49323,8 @@ var ENDPOINT_DEFINITIONS = {
49160
49323
  method: "POST",
49161
49324
  auth: "user",
49162
49325
  errors: [],
49163
- responseKind: "json"
49326
+ responseKind: "json",
49327
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED
49164
49328
  },
49165
49329
  goLiveSite: {
49166
49330
  path: "/sites/{siteId}/launch/go-live",
@@ -49229,20 +49393,23 @@ var ENDPOINT_DEFINITIONS = {
49229
49393
  path: "/sites/{siteId}/ai/site-wizard/goals",
49230
49394
  method: "POST",
49231
49395
  auth: "user",
49232
- responseKind: "json"
49396
+ responseKind: "json",
49397
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49233
49398
  },
49234
49399
  aiSiteWizardIntakeTriage: {
49235
49400
  path: "/sites/{siteId}/ai/site-wizard/intake-triage",
49236
49401
  method: "POST",
49237
49402
  auth: "user",
49238
- responseKind: "json"
49403
+ responseKind: "json",
49404
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49239
49405
  },
49240
49406
  aiSiteWizardTelemetry: {
49241
49407
  path: "/sites/{siteId}/ai/site-wizard/telemetry",
49242
49408
  method: "POST",
49243
49409
  auth: "user",
49244
49410
  errors: [],
49245
- responseKind: "json"
49411
+ responseKind: "json",
49412
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49246
49413
  },
49247
49414
  // Admin SEO
49248
49415
  listGscPropertiesAdmin: {
@@ -49449,7 +49616,7 @@ var ENDPOINT_DEFINITIONS = {
49449
49616
  responseKind: "json",
49450
49617
  errors: ["resource:not_found", "server:internal_error"]
49451
49618
  },
49452
- // Ops (event hosts/admins)
49619
+ // Ops (staff event operators/admins)
49453
49620
  opsListUpcomingEventOccurrences: {
49454
49621
  path: "/ops/sites/{siteId}/events",
49455
49622
  method: "GET",
@@ -49467,6 +49634,7 @@ var ENDPOINT_DEFINITIONS = {
49467
49634
  method: "POST",
49468
49635
  auth: "user",
49469
49636
  responseKind: "json",
49637
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49470
49638
  errors: [
49471
49639
  "validation:invalid_input",
49472
49640
  "auth:forbidden",
@@ -49479,6 +49647,7 @@ var ENDPOINT_DEFINITIONS = {
49479
49647
  method: "POST",
49480
49648
  auth: "user",
49481
49649
  responseKind: "json",
49650
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49482
49651
  errors: [
49483
49652
  "validation:invalid_input",
49484
49653
  "auth:forbidden",
@@ -49497,6 +49666,7 @@ var ENDPOINT_DEFINITIONS = {
49497
49666
  method: "POST",
49498
49667
  auth: "user",
49499
49668
  responseKind: "json",
49669
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49500
49670
  errors: [
49501
49671
  "validation:invalid_input",
49502
49672
  "auth:forbidden",
@@ -49530,6 +49700,7 @@ var ENDPOINT_DEFINITIONS = {
49530
49700
  method: "POST",
49531
49701
  auth: "user",
49532
49702
  responseKind: "json",
49703
+ demoMutation: DEMO_MUTATION_INTERNAL_ONLY,
49533
49704
  errors: [
49534
49705
  "validation:invalid_input",
49535
49706
  "auth:forbidden",
@@ -49558,7 +49729,8 @@ var ENDPOINT_DEFINITIONS = {
49558
49729
  method: "POST",
49559
49730
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteEmailSettings],
49560
49731
  auth: "user",
49561
- responseKind: "json"
49732
+ responseKind: "json",
49733
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49562
49734
  },
49563
49735
  previewEmailTemplate: {
49564
49736
  path: "/sites/{siteId}/settings/emails/preview",
@@ -49609,14 +49781,16 @@ var ENDPOINT_DEFINITIONS = {
49609
49781
  method: "POST",
49610
49782
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49611
49783
  auth: "user",
49612
- responseKind: "json"
49784
+ responseKind: "json",
49785
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49613
49786
  },
49614
49787
  createNewsletterSubscribersImportUploadUrl: {
49615
49788
  path: "/sites/{siteId}/newsletter/subscribers/import-url",
49616
49789
  method: "POST",
49617
49790
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49618
49791
  auth: "user",
49619
- responseKind: "json"
49792
+ responseKind: "json",
49793
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49620
49794
  },
49621
49795
  exportNewsletterSubscribersCsv: {
49622
49796
  path: "/sites/{siteId}/newsletter/subscribers/export.csv",
@@ -49813,14 +49987,16 @@ var ENDPOINT_DEFINITIONS = {
49813
49987
  method: "POST",
49814
49988
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49815
49989
  auth: "user",
49816
- responseKind: "json"
49990
+ responseKind: "json",
49991
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49817
49992
  },
49818
49993
  testSendNewsletterCampaign: {
49819
49994
  path: "/sites/{siteId}/newsletter/campaigns/{campaignId}/test-send",
49820
49995
  method: "POST",
49821
49996
  tags: [TAG_TEMPLATES.site, TAG_TEMPLATES.siteNewsletter],
49822
49997
  auth: "user",
49823
- responseKind: "json"
49998
+ responseKind: "json",
49999
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
49824
50000
  },
49825
50001
  listNewsletterSendJobs: {
49826
50002
  path: "/sites/{siteId}/newsletter/jobs",
@@ -50508,7 +50684,8 @@ var ENDPOINT_DEFINITIONS = {
50508
50684
  method: "DELETE",
50509
50685
  tags: ["site", "site-{siteId}"],
50510
50686
  auth: "user",
50511
- responseKind: "json"
50687
+ responseKind: "json",
50688
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
50512
50689
  },
50513
50690
  listSiteMembers: {
50514
50691
  path: "/sites/{siteId}/members",
@@ -50964,7 +51141,8 @@ var ENDPOINT_DEFINITIONS = {
50964
51141
  method: "POST",
50965
51142
  tags: ["site-{siteId}", "content-{siteId}-{type}"],
50966
51143
  auth: "user",
50967
- responseKind: "json"
51144
+ responseKind: "json",
51145
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN
50968
51146
  },
50969
51147
  updateSiteGeneralSettings: {
50970
51148
  path: "/sites/{siteId}/settings/general",
@@ -53203,6 +53381,7 @@ var ENDPOINT_DEFINITIONS = {
53203
53381
  method: "POST",
53204
53382
  tags: ["site-{siteId}"],
53205
53383
  auth: "user",
53384
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
53206
53385
  errors: [
53207
53386
  "validation:invalid_input",
53208
53387
  "auth:forbidden",
@@ -53217,6 +53396,7 @@ var ENDPOINT_DEFINITIONS = {
53217
53396
  method: "POST",
53218
53397
  tags: ["site-{siteId}"],
53219
53398
  auth: "user",
53399
+ demoMutation: DEMO_MUTATION_BLOCKED_HIDDEN,
53220
53400
  errors: [
53221
53401
  "validation:invalid_input",
53222
53402
  "auth:forbidden",
@@ -53526,6 +53706,7 @@ var ENDPOINT_DEFINITIONS = {
53526
53706
  tags: ["site-{siteId}", "passes-{siteId}"],
53527
53707
  auth: "user",
53528
53708
  responseKind: "json",
53709
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53529
53710
  errors: ["validation:invalid_input", "server:internal_error"]
53530
53711
  },
53531
53712
  getBookingPass: {
@@ -53541,6 +53722,7 @@ var ENDPOINT_DEFINITIONS = {
53541
53722
  tags: ["site-{siteId}", "passes-{siteId}"],
53542
53723
  auth: "user",
53543
53724
  responseKind: "json",
53725
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53544
53726
  errors: [
53545
53727
  "validation:invalid_input",
53546
53728
  "resource:not_found",
@@ -53553,6 +53735,7 @@ var ENDPOINT_DEFINITIONS = {
53553
53735
  tags: ["site-{siteId}", "passes-{siteId}"],
53554
53736
  auth: "user",
53555
53737
  responseKind: "json",
53738
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53556
53739
  errors: [
53557
53740
  "validation:invalid_input",
53558
53741
  "resource:not_found",
@@ -53608,6 +53791,7 @@ var ENDPOINT_DEFINITIONS = {
53608
53791
  tags: ["site-{siteId}", "memberships-{siteId}"],
53609
53792
  auth: "user",
53610
53793
  responseKind: "json",
53794
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53611
53795
  errors: ["validation:invalid_input", "server:internal_error"]
53612
53796
  },
53613
53797
  getBookingMembership: {
@@ -53623,6 +53807,7 @@ var ENDPOINT_DEFINITIONS = {
53623
53807
  tags: ["site-{siteId}", "memberships-{siteId}"],
53624
53808
  auth: "user",
53625
53809
  responseKind: "json",
53810
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53626
53811
  errors: [
53627
53812
  "validation:invalid_input",
53628
53813
  "resource:not_found",
@@ -53635,6 +53820,7 @@ var ENDPOINT_DEFINITIONS = {
53635
53820
  tags: ["site-{siteId}", "memberships-{siteId}"],
53636
53821
  auth: "user",
53637
53822
  responseKind: "json",
53823
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53638
53824
  errors: [
53639
53825
  "validation:invalid_input",
53640
53826
  "resource:not_found",
@@ -53851,6 +54037,7 @@ var ENDPOINT_DEFINITIONS = {
53851
54037
  tags: ["site-{siteId}", "customers-{siteId}"],
53852
54038
  auth: "user",
53853
54039
  responseKind: "json",
54040
+ demoMutation: DEMO_MUTATION_BLOCKED_DISABLED,
53854
54041
  errors: [
53855
54042
  "validation:invalid_input",
53856
54043
  "auth:forbidden",
@@ -55228,8 +55415,7 @@ var dashboardNavVisibilityBaseSchema = z66.object({
55228
55415
  var dashboardNavVisibilityRolesSchema = z66.object({
55229
55416
  administrator: dashboardNavVisibilityBaseSchema.optional(),
55230
55417
  editor: dashboardNavVisibilityBaseSchema.optional(),
55231
- team_member: dashboardNavVisibilityBaseSchema.optional(),
55232
- event_host: dashboardNavVisibilityBaseSchema.optional()
55418
+ team_member: dashboardNavVisibilityBaseSchema.optional()
55233
55419
  }).strip().optional();
55234
55420
  var dashboardNavVisibilitySchema = dashboardNavVisibilityBaseSchema.extend({
55235
55421
  roles: dashboardNavVisibilityRolesSchema
@@ -55750,6 +55936,21 @@ var appointmentSetupServiceDraftSchema = z68.object({
55750
55936
  timezone: z68.string().trim().min(1).nullable(),
55751
55937
  payment: appointmentSetupPaymentDraftSchema,
55752
55938
  assignment: appointmentSetupServiceAssignmentDraftSchema
55939
+ }).superRefine((service, ctx) => {
55940
+ if (service.payment.priceType === "paid" && (service.priceAmount === null || service.priceAmount <= 0)) {
55941
+ ctx.addIssue({
55942
+ code: "custom",
55943
+ path: ["priceAmount"],
55944
+ message: "Paid appointment services need a positive price."
55945
+ });
55946
+ }
55947
+ if (service.payment.priceType === "free" && service.priceAmount !== null && service.priceAmount > 0) {
55948
+ ctx.addIssue({
55949
+ code: "custom",
55950
+ path: ["priceAmount"],
55951
+ message: "Free appointment services cannot carry a positive price."
55952
+ });
55953
+ }
55753
55954
  });
55754
55955
  var appointmentSetupPractitionerDraftSchema = z68.object({
55755
55956
  ref: appointmentSetupRefSchema,