@motion-proto/live-tokens 0.47.0 → 0.48.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 (124) hide show
  1. package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +68 -0
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +2 -2
  3. package/.claude/skills/live-tokens-generate-theme/SKILL.md +152 -0
  4. package/CHANGELOG.md +292 -0
  5. package/README.md +37 -26
  6. package/bin/adjust.mjs +254 -0
  7. package/bin/cli.mjs +94 -7
  8. package/bin/generate-theme.mjs +251 -0
  9. package/bin/migrate.mjs +95 -6
  10. package/dist-plugin/adjust/index.cjs +259 -0
  11. package/dist-plugin/adjust/index.d.cts +45 -0
  12. package/dist-plugin/adjust/index.d.ts +45 -0
  13. package/dist-plugin/adjust/index.js +176 -0
  14. package/dist-plugin/{chunk-H4TRUINI.js → chunk-44RSTAII.js} +0 -48
  15. package/dist-plugin/chunk-6OZFXIQI.js +316 -0
  16. package/dist-plugin/chunk-76TFDTJO.js +556 -0
  17. package/dist-plugin/chunk-D3ZVKOR4.js +52 -0
  18. package/dist-plugin/dataPaths-DBN0RPuT.d.cts +54 -0
  19. package/dist-plugin/dataPaths-DBN0RPuT.d.ts +54 -0
  20. package/dist-plugin/generateColorsAndType/index.cjs +1781 -0
  21. package/dist-plugin/generateColorsAndType/index.d.cts +81 -0
  22. package/dist-plugin/generateColorsAndType/index.d.ts +81 -0
  23. package/dist-plugin/generateColorsAndType/index.js +1210 -0
  24. package/dist-plugin/index.cjs +901 -533
  25. package/dist-plugin/index.d.cts +3 -2
  26. package/dist-plugin/index.d.ts +3 -2
  27. package/dist-plugin/index.js +658 -1082
  28. package/dist-plugin/migrateData/index.cjs +728 -0
  29. package/dist-plugin/migrateData/index.d.cts +60 -0
  30. package/dist-plugin/migrateData/index.d.ts +60 -0
  31. package/dist-plugin/migrateData/index.js +348 -0
  32. package/dist-plugin/themeTypes-DMHZOnUn.d.cts +211 -0
  33. package/dist-plugin/themeTypes-DMHZOnUn.d.ts +211 -0
  34. package/dist-plugin/tokensCssMigrations/index.cjs +2 -1
  35. package/dist-plugin/tokensCssMigrations/index.d.cts +3 -15
  36. package/dist-plugin/tokensCssMigrations/index.d.ts +3 -15
  37. package/dist-plugin/tokensCssMigrations/index.js +4 -2
  38. package/package.json +18 -4
  39. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +183 -158
  40. package/src/editor/component-editor/scaffolding/ComponentFileMenu.svelte +0 -4
  41. package/src/editor/component-editor/scaffolding/SaveAsDialog.svelte +4 -4
  42. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +2 -59
  43. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +1 -1
  44. package/src/editor/core/components/adjustAliases.ts +180 -0
  45. package/src/editor/core/components/aliasKinds.ts +73 -0
  46. package/src/editor/core/components/componentConfigService.ts +26 -38
  47. package/src/editor/core/flashStatus.ts +1 -1
  48. package/src/editor/core/fonts/fontMigration.ts +13 -13
  49. package/src/editor/core/fonts/fontPairing.ts +35 -0
  50. package/src/editor/core/palettes/paletteDerivation.ts +128 -16
  51. package/src/editor/core/preview/lookPreview.ts +141 -0
  52. package/src/editor/core/productionPulse.ts +34 -21
  53. package/src/editor/core/storage/files/versionedFileResourceClient.ts +18 -45
  54. package/src/editor/core/store/editorConfigStore.ts +2 -2
  55. package/src/editor/core/store/editorPersistence.ts +0 -1
  56. package/src/editor/core/store/editorStore.ts +114 -51
  57. package/src/editor/core/store/editorTypes.ts +0 -1
  58. package/src/editor/core/store/gradientSource.ts +2 -2
  59. package/src/editor/core/themes/colorsAndTypeService.ts +95 -0
  60. package/src/editor/core/themes/generateColorsAndType.ts +433 -0
  61. package/src/editor/core/themes/loadRows.ts +64 -0
  62. package/src/editor/core/themes/lookSummary.ts +75 -0
  63. package/src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +3 -3
  64. package/src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts +2 -2
  65. package/src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts +3 -3
  66. package/src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts +38 -0
  67. package/src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts +57 -0
  68. package/src/editor/core/themes/migrations/index.ts +19 -11
  69. package/src/editor/core/themes/slices/components.ts +4 -4
  70. package/src/editor/core/themes/slices/fonts.ts +1 -1
  71. package/src/editor/core/themes/slices/gradients.ts +22 -0
  72. package/src/editor/core/themes/slices/palettes.ts +2 -2
  73. package/src/editor/core/themes/themeInit.ts +21 -29
  74. package/src/editor/core/themes/themeService.ts +218 -78
  75. package/src/editor/core/themes/themeTypes.ts +94 -51
  76. package/src/editor/docs/Docs.svelte +1 -0
  77. package/src/editor/docs/chapters.ts +1 -0
  78. package/src/editor/docs/content/01-overview.md +1 -1
  79. package/src/editor/docs/content/editing-tokens.md +6 -6
  80. package/src/editor/docs/content/getting-started.md +9 -7
  81. package/src/editor/docs/content/themes-workflow.md +74 -34
  82. package/src/editor/docs/content/where-themes-live.md +61 -0
  83. package/src/editor/docs/content.generated.ts +5 -4
  84. package/src/editor/index.ts +27 -27
  85. package/src/editor/pages/ComponentEditorPage.svelte +2 -2
  86. package/src/editor/pages/EditorShell.svelte +4 -30
  87. package/src/editor/ui/BezierCurveEditor.svelte +2 -2
  88. package/src/editor/ui/ColorEditPanel.svelte +1 -1
  89. package/src/editor/ui/FileLoadList.svelte +67 -7
  90. package/src/editor/ui/GradientEditor.svelte +3 -3
  91. package/src/editor/ui/PaletteEditor.svelte +26 -12
  92. package/src/editor/ui/ThemePanel.svelte +1067 -0
  93. package/src/editor/ui/UIDialog.svelte +11 -9
  94. package/src/editor/ui/UIPillButton.svelte +7 -2
  95. package/src/editor/ui/colors/ColorWheel.svelte +34 -1
  96. package/src/editor/ui/curveEngine.ts +48 -0
  97. package/src/editor/ui/index.ts +4 -2
  98. package/src/editor/ui/palette/PaletteBase.svelte +75 -51
  99. package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -8
  100. package/src/live-tokens/data/colors-and-type/autumn.json +2490 -0
  101. package/src/live-tokens/data/{themes → colors-and-type}/default.json +816 -293
  102. package/src/live-tokens/data/colors-and-type/halloween.json +2529 -0
  103. package/src/live-tokens/data/colors-and-type/midnight-study.json +2536 -0
  104. package/src/live-tokens/data/colors-and-type/ocean.json +2489 -0
  105. package/src/live-tokens/data/colors-and-type/royal-velvet.json +2520 -0
  106. package/src/live-tokens/data/colors-and-type/spring-meadow.json +2476 -0
  107. package/src/live-tokens/data/colors-and-type/sunset.json +2528 -0
  108. package/src/live-tokens/data/themes/autumn.json +3918 -0
  109. package/src/live-tokens/data/themes/halloween.json +3992 -0
  110. package/src/live-tokens/data/themes/midnight-study.json +3932 -0
  111. package/src/live-tokens/data/themes/ocean.json +3917 -0
  112. package/src/live-tokens/data/themes/royal-velvet.json +3983 -0
  113. package/src/live-tokens/data/themes/spring-meadow.json +3904 -0
  114. package/src/live-tokens/data/themes/sunset.json +3931 -0
  115. package/src/live-tokens/data/tokens.generated.css +106 -117
  116. package/src/system/styles/CONVENTIONS.md +1 -1
  117. package/src/system/styles/fonts.css +1 -1
  118. package/template/README.md +7 -5
  119. package/template/_gitignore +0 -6
  120. package/src/editor/core/components/componentPersist.ts +0 -62
  121. package/src/editor/core/manifests/manifestService.ts +0 -172
  122. package/src/editor/ui/ManifestFileManager.svelte +0 -446
  123. package/src/editor/ui/ThemeFileManager.svelte +0 -785
  124. package/src/live-tokens/data/manifests/default.json +0 -35
@@ -0,0 +1,1781 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // vite-plugin/generateColorsAndType/index.ts
31
+ var generateColorsAndType_exports = {};
32
+ __export(generateColorsAndType_exports, {
33
+ buildColorsAndTypeFromSeeds: () => buildColorsAndTypeFromSeeds,
34
+ readLiveTokensConfig: () => readLiveTokensConfig,
35
+ resolveDataDirs: () => resolveDataDirs,
36
+ sanitizeFileName: () => sanitizeFileName
37
+ });
38
+ module.exports = __toCommonJS(generateColorsAndType_exports);
39
+
40
+ // src/editor/core/palettes/oklch.ts
41
+ function srgbToLinear(c) {
42
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
43
+ }
44
+ function linearToSrgb(c) {
45
+ return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
46
+ }
47
+ function hexToLinearRgb(hex) {
48
+ const r = parseInt(hex.slice(1, 3), 16) / 255;
49
+ const g = parseInt(hex.slice(3, 5), 16) / 255;
50
+ const b = parseInt(hex.slice(5, 7), 16) / 255;
51
+ return [srgbToLinear(r), srgbToLinear(g), srgbToLinear(b)];
52
+ }
53
+ function linearRgbToHex(r, g, b) {
54
+ const toHex = (c) => {
55
+ const v = Math.round(Math.max(0, Math.min(1, linearToSrgb(c))) * 255);
56
+ return v.toString(16).padStart(2, "0");
57
+ };
58
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
59
+ }
60
+ function linearRgbToOklab(r, g, b) {
61
+ const l_ = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
62
+ const m_ = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
63
+ const s_ = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
64
+ const l = Math.cbrt(l_);
65
+ const m = Math.cbrt(m_);
66
+ const s = Math.cbrt(s_);
67
+ return [
68
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
69
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
70
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
71
+ ];
72
+ }
73
+ function oklabToLinearRgb(L, a, b) {
74
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
75
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
76
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
77
+ const l = l_ * l_ * l_;
78
+ const m = m_ * m_ * m_;
79
+ const s = s_ * s_ * s_;
80
+ return [
81
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
82
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
83
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
84
+ ];
85
+ }
86
+ function oklabToOklch(L, a, b) {
87
+ const c = Math.sqrt(a * a + b * b);
88
+ let h = Math.atan2(b, a) * 180 / Math.PI;
89
+ if (h < 0) h += 360;
90
+ return { l: L, c, h };
91
+ }
92
+ function oklchToOklab(l, c, h) {
93
+ const hRad = h * Math.PI / 180;
94
+ return [l, c * Math.cos(hRad), c * Math.sin(hRad)];
95
+ }
96
+ function hexToOklch(hex) {
97
+ const [r, g, b] = hexToLinearRgb(hex);
98
+ const [L, a, bVal] = linearRgbToOklab(r, g, b);
99
+ return oklabToOklch(L, a, bVal);
100
+ }
101
+ function oklchToHex(l, c, h) {
102
+ const [L, a, b] = oklchToOklab(l, c, h);
103
+ const [r, g, bVal] = oklabToLinearRgb(L, a, b);
104
+ return linearRgbToHex(r, g, bVal);
105
+ }
106
+ function isInGamut(r, g, b) {
107
+ const eps = 1e-4;
108
+ return r >= -eps && r <= 1 + eps && g >= -eps && g <= 1 + eps && b >= -eps && b <= 1 + eps;
109
+ }
110
+ function oklchToHexClamped(l, c, h) {
111
+ const g = gamutClamp(l, c, h);
112
+ return oklchToHex(g.l, g.c, g.h);
113
+ }
114
+ function gamutClamp(l, c, h) {
115
+ if (l <= 0) return { l: 0, c: 0, h };
116
+ if (l >= 1) return { l: 1, c: 0, h };
117
+ const [L, a, b] = oklchToOklab(l, c, h);
118
+ const [r, g, bVal] = oklabToLinearRgb(L, a, b);
119
+ if (isInGamut(r, g, bVal)) return { l, c, h };
120
+ let lo = 0;
121
+ let hi = c;
122
+ for (let i = 0; i < 20; i++) {
123
+ const mid = (lo + hi) / 2;
124
+ const [La, aa, ba] = oklchToOklab(l, mid, h);
125
+ const [rr, gg, bb] = oklabToLinearRgb(La, aa, ba);
126
+ if (isInGamut(rr, gg, bb)) {
127
+ lo = mid;
128
+ } else {
129
+ hi = mid;
130
+ }
131
+ }
132
+ return { l, c: lo, h };
133
+ }
134
+
135
+ // src/editor/ui/curveEngine.ts
136
+ function makeAnchor(x, y, tangentLen = 15) {
137
+ return { x, y, inDx: -tangentLen, inDy: 0, outDx: tangentLen, outDy: 0 };
138
+ }
139
+ var HANDLE_SPAN = 1 / 3;
140
+ function tangentSlope(prev, x, y, next) {
141
+ const hPrev = prev ? x - prev.x : 0;
142
+ const hNext = next ? next.x - x : 0;
143
+ const dPrev = hPrev > 0 ? (y - prev.y) / hPrev : null;
144
+ const dNext = hNext > 0 ? (next.y - y) / hNext : null;
145
+ if (dPrev === null) return dNext ?? 0;
146
+ if (dNext === null) return dPrev;
147
+ if (dPrev * dNext <= 0) return 0;
148
+ const wPrev = 2 * hNext + hPrev;
149
+ const wNext = hNext + 2 * hPrev;
150
+ return (wPrev + wNext) / (wPrev / dPrev + wNext / dNext);
151
+ }
152
+ function tangentAnchor(x, y, prev, next) {
153
+ const m = tangentSlope(prev, x, y, next);
154
+ const inDx = prev ? -(x - prev.x) * HANDLE_SPAN : 0;
155
+ const outDx = next ? (next.x - x) * HANDLE_SPAN : 0;
156
+ return { x, y, inDx, inDy: m * inDx, outDx, outDy: m * outDx };
157
+ }
158
+ function evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, t) {
159
+ const u = 1 - t, u2 = u * u, u3 = u2 * u;
160
+ const t2 = t * t, t3 = t2 * t;
161
+ return {
162
+ x: u3 * p0x + 3 * u2 * t * c0x + 3 * u * t2 * c1x + t3 * p1x,
163
+ y: u3 * p0y + 3 * u2 * t * c0y + 3 * u * t2 * c1y + t3 * p1y
164
+ };
165
+ }
166
+ function sampleCurve(anchors, xPos) {
167
+ if (anchors.length === 0) return 0;
168
+ if (anchors.length === 1) return anchors[0].y;
169
+ if (xPos <= anchors[0].x) return anchors[0].y;
170
+ if (xPos >= anchors[anchors.length - 1].x) return anchors[anchors.length - 1].y;
171
+ let seg = 0;
172
+ while (seg < anchors.length - 2 && anchors[seg + 1].x < xPos) seg++;
173
+ const a0 = anchors[seg], a1 = anchors[seg + 1];
174
+ const p0x = a0.x, p0y = a0.y;
175
+ const c0x = a0.x + a0.outDx, c0y = a0.y + a0.outDy;
176
+ const c1x = a1.x + a1.inDx, c1y = a1.y + a1.inDy;
177
+ const p1x = a1.x, p1y = a1.y;
178
+ let lo = 0, hi = 1;
179
+ for (let i = 0; i < 20; i++) {
180
+ const mid = (lo + hi) / 2;
181
+ const pt = evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, mid);
182
+ if (pt.x < xPos) lo = mid;
183
+ else hi = mid;
184
+ }
185
+ return evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, (lo + hi) / 2).y;
186
+ }
187
+
188
+ // src/editor/core/palettes/paletteDerivation.ts
189
+ var PALETTE_SPECS = [
190
+ { label: "Brand", cssNamespace: "brand", initialColor: { l: 0.5573, c: 0.1841, h: 25.49 } },
191
+ { label: "Accent", cssNamespace: "accent", initialColor: { l: 0.7674, c: 0.164, h: 70.44 } },
192
+ { label: "Special", cssNamespace: "special", initialColor: { l: 0.6056, c: 0.2189, h: 292.72 } },
193
+ { label: "Canvas", cssNamespace: "canvas", emptySelector: true, initialColor: { l: 0.2284, c: 0.0384, h: 282.93 } },
194
+ { label: "Neutral", cssNamespace: "neutral", neutral: true, initialColor: { l: 0.5679, c: 0.0134, h: 240.07 } },
195
+ { label: "Alternate", cssNamespace: "alternate", neutral: true, displayLabel: "Alternate (neutral)", initialColor: { l: 0.5873, c: 87e-4, h: 48.57 } },
196
+ { label: "Info", cssNamespace: "info", initialColor: { l: 0.5871, c: 0.1855, h: 259.56 } },
197
+ { label: "Success", cssNamespace: "success", initialColor: { l: 0.7198, c: 0.1918, h: 149.52 } },
198
+ { label: "Warning", cssNamespace: "warning", initialColor: { l: 0.6704, c: 0.1716, h: 48.75 } },
199
+ { label: "Danger", cssNamespace: "danger", initialColor: { l: 0.6103, c: 0.2165, h: 18.1 } }
200
+ ];
201
+ var PALETTE_STEPS = [
202
+ { label: "100" },
203
+ { label: "200" },
204
+ { label: "300" },
205
+ { label: "400" },
206
+ { label: "500" },
207
+ { label: "600" },
208
+ { label: "700" },
209
+ { label: "800" },
210
+ { label: "850" },
211
+ { label: "900" },
212
+ { label: "950" }
213
+ ];
214
+ var SCALES = [
215
+ {
216
+ title: "Surfaces",
217
+ isText: false,
218
+ steps: [
219
+ { name: "lowest", position: -1 },
220
+ { name: "lower", position: -2 / 3 },
221
+ { name: "low", position: -1 / 3 },
222
+ { name: "default", position: 0 },
223
+ { name: "high", position: 1 / 3 },
224
+ { name: "higher", position: 2 / 3 },
225
+ { name: "highest", position: 1 }
226
+ ]
227
+ },
228
+ {
229
+ title: "Borders",
230
+ isText: false,
231
+ steps: [
232
+ { name: "faint", position: -1 },
233
+ { name: "subtle", position: -0.5 },
234
+ { name: "default", position: 0 },
235
+ { name: "medium", position: 0.5 },
236
+ { name: "strong", position: 1 }
237
+ ]
238
+ },
239
+ {
240
+ title: "Text",
241
+ isText: true,
242
+ steps: [
243
+ { name: "primary", position: 0 },
244
+ { name: "secondary", position: 0 },
245
+ { name: "tertiary", position: 0 },
246
+ { name: "muted", position: 0 },
247
+ { name: "disabled", position: 0 }
248
+ ]
249
+ }
250
+ ];
251
+ var BW_GUARD_MIN_L = 0.17;
252
+ var BW_GUARD_MAX_L = 0.93;
253
+ var DEFAULT_PALETTE_LIGHTNESS = () => [makeAnchor(0, 95, 5), makeAnchor(100, 8, 5)];
254
+ var DEFAULT_PALETTE_SATURATION = () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)];
255
+ function scaleCurveDefaults(scheme = "dark") {
256
+ if (scheme === "light") {
257
+ return {
258
+ Surfaces: {
259
+ lightness: () => [makeAnchor(0, 98, 5), makeAnchor(100, 82, 5)],
260
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
261
+ },
262
+ Borders: {
263
+ lightness: () => [makeAnchor(0, 92, 5), makeAnchor(100, 45, 5)],
264
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
265
+ },
266
+ Text: {
267
+ lightness: () => [makeAnchor(0, 30, 30), makeAnchor(100, 120, 30)],
268
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 15, 30)]
269
+ }
270
+ };
271
+ }
272
+ return {
273
+ Surfaces: {
274
+ lightness: () => [makeAnchor(0, 15, 5), makeAnchor(100, 47, 5)],
275
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
276
+ },
277
+ Borders: {
278
+ lightness: () => [makeAnchor(0, 25, 5), makeAnchor(100, 80, 5)],
279
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
280
+ },
281
+ Text: {
282
+ lightness: () => [makeAnchor(0, 120, 30), makeAnchor(100, 55, 30)],
283
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 15, 30)]
284
+ }
285
+ };
286
+ }
287
+ var defaultScaleCurves = scaleCurveDefaults("dark");
288
+ function paletteStepKey(label) {
289
+ return `Palette-${label}`;
290
+ }
291
+ function stepKey(scaleTitle, stepName) {
292
+ return `${scaleTitle}-${stepName}`;
293
+ }
294
+ function stepIndexToX(index) {
295
+ return index / (PALETTE_STEPS.length - 1) * 100;
296
+ }
297
+ function scaleStepToX(step, scale) {
298
+ const idx = scale.steps.indexOf(step);
299
+ return scale.steps.length > 1 ? idx / (scale.steps.length - 1) * 100 : 50;
300
+ }
301
+ function serializeDerivedValue(value) {
302
+ return value.kind === "raw" ? value.css : oklchToHexClamped(value.l, value.c, value.h);
303
+ }
304
+ function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset) {
305
+ const { c: baseC, h } = base;
306
+ const xPos = stepIndexToX(index);
307
+ const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset.lightness ?? 0))) / 100;
308
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset.saturation ?? 0)) / 100));
309
+ const targetC = baseC * satMul;
310
+ return gamutClamp(targetL, targetC, h);
311
+ }
312
+ function nearestPaletteStep(lightnessCurve, baseL) {
313
+ let best = 0;
314
+ let bestD = Infinity;
315
+ for (let i = 0; i < PALETTE_STEPS.length; i++) {
316
+ const d = Math.abs(sampleCurve(lightnessCurve, stepIndexToX(i)) - baseL * 100);
317
+ if (d < bestD) {
318
+ bestD = d;
319
+ best = i;
320
+ }
321
+ }
322
+ return best;
323
+ }
324
+ function setCurveAnchor(curve, x, y, smooth = false) {
325
+ if (smooth && curve.length === 2) {
326
+ const [p0, p2] = curve;
327
+ const mid = { x, y, inDx: 0, inDy: 0, outDx: 0, outDy: 0 };
328
+ if (Math.abs(p0.x - x) < 0.5) {
329
+ return {
330
+ curve: [tangentAnchor(x, y, null, p2), tangentAnchor(p2.x, p2.y, mid, null)],
331
+ displacedY: p0.y,
332
+ priorEndpoints: [p0, p2]
333
+ };
334
+ }
335
+ if (Math.abs(p2.x - x) < 0.5) {
336
+ return {
337
+ curve: [tangentAnchor(p0.x, p0.y, null, mid), tangentAnchor(x, y, p0, null)],
338
+ displacedY: p2.y,
339
+ priorEndpoints: [p0, p2]
340
+ };
341
+ }
342
+ return {
343
+ curve: [
344
+ tangentAnchor(p0.x, p0.y, null, mid),
345
+ tangentAnchor(x, y, p0, p2),
346
+ tangentAnchor(p2.x, p2.y, mid, null)
347
+ ],
348
+ priorEndpoints: [p0, p2]
349
+ };
350
+ }
351
+ const existing = curve.findIndex((a) => Math.abs(a.x - x) < 0.5);
352
+ if (existing >= 0) {
353
+ const displacedY = curve[existing].y;
354
+ return { curve: curve.map((a, i) => i === existing ? { ...a, x, y } : a), displacedY };
355
+ }
356
+ let insertAt = curve.findIndex((a) => a.x > x);
357
+ if (insertAt < 0) insertAt = curve.length;
358
+ const prev = curve[insertAt - 1] ?? null;
359
+ const next = curve[insertAt] ?? null;
360
+ const out = [...curve];
361
+ if (prev && next) {
362
+ const span = next.x - prev.x;
363
+ out[insertAt - 1] = scaleOutHandle(prev, (x - prev.x) / span);
364
+ out[insertAt] = scaleInHandle(next, (next.x - x) / span);
365
+ }
366
+ out.splice(insertAt, 0, fitBetween(tangentAnchor(x, y, prev, next), out[insertAt - 1] ?? null, out[insertAt] ?? null));
367
+ return { curve: out };
368
+ }
369
+ var scaleOutHandle = (a, k) => ({ ...a, outDx: a.outDx * k, outDy: a.outDy * k });
370
+ var scaleInHandle = (a, k) => ({ ...a, inDx: a.inDx * k, inDy: a.inDy * k });
371
+ function fitBetween(a, prev, next) {
372
+ let out = a;
373
+ if (prev) {
374
+ const room = a.x - (prev.x + prev.outDx);
375
+ if (room < -out.inDx) out = scaleInHandle(out, room <= 0 ? 0 : room / -out.inDx);
376
+ }
377
+ if (next) {
378
+ const room = next.x + next.inDx - a.x;
379
+ if (room < out.outDx) out = scaleOutHandle(out, room <= 0 ? 0 : room / out.outDx);
380
+ }
381
+ return out;
382
+ }
383
+ function liftCurveAnchor(curve, x, displacedY, priorEndpoints) {
384
+ if (priorEndpoints) return priorEndpoints;
385
+ const idx = curve.findIndex((a) => Math.abs(a.x - x) < 0.5);
386
+ if (idx < 0) return curve;
387
+ if (displacedY !== void 0) return curve.map((a, i) => i === idx ? { ...a, y: displacedY } : a);
388
+ if (idx === 0 || idx === curve.length - 1) return curve;
389
+ const out = curve.filter((_, i) => i !== idx);
390
+ const prev = curve[idx - 1];
391
+ const next = curve[idx + 1];
392
+ if (prev && next) {
393
+ const span = next.x - prev.x;
394
+ out[idx - 1] = scaleOutHandle(prev, span / (curve[idx].x - prev.x));
395
+ out[idx] = scaleInHandle(next, span / (next.x - curve[idx].x));
396
+ }
397
+ return out;
398
+ }
399
+ function syncBaseAnchor(cfg) {
400
+ if (cfg.anchorToBase === false) return;
401
+ const prev = cfg.anchorPlacement;
402
+ const fresh = prev === void 0;
403
+ let lCurve = cfg.lightnessCurve;
404
+ let sCurve = cfg.saturationCurve;
405
+ if (prev) {
406
+ const prevX = stepIndexToX(prev.step);
407
+ lCurve = liftCurveAnchor(lCurve, prevX, prev.displacedL);
408
+ sCurve = liftCurveAnchor(sCurve, prevX, prev.displacedS);
409
+ }
410
+ const step = nearestPaletteStep(lCurve, cfg.baseColor.l);
411
+ const x = stepIndexToX(step);
412
+ const l = setCurveAnchor(lCurve, x, cfg.baseColor.l * 100, fresh);
413
+ const s = setCurveAnchor(sCurve, x, 100, fresh);
414
+ cfg.lightnessCurve = l.curve;
415
+ cfg.saturationCurve = s.curve;
416
+ cfg.anchorPlacement = {
417
+ step,
418
+ displacedL: l.displacedY,
419
+ displacedS: s.displacedY,
420
+ priorLightnessEndpoints: prev?.priorLightnessEndpoints ?? l.priorEndpoints,
421
+ priorSaturationEndpoints: prev?.priorSaturationEndpoints ?? s.priorEndpoints
422
+ };
423
+ }
424
+ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
425
+ const scale = SCALES.find((s) => s.title === scaleTitle);
426
+ const xPos = scaleStepToX(step, scale);
427
+ const defs = defaultScaleCurves[scaleTitle];
428
+ const lCurve = scaleCurves[scaleTitle]?.lightness ?? defs.lightness();
429
+ const sCurve = scaleCurves[scaleTitle]?.saturation ?? defs.saturation();
430
+ const lOff = curveOffset[`${scaleTitle}-lightness`] ?? 0;
431
+ const sOff = curveOffset[`${scaleTitle}-saturation`] ?? 0;
432
+ const { l: baseL, c: baseC, h: baseH } = base;
433
+ let targetL;
434
+ if (scale.isText) {
435
+ const lMul = Math.max(0, Math.min(2, (sampleCurve(lCurve, xPos) + lOff) / 100));
436
+ targetL = Math.max(0, Math.min(1, baseL * lMul));
437
+ } else {
438
+ targetL = Math.max(0, Math.min(100, sampleCurve(lCurve, xPos) + lOff)) / 100;
439
+ }
440
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(sCurve, xPos) + sOff) / 100));
441
+ const targetC = baseC * satMul;
442
+ return gamutClamp(targetL, targetC, baseH);
443
+ }
444
+ function scaleToCssVar(scaleTitle, stepName, cssNamespace) {
445
+ if (cssNamespace === null) return null;
446
+ if (scaleTitle === "Surfaces") {
447
+ const suffix = stepName === "default" ? "" : `-${stepName}`;
448
+ return cssNamespace === "neutral" ? `--surface-neutral${suffix}` : `--surface-${cssNamespace}${suffix}`;
449
+ }
450
+ if (scaleTitle === "Borders") {
451
+ const suffix = stepName === "default" ? "" : `-${stepName}`;
452
+ return cssNamespace === "neutral" ? `--border-neutral${suffix}` : `--border-${cssNamespace}${suffix}`;
453
+ }
454
+ if (scaleTitle === "Text") {
455
+ if (cssNamespace === "neutral") return `--text-${stepName}`;
456
+ return stepName === "primary" ? `--text-${cssNamespace}` : `--text-${cssNamespace}-${stepName}`;
457
+ }
458
+ return null;
459
+ }
460
+ function derivePaletteValues(spec, config) {
461
+ const out = {};
462
+ if (!config) return out;
463
+ const baseColor = config.baseColor ?? spec.initialColor;
464
+ const overrides = config.overrides ?? {};
465
+ const curveOffset = config.curveOffset ?? {};
466
+ const scaleCurves = config.scaleCurves ?? {};
467
+ const lightnessCurve = config.lightnessCurve ?? DEFAULT_PALETTE_LIGHTNESS();
468
+ const saturationCurve = config.saturationCurve ?? DEFAULT_PALETTE_SATURATION();
469
+ PALETTE_STEPS.forEach((ps, index) => {
470
+ const k = paletteStepKey(ps.label);
471
+ const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computePaletteOklch(index, baseColor, lightnessCurve, saturationCurve, curveOffset) };
472
+ out[`--color-${spec.cssNamespace}-${ps.label}`] = value;
473
+ });
474
+ for (const scale of SCALES) {
475
+ for (const step of scale.steps) {
476
+ const k = stepKey(scale.title, step.name);
477
+ const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computeDerivedOklch(step, baseColor, scale.title, scaleCurves, curveOffset) };
478
+ const varName = scaleToCssVar(scale.title, step.name, spec.cssNamespace);
479
+ if (varName) out[varName] = value;
480
+ }
481
+ }
482
+ const textPrimary = out["--text-primary"];
483
+ if (textPrimary?.kind === "color") {
484
+ const mirroredL = Math.max(BW_GUARD_MIN_L, Math.min(BW_GUARD_MAX_L, 1 - textPrimary.l));
485
+ out["--text-inverted"] = { kind: "color", ...gamutClamp(mirroredL, textPrimary.c, textPrimary.h) };
486
+ }
487
+ if (spec.emptySelector) {
488
+ const emptyMode = config.emptyMode ?? "solid";
489
+ const gradientStyle = config.gradientStyle ?? "linear";
490
+ const gradientAngle = config.gradientAngle ?? 180;
491
+ const gradientReverse = config.gradientReverse ?? false;
492
+ const gradientSize = config.gradientSize ?? "page";
493
+ const gradientStops = config.gradientStops ?? [
494
+ { position: 0, paletteLabel: "800" },
495
+ { position: 100, paletteLabel: "950" }
496
+ ];
497
+ if (emptyMode === "solid") {
498
+ out["--page-bg"] = { kind: "color", ...baseColor };
499
+ out["--page-bg-attachment"] = { kind: "raw", css: "scroll" };
500
+ } else {
501
+ const sortedStops = [...gradientStops].sort(
502
+ (a, b) => gradientReverse ? b.position - a.position : a.position - b.position
503
+ );
504
+ const stopsCss = sortedStops.map((s) => {
505
+ const stopValue = out[`--color-${spec.cssNamespace}-${s.paletteLabel}`];
506
+ const hex = stopValue ? serializeDerivedValue(stopValue) : "#000000";
507
+ return `${hex} ${s.position}%`;
508
+ }).join(", ");
509
+ let gradient;
510
+ switch (gradientStyle) {
511
+ case "radial":
512
+ gradient = `radial-gradient(circle, ${stopsCss})`;
513
+ break;
514
+ case "conic":
515
+ gradient = `conic-gradient(from ${gradientAngle}deg, ${stopsCss})`;
516
+ break;
517
+ default:
518
+ gradient = `linear-gradient(${gradientAngle}deg, ${stopsCss})`;
519
+ }
520
+ out["--page-bg"] = { kind: "raw", css: gradient };
521
+ out["--page-bg-attachment"] = { kind: "raw", css: gradientSize === "window" ? "fixed" : "scroll" };
522
+ }
523
+ }
524
+ return out;
525
+ }
526
+ function palettesToValues(palettes) {
527
+ const out = {};
528
+ for (const spec of PALETTE_SPECS) {
529
+ Object.assign(out, derivePaletteValues(spec, palettes[spec.label]));
530
+ }
531
+ return out;
532
+ }
533
+ function palettesToVars(palettes) {
534
+ const out = {};
535
+ for (const [k, v] of Object.entries(palettesToValues(palettes))) {
536
+ out[k] = serializeDerivedValue(v);
537
+ }
538
+ return out;
539
+ }
540
+
541
+ // src/editor/core/store/editorCore.ts
542
+ var import_store = require("svelte/store");
543
+ var emptyStateFactory = () => ({});
544
+ var store = (0, import_store.writable)(emptyStateFactory());
545
+ var past = [];
546
+ var future = [];
547
+ var savedAtIndex = 0;
548
+ var historyTick = (0, import_store.writable)(0);
549
+ var editorState = { subscribe: store.subscribe };
550
+ var canUndo = (0, import_store.derived)(historyTick, () => past.length > 0);
551
+ var canRedo = (0, import_store.derived)(historyTick, () => future.length > 0);
552
+ var dirty = (0, import_store.derived)(historyTick, () => past.length !== savedAtIndex);
553
+
554
+ // src/editor/core/themes/slices/gradients.ts
555
+ function makeDefaultGradients() {
556
+ return [
557
+ {
558
+ variable: "--gradient-1",
559
+ type: "linear",
560
+ angle: 90,
561
+ stops: [
562
+ { position: 0, color: "--color-brand-500" },
563
+ { position: 100, color: "--color-accent-500" }
564
+ ]
565
+ },
566
+ {
567
+ variable: "--gradient-2",
568
+ type: "linear",
569
+ angle: 135,
570
+ stops: [
571
+ { position: 0, color: "--color-brand-500" },
572
+ { position: 100, color: "--color-special-500" }
573
+ ]
574
+ },
575
+ {
576
+ variable: "--gradient-3",
577
+ type: "linear",
578
+ angle: 90,
579
+ stops: [
580
+ { position: 0, color: "--color-success-500" },
581
+ { position: 100, color: "--color-info-500" }
582
+ ]
583
+ },
584
+ {
585
+ variable: "--gradient-4",
586
+ type: "linear",
587
+ angle: 45,
588
+ stops: [
589
+ { position: 0, color: "--color-danger-500" },
590
+ { position: 100, color: "--color-warning-500" }
591
+ ]
592
+ }
593
+ ];
594
+ }
595
+ function formatGradientStop(s) {
596
+ return `${formatGradientStopColor(s)} ${s.position}%`;
597
+ }
598
+ function formatGradientValue(v) {
599
+ if (v.type === "none") return "transparent";
600
+ if (v.type === "solid") {
601
+ const first = v.stops[0];
602
+ if (!first) return "transparent";
603
+ return formatGradientStopColor(first);
604
+ }
605
+ const stops = v.stops.map(formatGradientStop).join(", ");
606
+ if (v.type === "linear") return `linear-gradient(${v.angle}deg, ${stops})`;
607
+ const cx = v.centerX ?? 50;
608
+ return `radial-gradient(${formatRadialShape(v)} at ${cx}% 50%, ${stops})`;
609
+ }
610
+ var DEFAULT_RADIAL_BASE_PX = 100;
611
+ function formatRadialShape(v) {
612
+ const ax = v.aspectX ?? 1;
613
+ const ay = v.aspectY ?? 1;
614
+ if (ax === 1 && ay === 1) {
615
+ return v.radius && v.radius > 0 ? `circle ${v.radius}px` : "circle";
616
+ }
617
+ const base = v.radius && v.radius > 0 ? v.radius : DEFAULT_RADIAL_BASE_PX;
618
+ const rx = base * ax;
619
+ const ry = base * ay;
620
+ return `ellipse ${rx.toFixed(2)}px ${ry.toFixed(2)}px`;
621
+ }
622
+ function formatGradientStopColor(s) {
623
+ const base = s.color.startsWith("--") ? `var(${s.color})` : s.color;
624
+ const opacity = s.opacity ?? 100;
625
+ return opacity >= 100 ? base : `color-mix(in srgb, ${base} ${opacity}%, transparent)`;
626
+ }
627
+
628
+ // src/editor/core/palettes/contrast.ts
629
+ var AA_BODY = 4.5;
630
+ var AA_LARGE = 3;
631
+ function linearizeChannel(v8) {
632
+ const s = v8 / 255;
633
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
634
+ }
635
+ function relativeLuminance(hex) {
636
+ const r = linearizeChannel(parseInt(hex.slice(1, 3), 16));
637
+ const g = linearizeChannel(parseInt(hex.slice(3, 5), 16));
638
+ const b = linearizeChannel(parseInt(hex.slice(5, 7), 16));
639
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
640
+ }
641
+ function contrastRatio(a, b) {
642
+ const la = relativeLuminance(a);
643
+ const lb = relativeLuminance(b);
644
+ const hi = Math.max(la, lb);
645
+ const lo = Math.min(la, lb);
646
+ return (hi + 0.05) / (lo + 0.05);
647
+ }
648
+ function findLForContrast(opts) {
649
+ const { against, ratio, direction, c, h } = opts;
650
+ const margin = opts.margin ?? 0.05;
651
+ const lMin = opts.lMin ?? 0;
652
+ const lMax = opts.lMax ?? 1;
653
+ const target = ratio + margin;
654
+ const againstL = hexToOklch(against).l;
655
+ const evalAt = (l2, cc) => {
656
+ const g = gamutClamp(l2, cc, h);
657
+ const hex2 = oklchToHex(g.l, g.c, g.h);
658
+ return { hex: hex2, chroma: g.c, ratio: contrastRatio(hex2, against) };
659
+ };
660
+ const solveAtChroma = (cc) => {
661
+ const lighter = direction === "lighter";
662
+ const lo0 = lighter ? Math.max(lMin, againstL) : lMin;
663
+ const hi0 = lighter ? lMax : Math.min(lMax, againstL);
664
+ if (lo0 >= hi0) return null;
665
+ const extreme = lighter ? hi0 : lo0;
666
+ if (evalAt(extreme, cc).ratio < target) return null;
667
+ let lo = lo0;
668
+ let hi = hi0;
669
+ for (let i = 0; i < 24; i++) {
670
+ const mid = (lo + hi) / 2;
671
+ const meets = evalAt(mid, cc).ratio >= target;
672
+ if (lighter ? meets : !meets) hi = mid;
673
+ else lo = mid;
674
+ }
675
+ const at = lighter ? hi : lo;
676
+ const e = evalAt(at, cc);
677
+ return { l: at, hex: e.hex, chroma: e.chroma };
678
+ };
679
+ let sol = solveAtChroma(c);
680
+ if (!sol) {
681
+ if (!solveAtChroma(0)) {
682
+ const extremeL = direction === "lighter" ? lMax : lMin;
683
+ const e = evalAt(extremeL, 0);
684
+ return { l: extremeL, c: 0, hex: e.hex };
685
+ }
686
+ let lo = 0;
687
+ let hi = c;
688
+ for (let i = 0; i < 24; i++) {
689
+ const mid = (lo + hi) / 2;
690
+ if (solveAtChroma(mid)) lo = mid;
691
+ else hi = mid;
692
+ }
693
+ sol = solveAtChroma(lo);
694
+ }
695
+ let { l, hex, chroma } = sol;
696
+ const step = direction === "lighter" ? 4e-3 : -4e-3;
697
+ for (let k = 0; k < 12 && contrastRatio(hex, against) < ratio; k++) {
698
+ l = Math.min(lMax, Math.max(lMin, l + step));
699
+ const g = gamutClamp(l, chroma, h);
700
+ l = g.l;
701
+ chroma = g.c;
702
+ hex = oklchToHex(g.l, g.c, g.h);
703
+ }
704
+ return { l, c: chroma, hex };
705
+ }
706
+
707
+ // src/editor/ui/palette/paletteMath.ts
708
+ var DEFAULT_NEUTRAL_LIGHTNESS = () => [makeAnchor(0, 92, 5), makeAnchor(100, 3, 5)];
709
+ function defaultPaletteConfig(opts) {
710
+ const cfg = {
711
+ baseColor: opts.baseColor,
712
+ lightnessCurve: opts.neutral ? DEFAULT_NEUTRAL_LIGHTNESS() : DEFAULT_PALETTE_LIGHTNESS(),
713
+ saturationCurve: DEFAULT_PALETTE_SATURATION(),
714
+ scaleCurves: defaultScaleCurvesObject(opts.scheme ?? "dark"),
715
+ curveOffset: { lightness: 0, saturation: 0 },
716
+ overrides: {},
717
+ snappedScales: [],
718
+ anchorToBase: true
719
+ };
720
+ syncBaseAnchor(cfg);
721
+ return cfg;
722
+ }
723
+ function defaultScaleCurvesObject(scheme = "dark") {
724
+ const defs = scaleCurveDefaults(scheme);
725
+ return {
726
+ Surfaces: { lightness: defs.Surfaces.lightness(), saturation: defs.Surfaces.saturation() },
727
+ Borders: { lightness: defs.Borders.lightness(), saturation: defs.Borders.saturation() },
728
+ Text: { lightness: defs.Text.lightness(), saturation: defs.Text.saturation() }
729
+ };
730
+ }
731
+
732
+ // src/editor/core/storage/files/versionedFileResourceClient.ts
733
+ function sanitizeFileName(name) {
734
+ return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^[-_]+|-+$/g, "") || "unnamed";
735
+ }
736
+
737
+ // src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts
738
+ var LEGACY_KEY_RENAMES = {
739
+ "--empty": "--page-bg",
740
+ "--empty-attachment": "--page-bg-attachment",
741
+ // Orphan exports dropped from tokens.css; no new home — silently discard.
742
+ "--border-neutral": null,
743
+ // Shadow cleanup: these five tokens were removed (low/zero consumers,
744
+ // aesthetic drift). Dialog migrated onto --shadow-2xl; focus rings moved
745
+ // to their own --ring-focus-* namespace, which themes don't carry by
746
+ // default — tokens.css provides the canonical values.
747
+ "--shadow-app": null,
748
+ "--shadow-card": null,
749
+ "--shadow-overlay": null,
750
+ "--shadow-focus": null,
751
+ "--shadow-glow-green": null
752
+ };
753
+ var BG_TO_CANVAS_PREFIXES = ["--color-bg-", "--surface-bg", "--border-bg", "--text-bg"];
754
+ function migrateBgToCanvas(rawVars) {
755
+ for (const oldKey of Object.keys(rawVars)) {
756
+ for (const prefix of BG_TO_CANVAS_PREFIXES) {
757
+ if (!oldKey.startsWith(prefix)) continue;
758
+ const suffix = oldKey.slice(prefix.length);
759
+ if (suffix && !suffix.startsWith("-")) continue;
760
+ const newKey = prefix.replace("-bg", "-canvas") + suffix;
761
+ if (newKey === oldKey) continue;
762
+ const value = rawVars[oldKey];
763
+ delete rawVars[oldKey];
764
+ if (!(newKey in rawVars)) rawVars[newKey] = value;
765
+ break;
766
+ }
767
+ }
768
+ }
769
+ function migrateLegacyKeys(rawVars) {
770
+ for (const [oldKey, newKey] of Object.entries(LEGACY_KEY_RENAMES)) {
771
+ if (!(oldKey in rawVars)) continue;
772
+ const value = rawVars[oldKey];
773
+ delete rawVars[oldKey];
774
+ if (newKey && !(newKey in rawVars)) rawVars[newKey] = value;
775
+ }
776
+ migrateBgToCanvas(rawVars);
777
+ }
778
+ var colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas = {
779
+ id: "2026-04-24-legacy-keys-and-bg-to-canvas",
780
+ fromVersion: 0,
781
+ toVersion: 1,
782
+ appliesTo: "colors-and-type",
783
+ apply(rawVars) {
784
+ const out = { ...rawVars };
785
+ migrateLegacyKeys(out);
786
+ return out;
787
+ }
788
+ };
789
+
790
+ // src/editor/core/themes/migrations/2026-04-24-component-prefix-and-suffix-renames.ts
791
+ var COMPONENT_PREFIX_RENAMES = {
792
+ "--segment-": "--segmentedcontrol-",
793
+ "--collapsible-": "--collapsiblesection-",
794
+ "--progress-": "--progressbar-",
795
+ "--section-divider-": "--sectiondivider-",
796
+ "--radio-": "--radiobutton-",
797
+ "--inline-edit-": "--inlineeditactions-"
798
+ };
799
+ var COMPONENT_SUFFIX_RENAMES = {
800
+ progressbar: [["-track-bg", "-track-surface"]],
801
+ inlineeditactions: [
802
+ ["-bg-hover", "-hover-surface"],
803
+ ["-bg", "-surface"]
804
+ ]
805
+ };
806
+ var componentMigration_2026_04_24_prefixAndSuffixRenames = {
807
+ id: "2026-04-24-component-prefix-and-suffix-renames",
808
+ fromVersion: 0,
809
+ toVersion: 1,
810
+ appliesTo: "component-config",
811
+ apply(rawVars, meta) {
812
+ const component = meta.component ?? "";
813
+ const out = {};
814
+ const suffixRules = COMPONENT_SUFFIX_RENAMES[component] ?? [];
815
+ for (const [oldKey, value] of Object.entries(rawVars)) {
816
+ let key = oldKey;
817
+ if (key === "--detail-nav-bg") key = "--detailnav-surface";
818
+ for (const [oldPrefix, newPrefix] of Object.entries(COMPONENT_PREFIX_RENAMES)) {
819
+ if (key.startsWith(oldPrefix)) {
820
+ key = newPrefix + key.slice(oldPrefix.length);
821
+ break;
822
+ }
823
+ }
824
+ for (const [oldSuffix, newSuffix] of suffixRules) {
825
+ if (key.endsWith(oldSuffix)) {
826
+ key = key.slice(0, -oldSuffix.length) + newSuffix;
827
+ break;
828
+ }
829
+ }
830
+ if (!(key in out)) out[key] = value;
831
+ }
832
+ return out;
833
+ }
834
+ };
835
+
836
+ // src/editor/core/themes/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts
837
+ var OPTION_DISABLED_PREFIX = "--segmentedcontrol-option-disabled-";
838
+ var DISABLED_PREFIX = "--segmentedcontrol-disabled-";
839
+ var SELECTED_DISABLED_PREFIX = "--segmentedcontrol-selected-disabled-";
840
+ var SELECTED_HOVER_PREFIX = "--segmentedcontrol-selected-hover-";
841
+ var componentMigration_2026_04_27_segmentedcontrolDisabledFlatten = {
842
+ id: "2026-04-27-segmentedcontrol-disabled-flatten",
843
+ fromVersion: 1,
844
+ toVersion: 2,
845
+ appliesTo: "component-config",
846
+ apply(rawVars, meta) {
847
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
848
+ const out = {};
849
+ for (const [oldKey, value] of Object.entries(rawVars)) {
850
+ let key = oldKey;
851
+ if (key.startsWith(SELECTED_DISABLED_PREFIX)) continue;
852
+ if (key.startsWith(SELECTED_HOVER_PREFIX)) continue;
853
+ if (key.startsWith(OPTION_DISABLED_PREFIX)) {
854
+ key = DISABLED_PREFIX + key.slice(OPTION_DISABLED_PREFIX.length);
855
+ }
856
+ if (!(key in out)) out[key] = value;
857
+ }
858
+ return out;
859
+ }
860
+ };
861
+
862
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-variant-namespace.ts
863
+ var PREFIX = "--collapsiblesection-";
864
+ var STATE_NAMES = /* @__PURE__ */ new Set(["default", "hover", "active", "expanded"]);
865
+ var componentMigration_2026_05_08_collapsiblesectionVariantNamespace = {
866
+ id: "2026-05-08-collapsiblesection-variant-namespace",
867
+ fromVersion: 2,
868
+ toVersion: 3,
869
+ appliesTo: "component-config",
870
+ apply(rawVars, meta) {
871
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
872
+ const out = {};
873
+ for (const [oldKey, value] of Object.entries(rawVars)) {
874
+ let key = oldKey;
875
+ if (key.startsWith(PREFIX)) {
876
+ const tail = key.slice(PREFIX.length);
877
+ const firstSegment = tail.split("-", 1)[0];
878
+ if (STATE_NAMES.has(firstSegment)) {
879
+ key = `${PREFIX}container-${tail}`;
880
+ }
881
+ }
882
+ if (!(key in out)) out[key] = value;
883
+ }
884
+ return out;
885
+ }
886
+ };
887
+
888
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts
889
+ var PFX = "--collapsiblesection-";
890
+ var componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup = {
891
+ id: "2026-05-08-collapsiblesection-frame-and-cleanup",
892
+ fromVersion: 3,
893
+ toVersion: 4,
894
+ appliesTo: "component-config",
895
+ apply(rawVars, meta) {
896
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
897
+ const out = {};
898
+ for (const prop of ["surface", "border", "border-width", "radius"]) {
899
+ const src = `${PFX}container-default-${prop}`;
900
+ if (src in rawVars) {
901
+ out[`${PFX}container-frame-${prop}`] = rawVars[src];
902
+ }
903
+ }
904
+ for (const [key, value] of Object.entries(rawVars)) {
905
+ if (/^--collapsiblesection-chromeless-(default|hover|active)-(border|border-width|radius)$/.test(key)) continue;
906
+ if (/^--collapsiblesection-container-(hover|active)-(border|border-width|radius)$/.test(key)) continue;
907
+ if (/^--collapsiblesection-container-default-(border|border-width|radius)$/.test(key)) continue;
908
+ if (/^--collapsiblesection-divider-(default|hover|active)-radius$/.test(key)) continue;
909
+ if (/^--collapsiblesection-(chromeless|divider|container)-expanded-(border|border-width|radius)$/.test(key)) continue;
910
+ if (/^--collapsiblesection-(chromeless|divider)-expanded-surface$/.test(key)) continue;
911
+ if (!(key in out)) out[key] = value;
912
+ }
913
+ return out;
914
+ }
915
+ };
916
+
917
+ // src/editor/core/themes/migrations/2026-05-10-sectiondivider-gradient-stops.ts
918
+ var PFX2 = "--sectiondivider-";
919
+ var VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
920
+ var OLD_STOP_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-stop-\d+$/;
921
+ var componentMigration_2026_05_10_sectiondividerGradientStops = {
922
+ id: "2026-05-10-sectiondivider-gradient-stops",
923
+ fromVersion: 4,
924
+ toVersion: 5,
925
+ appliesTo: "component-config",
926
+ apply(rawVars, meta) {
927
+ if (meta.component !== "sectiondivider") return { ...rawVars };
928
+ const out = {};
929
+ for (const [key, value] of Object.entries(rawVars)) {
930
+ if (OLD_STOP_RE.test(key)) continue;
931
+ out[key] = value;
932
+ }
933
+ const setIfMissing = (key, fallback) => {
934
+ if (!(key in out)) out[key] = fallback;
935
+ };
936
+ for (const v of VARIANTS) {
937
+ const old1 = rawVars[`${PFX2}${v}-gradient-stop-1`];
938
+ const old2 = rawVars[`${PFX2}${v}-gradient-stop-2`];
939
+ const old4 = rawVars[`${PFX2}${v}-gradient-stop-4`];
940
+ setIfMissing(`${PFX2}${v}-gradient-angle`, "--gradient-angle-diagonal");
941
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-color`, old1 ?? `--surface-${v}-highest`);
942
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-position`, "--gradient-stop-start");
943
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-color`, old2 ?? `--surface-${v}-higher`);
944
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-position`, "--gradient-stop-mid");
945
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-color`, old4 ?? `--surface-${v}`);
946
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-position`, "--gradient-stop-end");
947
+ }
948
+ return out;
949
+ }
950
+ };
951
+
952
+ // src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts
953
+ var PALETTE_STEPS2 = ["100", "200", "300", "400", "500", "600", "700", "800", "850", "900", "950"];
954
+ var SURFACE_SUFFIXES = ["lowest", "lower", "low", "high", "higher", "highest"];
955
+ var BORDER_SUFFIXES = ["faint", "subtle", "medium", "strong"];
956
+ var TEXT_SUFFIXES = ["secondary", "tertiary", "muted", "disabled"];
957
+ var RENAME_MAP = (() => {
958
+ const m = {};
959
+ for (const step of PALETTE_STEPS2) m[`--color-primary-${step}`] = `--color-brand-${step}`;
960
+ m["--surface-primary"] = "--surface-brand";
961
+ for (const suf of SURFACE_SUFFIXES) m[`--surface-primary-${suf}`] = `--surface-brand-${suf}`;
962
+ m["--border-primary"] = "--border-brand";
963
+ for (const suf of BORDER_SUFFIXES) m[`--border-primary-${suf}`] = `--border-brand-${suf}`;
964
+ m["--text-primary-color"] = "--text-brand";
965
+ for (const suf of TEXT_SUFFIXES) m[`--text-primary-${suf}`] = `--text-brand-${suf}`;
966
+ return m;
967
+ })();
968
+ function renameToken(name) {
969
+ return RENAME_MAP[name] ?? name;
970
+ }
971
+ function renameKeys(rawVars) {
972
+ const out = {};
973
+ for (const [k, v] of Object.entries(rawVars)) {
974
+ out[renameToken(k)] = v;
975
+ }
976
+ return out;
977
+ }
978
+ function renameKeysAndValues(rawVars) {
979
+ const out = {};
980
+ for (const [k, v] of Object.entries(rawVars)) {
981
+ out[renameToken(k)] = renameToken(v);
982
+ }
983
+ return out;
984
+ }
985
+ var colorsAndTypeMigration_2026_05_13_primaryToBrand = {
986
+ id: "2026-05-13-primary-to-brand-theme",
987
+ fromVersion: 1,
988
+ toVersion: 2,
989
+ appliesTo: "colors-and-type",
990
+ apply: renameKeys
991
+ };
992
+ var componentMigration_2026_05_13_primaryToBrand = {
993
+ id: "2026-05-13-primary-to-brand-component",
994
+ fromVersion: 5,
995
+ toVersion: 6,
996
+ appliesTo: "component-config",
997
+ apply: renameKeysAndValues
998
+ };
999
+
1000
+ // src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts
1001
+ function dropFrameSurface(rawVars, meta) {
1002
+ if (meta.component !== "collapsiblesection") return rawVars;
1003
+ const { "--collapsiblesection-container-frame-surface": _drop, ...rest } = rawVars;
1004
+ return rest;
1005
+ }
1006
+ var componentMigration_2026_05_19_collapsiblesectionDropFrameSurface = {
1007
+ id: "2026-05-19-collapsiblesection-drop-frame-surface",
1008
+ fromVersion: 6,
1009
+ toVersion: 7,
1010
+ appliesTo: "component-config",
1011
+ apply: dropFrameSurface
1012
+ };
1013
+
1014
+ // src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts
1015
+ var FLAT_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-(angle|stop-[123]-(color|position))$/;
1016
+ var componentMigration_2026_05_19_sectiondividerRichGradient = {
1017
+ id: "2026-05-19-sectiondivider-rich-gradient",
1018
+ fromVersion: 7,
1019
+ toVersion: 8,
1020
+ appliesTo: "component-config",
1021
+ apply(rawVars, meta) {
1022
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1023
+ const out = {};
1024
+ for (const [key, value] of Object.entries(rawVars)) {
1025
+ if (FLAT_RE.test(key)) continue;
1026
+ out[key] = value;
1027
+ }
1028
+ return out;
1029
+ }
1030
+ };
1031
+
1032
+ // src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts
1033
+ var VARIANTS2 = ["lg", "md", "sm"];
1034
+ var SUFFIX_RENAMES = [
1035
+ [/-title-border-width$/, "-title-outline-width"],
1036
+ [/-title-stroke-color$/, "-title-outline-color"],
1037
+ [/-padding$/, "-spacing"]
1038
+ ];
1039
+ function renameKeySuffix(key) {
1040
+ for (const [re, repl] of SUFFIX_RENAMES) {
1041
+ if (re.test(key)) return key.replace(re, repl);
1042
+ }
1043
+ return key;
1044
+ }
1045
+ function splitFamilyKey(key) {
1046
+ const m = key.match(/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-(.+)$/);
1047
+ if (!m) return null;
1048
+ return { family: m[1], suffix: m[2] };
1049
+ }
1050
+ var componentMigration_2026_05_20_sectiondividerSlimVariants = {
1051
+ id: "2026-05-20-sectiondivider-slim-variants",
1052
+ fromVersion: 8,
1053
+ toVersion: 9,
1054
+ appliesTo: "component-config",
1055
+ apply(rawVars, meta) {
1056
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1057
+ const out = {};
1058
+ const canvasValues = {};
1059
+ for (const [rawKey, value] of Object.entries(rawVars)) {
1060
+ const key = renameKeySuffix(rawKey);
1061
+ const parts = splitFamilyKey(key);
1062
+ if (!parts) {
1063
+ out[key] = value;
1064
+ continue;
1065
+ }
1066
+ if (parts.family !== "canvas") continue;
1067
+ canvasValues[parts.suffix] = value;
1068
+ }
1069
+ for (const suffix of Object.keys(canvasValues)) {
1070
+ for (const v of VARIANTS2) {
1071
+ out[`--sectiondivider-${v}-${suffix}`] = canvasValues[suffix];
1072
+ }
1073
+ }
1074
+ return out;
1075
+ }
1076
+ };
1077
+
1078
+ // src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts
1079
+ var componentMigration_2026_05_21_sectiondividerSpacingToPadding = {
1080
+ id: "2026-05-21-sectiondivider-spacing-to-padding",
1081
+ fromVersion: 9,
1082
+ toVersion: 10,
1083
+ appliesTo: "component-config",
1084
+ apply(rawVars, meta) {
1085
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1086
+ const out = {};
1087
+ for (const [key, value] of Object.entries(rawVars)) {
1088
+ const renamed = key.replace(/-spacing$/, "-padding");
1089
+ out[renamed] = value;
1090
+ }
1091
+ return out;
1092
+ }
1093
+ };
1094
+
1095
+ // src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts
1096
+ var componentMigration_2026_05_22_sectiondividerIntrinsicsToCss = {
1097
+ id: "2026-05-22-sectiondivider-intrinsics-to-css",
1098
+ fromVersion: 10,
1099
+ toVersion: 11,
1100
+ appliesTo: "component-config",
1101
+ apply(rawVars, meta) {
1102
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1103
+ const VARIANTS4 = ["lg", "md", "sm"];
1104
+ const prefix = "--sectiondivider-";
1105
+ const dropped = /* @__PURE__ */ new Set();
1106
+ for (const v of VARIANTS4) {
1107
+ dropped.add(`${prefix}${v}-show-eyebrow`);
1108
+ dropped.add(`${prefix}${v}-show-description`);
1109
+ dropped.add(`${prefix}${v}-show-hairline`);
1110
+ dropped.add(`${prefix}${v}-hairline`);
1111
+ dropped.add(`${prefix}${v}-eyebrow-uppercase`);
1112
+ }
1113
+ const out = {};
1114
+ for (const [key, value] of Object.entries(rawVars)) {
1115
+ if (dropped.has(key)) continue;
1116
+ out[key] = value;
1117
+ }
1118
+ for (const v of VARIANTS4) {
1119
+ const showEyebrow = rawVars[`${prefix}${v}-show-eyebrow`];
1120
+ if (showEyebrow !== void 0) {
1121
+ out[`${prefix}${v}-eyebrow-display`] = showEyebrow === "1" ? "block" : "none";
1122
+ }
1123
+ const showDesc = rawVars[`${prefix}${v}-show-description`];
1124
+ if (showDesc !== void 0) {
1125
+ out[`${prefix}${v}-description-display`] = showDesc === "1" ? "flex" : "none";
1126
+ }
1127
+ const showHair = rawVars[`${prefix}${v}-show-hairline`];
1128
+ const oldHair = rawVars[`${prefix}${v}-hairline`];
1129
+ const oldHairIsPos = typeof oldHair === "string" && oldHair !== "" && oldHair !== "off";
1130
+ let newHair;
1131
+ if (showHair === "") newHair = "none";
1132
+ else if (showHair === "1") newHair = oldHairIsPos ? oldHair : "above-label";
1133
+ else if (oldHair !== void 0) newHair = oldHairIsPos ? oldHair : "none";
1134
+ if (newHair !== void 0) {
1135
+ out[`${prefix}${v}-hairline`] = newHair;
1136
+ }
1137
+ const upper = rawVars[`${prefix}${v}-eyebrow-uppercase`];
1138
+ if (upper !== void 0) {
1139
+ out[`${prefix}${v}-eyebrow-text-transform`] = upper === "1" ? "uppercase" : "none";
1140
+ }
1141
+ }
1142
+ return out;
1143
+ }
1144
+ };
1145
+
1146
+ // src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts
1147
+ var componentMigration_2026_05_24_segmentedcontrolDividerInset = {
1148
+ id: "2026-05-24-segmentedcontrol-divider-inset",
1149
+ fromVersion: 11,
1150
+ toVersion: 12,
1151
+ appliesTo: "component-config",
1152
+ apply(rawVars, meta) {
1153
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
1154
+ const out = {};
1155
+ for (const [key, value] of Object.entries(rawVars)) {
1156
+ if (key === "--segmentedcontrol-divider-height") continue;
1157
+ out[key] = value;
1158
+ }
1159
+ return out;
1160
+ }
1161
+ };
1162
+
1163
+ // src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts
1164
+ var BUTTON_VARIANTS = ["primary", "secondary", "outline", "success", "danger", "warning"];
1165
+ var BUTTON_STATES = ["hover", "disabled"];
1166
+ var BUTTON_PROPS = ["padding", "radius", "border-width"];
1167
+ var buttonDeadKeys = new Set(
1168
+ BUTTON_VARIANTS.flatMap(
1169
+ (v) => BUTTON_STATES.flatMap(
1170
+ (s) => BUTTON_PROPS.map((p) => `--button-${v}-${s}-${p}`)
1171
+ )
1172
+ )
1173
+ );
1174
+ var segmentedcontrolDeadKeys = /* @__PURE__ */ new Set([
1175
+ "--segmentedcontrol-selected-icon-size",
1176
+ "--segmentedcontrol-option-hover-icon-size",
1177
+ "--segmentedcontrol-disabled-icon-size"
1178
+ ]);
1179
+ var componentMigration_2026_05_24_promoteStateSharedTokens = {
1180
+ id: "2026-05-24-promote-state-shared-tokens",
1181
+ fromVersion: 12,
1182
+ toVersion: 13,
1183
+ appliesTo: "component-config",
1184
+ apply(rawVars, meta) {
1185
+ const dead = meta.component === "button" ? buttonDeadKeys : meta.component === "segmentedcontrol" ? segmentedcontrolDeadKeys : null;
1186
+ if (!dead) return { ...rawVars };
1187
+ const out = {};
1188
+ for (const [key, value] of Object.entries(rawVars)) {
1189
+ if (dead.has(key)) continue;
1190
+ out[key] = value;
1191
+ }
1192
+ return out;
1193
+ }
1194
+ };
1195
+
1196
+ // src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts
1197
+ var PRIMARY_PREFIX = "--progressbar-primary-";
1198
+ var NEW_PREFIX = "--progressbar-";
1199
+ var DROP_PREFIXES = [
1200
+ "--progressbar-success-",
1201
+ "--progressbar-warning-",
1202
+ "--progressbar-danger-",
1203
+ "--progressbar-info-"
1204
+ ];
1205
+ var componentMigration_2026_05_24_progressbarCollapseVariants = {
1206
+ id: "2026-05-24-progressbar-collapse-variants",
1207
+ fromVersion: 13,
1208
+ toVersion: 14,
1209
+ appliesTo: "component-config",
1210
+ apply(rawVars, meta) {
1211
+ if (meta.component !== "progressbar") return { ...rawVars };
1212
+ const out = {};
1213
+ for (const [oldKey, value] of Object.entries(rawVars)) {
1214
+ if (DROP_PREFIXES.some((p) => oldKey.startsWith(p))) continue;
1215
+ const key = oldKey.startsWith(PRIMARY_PREFIX) ? NEW_PREFIX + oldKey.slice(PRIMARY_PREFIX.length) : oldKey;
1216
+ if (!(key in out)) out[key] = value;
1217
+ }
1218
+ return out;
1219
+ }
1220
+ };
1221
+
1222
+ // src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts
1223
+ function dropActiveState(rawVars, meta) {
1224
+ if (meta.component !== "collapsiblesection") return rawVars;
1225
+ const re = /^--collapsiblesection-(chromeless|divider|container)-active-/;
1226
+ const out = {};
1227
+ for (const [key, value] of Object.entries(rawVars)) {
1228
+ if (re.test(key)) continue;
1229
+ out[key] = value;
1230
+ }
1231
+ return out;
1232
+ }
1233
+ var componentMigration_2026_05_24_collapsiblesectionDropActiveState = {
1234
+ id: "2026-05-24-collapsiblesection-drop-active-state",
1235
+ fromVersion: 14,
1236
+ toVersion: 15,
1237
+ appliesTo: "component-config",
1238
+ apply: dropActiveState
1239
+ };
1240
+
1241
+ // src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts
1242
+ var VARIANTS3 = ["primary", "accent", "neutral", "alternate", "canvas", "special", "success", "warning", "danger", "info"];
1243
+ var RE = new RegExp(`^--corner-badge-(${VARIANTS3.join("|")})-(.+)$`);
1244
+ function flattenVariants(rawVars, meta) {
1245
+ if (meta.component !== "cornerbadge") return rawVars;
1246
+ const out = {};
1247
+ const collected = /* @__PURE__ */ new Map();
1248
+ for (const [key, value] of Object.entries(rawVars)) {
1249
+ const m = key.match(RE);
1250
+ if (m) {
1251
+ const prop = m[2];
1252
+ if (!collected.has(prop)) collected.set(prop, value);
1253
+ continue;
1254
+ }
1255
+ out[key] = value;
1256
+ }
1257
+ for (const [prop, value] of collected) {
1258
+ const flatKey = `--corner-badge-${prop}`;
1259
+ if (!(flatKey in out)) out[flatKey] = value;
1260
+ }
1261
+ return out;
1262
+ }
1263
+ var componentMigration_2026_05_25_cornerbadgeFlattenVariants = {
1264
+ id: "2026-05-25-cornerbadge-flatten-variants",
1265
+ fromVersion: 15,
1266
+ toVersion: 16,
1267
+ appliesTo: "component-config",
1268
+ apply: flattenVariants
1269
+ };
1270
+
1271
+ // src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts
1272
+ var DROPPED_TO_KEPT = {
1273
+ "--overlay-lowest": "--overlay-low",
1274
+ "--overlay-lower": "--overlay-low",
1275
+ "--overlay-higher": "--overlay-high",
1276
+ "--overlay-highest": "--overlay-high"
1277
+ };
1278
+ var colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops = {
1279
+ id: "2026-05-26-drop-overlay-extra-stops-theme",
1280
+ fromVersion: 2,
1281
+ toVersion: 3,
1282
+ appliesTo: "colors-and-type",
1283
+ apply(rawVars) {
1284
+ const out = {};
1285
+ for (const [key, value] of Object.entries(rawVars)) {
1286
+ if (key in DROPPED_TO_KEPT) continue;
1287
+ out[key] = value;
1288
+ }
1289
+ return out;
1290
+ }
1291
+ };
1292
+ var componentMigration_2026_05_26_dropOverlayExtraStops = {
1293
+ id: "2026-05-26-drop-overlay-extra-stops-component",
1294
+ fromVersion: 16,
1295
+ toVersion: 17,
1296
+ appliesTo: "component-config",
1297
+ apply(rawVars) {
1298
+ const out = {};
1299
+ for (const [key, value] of Object.entries(rawVars)) {
1300
+ out[key] = DROPPED_TO_KEPT[value] ?? value;
1301
+ }
1302
+ return out;
1303
+ }
1304
+ };
1305
+
1306
+ // src/editor/core/themes/migrations/2026-05-29-tabbar-indicator-thickness-to-per-state-width.ts
1307
+ var TABBAR_STATES = ["default", "hover", "active", "disabled"];
1308
+ var OLD_KEY = "--tabbar-bar-indicator-thickness";
1309
+ var FALLBACK = "--border-width-2";
1310
+ var componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth = {
1311
+ id: "2026-05-29-tabbar-indicator-thickness-to-per-state-width",
1312
+ fromVersion: 17,
1313
+ toVersion: 18,
1314
+ appliesTo: "component-config",
1315
+ apply(rawVars, meta) {
1316
+ if (meta.component !== "tabbar") return { ...rawVars };
1317
+ const seed = rawVars[OLD_KEY] ?? FALLBACK;
1318
+ const out = {};
1319
+ for (const [key, value] of Object.entries(rawVars)) {
1320
+ if (key === OLD_KEY) continue;
1321
+ out[key] = value;
1322
+ }
1323
+ for (const state of TABBAR_STATES) {
1324
+ const newKey = `--tabbar-${state}-indicator-border-width`;
1325
+ if (!(newKey in out)) out[newKey] = seed;
1326
+ }
1327
+ return out;
1328
+ }
1329
+ };
1330
+
1331
+ // src/editor/core/themes/migrations/2026-05-29-segmentedcontrol-small-divider-rename.ts
1332
+ var RENAMES = {
1333
+ "--segmentedcontrol-divider-small-thickness": "--segmentedcontrol-small-divider-thickness",
1334
+ "--segmentedcontrol-divider-small-inset": "--segmentedcontrol-small-divider-inset"
1335
+ };
1336
+ var componentMigration_2026_05_29_segmentedcontrolSmallDividerRename = {
1337
+ id: "2026-05-29-segmentedcontrol-small-divider-rename",
1338
+ fromVersion: 18,
1339
+ toVersion: 19,
1340
+ appliesTo: "component-config",
1341
+ apply(rawVars, meta) {
1342
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
1343
+ const out = {};
1344
+ for (const [key, value] of Object.entries(rawVars)) {
1345
+ out[RENAMES[key] ?? key] = value;
1346
+ }
1347
+ return out;
1348
+ }
1349
+ };
1350
+
1351
+ // src/editor/core/themes/migrations/2026-05-29-toggle-derive-track-from-thumb.ts
1352
+ var componentMigration_2026_05_29_toggleDeriveTrackFromThumb = {
1353
+ id: "2026-05-29-toggle-derive-track-from-thumb",
1354
+ fromVersion: 19,
1355
+ toVersion: 20,
1356
+ appliesTo: "component-config",
1357
+ apply(rawVars, meta) {
1358
+ if (meta.component !== "toggle") return { ...rawVars };
1359
+ const out = {};
1360
+ for (const [key, value] of Object.entries(rawVars)) {
1361
+ if (key === "--toggle-track-width" || key === "--toggle-track-thickness") continue;
1362
+ out[key] = value;
1363
+ }
1364
+ if (!("--toggle-track-padding" in out)) {
1365
+ out["--toggle-track-padding"] = "--space-2";
1366
+ }
1367
+ return out;
1368
+ }
1369
+ };
1370
+
1371
+ // src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts
1372
+ var DROPPED = /* @__PURE__ */ new Set([
1373
+ "--badge-trait-radius",
1374
+ "--badge-trait-padding",
1375
+ "--sectiondivider-padding",
1376
+ "--dialog-primary-default-radius",
1377
+ "--dialog-primary-default-padding",
1378
+ "--dialog-primary-hover-radius",
1379
+ "--dialog-primary-hover-padding",
1380
+ "--dialog-secondary-default-radius",
1381
+ "--dialog-secondary-default-padding",
1382
+ "--dialog-secondary-hover-radius",
1383
+ "--dialog-secondary-hover-padding"
1384
+ ]);
1385
+ var colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys = {
1386
+ id: "2026-08-13-drop-legacy-shape-space-keys",
1387
+ fromVersion: 3,
1388
+ toVersion: 4,
1389
+ appliesTo: "colors-and-type",
1390
+ apply(rawVars) {
1391
+ const out = {};
1392
+ for (const [key, value] of Object.entries(rawVars)) {
1393
+ if (DROPPED.has(key)) continue;
1394
+ out[key] = value;
1395
+ }
1396
+ return out;
1397
+ }
1398
+ };
1399
+
1400
+ // src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts
1401
+ var RENAMED = {
1402
+ "--line-height-xs": "--line-height-none",
1403
+ "--line-height-sm": "--line-height-tighter",
1404
+ "--line-height-md": "--line-height-normal",
1405
+ "--line-height-lg": "--line-height-relaxed",
1406
+ "--line-height-xl": "--line-height-relaxed"
1407
+ };
1408
+ var REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
1409
+ function renameValues(rawVars) {
1410
+ const out = {};
1411
+ for (const [key, value] of Object.entries(rawVars)) {
1412
+ out[key] = typeof value === "string" ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
1413
+ }
1414
+ return out;
1415
+ }
1416
+ var colorsAndTypeMigration_2026_08_15_lineHeightScaleRename = {
1417
+ id: "2026-08-15-line-height-scale-rename-colors-and-type",
1418
+ fromVersion: 4,
1419
+ toVersion: 5,
1420
+ appliesTo: "colors-and-type",
1421
+ apply: renameValues
1422
+ };
1423
+ var componentMigration_2026_08_15_lineHeightScaleRename = {
1424
+ id: "2026-08-15-line-height-scale-rename-component",
1425
+ fromVersion: 20,
1426
+ toVersion: 21,
1427
+ appliesTo: "component-config",
1428
+ apply: renameValues
1429
+ };
1430
+
1431
+ // src/editor/core/themes/migrations/index.ts
1432
+ var MIGRATIONS = [
1433
+ colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
1434
+ colorsAndTypeMigration_2026_05_13_primaryToBrand,
1435
+ componentMigration_2026_04_24_prefixAndSuffixRenames,
1436
+ componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
1437
+ componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
1438
+ componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup,
1439
+ componentMigration_2026_05_10_sectiondividerGradientStops,
1440
+ componentMigration_2026_05_13_primaryToBrand,
1441
+ componentMigration_2026_05_19_collapsiblesectionDropFrameSurface,
1442
+ componentMigration_2026_05_19_sectiondividerRichGradient,
1443
+ componentMigration_2026_05_20_sectiondividerSlimVariants,
1444
+ componentMigration_2026_05_21_sectiondividerSpacingToPadding,
1445
+ componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
1446
+ componentMigration_2026_05_24_segmentedcontrolDividerInset,
1447
+ componentMigration_2026_05_24_promoteStateSharedTokens,
1448
+ componentMigration_2026_05_24_progressbarCollapseVariants,
1449
+ componentMigration_2026_05_24_collapsiblesectionDropActiveState,
1450
+ componentMigration_2026_05_25_cornerbadgeFlattenVariants,
1451
+ colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
1452
+ componentMigration_2026_05_26_dropOverlayExtraStops,
1453
+ componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
1454
+ componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
1455
+ componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
1456
+ colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
1457
+ colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
1458
+ componentMigration_2026_08_15_lineHeightScaleRename
1459
+ ];
1460
+ function countFor(kind) {
1461
+ return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
1462
+ }
1463
+ var CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor("colors-and-type");
1464
+ var CURRENT_COMPONENT_SCHEMA_VERSION = countFor("component-config");
1465
+
1466
+ // src/editor/core/themes/generateColorsAndType.ts
1467
+ var HEX_RE = /^#[0-9a-f]{6}$/i;
1468
+ var HARMONY_MODES = [
1469
+ "complementary",
1470
+ "split-complementary",
1471
+ "triadic",
1472
+ "tetradic",
1473
+ "compound",
1474
+ "square",
1475
+ "analogous",
1476
+ "monochromatic",
1477
+ "custom"
1478
+ ];
1479
+ var TEXT_SCALE = SCALES.find((s) => s.title === "Text");
1480
+ var SURFACE_SCALE = SCALES.find((s) => s.title === "Surfaces");
1481
+ var NEUTRAL_TEXT_FLOORS = [
1482
+ ["primary", AA_BODY, 7],
1483
+ ["secondary", AA_BODY, 5.5],
1484
+ ["tertiary", AA_LARGE, 3.5]
1485
+ ];
1486
+ var FUNCTIONAL_TEXT_TARGET = 3.5;
1487
+ var FUNCTIONAL_TEXT_LABELS = PALETTE_SPECS.filter((s) => s.label !== "Neutral" && s.label !== "Canvas").map((s) => s.label);
1488
+ var norm = (h) => h >= 0 && h < 360 ? h : (h % 360 + 360) % 360;
1489
+ function parseSeed(label, raw, problems) {
1490
+ if (typeof raw === "string") {
1491
+ if (!HEX_RE.test(raw.trim())) {
1492
+ problems.push(`${label}: "${raw}" is not a #rrggbb hex color`);
1493
+ return null;
1494
+ }
1495
+ return hexToOklch(raw.trim());
1496
+ }
1497
+ const { l, c, h } = raw ?? {};
1498
+ if (typeof l !== "number" || l <= 0 || l >= 1) problems.push(`${label}: l must be in (0, 1), got ${l}`);
1499
+ if (typeof c !== "number" || c < 0 || c > 0.4) problems.push(`${label}: c must be in [0, 0.4], got ${c}`);
1500
+ if (typeof h !== "number" || !Number.isFinite(h)) problems.push(`${label}: h must be a finite number, got ${h}`);
1501
+ if (problems.length > 0) return null;
1502
+ return { l, c, h: norm(h) };
1503
+ }
1504
+ function validateBrief(brief) {
1505
+ const problems = [];
1506
+ const name = typeof brief.name === "string" ? brief.name.trim() : "";
1507
+ if (!name) problems.push("name: required");
1508
+ const slug = sanitizeFileName(name || "unnamed");
1509
+ if (slug === "default") problems.push('name: "default" is the protected package theme; pick another name');
1510
+ if (brief.scheme !== "light" && brief.scheme !== "dark") {
1511
+ problems.push(`scheme: must be "light" or "dark", got ${JSON.stringify(brief.scheme)}`);
1512
+ }
1513
+ if (brief.harmony && !HARMONY_MODES.includes(brief.harmony.mode)) {
1514
+ problems.push(`harmony.mode: unknown mode ${JSON.stringify(brief.harmony.mode)}`);
1515
+ }
1516
+ if (brief.canvasGradient !== void 0 && typeof brief.canvasGradient !== "boolean") {
1517
+ problems.push(`canvasGradient: must be a boolean, got ${JSON.stringify(brief.canvasGradient)}`);
1518
+ }
1519
+ const seeds = {};
1520
+ const given = brief.seeds ?? {};
1521
+ for (const spec of PALETTE_SPECS) {
1522
+ if (!(spec.label in given)) {
1523
+ problems.push(`seeds.${spec.label}: missing`);
1524
+ continue;
1525
+ }
1526
+ const parsed = parseSeed(spec.label, given[spec.label], problems);
1527
+ if (parsed) seeds[spec.label] = parsed;
1528
+ }
1529
+ const known = new Set(PALETTE_SPECS.map((s) => s.label));
1530
+ for (const label of Object.keys(given)) {
1531
+ if (!known.has(label)) problems.push(`seeds.${label}: unknown palette (expected ${[...known].join(", ")})`);
1532
+ }
1533
+ if (problems.length > 0) {
1534
+ throw new Error(`Invalid theme brief:
1535
+ ${problems.join("\n ")}`);
1536
+ }
1537
+ return { seeds, slug };
1538
+ }
1539
+ function checkDefs() {
1540
+ const defs = [];
1541
+ for (const [stepName, floor, target] of NEUTRAL_TEXT_FLOORS) {
1542
+ defs.push({
1543
+ paletteLabel: "Neutral",
1544
+ step: TEXT_SCALE.steps.find((s) => s.name === stepName),
1545
+ textVar: scaleToCssVar("Text", stepName, "neutral"),
1546
+ floor,
1547
+ target
1548
+ });
1549
+ }
1550
+ const primary = TEXT_SCALE.steps.find((s) => s.name === "primary");
1551
+ for (const label of FUNCTIONAL_TEXT_LABELS) {
1552
+ const ns = PALETTE_SPECS.find((s) => s.label === label).cssNamespace;
1553
+ defs.push({
1554
+ paletteLabel: label,
1555
+ step: primary,
1556
+ textVar: scaleToCssVar("Text", "primary", ns),
1557
+ floor: AA_LARGE,
1558
+ target: FUNCTIONAL_TEXT_TARGET
1559
+ });
1560
+ }
1561
+ return defs;
1562
+ }
1563
+ function surfaceVars() {
1564
+ return [
1565
+ ...SURFACE_SCALE.steps.map((s) => scaleToCssVar("Surfaces", s.name, "neutral")),
1566
+ "--page-bg"
1567
+ ];
1568
+ }
1569
+ function worstSurface(textHex, vars) {
1570
+ let against = "";
1571
+ let ratio = Infinity;
1572
+ for (const surfVar of surfaceVars()) {
1573
+ const surfHex = vars[surfVar];
1574
+ if (!surfHex || !HEX_RE.test(surfHex)) continue;
1575
+ const r = contrastRatio(textHex, surfHex);
1576
+ if (r < ratio) {
1577
+ ratio = r;
1578
+ against = surfVar;
1579
+ }
1580
+ }
1581
+ return { against, ratio };
1582
+ }
1583
+ function pinTextStep(cfg, step, solved) {
1584
+ const x = scaleStepToX(step, TEXT_SCALE);
1585
+ const seed = cfg.baseColor;
1586
+ const yL = Math.max(0, Math.min(200, solved.l / seed.l * 100));
1587
+ cfg.scaleCurves.Text.lightness = setCurveAnchor(cfg.scaleCurves.Text.lightness, x, yL).curve;
1588
+ if (seed.c > 0) {
1589
+ const yC = Math.max(0, Math.min(200, solved.c / seed.c * 100));
1590
+ cfg.scaleCurves.Text.saturation = setCurveAnchor(cfg.scaleCurves.Text.saturation, x, yC).curve;
1591
+ }
1592
+ }
1593
+ var MAX_CORRECTION_ROUNDS = 3;
1594
+ function runContrastGate(configs, scheme) {
1595
+ const defs = checkDefs();
1596
+ const direction = scheme === "light" ? "darker" : "lighter";
1597
+ const corrected = /* @__PURE__ */ new Set();
1598
+ for (let round = 0; round < MAX_CORRECTION_ROUNDS; round++) {
1599
+ const vars = palettesToVars(configs);
1600
+ let anyFixed = false;
1601
+ for (const def of defs) {
1602
+ const textHex = vars[def.textVar];
1603
+ if (!textHex) continue;
1604
+ const worst = worstSurface(textHex, vars);
1605
+ if (worst.ratio >= def.floor) continue;
1606
+ const cfg = configs[def.paletteLabel];
1607
+ const seed = cfg.baseColor;
1608
+ const solved = findLForContrast({
1609
+ against: vars[worst.against],
1610
+ ratio: def.target,
1611
+ direction,
1612
+ c: hexToOklch(textHex).c,
1613
+ h: seed.h,
1614
+ lMax: Math.min(1, 2 * seed.l)
1615
+ });
1616
+ pinTextStep(cfg, def.step, solved);
1617
+ corrected.add(def.textVar);
1618
+ anyFixed = true;
1619
+ }
1620
+ if (!anyFixed) break;
1621
+ }
1622
+ const finalVars = palettesToVars(configs);
1623
+ const checks = defs.map((def) => {
1624
+ const worst = worstSurface(finalVars[def.textVar] ?? "#000000", finalVars);
1625
+ return {
1626
+ textVar: def.textVar,
1627
+ floor: def.floor,
1628
+ against: worst.against,
1629
+ ratio: worst.ratio,
1630
+ pass: worst.ratio >= def.floor,
1631
+ corrected: corrected.has(def.textVar)
1632
+ };
1633
+ });
1634
+ const failures = checks.filter((c) => !c.pass).map((c) => {
1635
+ const label = defs.find((d) => d.textVar === c.textVar).paletteLabel;
1636
+ const hint = scheme === "dark" ? `raise the ${label} seed lightness (derived text tops out at 2\xD7 seed L)` : `raise the ${label} seed lightness or reduce its chroma`;
1637
+ return `${c.textVar} reaches ${c.ratio.toFixed(2)}:1 vs ${c.against} (floor ${c.floor}:1) \u2014 ${hint}`;
1638
+ });
1639
+ return { scheme, checks, failures };
1640
+ }
1641
+ var ADJACENT_HUE_MAX = 120;
1642
+ var hueDist = (a, b) => {
1643
+ const d = Math.abs(norm(a) - norm(b));
1644
+ return Math.min(d, 360 - d);
1645
+ };
1646
+ var linear = (variable, angle, from, to) => ({
1647
+ variable,
1648
+ type: "linear",
1649
+ angle,
1650
+ stops: [{ position: 0, color: from }, { position: 100, color: to }]
1651
+ });
1652
+ function recipeGradients(seeds, scheme) {
1653
+ return [
1654
+ linear("--gradient-1", 90, "--color-brand-400", "--color-brand-700"),
1655
+ hueDist(seeds.Special.h, seeds.Brand.h) <= ADJACENT_HUE_MAX ? linear("--gradient-2", 135, "--color-special-500", "--color-brand-500") : linear("--gradient-2", 135, "--color-special-400", "--color-special-700"),
1656
+ hueDist(seeds.Brand.h, seeds.Accent.h) <= ADJACENT_HUE_MAX ? linear("--gradient-3", 90, "--color-brand-500", "--color-accent-500") : linear("--gradient-3", 90, "--color-accent-400", "--color-accent-700"),
1657
+ scheme === "dark" ? linear("--gradient-4", 180, "--color-canvas-600", "--color-canvas-900") : linear("--gradient-4", 180, "--color-canvas-200", "--color-canvas-500")
1658
+ ];
1659
+ }
1660
+ function isStockGradients(gradients) {
1661
+ return !gradients || gradients.length === 0 || JSON.stringify(gradients) === JSON.stringify(makeDefaultGradients());
1662
+ }
1663
+ function applyCanvasGradient(canvas, scheme) {
1664
+ const labels = PALETTE_STEPS.map((s) => s.label);
1665
+ const anchor = canvas.anchorPlacement.step;
1666
+ const sky = scheme === "dark" ? Math.min(anchor + 2, labels.length - 1) : Math.max(anchor - 2, 0);
1667
+ if (sky === anchor) {
1668
+ return `skipped \u2014 the Canvas seed anchors at the ramp edge (${labels[anchor]}), leaving no room for a sky; commit the canvas further from ${scheme === "dark" ? "black" : "white"}`;
1669
+ }
1670
+ canvas.emptyMode = "gradient";
1671
+ canvas.gradientStyle = "linear";
1672
+ canvas.gradientAngle = 180;
1673
+ canvas.gradientReverse = false;
1674
+ canvas.gradientStops = [
1675
+ { position: 0, paletteLabel: labels[sky] },
1676
+ { position: 100, paletteLabel: labels[anchor] }
1677
+ ];
1678
+ canvas.gradientSize = "window";
1679
+ return `on, ${labels[sky]} \u2192 ${labels[anchor]}`;
1680
+ }
1681
+ function buildColorsAndTypeFromSeeds(brief, carry = {}, now = (/* @__PURE__ */ new Date()).toISOString()) {
1682
+ const { seeds, slug } = validateBrief(brief);
1683
+ const configs = {};
1684
+ for (const spec of PALETTE_SPECS) {
1685
+ configs[spec.label] = defaultPaletteConfig({
1686
+ baseColor: seeds[spec.label],
1687
+ neutral: spec.neutral,
1688
+ scheme: brief.scheme
1689
+ });
1690
+ }
1691
+ const report = runContrastGate(configs, brief.scheme);
1692
+ const canvasGradient = brief.canvasGradient ? applyCanvasGradient(configs.Canvas, brief.scheme) : void 0;
1693
+ const gradients = isStockGradients(carry.gradients) ? recipeGradients(seeds, brief.scheme) : carry.gradients;
1694
+ const harmonyAxes = [
1695
+ { hue: norm(seeds.Brand.h), family: "Brand" },
1696
+ { hue: norm(seeds.Accent.h), family: "Accent" },
1697
+ { hue: norm(seeds.Canvas.h), family: "Canvas" },
1698
+ { hue: norm(seeds.Brand.h + 270), family: null }
1699
+ ];
1700
+ const owned = new Set(Object.keys(palettesToVars(configs)));
1701
+ const cssVariables = Object.fromEntries(
1702
+ Object.entries(carry.cssVariables ?? {}).filter(([k]) => !owned.has(k))
1703
+ );
1704
+ for (const t of gradients) cssVariables[t.variable] = formatGradientValue(t);
1705
+ const colorsAndType = {
1706
+ name: brief.name.trim(),
1707
+ createdAt: now,
1708
+ updatedAt: now,
1709
+ editorConfigs: configs,
1710
+ cssVariables,
1711
+ fontSources: carry.fontSources ?? [],
1712
+ fontStacks: carry.fontStacks ?? [],
1713
+ gradients,
1714
+ harmonyAxes,
1715
+ schemaVersion: CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION
1716
+ };
1717
+ return {
1718
+ colorsAndType,
1719
+ slug,
1720
+ report: {
1721
+ ...report,
1722
+ gradients: gradients === carry.gradients ? "carried" : "recipes",
1723
+ ...canvasGradient ? { canvasGradient } : {}
1724
+ }
1725
+ };
1726
+ }
1727
+
1728
+ // vite-plugin/files/dataPaths.ts
1729
+ var import_fs = __toESM(require("fs"), 1);
1730
+ var import_path = __toESM(require("path"), 1);
1731
+ var DEFAULT_DATA_DIR = "src/live-tokens/data";
1732
+ var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
1733
+ "dataDir",
1734
+ "colorsAndTypeDir",
1735
+ "componentConfigsDir",
1736
+ "themesDir",
1737
+ "manifestsDir",
1738
+ "tokensCssPath"
1739
+ ]);
1740
+ var cached = null;
1741
+ function readLiveTokensConfig() {
1742
+ if (cached) return cached;
1743
+ try {
1744
+ const configPath = import_path.default.resolve("live-tokens.config.json");
1745
+ if (!import_fs.default.existsSync(configPath)) return cached = {};
1746
+ const parsed = JSON.parse(import_fs.default.readFileSync(configPath, "utf-8"));
1747
+ if (!parsed || typeof parsed !== "object") return cached = {};
1748
+ const unknown = Object.keys(parsed).filter(
1749
+ (k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
1750
+ );
1751
+ if (unknown.length > 0) {
1752
+ console.warn(
1753
+ `[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
1754
+ );
1755
+ }
1756
+ cached = parsed;
1757
+ return cached;
1758
+ } catch {
1759
+ return cached = {};
1760
+ }
1761
+ }
1762
+ function resolveDataDirs(opts = {}) {
1763
+ const fileConfig = readLiveTokensConfig();
1764
+ const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
1765
+ const dataDir = import_path.default.resolve(dataDirRaw);
1766
+ const sub = (name) => import_path.default.resolve(dataDir, name);
1767
+ return {
1768
+ dataDir,
1769
+ colorsAndTypeDir: opts.colorsAndTypeDir ? import_path.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
1770
+ componentConfigsDir: opts.componentConfigsDir ? import_path.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
1771
+ themesDir: opts.themesDir ? import_path.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path.default.resolve(fileConfig.themesDir) : sub("themes"),
1772
+ legacyManifestsDir: fileConfig.manifestsDir ? import_path.default.resolve(fileConfig.manifestsDir) : void 0
1773
+ };
1774
+ }
1775
+ // Annotate the CommonJS export names for ESM import in node:
1776
+ 0 && (module.exports = {
1777
+ buildColorsAndTypeFromSeeds,
1778
+ readLiveTokensConfig,
1779
+ resolveDataDirs,
1780
+ sanitizeFileName
1781
+ });