@motion-proto/live-tokens 0.72.1 → 0.74.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 (81) hide show
  1. package/.claude/skills/live-tokens-build-page/SKILL.md +37 -2
  2. package/.claude/skills/live-tokens-build-page/references/layout-sources.md +48 -0
  3. package/.claude/skills/live-tokens-check-compliance/SKILL.md +2 -2
  4. package/.claude/skills/live-tokens-create-component/SKILL.md +4 -4
  5. package/.claude/skills/live-tokens-create-theme/SKILL.md +80 -0
  6. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +94 -0
  7. package/.claude/skills/live-tokens-pick-component/SKILL.md +1 -1
  8. package/.claude/skills/live-tokens-set-colors/SKILL.md +140 -0
  9. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +80 -0
  10. package/.claude/skills/{live-tokens-adjust-geometry → live-tokens-set-geometry}/SKILL.md +12 -7
  11. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +61 -0
  12. package/.claude/skills/{live-tokens-pair-fonts → live-tokens-set-type}/SKILL.md +18 -15
  13. package/.claude/skills/live-tokens-set-type/references/type-anchors.md +60 -0
  14. package/CHANGELOG.md +141 -0
  15. package/README.md +24 -15
  16. package/bin/check-page.mjs +3 -3
  17. package/bin/cli.mjs +92 -55
  18. package/bin/lib/liveState.mjs +110 -0
  19. package/bin/save-theme.mjs +177 -0
  20. package/bin/set-colors.mjs +191 -0
  21. package/bin/{adjust.mjs → set-geometry.mjs} +18 -50
  22. package/bin/{set-fonts.mjs → set-type.mjs} +21 -55
  23. package/dist-plugin/{chunk-RIXO2E55.js → chunk-7VRTBGJT.js} +1 -1
  24. package/dist-plugin/{chunk-YLCOIGQC.js → chunk-V3YF6CGT.js} +56 -2
  25. package/dist-plugin/index.cjs +58 -3
  26. package/dist-plugin/index.js +11 -11
  27. package/dist-plugin/migrateData/index.cjs +56 -1
  28. package/dist-plugin/migrateData/index.js +2 -2
  29. package/dist-plugin/{generateColorsAndType → setColors}/index.cjs +1109 -1071
  30. package/dist-plugin/{generateColorsAndType → setColors}/index.d.cts +33 -24
  31. package/dist-plugin/{generateColorsAndType → setColors}/index.d.ts +33 -24
  32. package/dist-plugin/{generateColorsAndType → setColors}/index.js +45 -63
  33. package/dist-plugin/{adjust → setGeometry}/index.cjs +60 -5
  34. package/dist-plugin/{adjust → setGeometry}/index.d.cts +1 -1
  35. package/dist-plugin/{adjust → setGeometry}/index.d.ts +1 -1
  36. package/dist-plugin/{adjust → setGeometry}/index.js +1 -1
  37. package/dist-plugin/{fontPairing → setType}/index.cjs +4 -4
  38. package/dist-plugin/{fontPairing → setType}/index.d.cts +1 -1
  39. package/dist-plugin/{fontPairing → setType}/index.d.ts +1 -1
  40. package/dist-plugin/{themeTypes-DSV3Zisf.d.cts → themeTypes-BxRtuN5V.d.cts} +1 -1
  41. package/dist-plugin/{themeTypes-DSV3Zisf.d.ts → themeTypes-BxRtuN5V.d.ts} +1 -1
  42. package/package.json +10 -2
  43. package/src/editor/core/themes/{generateColorsAndType.ts → buildColors.ts} +82 -96
  44. package/src/editor/core/themes/migrations/2026-09-03-drop-legacy-component-keys.ts +62 -0
  45. package/src/editor/core/themes/migrations/index.ts +2 -0
  46. package/src/editor/docs/content/creating-components.md +13 -0
  47. package/src/editor/docs/content/themes-workflow.md +2 -2
  48. package/src/editor/docs/content.generated.ts +2 -2
  49. package/src/editor/overlay/LiveEditorOverlay.svelte +519 -28
  50. package/src/editor/skill-atlas/SkillAtlas.svelte +836 -0
  51. package/src/editor/skill-atlas/SkillAtlas.svelte.d.ts +4 -0
  52. package/src/editor/skill-atlas/SourcePane.svelte +364 -0
  53. package/src/editor/skill-atlas/TreeNodeCard.svelte +206 -0
  54. package/src/editor/skill-atlas/skillSources.generated.ts +45 -0
  55. package/src/editor/skill-atlas/skillSources.ts +1 -0
  56. package/src/editor/skill-atlas/skillTrees.ts +3844 -0
  57. package/src/editor/skill-atlas/types.ts +65 -0
  58. package/src/live-tokens/data/colors-and-type/autumn.json +1 -37
  59. package/src/live-tokens/data/colors-and-type/default.json +1 -37
  60. package/src/live-tokens/data/colors-and-type/halloween.json +1 -37
  61. package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -37
  62. package/src/live-tokens/data/colors-and-type/ocean.json +1 -37
  63. package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -37
  64. package/src/live-tokens/data/colors-and-type/sketchy.json +1 -37
  65. package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -37
  66. package/src/live-tokens/data/colors-and-type/sunset.json +1 -37
  67. package/src/live-tokens/data/themes/autumn.json +1 -37
  68. package/src/live-tokens/data/themes/halloween.json +1 -37
  69. package/src/live-tokens/data/themes/midnight-study.json +1 -37
  70. package/src/live-tokens/data/themes/ocean.json +1 -37
  71. package/src/live-tokens/data/themes/royal-velvet.json +1 -37
  72. package/src/live-tokens/data/themes/sketchy.json +1 -37
  73. package/src/live-tokens/data/themes/spring-meadow.json +1 -37
  74. package/src/live-tokens/data/themes/sunset.json +1 -37
  75. package/src/live-tokens/data/tokens.generated.css +0 -36
  76. package/.claude/skills/live-tokens-generate-theme/SKILL.md +0 -156
  77. package/.claude/skills/live-tokens-generate-theme/references/mood-vocabulary.md +0 -43
  78. package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +0 -18
  79. package/.claude/skills/live-tokens-generate-theme/references/style-vocabulary.md +0 -35
  80. package/bin/generate-theme.mjs +0 -260
  81. /package/dist-plugin/{fontPairing → setType}/index.js +0 -0
@@ -27,16 +27,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // vite-plugin/generateColorsAndType/index.ts
31
- var generateColorsAndType_exports = {};
32
- __export(generateColorsAndType_exports, {
30
+ // vite-plugin/setColors/index.ts
31
+ var setColors_exports = {};
32
+ __export(setColors_exports, {
33
33
  CURRENT_COMPONENT_SCHEMA_VERSION: () => CURRENT_COMPONENT_SCHEMA_VERSION,
34
- buildColorsAndTypeFromSeeds: () => buildColorsAndTypeFromSeeds,
34
+ buildColors: () => buildColors,
35
35
  readLiveTokensConfig: () => readLiveTokensConfig,
36
36
  resolveDataDirs: () => resolveDataDirs,
37
37
  sanitizeFileName: () => sanitizeFileName
38
38
  });
39
- module.exports = __toCommonJS(generateColorsAndType_exports);
39
+ module.exports = __toCommonJS(setColors_exports);
40
40
 
41
41
  // src/system/internal/oklch.ts
42
42
  function srgbToLinear(c) {
@@ -841,1232 +841,1270 @@ function defaultScaleCurvesObject(scheme = "dark") {
841
841
  };
842
842
  }
843
843
 
844
- // src/editor/core/storage/files/versionedFileResourceClient.ts
845
- function sanitizeFileName(name) {
846
- return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^[-_]+|-+$/g, "") || "unnamed";
847
- }
848
-
849
- // src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts
850
- var LEGACY_KEY_RENAMES = {
851
- "--empty": "--page-bg",
852
- "--empty-attachment": "--page-bg-attachment",
853
- // Orphan exports dropped from tokens.css; no new home — silently discard.
854
- "--border-neutral": null,
855
- // Shadow cleanup: these five tokens were removed (low/zero consumers,
856
- // aesthetic drift). Dialog migrated onto --shadow-2xl; focus rings moved
857
- // to their own --ring-focus-* namespace, which themes don't carry by
858
- // default — tokens.css provides the canonical values.
859
- "--shadow-app": null,
860
- "--shadow-card": null,
861
- "--shadow-overlay": null,
862
- "--shadow-focus": null,
863
- "--shadow-glow-green": null
864
- };
865
- var BG_TO_CANVAS_PREFIXES = ["--color-bg-", "--surface-bg", "--border-bg", "--text-bg"];
866
- function migrateBgToCanvas(rawVars) {
867
- for (const oldKey of Object.keys(rawVars)) {
868
- for (const prefix of BG_TO_CANVAS_PREFIXES) {
869
- if (!oldKey.startsWith(prefix)) continue;
870
- const suffix = oldKey.slice(prefix.length);
871
- if (suffix && !suffix.startsWith("-")) continue;
872
- const newKey = prefix.replace("-bg", "-canvas") + suffix;
873
- if (newKey === oldKey) continue;
874
- const value = rawVars[oldKey];
875
- delete rawVars[oldKey];
876
- if (!(newKey in rawVars)) rawVars[newKey] = value;
877
- break;
844
+ // src/editor/core/themes/buildColors.ts
845
+ var HEX_RE = /^#[0-9a-f]{6}$/i;
846
+ var HARMONY_MODES = [
847
+ "complementary",
848
+ "split-complementary",
849
+ "triadic",
850
+ "tetradic",
851
+ "compound",
852
+ "square",
853
+ "analogous",
854
+ "monochromatic",
855
+ "custom"
856
+ ];
857
+ var TEXT_SCALE = SCALES.find((s) => s.title === "Text");
858
+ var SURFACE_SCALE = SCALES.find((s) => s.title === "Surfaces");
859
+ var NEUTRAL_TEXT_FLOORS = [
860
+ ["primary", AA_BODY, 7],
861
+ ["secondary", AA_BODY, 5.5],
862
+ ["tertiary", AA_LARGE, 3.5]
863
+ ];
864
+ var FUNCTIONAL_TEXT_TARGET = 3.5;
865
+ var FUNCTIONAL_TEXT_LABELS = PALETTE_SPECS.filter((s) => s.label !== "Neutral" && s.label !== "Canvas").map((s) => s.label);
866
+ var norm = (h) => h >= 0 && h < 360 ? h : (h % 360 + 360) % 360;
867
+ function parseBaseColor(label, raw, problems) {
868
+ if (typeof raw === "string") {
869
+ if (!HEX_RE.test(raw.trim())) {
870
+ problems.push(`${label}: "${raw}" is not a #rrggbb hex color`);
871
+ return null;
878
872
  }
873
+ return hexToOklch(raw.trim());
879
874
  }
875
+ const { l, c, h } = raw ?? {};
876
+ if (typeof l !== "number" || l <= 0 || l >= 1) problems.push(`${label}: l must be in (0, 1), got ${l}`);
877
+ if (typeof c !== "number" || c < 0 || c > 0.4) problems.push(`${label}: c must be in [0, 0.4], got ${c}`);
878
+ if (typeof h !== "number" || !Number.isFinite(h)) problems.push(`${label}: h must be a finite number, got ${h}`);
879
+ if (problems.length > 0) return null;
880
+ return { l, c, h: norm(h) };
880
881
  }
881
- function migrateLegacyKeys(rawVars) {
882
- for (const [oldKey, newKey] of Object.entries(LEGACY_KEY_RENAMES)) {
883
- if (!(oldKey in rawVars)) continue;
884
- const value = rawVars[oldKey];
885
- delete rawVars[oldKey];
886
- if (newKey && !(newKey in rawVars)) rawVars[newKey] = value;
882
+ function validateInput(input) {
883
+ const problems = [];
884
+ if (input.scheme !== "light" && input.scheme !== "dark") {
885
+ problems.push(`scheme: must be "light" or "dark", got ${JSON.stringify(input.scheme)}`);
887
886
  }
888
- migrateBgToCanvas(rawVars);
889
- }
890
- var colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas = {
891
- id: "2026-04-24-legacy-keys-and-bg-to-canvas",
892
- fromVersion: 0,
893
- toVersion: 1,
894
- appliesTo: "colors-and-type",
895
- apply(rawVars) {
896
- const out = { ...rawVars };
897
- migrateLegacyKeys(out);
898
- return out;
887
+ if (input.harmony && !HARMONY_MODES.includes(input.harmony.mode)) {
888
+ problems.push(`harmony.mode: unknown mode ${JSON.stringify(input.harmony.mode)}`);
899
889
  }
900
- };
901
-
902
- // src/editor/core/themes/migrations/2026-04-24-component-prefix-and-suffix-renames.ts
903
- var COMPONENT_PREFIX_RENAMES = {
904
- "--segment-": "--segmentedcontrol-",
905
- "--collapsible-": "--collapsiblesection-",
906
- "--progress-": "--progressbar-",
907
- "--section-divider-": "--sectiondivider-",
908
- "--radio-": "--radiobutton-",
909
- "--inline-edit-": "--inlineeditactions-"
910
- };
911
- var COMPONENT_SUFFIX_RENAMES = {
912
- progressbar: [["-track-bg", "-track-surface"]],
913
- inlineeditactions: [
914
- ["-bg-hover", "-hover-surface"],
915
- ["-bg", "-surface"]
916
- ]
917
- };
918
- var componentMigration_2026_04_24_prefixAndSuffixRenames = {
919
- id: "2026-04-24-component-prefix-and-suffix-renames",
920
- fromVersion: 0,
921
- toVersion: 1,
922
- appliesTo: "component-config",
923
- apply(rawVars, meta) {
924
- const component = meta.component ?? "";
925
- const out = {};
926
- const suffixRules = COMPONENT_SUFFIX_RENAMES[component] ?? [];
927
- for (const [oldKey, value] of Object.entries(rawVars)) {
928
- let key = oldKey;
929
- if (key === "--detail-nav-bg") key = "--detailnav-surface";
930
- for (const [oldPrefix, newPrefix] of Object.entries(COMPONENT_PREFIX_RENAMES)) {
931
- if (key.startsWith(oldPrefix)) {
932
- key = newPrefix + key.slice(oldPrefix.length);
933
- break;
934
- }
935
- }
936
- for (const [oldSuffix, newSuffix] of suffixRules) {
937
- if (key.endsWith(oldSuffix)) {
938
- key = key.slice(0, -oldSuffix.length) + newSuffix;
939
- break;
940
- }
941
- }
942
- if (!(key in out)) out[key] = value;
943
- }
944
- return out;
890
+ if (input.canvasGradient !== void 0 && typeof input.canvasGradient !== "boolean") {
891
+ problems.push(`canvasGradient: must be a boolean, got ${JSON.stringify(input.canvasGradient)}`);
945
892
  }
946
- };
947
-
948
- // src/editor/core/themes/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts
949
- var OPTION_DISABLED_PREFIX = "--segmentedcontrol-option-disabled-";
950
- var DISABLED_PREFIX = "--segmentedcontrol-disabled-";
951
- var SELECTED_DISABLED_PREFIX = "--segmentedcontrol-selected-disabled-";
952
- var SELECTED_HOVER_PREFIX = "--segmentedcontrol-selected-hover-";
953
- var componentMigration_2026_04_27_segmentedcontrolDisabledFlatten = {
954
- id: "2026-04-27-segmentedcontrol-disabled-flatten",
955
- fromVersion: 1,
956
- toVersion: 2,
957
- appliesTo: "component-config",
958
- apply(rawVars, meta) {
959
- if (meta.component !== "segmentedcontrol") return { ...rawVars };
960
- const out = {};
961
- for (const [oldKey, value] of Object.entries(rawVars)) {
962
- let key = oldKey;
963
- if (key.startsWith(SELECTED_DISABLED_PREFIX)) continue;
964
- if (key.startsWith(SELECTED_HOVER_PREFIX)) continue;
965
- if (key.startsWith(OPTION_DISABLED_PREFIX)) {
966
- key = DISABLED_PREFIX + key.slice(OPTION_DISABLED_PREFIX.length);
967
- }
968
- if (!(key in out)) out[key] = value;
969
- }
970
- return out;
971
- }
972
- };
973
-
974
- // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-variant-namespace.ts
975
- var PREFIX = "--collapsiblesection-";
976
- var STATE_NAMES = /* @__PURE__ */ new Set(["default", "hover", "active", "expanded"]);
977
- var componentMigration_2026_05_08_collapsiblesectionVariantNamespace = {
978
- id: "2026-05-08-collapsiblesection-variant-namespace",
979
- fromVersion: 2,
980
- toVersion: 3,
981
- appliesTo: "component-config",
982
- apply(rawVars, meta) {
983
- if (meta.component !== "collapsiblesection") return { ...rawVars };
984
- const out = {};
985
- for (const [oldKey, value] of Object.entries(rawVars)) {
986
- let key = oldKey;
987
- if (key.startsWith(PREFIX)) {
988
- const tail = key.slice(PREFIX.length);
989
- const firstSegment = tail.split("-", 1)[0];
990
- if (STATE_NAMES.has(firstSegment)) {
991
- key = `${PREFIX}container-${tail}`;
992
- }
993
- }
994
- if (!(key in out)) out[key] = value;
893
+ const baseColors = {};
894
+ const given = input.baseColors ?? {};
895
+ for (const spec of PALETTE_SPECS) {
896
+ if (!(spec.label in given)) {
897
+ problems.push(`baseColors.${spec.label}: missing`);
898
+ continue;
995
899
  }
996
- return out;
900
+ const parsed = parseBaseColor(spec.label, given[spec.label], problems);
901
+ if (parsed) baseColors[spec.label] = parsed;
997
902
  }
998
- };
999
-
1000
- // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts
1001
- var PFX = "--collapsiblesection-";
1002
- var componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup = {
1003
- id: "2026-05-08-collapsiblesection-frame-and-cleanup",
1004
- fromVersion: 3,
1005
- toVersion: 4,
1006
- appliesTo: "component-config",
1007
- apply(rawVars, meta) {
1008
- if (meta.component !== "collapsiblesection") return { ...rawVars };
1009
- const out = {};
1010
- for (const prop of ["surface", "border", "border-width", "radius"]) {
1011
- const src = `${PFX}container-default-${prop}`;
1012
- if (src in rawVars) {
1013
- out[`${PFX}container-frame-${prop}`] = rawVars[src];
1014
- }
1015
- }
1016
- for (const [key, value] of Object.entries(rawVars)) {
1017
- if (/^--collapsiblesection-chromeless-(default|hover|active)-(border|border-width|radius)$/.test(key)) continue;
1018
- if (/^--collapsiblesection-container-(hover|active)-(border|border-width|radius)$/.test(key)) continue;
1019
- if (/^--collapsiblesection-container-default-(border|border-width|radius)$/.test(key)) continue;
1020
- if (/^--collapsiblesection-divider-(default|hover|active)-radius$/.test(key)) continue;
1021
- if (/^--collapsiblesection-(chromeless|divider|container)-expanded-(border|border-width|radius)$/.test(key)) continue;
1022
- if (/^--collapsiblesection-(chromeless|divider)-expanded-surface$/.test(key)) continue;
1023
- if (!(key in out)) out[key] = value;
1024
- }
1025
- return out;
903
+ const known = new Set(PALETTE_SPECS.map((s) => s.label));
904
+ for (const label of Object.keys(given)) {
905
+ if (!known.has(label)) problems.push(`baseColors.${label}: unknown palette (expected ${[...known].join(", ")})`);
1026
906
  }
1027
- };
1028
-
1029
- // src/editor/core/themes/migrations/2026-05-10-sectiondivider-gradient-stops.ts
1030
- var PFX2 = "--sectiondivider-";
1031
- var VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
1032
- var OLD_STOP_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-stop-\d+$/;
1033
- var componentMigration_2026_05_10_sectiondividerGradientStops = {
1034
- id: "2026-05-10-sectiondivider-gradient-stops",
1035
- fromVersion: 4,
1036
- toVersion: 5,
1037
- appliesTo: "component-config",
1038
- apply(rawVars, meta) {
1039
- if (meta.component !== "sectiondivider") return { ...rawVars };
1040
- const out = {};
1041
- for (const [key, value] of Object.entries(rawVars)) {
1042
- if (OLD_STOP_RE.test(key)) continue;
1043
- out[key] = value;
1044
- }
1045
- const setIfMissing = (key, fallback) => {
1046
- if (!(key in out)) out[key] = fallback;
1047
- };
1048
- for (const v of VARIANTS) {
1049
- const old1 = rawVars[`${PFX2}${v}-gradient-stop-1`];
1050
- const old2 = rawVars[`${PFX2}${v}-gradient-stop-2`];
1051
- const old4 = rawVars[`${PFX2}${v}-gradient-stop-4`];
1052
- setIfMissing(`${PFX2}${v}-gradient-angle`, "--gradient-angle-diagonal");
1053
- setIfMissing(`${PFX2}${v}-gradient-stop-1-color`, old1 ?? `--surface-${v}-highest`);
1054
- setIfMissing(`${PFX2}${v}-gradient-stop-1-position`, "--gradient-stop-start");
1055
- setIfMissing(`${PFX2}${v}-gradient-stop-2-color`, old2 ?? `--surface-${v}-higher`);
1056
- setIfMissing(`${PFX2}${v}-gradient-stop-2-position`, "--gradient-stop-mid");
1057
- setIfMissing(`${PFX2}${v}-gradient-stop-3-color`, old4 ?? `--surface-${v}`);
1058
- setIfMissing(`${PFX2}${v}-gradient-stop-3-position`, "--gradient-stop-end");
1059
- }
1060
- return out;
907
+ if (problems.length > 0) {
908
+ throw new Error(`Invalid base color file:
909
+ ${problems.join("\n ")}`);
1061
910
  }
1062
- };
1063
-
1064
- // src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts
1065
- var PALETTE_STEPS2 = ["100", "200", "300", "400", "500", "600", "700", "800", "850", "900", "950"];
1066
- var SURFACE_SUFFIXES = ["lowest", "lower", "low", "high", "higher", "highest"];
1067
- var BORDER_SUFFIXES = ["faint", "subtle", "medium", "strong"];
1068
- var TEXT_SUFFIXES = ["secondary", "tertiary", "muted", "disabled"];
1069
- var RENAME_MAP = (() => {
1070
- const m = {};
1071
- for (const step of PALETTE_STEPS2) m[`--color-primary-${step}`] = `--color-brand-${step}`;
1072
- m["--surface-primary"] = "--surface-brand";
1073
- for (const suf of SURFACE_SUFFIXES) m[`--surface-primary-${suf}`] = `--surface-brand-${suf}`;
1074
- m["--border-primary"] = "--border-brand";
1075
- for (const suf of BORDER_SUFFIXES) m[`--border-primary-${suf}`] = `--border-brand-${suf}`;
1076
- m["--text-primary-color"] = "--text-brand";
1077
- for (const suf of TEXT_SUFFIXES) m[`--text-primary-${suf}`] = `--text-brand-${suf}`;
1078
- return m;
1079
- })();
1080
- function renameToken(name) {
1081
- return RENAME_MAP[name] ?? name;
911
+ return baseColors;
1082
912
  }
1083
- function renameKeys(rawVars) {
1084
- const out = {};
1085
- for (const [k, v] of Object.entries(rawVars)) {
1086
- out[renameToken(k)] = v;
913
+ function checkDefs() {
914
+ const defs = [];
915
+ for (const [stepName, floor, target] of NEUTRAL_TEXT_FLOORS) {
916
+ defs.push({
917
+ paletteLabel: "Neutral",
918
+ step: TEXT_SCALE.steps.find((s) => s.name === stepName),
919
+ textVar: scaleToCssVar("Text", stepName, "neutral"),
920
+ floor,
921
+ target
922
+ });
1087
923
  }
1088
- return out;
1089
- }
1090
- function renameKeysAndValues(rawVars) {
1091
- const out = {};
1092
- for (const [k, v] of Object.entries(rawVars)) {
1093
- out[renameToken(k)] = renameToken(v);
924
+ const primary = TEXT_SCALE.steps.find((s) => s.name === "primary");
925
+ for (const label of FUNCTIONAL_TEXT_LABELS) {
926
+ const ns = PALETTE_SPECS.find((s) => s.label === label).cssNamespace;
927
+ defs.push({
928
+ paletteLabel: label,
929
+ step: primary,
930
+ textVar: scaleToCssVar("Text", "primary", ns),
931
+ floor: AA_LARGE,
932
+ target: FUNCTIONAL_TEXT_TARGET
933
+ });
1094
934
  }
1095
- return out;
1096
- }
1097
- var colorsAndTypeMigration_2026_05_13_primaryToBrand = {
1098
- id: "2026-05-13-primary-to-brand-theme",
1099
- fromVersion: 1,
1100
- toVersion: 2,
1101
- appliesTo: "colors-and-type",
1102
- apply: renameKeys
1103
- };
1104
- var componentMigration_2026_05_13_primaryToBrand = {
1105
- id: "2026-05-13-primary-to-brand-component",
1106
- fromVersion: 5,
1107
- toVersion: 6,
1108
- appliesTo: "component-config",
1109
- apply: renameKeysAndValues
1110
- };
1111
-
1112
- // src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts
1113
- function dropFrameSurface(rawVars, meta) {
1114
- if (meta.component !== "collapsiblesection") return rawVars;
1115
- const { "--collapsiblesection-container-frame-surface": _drop, ...rest } = rawVars;
1116
- return rest;
935
+ return defs;
1117
936
  }
1118
- var componentMigration_2026_05_19_collapsiblesectionDropFrameSurface = {
1119
- id: "2026-05-19-collapsiblesection-drop-frame-surface",
1120
- fromVersion: 6,
1121
- toVersion: 7,
1122
- appliesTo: "component-config",
1123
- apply: dropFrameSurface
1124
- };
1125
-
1126
- // src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts
1127
- var FLAT_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-(angle|stop-[123]-(color|position))$/;
1128
- var componentMigration_2026_05_19_sectiondividerRichGradient = {
1129
- id: "2026-05-19-sectiondivider-rich-gradient",
1130
- fromVersion: 7,
1131
- toVersion: 8,
1132
- appliesTo: "component-config",
1133
- apply(rawVars, meta) {
1134
- if (meta.component !== "sectiondivider") return { ...rawVars };
1135
- const out = {};
1136
- for (const [key, value] of Object.entries(rawVars)) {
1137
- if (FLAT_RE.test(key)) continue;
1138
- out[key] = value;
1139
- }
1140
- return out;
1141
- }
1142
- };
1143
-
1144
- // src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts
1145
- var VARIANTS2 = ["lg", "md", "sm"];
1146
- var SUFFIX_RENAMES = [
1147
- [/-title-border-width$/, "-title-outline-width"],
1148
- [/-title-stroke-color$/, "-title-outline-color"],
1149
- [
1150
- /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-padding$/,
1151
- "--sectiondivider-$1-spacing"
1152
- ]
1153
- ];
1154
- function renameKeySuffix(key) {
1155
- for (const [re, repl] of SUFFIX_RENAMES) {
1156
- if (re.test(key)) return key.replace(re, repl);
1157
- }
1158
- return key;
937
+ function surfaceVars() {
938
+ return [
939
+ ...SURFACE_SCALE.steps.map((s) => scaleToCssVar("Surfaces", s.name, "neutral")),
940
+ "--page-bg"
941
+ ];
1159
942
  }
1160
- function splitFamilyKey(key) {
1161
- const m = key.match(/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-(.+)$/);
1162
- if (!m) return null;
1163
- return { family: m[1], suffix: m[2] };
943
+ function varToHex(value) {
944
+ const parsed = value ? cssColorToOklch(value) : null;
945
+ return parsed ? oklchToHexClamped(parsed.l, parsed.c, parsed.h) : null;
1164
946
  }
1165
- var componentMigration_2026_05_20_sectiondividerSlimVariants = {
1166
- id: "2026-05-20-sectiondivider-slim-variants",
1167
- fromVersion: 8,
1168
- toVersion: 9,
1169
- appliesTo: "component-config",
1170
- apply(rawVars, meta) {
1171
- if (meta.component !== "sectiondivider") return { ...rawVars };
1172
- const out = {};
1173
- const canvasValues = {};
1174
- for (const [rawKey, value] of Object.entries(rawVars)) {
1175
- const key = renameKeySuffix(rawKey);
1176
- const parts = splitFamilyKey(key);
1177
- if (!parts) {
1178
- out[key] = value;
1179
- continue;
1180
- }
1181
- if (parts.family !== "canvas") continue;
1182
- canvasValues[parts.suffix] = value;
1183
- }
1184
- for (const suffix of Object.keys(canvasValues)) {
1185
- for (const v of VARIANTS2) {
1186
- out[`--sectiondivider-${v}-${suffix}`] = canvasValues[suffix];
1187
- }
1188
- }
1189
- return out;
1190
- }
1191
- };
1192
-
1193
- // src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts
1194
- var componentMigration_2026_05_21_sectiondividerSpacingToPadding = {
1195
- id: "2026-05-21-sectiondivider-spacing-to-padding",
1196
- fromVersion: 9,
1197
- toVersion: 10,
1198
- appliesTo: "component-config",
1199
- apply(rawVars, meta) {
1200
- if (meta.component !== "sectiondivider") return { ...rawVars };
1201
- const out = {};
1202
- for (const [key, value] of Object.entries(rawVars)) {
1203
- const renamed = key.replace(
1204
- /^--sectiondivider-(lg|md|sm)-spacing$/,
1205
- "--sectiondivider-$1-padding"
1206
- );
1207
- out[renamed] = value;
1208
- }
1209
- return out;
1210
- }
1211
- };
1212
-
1213
- // src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts
1214
- var componentMigration_2026_05_22_sectiondividerIntrinsicsToCss = {
1215
- id: "2026-05-22-sectiondivider-intrinsics-to-css",
1216
- fromVersion: 10,
1217
- toVersion: 11,
1218
- appliesTo: "component-config",
1219
- apply(rawVars, meta) {
1220
- if (meta.component !== "sectiondivider") return { ...rawVars };
1221
- const VARIANTS4 = ["lg", "md", "sm"];
1222
- const prefix = "--sectiondivider-";
1223
- const dropped = /* @__PURE__ */ new Set();
1224
- for (const v of VARIANTS4) {
1225
- dropped.add(`${prefix}${v}-show-eyebrow`);
1226
- dropped.add(`${prefix}${v}-show-description`);
1227
- dropped.add(`${prefix}${v}-show-hairline`);
1228
- dropped.add(`${prefix}${v}-hairline`);
1229
- dropped.add(`${prefix}${v}-eyebrow-uppercase`);
1230
- }
1231
- const out = {};
1232
- for (const [key, value] of Object.entries(rawVars)) {
1233
- if (dropped.has(key)) continue;
1234
- out[key] = value;
1235
- }
1236
- for (const v of VARIANTS4) {
1237
- const showEyebrow = rawVars[`${prefix}${v}-show-eyebrow`];
1238
- if (showEyebrow !== void 0) {
1239
- out[`${prefix}${v}-eyebrow-display`] = showEyebrow === "1" ? "block" : "none";
1240
- }
1241
- const showDesc = rawVars[`${prefix}${v}-show-description`];
1242
- if (showDesc !== void 0) {
1243
- out[`${prefix}${v}-description-display`] = showDesc === "1" ? "flex" : "none";
1244
- }
1245
- const showHair = rawVars[`${prefix}${v}-show-hairline`];
1246
- const oldHair = rawVars[`${prefix}${v}-hairline`];
1247
- const oldHairIsPos = typeof oldHair === "string" && oldHair !== "" && oldHair !== "off";
1248
- let newHair;
1249
- if (showHair === "") newHair = "none";
1250
- else if (showHair === "1") newHair = oldHairIsPos ? oldHair : "above-label";
1251
- else if (oldHair !== void 0) newHair = oldHairIsPos ? oldHair : "none";
1252
- if (newHair !== void 0) {
1253
- out[`${prefix}${v}-hairline`] = newHair;
1254
- }
1255
- const upper = rawVars[`${prefix}${v}-eyebrow-uppercase`];
1256
- if (upper !== void 0) {
1257
- out[`${prefix}${v}-eyebrow-text-transform`] = upper === "1" ? "uppercase" : "none";
1258
- }
1259
- }
1260
- return out;
1261
- }
1262
- };
1263
-
1264
- // src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts
1265
- var componentMigration_2026_05_24_segmentedcontrolDividerInset = {
1266
- id: "2026-05-24-segmentedcontrol-divider-inset",
1267
- fromVersion: 11,
1268
- toVersion: 12,
1269
- appliesTo: "component-config",
1270
- apply(rawVars, meta) {
1271
- if (meta.component !== "segmentedcontrol") return { ...rawVars };
1272
- const out = {};
1273
- for (const [key, value] of Object.entries(rawVars)) {
1274
- if (key === "--segmentedcontrol-divider-height") continue;
1275
- out[key] = value;
947
+ function worstSurface(textHex, vars) {
948
+ let against = "";
949
+ let ratio = Infinity;
950
+ for (const surfVar of surfaceVars()) {
951
+ const surfHex = varToHex(vars[surfVar]);
952
+ if (!surfHex) continue;
953
+ const r = contrastRatio(textHex, surfHex);
954
+ if (r < ratio) {
955
+ ratio = r;
956
+ against = surfVar;
1276
957
  }
1277
- return out;
1278
958
  }
1279
- };
1280
-
1281
- // src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts
1282
- var BUTTON_VARIANTS = ["primary", "secondary", "outline", "success", "danger", "warning"];
1283
- var BUTTON_STATES = ["hover", "disabled"];
1284
- var BUTTON_PROPS = ["padding", "radius", "border-width"];
1285
- var buttonDeadKeys = new Set(
1286
- BUTTON_VARIANTS.flatMap(
1287
- (v) => BUTTON_STATES.flatMap(
1288
- (s) => BUTTON_PROPS.map((p) => `--button-${v}-${s}-${p}`)
1289
- )
1290
- )
1291
- );
1292
- var segmentedcontrolDeadKeys = /* @__PURE__ */ new Set([
1293
- "--segmentedcontrol-selected-icon-size",
1294
- "--segmentedcontrol-option-hover-icon-size",
1295
- "--segmentedcontrol-disabled-icon-size"
1296
- ]);
1297
- var componentMigration_2026_05_24_promoteStateSharedTokens = {
1298
- id: "2026-05-24-promote-state-shared-tokens",
1299
- fromVersion: 12,
1300
- toVersion: 13,
1301
- appliesTo: "component-config",
1302
- apply(rawVars, meta) {
1303
- const dead = meta.component === "button" ? buttonDeadKeys : meta.component === "segmentedcontrol" ? segmentedcontrolDeadKeys : null;
1304
- if (!dead) return { ...rawVars };
1305
- const out = {};
1306
- for (const [key, value] of Object.entries(rawVars)) {
1307
- if (dead.has(key)) continue;
1308
- out[key] = value;
959
+ return { against, ratio };
960
+ }
961
+ function pinTextStep(cfg, step, solved) {
962
+ const x = scaleStepToX(step, TEXT_SCALE);
963
+ const base = cfg.baseColor;
964
+ const yL = Math.max(0, Math.min(200, solved.l / base.l * 100));
965
+ cfg.scaleCurves.Text.lightness = setCurveAnchor(cfg.scaleCurves.Text.lightness, x, yL).curve;
966
+ if (base.c > 0) {
967
+ const yC = Math.max(0, Math.min(200, solved.c / base.c * 100));
968
+ cfg.scaleCurves.Text.saturation = setCurveAnchor(cfg.scaleCurves.Text.saturation, x, yC).curve;
969
+ }
970
+ }
971
+ var MAX_CORRECTION_ROUNDS = 3;
972
+ function runContrastGate(configs, scheme) {
973
+ const defs = checkDefs();
974
+ const direction = scheme === "light" ? "darker" : "lighter";
975
+ const corrected = /* @__PURE__ */ new Set();
976
+ for (let round = 0; round < MAX_CORRECTION_ROUNDS; round++) {
977
+ const vars = palettesToVars(configs);
978
+ let anyFixed = false;
979
+ for (const def of defs) {
980
+ const text = cssColorToOklch(vars[def.textVar] ?? "");
981
+ if (!text) continue;
982
+ const textHex = oklchToHexClamped(text.l, text.c, text.h);
983
+ const worst = worstSurface(textHex, vars);
984
+ if (worst.ratio >= def.floor) continue;
985
+ const cfg = configs[def.paletteLabel];
986
+ const base = cfg.baseColor;
987
+ const solved = findLForContrast({
988
+ against: varToHex(vars[worst.against]) ?? "#000000",
989
+ ratio: def.target,
990
+ direction,
991
+ c: text.c,
992
+ h: base.h,
993
+ lMax: Math.min(1, 2 * base.l)
994
+ });
995
+ pinTextStep(cfg, def.step, solved);
996
+ corrected.add(def.textVar);
997
+ anyFixed = true;
1309
998
  }
1310
- return out;
999
+ if (!anyFixed) break;
1311
1000
  }
1001
+ const finalVars = palettesToVars(configs);
1002
+ const checks = defs.map((def) => {
1003
+ const worst = worstSurface(varToHex(finalVars[def.textVar]) ?? "#000000", finalVars);
1004
+ return {
1005
+ textVar: def.textVar,
1006
+ floor: def.floor,
1007
+ against: worst.against,
1008
+ ratio: worst.ratio,
1009
+ pass: worst.ratio >= def.floor,
1010
+ corrected: corrected.has(def.textVar)
1011
+ };
1012
+ });
1013
+ const failures = checks.filter((c) => !c.pass).map((c) => {
1014
+ const label = defs.find((d) => d.textVar === c.textVar).paletteLabel;
1015
+ const hint = scheme === "dark" ? `raise the ${label} base color lightness (derived text tops out at 2\xD7 its L)` : `raise the ${label} base color lightness or reduce its chroma`;
1016
+ return `${c.textVar} reaches ${c.ratio.toFixed(2)}:1 vs ${c.against} (floor ${c.floor}:1) \u2014 ${hint}`;
1017
+ });
1018
+ return { scheme, checks, failures };
1019
+ }
1020
+ var ADJACENT_HUE_MAX = 120;
1021
+ var hueDist = (a, b) => {
1022
+ const d = Math.abs(norm(a) - norm(b));
1023
+ return Math.min(d, 360 - d);
1312
1024
  };
1313
-
1314
- // src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts
1315
- var PRIMARY_PREFIX = "--progressbar-primary-";
1316
- var NEW_PREFIX = "--progressbar-";
1317
- var DROP_PREFIXES = [
1318
- "--progressbar-success-",
1319
- "--progressbar-warning-",
1320
- "--progressbar-danger-",
1321
- "--progressbar-info-"
1322
- ];
1323
- var componentMigration_2026_05_24_progressbarCollapseVariants = {
1324
- id: "2026-05-24-progressbar-collapse-variants",
1325
- fromVersion: 13,
1326
- toVersion: 14,
1327
- appliesTo: "component-config",
1328
- apply(rawVars, meta) {
1329
- if (meta.component !== "progressbar") return { ...rawVars };
1330
- const out = {};
1331
- for (const [oldKey, value] of Object.entries(rawVars)) {
1332
- if (DROP_PREFIXES.some((p) => oldKey.startsWith(p))) continue;
1333
- const key = oldKey.startsWith(PRIMARY_PREFIX) ? NEW_PREFIX + oldKey.slice(PRIMARY_PREFIX.length) : oldKey;
1334
- if (!(key in out)) out[key] = value;
1335
- }
1336
- return out;
1025
+ var linear = (variable, angle, from, to) => ({
1026
+ variable,
1027
+ type: "linear",
1028
+ angle,
1029
+ stops: [{ position: 0, color: from }, { position: 100, color: to }]
1030
+ });
1031
+ function recipeGradients(baseColors, scheme) {
1032
+ return [
1033
+ linear("--gradient-1", 90, "--color-brand-400", "--color-brand-700"),
1034
+ hueDist(baseColors.Special.h, baseColors.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"),
1035
+ hueDist(baseColors.Brand.h, baseColors.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"),
1036
+ scheme === "dark" ? linear("--gradient-4", 180, "--color-canvas-600", "--color-canvas-900") : linear("--gradient-4", 180, "--color-canvas-200", "--color-canvas-500")
1037
+ ];
1038
+ }
1039
+ function isStockGradients(gradients) {
1040
+ return !gradients || gradients.length === 0 || JSON.stringify(gradients) === JSON.stringify(makeDefaultGradients());
1041
+ }
1042
+ function applyCanvasGradient(canvas, scheme) {
1043
+ const labels = PALETTE_STEPS.map((s) => s.label);
1044
+ const anchor = canvas.anchorPlacement.step;
1045
+ const sky = scheme === "dark" ? Math.min(anchor + 2, labels.length - 1) : Math.max(anchor - 2, 0);
1046
+ if (sky === anchor) {
1047
+ return `skipped \u2014 the Canvas base color anchors at the ramp edge (${labels[anchor]}), leaving no room for a sky; commit the canvas further from ${scheme === "dark" ? "black" : "white"}`;
1337
1048
  }
1049
+ canvas.emptyMode = "gradient";
1050
+ canvas.gradientStyle = "linear";
1051
+ canvas.gradientAngle = 180;
1052
+ canvas.gradientReverse = false;
1053
+ canvas.gradientStops = [
1054
+ { position: 0, paletteLabel: labels[sky] },
1055
+ { position: 100, paletteLabel: labels[anchor] }
1056
+ ];
1057
+ canvas.gradientSize = "window";
1058
+ return `on, ${labels[sky]} \u2192 ${labels[anchor]}`;
1059
+ }
1060
+ var STOCK_SHADOW_GEOMETRY = {
1061
+ "--shadow-sm": [1, 1, 2],
1062
+ "--shadow-md": [3, 3, 6],
1063
+ "--shadow-lg": [5, 5, 9],
1064
+ "--shadow-xl": [6, 7, 13],
1065
+ "--shadow-2xl": [8, 9, 16]
1338
1066
  };
1339
-
1340
- // src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts
1341
- function dropActiveState(rawVars, meta) {
1342
- if (meta.component !== "collapsiblesection") return rawVars;
1343
- const re = /^--collapsiblesection-(chromeless|divider|container)-active-/;
1067
+ var STOCK_SHADOW_COLOR = { spread: 0, hue: 237, saturation: 18, lightness: 3, opacity: 0.9 };
1068
+ var SHADOW_OPACITY_DEEP = 0.9;
1069
+ var SHADOW_OPACITY_SOFT = 0.2;
1070
+ var SHADOW_GROUND_DEEP = 0.5;
1071
+ var SHADOW_GROUND_SOFT = 0.9;
1072
+ function shadowOpacityForCanvas(canvasL) {
1073
+ const t = (canvasL - SHADOW_GROUND_DEEP) / (SHADOW_GROUND_SOFT - SHADOW_GROUND_DEEP);
1074
+ const ramp = Math.max(0, Math.min(1, t));
1075
+ const opacity = SHADOW_OPACITY_DEEP + ramp * (SHADOW_OPACITY_SOFT - SHADOW_OPACITY_DEEP);
1076
+ return Math.round(opacity * 100) / 100;
1077
+ }
1078
+ function shadowVars(carried, canvas) {
1079
+ const opacity = shadowOpacityForCanvas(canvas.l);
1344
1080
  const out = {};
1345
- for (const [key, value] of Object.entries(rawVars)) {
1346
- if (re.test(key)) continue;
1347
- out[key] = value;
1081
+ for (const variable of SHADOW_VAR_NAMES) {
1082
+ const [x, y, blur] = STOCK_SHADOW_GEOMETRY[variable];
1083
+ const base = parseShadowCss(variable, carried[variable] ?? "") ?? { x, y, blur, ...STOCK_SHADOW_COLOR };
1084
+ out[variable] = shadowTokenCss({ ...base, opacity });
1348
1085
  }
1349
1086
  return out;
1350
1087
  }
1351
- var componentMigration_2026_05_24_collapsiblesectionDropActiveState = {
1352
- id: "2026-05-24-collapsiblesection-drop-active-state",
1353
- fromVersion: 14,
1354
- toVersion: 15,
1355
- appliesTo: "component-config",
1356
- apply: dropActiveState
1357
- };
1088
+ function buildColors(input, carry = {}) {
1089
+ const baseColors = validateInput(input);
1090
+ const configs = {};
1091
+ for (const spec of PALETTE_SPECS) {
1092
+ configs[spec.label] = defaultPaletteConfig({
1093
+ baseColor: baseColors[spec.label],
1094
+ neutral: spec.neutral,
1095
+ scheme: input.scheme
1096
+ });
1097
+ }
1098
+ const report = runContrastGate(configs, input.scheme);
1099
+ const canvasGradient = input.canvasGradient ? applyCanvasGradient(configs.Canvas, input.scheme) : void 0;
1100
+ const gradients = isStockGradients(carry.gradients) ? recipeGradients(baseColors, input.scheme) : carry.gradients;
1101
+ const harmonyAxes = [
1102
+ { hue: norm(baseColors.Brand.h), family: "Brand" },
1103
+ { hue: norm(baseColors.Accent.h), family: "Accent" },
1104
+ { hue: norm(baseColors.Canvas.h), family: "Canvas" },
1105
+ { hue: norm(baseColors.Brand.h + 270), family: null }
1106
+ ];
1107
+ const owned = new Set(Object.keys(palettesToVars(configs)));
1108
+ const cssVariables = Object.fromEntries(
1109
+ Object.entries(carry.cssVariables ?? {}).filter(([k]) => !owned.has(k))
1110
+ );
1111
+ for (const t of gradients) cssVariables[t.variable] = formatGradientValue(t);
1112
+ Object.assign(cssVariables, shadowVars(carry.cssVariables ?? {}, baseColors.Canvas));
1113
+ return {
1114
+ colors: { editorConfigs: configs, harmonyAxes, gradients, cssVariables },
1115
+ report: {
1116
+ ...report,
1117
+ gradients: gradients === carry.gradients ? "carried" : "recipes",
1118
+ shadows: `opacity ${shadowOpacityForCanvas(baseColors.Canvas.l)} for a canvas at L ${baseColors.Canvas.l.toFixed(2)}`,
1119
+ ...canvasGradient ? { canvasGradient } : {}
1120
+ }
1121
+ };
1122
+ }
1358
1123
 
1359
- // src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts
1360
- var VARIANTS3 = ["primary", "accent", "neutral", "alternate", "canvas", "special", "success", "warning", "danger", "info"];
1361
- var RE = new RegExp(`^--corner-badge-(${VARIANTS3.join("|")})-(.+)$`);
1362
- var CURRENT_COLOR_PROPS = /* @__PURE__ */ new Set(["surface", "border", "text"]);
1363
- function flattenVariants(rawVars, meta) {
1364
- if (meta.component !== "cornerbadge") return rawVars;
1365
- const out = {};
1366
- const collected = /* @__PURE__ */ new Map();
1367
- for (const [key, value] of Object.entries(rawVars)) {
1368
- const m = key.match(RE);
1369
- if (m) {
1370
- const prop = m[2];
1371
- if (CURRENT_COLOR_PROPS.has(prop)) {
1372
- out[key] = value;
1373
- continue;
1374
- }
1375
- if (!collected.has(prop)) collected.set(prop, value);
1376
- continue;
1124
+ // src/editor/core/storage/files/versionedFileResourceClient.ts
1125
+ function sanitizeFileName(name) {
1126
+ return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^[-_]+|-+$/g, "") || "unnamed";
1127
+ }
1128
+
1129
+ // vite-plugin/files/dataPaths.ts
1130
+ var import_fs = __toESM(require("fs"), 1);
1131
+ var import_path = __toESM(require("path"), 1);
1132
+ var DEFAULT_DATA_DIR = "src/live-tokens/data";
1133
+ var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
1134
+ "dataDir",
1135
+ "colorsAndTypeDir",
1136
+ "componentConfigsDir",
1137
+ "themesDir",
1138
+ "manifestsDir",
1139
+ "tokensCssPath",
1140
+ "componentDirs",
1141
+ "checks"
1142
+ ]);
1143
+ var cached = null;
1144
+ function readLiveTokensConfig() {
1145
+ if (cached) return cached;
1146
+ try {
1147
+ const configPath = import_path.default.resolve("live-tokens.config.json");
1148
+ if (!import_fs.default.existsSync(configPath)) return cached = {};
1149
+ const parsed = JSON.parse(import_fs.default.readFileSync(configPath, "utf-8"));
1150
+ if (!parsed || typeof parsed !== "object") return cached = {};
1151
+ const unknown = Object.keys(parsed).filter(
1152
+ (k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
1153
+ );
1154
+ if (unknown.length > 0) {
1155
+ console.warn(
1156
+ `[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
1157
+ );
1377
1158
  }
1378
- out[key] = value;
1379
- }
1380
- for (const [prop, value] of collected) {
1381
- const flatKey = `--corner-badge-${prop}`;
1382
- if (!(flatKey in out)) out[flatKey] = value;
1159
+ cached = parsed;
1160
+ return cached;
1161
+ } catch {
1162
+ return cached = {};
1383
1163
  }
1384
- return out;
1385
1164
  }
1386
- var componentMigration_2026_05_25_cornerbadgeFlattenVariants = {
1387
- id: "2026-05-25-cornerbadge-flatten-variants",
1388
- fromVersion: 15,
1389
- toVersion: 16,
1390
- appliesTo: "component-config",
1391
- apply: flattenVariants
1392
- };
1165
+ function resolveDataDirs(opts = {}) {
1166
+ const fileConfig = readLiveTokensConfig();
1167
+ const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
1168
+ const dataDir = import_path.default.resolve(dataDirRaw);
1169
+ const sub = (name) => import_path.default.resolve(dataDir, name);
1170
+ return {
1171
+ dataDir,
1172
+ colorsAndTypeDir: opts.colorsAndTypeDir ? import_path.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
1173
+ componentConfigsDir: opts.componentConfigsDir ? import_path.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
1174
+ themesDir: opts.themesDir ? import_path.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path.default.resolve(fileConfig.themesDir) : sub("themes"),
1175
+ sketchStylesDir: sub("sketch-styles"),
1176
+ legacyManifestsDir: fileConfig.manifestsDir ? import_path.default.resolve(fileConfig.manifestsDir) : void 0
1177
+ };
1178
+ }
1393
1179
 
1394
- // src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts
1395
- var DROPPED_TO_KEPT = {
1396
- "--overlay-lowest": "--overlay-low",
1397
- "--overlay-lower": "--overlay-low",
1398
- "--overlay-higher": "--overlay-high",
1399
- "--overlay-highest": "--overlay-high"
1180
+ // src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts
1181
+ var LEGACY_KEY_RENAMES = {
1182
+ "--empty": "--page-bg",
1183
+ "--empty-attachment": "--page-bg-attachment",
1184
+ // Orphan exports dropped from tokens.css; no new home — silently discard.
1185
+ "--border-neutral": null,
1186
+ // Shadow cleanup: these five tokens were removed (low/zero consumers,
1187
+ // aesthetic drift). Dialog migrated onto --shadow-2xl; focus rings moved
1188
+ // to their own --ring-focus-* namespace, which themes don't carry by
1189
+ // default — tokens.css provides the canonical values.
1190
+ "--shadow-app": null,
1191
+ "--shadow-card": null,
1192
+ "--shadow-overlay": null,
1193
+ "--shadow-focus": null,
1194
+ "--shadow-glow-green": null
1400
1195
  };
1401
- var colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops = {
1402
- id: "2026-05-26-drop-overlay-extra-stops-theme",
1403
- fromVersion: 2,
1404
- toVersion: 3,
1405
- appliesTo: "colors-and-type",
1406
- apply(rawVars) {
1407
- const out = {};
1408
- for (const [key, value] of Object.entries(rawVars)) {
1409
- if (key in DROPPED_TO_KEPT) continue;
1410
- out[key] = value;
1196
+ var BG_TO_CANVAS_PREFIXES = ["--color-bg-", "--surface-bg", "--border-bg", "--text-bg"];
1197
+ function migrateBgToCanvas(rawVars) {
1198
+ for (const oldKey of Object.keys(rawVars)) {
1199
+ for (const prefix of BG_TO_CANVAS_PREFIXES) {
1200
+ if (!oldKey.startsWith(prefix)) continue;
1201
+ const suffix = oldKey.slice(prefix.length);
1202
+ if (suffix && !suffix.startsWith("-")) continue;
1203
+ const newKey = prefix.replace("-bg", "-canvas") + suffix;
1204
+ if (newKey === oldKey) continue;
1205
+ const value = rawVars[oldKey];
1206
+ delete rawVars[oldKey];
1207
+ if (!(newKey in rawVars)) rawVars[newKey] = value;
1208
+ break;
1411
1209
  }
1412
- return out;
1413
1210
  }
1414
- };
1415
- var componentMigration_2026_05_26_dropOverlayExtraStops = {
1416
- id: "2026-05-26-drop-overlay-extra-stops-component",
1417
- fromVersion: 16,
1418
- toVersion: 17,
1419
- appliesTo: "component-config",
1211
+ }
1212
+ function migrateLegacyKeys(rawVars) {
1213
+ for (const [oldKey, newKey] of Object.entries(LEGACY_KEY_RENAMES)) {
1214
+ if (!(oldKey in rawVars)) continue;
1215
+ const value = rawVars[oldKey];
1216
+ delete rawVars[oldKey];
1217
+ if (newKey && !(newKey in rawVars)) rawVars[newKey] = value;
1218
+ }
1219
+ migrateBgToCanvas(rawVars);
1220
+ }
1221
+ var colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas = {
1222
+ id: "2026-04-24-legacy-keys-and-bg-to-canvas",
1223
+ fromVersion: 0,
1224
+ toVersion: 1,
1225
+ appliesTo: "colors-and-type",
1420
1226
  apply(rawVars) {
1421
- const out = {};
1422
- for (const [key, value] of Object.entries(rawVars)) {
1423
- out[key] = DROPPED_TO_KEPT[value] ?? value;
1424
- }
1227
+ const out = { ...rawVars };
1228
+ migrateLegacyKeys(out);
1425
1229
  return out;
1426
1230
  }
1427
1231
  };
1428
1232
 
1429
- // src/editor/core/themes/migrations/2026-05-29-tabbar-indicator-thickness-to-per-state-width.ts
1430
- var TABBAR_STATES = ["default", "hover", "active", "disabled"];
1431
- var OLD_KEY = "--tabbar-bar-indicator-thickness";
1432
- var FALLBACK = "--border-width-2";
1433
- var componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth = {
1434
- id: "2026-05-29-tabbar-indicator-thickness-to-per-state-width",
1435
- fromVersion: 17,
1436
- toVersion: 18,
1233
+ // src/editor/core/themes/migrations/2026-04-24-component-prefix-and-suffix-renames.ts
1234
+ var COMPONENT_PREFIX_RENAMES = {
1235
+ "--segment-": "--segmentedcontrol-",
1236
+ "--collapsible-": "--collapsiblesection-",
1237
+ "--progress-": "--progressbar-",
1238
+ "--section-divider-": "--sectiondivider-",
1239
+ "--radio-": "--radiobutton-",
1240
+ "--inline-edit-": "--inlineeditactions-"
1241
+ };
1242
+ var COMPONENT_SUFFIX_RENAMES = {
1243
+ progressbar: [["-track-bg", "-track-surface"]],
1244
+ inlineeditactions: [
1245
+ ["-bg-hover", "-hover-surface"],
1246
+ ["-bg", "-surface"]
1247
+ ]
1248
+ };
1249
+ var componentMigration_2026_04_24_prefixAndSuffixRenames = {
1250
+ id: "2026-04-24-component-prefix-and-suffix-renames",
1251
+ fromVersion: 0,
1252
+ toVersion: 1,
1437
1253
  appliesTo: "component-config",
1438
1254
  apply(rawVars, meta) {
1439
- if (meta.component !== "tabbar") return { ...rawVars };
1440
- const seed = rawVars[OLD_KEY] ?? FALLBACK;
1255
+ const component = meta.component ?? "";
1441
1256
  const out = {};
1442
- for (const [key, value] of Object.entries(rawVars)) {
1443
- if (key === OLD_KEY) continue;
1444
- out[key] = value;
1445
- }
1446
- for (const state of TABBAR_STATES) {
1447
- const newKey = `--tabbar-${state}-indicator-border-width`;
1448
- if (!(newKey in out)) out[newKey] = seed;
1257
+ const suffixRules = COMPONENT_SUFFIX_RENAMES[component] ?? [];
1258
+ for (const [oldKey, value] of Object.entries(rawVars)) {
1259
+ let key = oldKey;
1260
+ if (key === "--detail-nav-bg") key = "--detailnav-surface";
1261
+ for (const [oldPrefix, newPrefix] of Object.entries(COMPONENT_PREFIX_RENAMES)) {
1262
+ if (key.startsWith(oldPrefix)) {
1263
+ key = newPrefix + key.slice(oldPrefix.length);
1264
+ break;
1265
+ }
1266
+ }
1267
+ for (const [oldSuffix, newSuffix] of suffixRules) {
1268
+ if (key.endsWith(oldSuffix)) {
1269
+ key = key.slice(0, -oldSuffix.length) + newSuffix;
1270
+ break;
1271
+ }
1272
+ }
1273
+ if (!(key in out)) out[key] = value;
1449
1274
  }
1450
1275
  return out;
1451
1276
  }
1452
1277
  };
1453
1278
 
1454
- // src/editor/core/themes/migrations/2026-05-29-segmentedcontrol-small-divider-rename.ts
1455
- var RENAMES = {
1456
- "--segmentedcontrol-divider-small-thickness": "--segmentedcontrol-small-divider-thickness",
1457
- "--segmentedcontrol-divider-small-inset": "--segmentedcontrol-small-divider-inset"
1458
- };
1459
- var componentMigration_2026_05_29_segmentedcontrolSmallDividerRename = {
1460
- id: "2026-05-29-segmentedcontrol-small-divider-rename",
1461
- fromVersion: 18,
1462
- toVersion: 19,
1279
+ // src/editor/core/themes/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts
1280
+ var OPTION_DISABLED_PREFIX = "--segmentedcontrol-option-disabled-";
1281
+ var DISABLED_PREFIX = "--segmentedcontrol-disabled-";
1282
+ var SELECTED_DISABLED_PREFIX = "--segmentedcontrol-selected-disabled-";
1283
+ var SELECTED_HOVER_PREFIX = "--segmentedcontrol-selected-hover-";
1284
+ var componentMigration_2026_04_27_segmentedcontrolDisabledFlatten = {
1285
+ id: "2026-04-27-segmentedcontrol-disabled-flatten",
1286
+ fromVersion: 1,
1287
+ toVersion: 2,
1463
1288
  appliesTo: "component-config",
1464
1289
  apply(rawVars, meta) {
1465
1290
  if (meta.component !== "segmentedcontrol") return { ...rawVars };
1466
1291
  const out = {};
1467
- for (const [key, value] of Object.entries(rawVars)) {
1468
- out[RENAMES[key] ?? key] = value;
1292
+ for (const [oldKey, value] of Object.entries(rawVars)) {
1293
+ let key = oldKey;
1294
+ if (key.startsWith(SELECTED_DISABLED_PREFIX)) continue;
1295
+ if (key.startsWith(SELECTED_HOVER_PREFIX)) continue;
1296
+ if (key.startsWith(OPTION_DISABLED_PREFIX)) {
1297
+ key = DISABLED_PREFIX + key.slice(OPTION_DISABLED_PREFIX.length);
1298
+ }
1299
+ if (!(key in out)) out[key] = value;
1469
1300
  }
1470
1301
  return out;
1471
1302
  }
1472
1303
  };
1473
1304
 
1474
- // src/editor/core/themes/migrations/2026-05-29-toggle-derive-track-from-thumb.ts
1475
- var componentMigration_2026_05_29_toggleDeriveTrackFromThumb = {
1476
- id: "2026-05-29-toggle-derive-track-from-thumb",
1477
- fromVersion: 19,
1478
- toVersion: 20,
1305
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-variant-namespace.ts
1306
+ var PREFIX = "--collapsiblesection-";
1307
+ var STATE_NAMES = /* @__PURE__ */ new Set(["default", "hover", "active", "expanded"]);
1308
+ var componentMigration_2026_05_08_collapsiblesectionVariantNamespace = {
1309
+ id: "2026-05-08-collapsiblesection-variant-namespace",
1310
+ fromVersion: 2,
1311
+ toVersion: 3,
1479
1312
  appliesTo: "component-config",
1480
1313
  apply(rawVars, meta) {
1481
- if (meta.component !== "toggle") return { ...rawVars };
1314
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
1482
1315
  const out = {};
1483
- for (const [key, value] of Object.entries(rawVars)) {
1484
- if (key === "--toggle-track-width" || key === "--toggle-track-thickness") continue;
1485
- out[key] = value;
1486
- }
1487
- if (!("--toggle-track-padding" in out)) {
1488
- out["--toggle-track-padding"] = "--space-2";
1316
+ for (const [oldKey, value] of Object.entries(rawVars)) {
1317
+ let key = oldKey;
1318
+ if (key.startsWith(PREFIX)) {
1319
+ const tail = key.slice(PREFIX.length);
1320
+ const firstSegment = tail.split("-", 1)[0];
1321
+ if (STATE_NAMES.has(firstSegment)) {
1322
+ key = `${PREFIX}container-${tail}`;
1323
+ }
1324
+ }
1325
+ if (!(key in out)) out[key] = value;
1489
1326
  }
1490
1327
  return out;
1491
1328
  }
1492
1329
  };
1493
1330
 
1494
- // src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts
1495
- var DROPPED = /* @__PURE__ */ new Set([
1496
- "--badge-trait-radius",
1497
- "--badge-trait-padding",
1498
- "--sectiondivider-padding",
1499
- "--dialog-primary-default-radius",
1500
- "--dialog-primary-default-padding",
1501
- "--dialog-primary-hover-radius",
1502
- "--dialog-primary-hover-padding",
1503
- "--dialog-secondary-default-radius",
1504
- "--dialog-secondary-default-padding",
1505
- "--dialog-secondary-hover-radius",
1506
- "--dialog-secondary-hover-padding"
1507
- ]);
1508
- var colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys = {
1509
- id: "2026-08-13-drop-legacy-shape-space-keys",
1331
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts
1332
+ var PFX = "--collapsiblesection-";
1333
+ var componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup = {
1334
+ id: "2026-05-08-collapsiblesection-frame-and-cleanup",
1510
1335
  fromVersion: 3,
1511
1336
  toVersion: 4,
1512
- appliesTo: "colors-and-type",
1513
- apply(rawVars) {
1337
+ appliesTo: "component-config",
1338
+ apply(rawVars, meta) {
1339
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
1340
+ const out = {};
1341
+ for (const prop of ["surface", "border", "border-width", "radius"]) {
1342
+ const src = `${PFX}container-default-${prop}`;
1343
+ if (src in rawVars) {
1344
+ out[`${PFX}container-frame-${prop}`] = rawVars[src];
1345
+ }
1346
+ }
1347
+ for (const [key, value] of Object.entries(rawVars)) {
1348
+ if (/^--collapsiblesection-chromeless-(default|hover|active)-(border|border-width|radius)$/.test(key)) continue;
1349
+ if (/^--collapsiblesection-container-(hover|active)-(border|border-width|radius)$/.test(key)) continue;
1350
+ if (/^--collapsiblesection-container-default-(border|border-width|radius)$/.test(key)) continue;
1351
+ if (/^--collapsiblesection-divider-(default|hover|active)-radius$/.test(key)) continue;
1352
+ if (/^--collapsiblesection-(chromeless|divider|container)-expanded-(border|border-width|radius)$/.test(key)) continue;
1353
+ if (/^--collapsiblesection-(chromeless|divider)-expanded-surface$/.test(key)) continue;
1354
+ if (!(key in out)) out[key] = value;
1355
+ }
1356
+ return out;
1357
+ }
1358
+ };
1359
+
1360
+ // src/editor/core/themes/migrations/2026-05-10-sectiondivider-gradient-stops.ts
1361
+ var PFX2 = "--sectiondivider-";
1362
+ var VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
1363
+ var OLD_STOP_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-stop-\d+$/;
1364
+ var componentMigration_2026_05_10_sectiondividerGradientStops = {
1365
+ id: "2026-05-10-sectiondivider-gradient-stops",
1366
+ fromVersion: 4,
1367
+ toVersion: 5,
1368
+ appliesTo: "component-config",
1369
+ apply(rawVars, meta) {
1370
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1514
1371
  const out = {};
1515
1372
  for (const [key, value] of Object.entries(rawVars)) {
1516
- if (DROPPED.has(key)) continue;
1373
+ if (OLD_STOP_RE.test(key)) continue;
1517
1374
  out[key] = value;
1518
1375
  }
1376
+ const setIfMissing = (key, fallback) => {
1377
+ if (!(key in out)) out[key] = fallback;
1378
+ };
1379
+ for (const v of VARIANTS) {
1380
+ const old1 = rawVars[`${PFX2}${v}-gradient-stop-1`];
1381
+ const old2 = rawVars[`${PFX2}${v}-gradient-stop-2`];
1382
+ const old4 = rawVars[`${PFX2}${v}-gradient-stop-4`];
1383
+ setIfMissing(`${PFX2}${v}-gradient-angle`, "--gradient-angle-diagonal");
1384
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-color`, old1 ?? `--surface-${v}-highest`);
1385
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-position`, "--gradient-stop-start");
1386
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-color`, old2 ?? `--surface-${v}-higher`);
1387
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-position`, "--gradient-stop-mid");
1388
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-color`, old4 ?? `--surface-${v}`);
1389
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-position`, "--gradient-stop-end");
1390
+ }
1519
1391
  return out;
1520
1392
  }
1521
1393
  };
1522
1394
 
1523
- // src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts
1524
- var RENAMED = {
1525
- "--line-height-xs": "--line-height-none",
1526
- "--line-height-sm": "--line-height-tighter",
1527
- "--line-height-md": "--line-height-normal",
1528
- "--line-height-lg": "--line-height-relaxed",
1529
- "--line-height-xl": "--line-height-relaxed"
1530
- };
1531
- var REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
1532
- function renameValues(rawVars) {
1395
+ // src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts
1396
+ var PALETTE_STEPS2 = ["100", "200", "300", "400", "500", "600", "700", "800", "850", "900", "950"];
1397
+ var SURFACE_SUFFIXES = ["lowest", "lower", "low", "high", "higher", "highest"];
1398
+ var BORDER_SUFFIXES = ["faint", "subtle", "medium", "strong"];
1399
+ var TEXT_SUFFIXES = ["secondary", "tertiary", "muted", "disabled"];
1400
+ var RENAME_MAP = (() => {
1401
+ const m = {};
1402
+ for (const step of PALETTE_STEPS2) m[`--color-primary-${step}`] = `--color-brand-${step}`;
1403
+ m["--surface-primary"] = "--surface-brand";
1404
+ for (const suf of SURFACE_SUFFIXES) m[`--surface-primary-${suf}`] = `--surface-brand-${suf}`;
1405
+ m["--border-primary"] = "--border-brand";
1406
+ for (const suf of BORDER_SUFFIXES) m[`--border-primary-${suf}`] = `--border-brand-${suf}`;
1407
+ m["--text-primary-color"] = "--text-brand";
1408
+ for (const suf of TEXT_SUFFIXES) m[`--text-primary-${suf}`] = `--text-brand-${suf}`;
1409
+ return m;
1410
+ })();
1411
+ function renameToken(name) {
1412
+ return RENAME_MAP[name] ?? name;
1413
+ }
1414
+ function renameKeys(rawVars) {
1533
1415
  const out = {};
1534
- for (const [key, value] of Object.entries(rawVars)) {
1535
- out[key] = typeof value === "string" ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
1416
+ for (const [k, v] of Object.entries(rawVars)) {
1417
+ out[renameToken(k)] = v;
1536
1418
  }
1537
1419
  return out;
1538
1420
  }
1539
- var colorsAndTypeMigration_2026_08_15_lineHeightScaleRename = {
1540
- id: "2026-08-15-line-height-scale-rename-colors-and-type",
1541
- fromVersion: 4,
1542
- toVersion: 5,
1421
+ function renameKeysAndValues(rawVars) {
1422
+ const out = {};
1423
+ for (const [k, v] of Object.entries(rawVars)) {
1424
+ out[renameToken(k)] = renameToken(v);
1425
+ }
1426
+ return out;
1427
+ }
1428
+ var colorsAndTypeMigration_2026_05_13_primaryToBrand = {
1429
+ id: "2026-05-13-primary-to-brand-theme",
1430
+ fromVersion: 1,
1431
+ toVersion: 2,
1543
1432
  appliesTo: "colors-and-type",
1544
- apply: renameValues
1433
+ apply: renameKeys
1545
1434
  };
1546
- var componentMigration_2026_08_15_lineHeightScaleRename = {
1547
- id: "2026-08-15-line-height-scale-rename-component",
1548
- fromVersion: 20,
1549
- toVersion: 21,
1435
+ var componentMigration_2026_05_13_primaryToBrand = {
1436
+ id: "2026-05-13-primary-to-brand-component",
1437
+ fromVersion: 5,
1438
+ toVersion: 6,
1550
1439
  appliesTo: "component-config",
1551
- apply: renameValues
1440
+ apply: renameKeysAndValues
1552
1441
  };
1553
1442
 
1554
- // src/editor/core/themes/migrations/2026-09-01-scrim-rename.ts
1555
- var RENAMED2 = {
1556
- "--overlay-low": "--scrim-low",
1557
- "--overlay": "--scrim",
1558
- "--overlay-high": "--scrim-high"
1559
- };
1560
- var RENAMED_COMPONENT_KEYS = {
1561
- "--dialog-overlay-surface": "--dialog-scrim-surface"
1443
+ // src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts
1444
+ function dropFrameSurface(rawVars, meta) {
1445
+ if (meta.component !== "collapsiblesection") return rawVars;
1446
+ const { "--collapsiblesection-container-frame-surface": _drop, ...rest } = rawVars;
1447
+ return rest;
1448
+ }
1449
+ var componentMigration_2026_05_19_collapsiblesectionDropFrameSurface = {
1450
+ id: "2026-05-19-collapsiblesection-drop-frame-surface",
1451
+ fromVersion: 6,
1452
+ toVersion: 7,
1453
+ appliesTo: "component-config",
1454
+ apply: dropFrameSurface
1562
1455
  };
1563
- var colorsAndTypeMigration_2026_09_01_scrimRename = {
1564
- id: "2026-09-01-scrim-rename-theme",
1565
- fromVersion: 5,
1566
- toVersion: 6,
1567
- appliesTo: "colors-and-type",
1568
- apply(rawVars) {
1456
+
1457
+ // src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts
1458
+ var FLAT_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-(angle|stop-[123]-(color|position))$/;
1459
+ var componentMigration_2026_05_19_sectiondividerRichGradient = {
1460
+ id: "2026-05-19-sectiondivider-rich-gradient",
1461
+ fromVersion: 7,
1462
+ toVersion: 8,
1463
+ appliesTo: "component-config",
1464
+ apply(rawVars, meta) {
1465
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1569
1466
  const out = {};
1570
1467
  for (const [key, value] of Object.entries(rawVars)) {
1571
- out[RENAMED2[key] ?? key] = value;
1468
+ if (FLAT_RE.test(key)) continue;
1469
+ out[key] = value;
1572
1470
  }
1573
1471
  return out;
1574
1472
  }
1575
1473
  };
1576
- var componentMigration_2026_09_01_scrimRename = {
1577
- id: "2026-09-01-scrim-rename-component",
1578
- fromVersion: 21,
1579
- toVersion: 22,
1474
+
1475
+ // src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts
1476
+ var VARIANTS2 = ["lg", "md", "sm"];
1477
+ var SUFFIX_RENAMES = [
1478
+ [/-title-border-width$/, "-title-outline-width"],
1479
+ [/-title-stroke-color$/, "-title-outline-color"],
1480
+ [
1481
+ /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-padding$/,
1482
+ "--sectiondivider-$1-spacing"
1483
+ ]
1484
+ ];
1485
+ function renameKeySuffix(key) {
1486
+ for (const [re, repl] of SUFFIX_RENAMES) {
1487
+ if (re.test(key)) return key.replace(re, repl);
1488
+ }
1489
+ return key;
1490
+ }
1491
+ function splitFamilyKey(key) {
1492
+ const m = key.match(/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-(.+)$/);
1493
+ if (!m) return null;
1494
+ return { family: m[1], suffix: m[2] };
1495
+ }
1496
+ var componentMigration_2026_05_20_sectiondividerSlimVariants = {
1497
+ id: "2026-05-20-sectiondivider-slim-variants",
1498
+ fromVersion: 8,
1499
+ toVersion: 9,
1580
1500
  appliesTo: "component-config",
1581
- apply(rawVars) {
1501
+ apply(rawVars, meta) {
1502
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1582
1503
  const out = {};
1583
- for (const [key, value] of Object.entries(rawVars)) {
1584
- out[RENAMED_COMPONENT_KEYS[key] ?? key] = RENAMED2[value] ?? value;
1504
+ const canvasValues = {};
1505
+ for (const [rawKey, value] of Object.entries(rawVars)) {
1506
+ const key = renameKeySuffix(rawKey);
1507
+ const parts = splitFamilyKey(key);
1508
+ if (!parts) {
1509
+ out[key] = value;
1510
+ continue;
1511
+ }
1512
+ if (parts.family !== "canvas") continue;
1513
+ canvasValues[parts.suffix] = value;
1514
+ }
1515
+ for (const suffix of Object.keys(canvasValues)) {
1516
+ for (const v of VARIANTS2) {
1517
+ out[`--sectiondivider-${v}-${suffix}`] = canvasValues[suffix];
1518
+ }
1585
1519
  }
1586
1520
  return out;
1587
1521
  }
1588
1522
  };
1589
1523
 
1590
- // src/editor/core/themes/migrations/2026-09-01-tint-rename.ts
1591
- var RENAMED3 = {
1592
- "--hover-low": "--tint-low",
1593
- "--hover": "--tint",
1594
- "--hover-high": "--tint-high"
1595
- };
1596
- var colorsAndTypeMigration_2026_09_01_tintRename = {
1597
- id: "2026-09-01-tint-rename-theme",
1598
- fromVersion: 6,
1599
- toVersion: 7,
1600
- appliesTo: "colors-and-type",
1601
- apply(rawVars) {
1524
+ // src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts
1525
+ var componentMigration_2026_05_21_sectiondividerSpacingToPadding = {
1526
+ id: "2026-05-21-sectiondivider-spacing-to-padding",
1527
+ fromVersion: 9,
1528
+ toVersion: 10,
1529
+ appliesTo: "component-config",
1530
+ apply(rawVars, meta) {
1531
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1602
1532
  const out = {};
1603
- for (const [key, value] of Object.entries(rawVars)) out[RENAMED3[key] ?? key] = value;
1533
+ for (const [key, value] of Object.entries(rawVars)) {
1534
+ const renamed = key.replace(
1535
+ /^--sectiondivider-(lg|md|sm)-spacing$/,
1536
+ "--sectiondivider-$1-padding"
1537
+ );
1538
+ out[renamed] = value;
1539
+ }
1604
1540
  return out;
1605
1541
  }
1606
1542
  };
1607
- var componentMigration_2026_09_01_tintRename = {
1608
- id: "2026-09-01-tint-rename-component",
1609
- fromVersion: 22,
1610
- toVersion: 23,
1543
+
1544
+ // src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts
1545
+ var componentMigration_2026_05_22_sectiondividerIntrinsicsToCss = {
1546
+ id: "2026-05-22-sectiondivider-intrinsics-to-css",
1547
+ fromVersion: 10,
1548
+ toVersion: 11,
1611
1549
  appliesTo: "component-config",
1612
- apply(rawVars) {
1550
+ apply(rawVars, meta) {
1551
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1552
+ const VARIANTS4 = ["lg", "md", "sm"];
1553
+ const prefix = "--sectiondivider-";
1554
+ const dropped = /* @__PURE__ */ new Set();
1555
+ for (const v of VARIANTS4) {
1556
+ dropped.add(`${prefix}${v}-show-eyebrow`);
1557
+ dropped.add(`${prefix}${v}-show-description`);
1558
+ dropped.add(`${prefix}${v}-show-hairline`);
1559
+ dropped.add(`${prefix}${v}-hairline`);
1560
+ dropped.add(`${prefix}${v}-eyebrow-uppercase`);
1561
+ }
1613
1562
  const out = {};
1614
- for (const [key, value] of Object.entries(rawVars)) out[key] = RENAMED3[value] ?? value;
1563
+ for (const [key, value] of Object.entries(rawVars)) {
1564
+ if (dropped.has(key)) continue;
1565
+ out[key] = value;
1566
+ }
1567
+ for (const v of VARIANTS4) {
1568
+ const showEyebrow = rawVars[`${prefix}${v}-show-eyebrow`];
1569
+ if (showEyebrow !== void 0) {
1570
+ out[`${prefix}${v}-eyebrow-display`] = showEyebrow === "1" ? "block" : "none";
1571
+ }
1572
+ const showDesc = rawVars[`${prefix}${v}-show-description`];
1573
+ if (showDesc !== void 0) {
1574
+ out[`${prefix}${v}-description-display`] = showDesc === "1" ? "flex" : "none";
1575
+ }
1576
+ const showHair = rawVars[`${prefix}${v}-show-hairline`];
1577
+ const oldHair = rawVars[`${prefix}${v}-hairline`];
1578
+ const oldHairIsPos = typeof oldHair === "string" && oldHair !== "" && oldHair !== "off";
1579
+ let newHair;
1580
+ if (showHair === "") newHair = "none";
1581
+ else if (showHair === "1") newHair = oldHairIsPos ? oldHair : "above-label";
1582
+ else if (oldHair !== void 0) newHair = oldHairIsPos ? oldHair : "none";
1583
+ if (newHair !== void 0) {
1584
+ out[`${prefix}${v}-hairline`] = newHair;
1585
+ }
1586
+ const upper = rawVars[`${prefix}${v}-eyebrow-uppercase`];
1587
+ if (upper !== void 0) {
1588
+ out[`${prefix}${v}-eyebrow-text-transform`] = upper === "1" ? "uppercase" : "none";
1589
+ }
1590
+ }
1615
1591
  return out;
1616
1592
  }
1617
1593
  };
1618
1594
 
1619
- // src/editor/core/themes/migrations/2026-09-01-tabbar-active-tint.ts
1620
- var componentMigration_2026_09_01_tabbarActiveTint = {
1621
- id: "2026-09-01-tabbar-active-tint",
1622
- fromVersion: 23,
1623
- toVersion: 24,
1595
+ // src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts
1596
+ var componentMigration_2026_05_24_segmentedcontrolDividerInset = {
1597
+ id: "2026-05-24-segmentedcontrol-divider-inset",
1598
+ fromVersion: 11,
1599
+ toVersion: 12,
1624
1600
  appliesTo: "component-config",
1625
1601
  apply(rawVars, meta) {
1626
- if (meta.component !== "tabbar") return { ...rawVars };
1627
- const out = { ...rawVars };
1628
- if (out["--tabbar-active-surface"] === "--scrim-low") {
1629
- out["--tabbar-active-surface"] = "--tint-low";
1602
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
1603
+ const out = {};
1604
+ for (const [key, value] of Object.entries(rawVars)) {
1605
+ if (key === "--segmentedcontrol-divider-height") continue;
1606
+ out[key] = value;
1630
1607
  }
1631
1608
  return out;
1632
1609
  }
1633
1610
  };
1634
1611
 
1635
- // src/editor/core/themes/migrations/2026-09-01-gate-suffix-enabled.ts
1636
- var RENAMED4 = {
1637
- "--card-hover-border-active": "--card-hover-border-enabled",
1638
- "--card-hover-shadow-active": "--card-hover-shadow-enabled",
1639
- "--image-zoom-hover": "--image-zoom-enabled",
1640
- "--image-grow-hover": "--image-grow-enabled"
1641
- };
1642
- var componentMigration_2026_09_01_gateSuffixEnabled = {
1643
- id: "2026-09-01-gate-suffix-enabled",
1644
- fromVersion: 24,
1645
- toVersion: 25,
1612
+ // src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts
1613
+ var BUTTON_VARIANTS = ["primary", "secondary", "outline", "success", "danger", "warning"];
1614
+ var BUTTON_STATES = ["hover", "disabled"];
1615
+ var BUTTON_PROPS = ["padding", "radius", "border-width"];
1616
+ var buttonDeadKeys = new Set(
1617
+ BUTTON_VARIANTS.flatMap(
1618
+ (v) => BUTTON_STATES.flatMap(
1619
+ (s) => BUTTON_PROPS.map((p) => `--button-${v}-${s}-${p}`)
1620
+ )
1621
+ )
1622
+ );
1623
+ var segmentedcontrolDeadKeys = /* @__PURE__ */ new Set([
1624
+ "--segmentedcontrol-selected-icon-size",
1625
+ "--segmentedcontrol-option-hover-icon-size",
1626
+ "--segmentedcontrol-disabled-icon-size"
1627
+ ]);
1628
+ var componentMigration_2026_05_24_promoteStateSharedTokens = {
1629
+ id: "2026-05-24-promote-state-shared-tokens",
1630
+ fromVersion: 12,
1631
+ toVersion: 13,
1646
1632
  appliesTo: "component-config",
1647
- apply(rawVars) {
1633
+ apply(rawVars, meta) {
1634
+ const dead = meta.component === "button" ? buttonDeadKeys : meta.component === "segmentedcontrol" ? segmentedcontrolDeadKeys : null;
1635
+ if (!dead) return { ...rawVars };
1648
1636
  const out = {};
1649
- for (const [key, value] of Object.entries(rawVars)) out[RENAMED4[key] ?? key] = value;
1637
+ for (const [key, value] of Object.entries(rawVars)) {
1638
+ if (dead.has(key)) continue;
1639
+ out[key] = value;
1640
+ }
1650
1641
  return out;
1651
1642
  }
1652
1643
  };
1653
1644
 
1654
- // src/editor/core/themes/migrations/2026-09-02-sectiondivider-drop-title-outline.ts
1655
- var DROPPED2 = new Set(
1656
- ["lg", "md", "sm"].flatMap((v) => [
1657
- `--sectiondivider-${v}-title-outline-width`,
1658
- `--sectiondivider-${v}-title-outline-color`
1659
- ])
1660
- );
1661
- var componentMigration_2026_09_02_sectiondividerDropTitleOutline = {
1662
- id: "2026-09-02-sectiondivider-drop-title-outline",
1663
- fromVersion: 25,
1664
- toVersion: 26,
1645
+ // src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts
1646
+ var PRIMARY_PREFIX = "--progressbar-primary-";
1647
+ var NEW_PREFIX = "--progressbar-";
1648
+ var DROP_PREFIXES = [
1649
+ "--progressbar-success-",
1650
+ "--progressbar-warning-",
1651
+ "--progressbar-danger-",
1652
+ "--progressbar-info-"
1653
+ ];
1654
+ var componentMigration_2026_05_24_progressbarCollapseVariants = {
1655
+ id: "2026-05-24-progressbar-collapse-variants",
1656
+ fromVersion: 13,
1657
+ toVersion: 14,
1665
1658
  appliesTo: "component-config",
1666
1659
  apply(rawVars, meta) {
1667
- if (meta.component !== "sectiondivider") return { ...rawVars };
1660
+ if (meta.component !== "progressbar") return { ...rawVars };
1668
1661
  const out = {};
1669
- for (const [key, value] of Object.entries(rawVars)) {
1670
- if (DROPPED2.has(key)) continue;
1671
- out[key] = value;
1662
+ for (const [oldKey, value] of Object.entries(rawVars)) {
1663
+ if (DROP_PREFIXES.some((p) => oldKey.startsWith(p))) continue;
1664
+ const key = oldKey.startsWith(PRIMARY_PREFIX) ? NEW_PREFIX + oldKey.slice(PRIMARY_PREFIX.length) : oldKey;
1665
+ if (!(key in out)) out[key] = value;
1672
1666
  }
1673
1667
  return out;
1674
1668
  }
1675
1669
  };
1676
1670
 
1677
- // src/editor/core/themes/migrations/index.ts
1678
- var MIGRATIONS = [
1679
- colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
1680
- colorsAndTypeMigration_2026_05_13_primaryToBrand,
1681
- componentMigration_2026_04_24_prefixAndSuffixRenames,
1682
- componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
1683
- componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
1684
- componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup,
1685
- componentMigration_2026_05_10_sectiondividerGradientStops,
1686
- componentMigration_2026_05_13_primaryToBrand,
1687
- componentMigration_2026_05_19_collapsiblesectionDropFrameSurface,
1688
- componentMigration_2026_05_19_sectiondividerRichGradient,
1689
- componentMigration_2026_05_20_sectiondividerSlimVariants,
1690
- componentMigration_2026_05_21_sectiondividerSpacingToPadding,
1691
- componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
1692
- componentMigration_2026_05_24_segmentedcontrolDividerInset,
1693
- componentMigration_2026_05_24_promoteStateSharedTokens,
1694
- componentMigration_2026_05_24_progressbarCollapseVariants,
1695
- componentMigration_2026_05_24_collapsiblesectionDropActiveState,
1696
- componentMigration_2026_05_25_cornerbadgeFlattenVariants,
1697
- colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
1698
- componentMigration_2026_05_26_dropOverlayExtraStops,
1699
- componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
1700
- componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
1701
- componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
1702
- colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
1703
- colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
1704
- componentMigration_2026_08_15_lineHeightScaleRename,
1705
- colorsAndTypeMigration_2026_09_01_scrimRename,
1706
- componentMigration_2026_09_01_scrimRename,
1707
- colorsAndTypeMigration_2026_09_01_tintRename,
1708
- componentMigration_2026_09_01_tintRename,
1709
- componentMigration_2026_09_01_tabbarActiveTint,
1710
- componentMigration_2026_09_01_gateSuffixEnabled,
1711
- componentMigration_2026_09_02_sectiondividerDropTitleOutline
1712
- ];
1713
- function countFor(kind) {
1714
- return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
1715
- }
1716
- var CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor("colors-and-type");
1717
- var CURRENT_COMPONENT_SCHEMA_VERSION = countFor("component-config");
1718
-
1719
- // src/editor/core/themes/generateColorsAndType.ts
1720
- var HEX_RE = /^#[0-9a-f]{6}$/i;
1721
- var HARMONY_MODES = [
1722
- "complementary",
1723
- "split-complementary",
1724
- "triadic",
1725
- "tetradic",
1726
- "compound",
1727
- "square",
1728
- "analogous",
1729
- "monochromatic",
1730
- "custom"
1731
- ];
1732
- var TEXT_SCALE = SCALES.find((s) => s.title === "Text");
1733
- var SURFACE_SCALE = SCALES.find((s) => s.title === "Surfaces");
1734
- var NEUTRAL_TEXT_FLOORS = [
1735
- ["primary", AA_BODY, 7],
1736
- ["secondary", AA_BODY, 5.5],
1737
- ["tertiary", AA_LARGE, 3.5]
1738
- ];
1739
- var FUNCTIONAL_TEXT_TARGET = 3.5;
1740
- var FUNCTIONAL_TEXT_LABELS = PALETTE_SPECS.filter((s) => s.label !== "Neutral" && s.label !== "Canvas").map((s) => s.label);
1741
- var norm = (h) => h >= 0 && h < 360 ? h : (h % 360 + 360) % 360;
1742
- function parseSeed(label, raw, problems) {
1743
- if (typeof raw === "string") {
1744
- if (!HEX_RE.test(raw.trim())) {
1745
- problems.push(`${label}: "${raw}" is not a #rrggbb hex color`);
1746
- return null;
1747
- }
1748
- return hexToOklch(raw.trim());
1671
+ // src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts
1672
+ function dropActiveState(rawVars, meta) {
1673
+ if (meta.component !== "collapsiblesection") return rawVars;
1674
+ const re = /^--collapsiblesection-(chromeless|divider|container)-active-/;
1675
+ const out = {};
1676
+ for (const [key, value] of Object.entries(rawVars)) {
1677
+ if (re.test(key)) continue;
1678
+ out[key] = value;
1749
1679
  }
1750
- const { l, c, h } = raw ?? {};
1751
- if (typeof l !== "number" || l <= 0 || l >= 1) problems.push(`${label}: l must be in (0, 1), got ${l}`);
1752
- if (typeof c !== "number" || c < 0 || c > 0.4) problems.push(`${label}: c must be in [0, 0.4], got ${c}`);
1753
- if (typeof h !== "number" || !Number.isFinite(h)) problems.push(`${label}: h must be a finite number, got ${h}`);
1754
- if (problems.length > 0) return null;
1755
- return { l, c, h: norm(h) };
1680
+ return out;
1756
1681
  }
1757
- function validateBrief(brief) {
1758
- const problems = [];
1759
- const name = typeof brief.name === "string" ? brief.name.trim() : "";
1760
- if (!name) problems.push("name: required");
1761
- const slug = sanitizeFileName(name || "unnamed");
1762
- if (slug === "default") problems.push('name: "default" is the protected package theme; pick another name');
1763
- if (brief.scheme !== "light" && brief.scheme !== "dark") {
1764
- problems.push(`scheme: must be "light" or "dark", got ${JSON.stringify(brief.scheme)}`);
1765
- }
1766
- if (brief.harmony && !HARMONY_MODES.includes(brief.harmony.mode)) {
1767
- problems.push(`harmony.mode: unknown mode ${JSON.stringify(brief.harmony.mode)}`);
1768
- }
1769
- if (brief.canvasGradient !== void 0 && typeof brief.canvasGradient !== "boolean") {
1770
- problems.push(`canvasGradient: must be a boolean, got ${JSON.stringify(brief.canvasGradient)}`);
1771
- }
1772
- const seeds = {};
1773
- const given = brief.seeds ?? {};
1774
- for (const spec of PALETTE_SPECS) {
1775
- if (!(spec.label in given)) {
1776
- problems.push(`seeds.${spec.label}: missing`);
1682
+ var componentMigration_2026_05_24_collapsiblesectionDropActiveState = {
1683
+ id: "2026-05-24-collapsiblesection-drop-active-state",
1684
+ fromVersion: 14,
1685
+ toVersion: 15,
1686
+ appliesTo: "component-config",
1687
+ apply: dropActiveState
1688
+ };
1689
+
1690
+ // src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts
1691
+ var VARIANTS3 = ["primary", "accent", "neutral", "alternate", "canvas", "special", "success", "warning", "danger", "info"];
1692
+ var RE = new RegExp(`^--corner-badge-(${VARIANTS3.join("|")})-(.+)$`);
1693
+ var CURRENT_COLOR_PROPS = /* @__PURE__ */ new Set(["surface", "border", "text"]);
1694
+ function flattenVariants(rawVars, meta) {
1695
+ if (meta.component !== "cornerbadge") return rawVars;
1696
+ const out = {};
1697
+ const collected = /* @__PURE__ */ new Map();
1698
+ for (const [key, value] of Object.entries(rawVars)) {
1699
+ const m = key.match(RE);
1700
+ if (m) {
1701
+ const prop = m[2];
1702
+ if (CURRENT_COLOR_PROPS.has(prop)) {
1703
+ out[key] = value;
1704
+ continue;
1705
+ }
1706
+ if (!collected.has(prop)) collected.set(prop, value);
1777
1707
  continue;
1778
1708
  }
1779
- const parsed = parseSeed(spec.label, given[spec.label], problems);
1780
- if (parsed) seeds[spec.label] = parsed;
1781
- }
1782
- const known = new Set(PALETTE_SPECS.map((s) => s.label));
1783
- for (const label of Object.keys(given)) {
1784
- if (!known.has(label)) problems.push(`seeds.${label}: unknown palette (expected ${[...known].join(", ")})`);
1709
+ out[key] = value;
1785
1710
  }
1786
- if (problems.length > 0) {
1787
- throw new Error(`Invalid theme brief:
1788
- ${problems.join("\n ")}`);
1711
+ for (const [prop, value] of collected) {
1712
+ const flatKey = `--corner-badge-${prop}`;
1713
+ if (!(flatKey in out)) out[flatKey] = value;
1789
1714
  }
1790
- return { seeds, slug };
1715
+ return out;
1791
1716
  }
1792
- function checkDefs() {
1793
- const defs = [];
1794
- for (const [stepName, floor, target] of NEUTRAL_TEXT_FLOORS) {
1795
- defs.push({
1796
- paletteLabel: "Neutral",
1797
- step: TEXT_SCALE.steps.find((s) => s.name === stepName),
1798
- textVar: scaleToCssVar("Text", stepName, "neutral"),
1799
- floor,
1800
- target
1801
- });
1717
+ var componentMigration_2026_05_25_cornerbadgeFlattenVariants = {
1718
+ id: "2026-05-25-cornerbadge-flatten-variants",
1719
+ fromVersion: 15,
1720
+ toVersion: 16,
1721
+ appliesTo: "component-config",
1722
+ apply: flattenVariants
1723
+ };
1724
+
1725
+ // src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts
1726
+ var DROPPED_TO_KEPT = {
1727
+ "--overlay-lowest": "--overlay-low",
1728
+ "--overlay-lower": "--overlay-low",
1729
+ "--overlay-higher": "--overlay-high",
1730
+ "--overlay-highest": "--overlay-high"
1731
+ };
1732
+ var colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops = {
1733
+ id: "2026-05-26-drop-overlay-extra-stops-theme",
1734
+ fromVersion: 2,
1735
+ toVersion: 3,
1736
+ appliesTo: "colors-and-type",
1737
+ apply(rawVars) {
1738
+ const out = {};
1739
+ for (const [key, value] of Object.entries(rawVars)) {
1740
+ if (key in DROPPED_TO_KEPT) continue;
1741
+ out[key] = value;
1742
+ }
1743
+ return out;
1802
1744
  }
1803
- const primary = TEXT_SCALE.steps.find((s) => s.name === "primary");
1804
- for (const label of FUNCTIONAL_TEXT_LABELS) {
1805
- const ns = PALETTE_SPECS.find((s) => s.label === label).cssNamespace;
1806
- defs.push({
1807
- paletteLabel: label,
1808
- step: primary,
1809
- textVar: scaleToCssVar("Text", "primary", ns),
1810
- floor: AA_LARGE,
1811
- target: FUNCTIONAL_TEXT_TARGET
1812
- });
1745
+ };
1746
+ var componentMigration_2026_05_26_dropOverlayExtraStops = {
1747
+ id: "2026-05-26-drop-overlay-extra-stops-component",
1748
+ fromVersion: 16,
1749
+ toVersion: 17,
1750
+ appliesTo: "component-config",
1751
+ apply(rawVars) {
1752
+ const out = {};
1753
+ for (const [key, value] of Object.entries(rawVars)) {
1754
+ out[key] = DROPPED_TO_KEPT[value] ?? value;
1755
+ }
1756
+ return out;
1813
1757
  }
1814
- return defs;
1815
- }
1816
- function surfaceVars() {
1817
- return [
1818
- ...SURFACE_SCALE.steps.map((s) => scaleToCssVar("Surfaces", s.name, "neutral")),
1819
- "--page-bg"
1820
- ];
1821
- }
1822
- function varToHex(value) {
1823
- const parsed = value ? cssColorToOklch(value) : null;
1824
- return parsed ? oklchToHexClamped(parsed.l, parsed.c, parsed.h) : null;
1825
- }
1826
- function worstSurface(textHex, vars) {
1827
- let against = "";
1828
- let ratio = Infinity;
1829
- for (const surfVar of surfaceVars()) {
1830
- const surfHex = varToHex(vars[surfVar]);
1831
- if (!surfHex) continue;
1832
- const r = contrastRatio(textHex, surfHex);
1833
- if (r < ratio) {
1834
- ratio = r;
1835
- against = surfVar;
1758
+ };
1759
+
1760
+ // src/editor/core/themes/migrations/2026-05-29-tabbar-indicator-thickness-to-per-state-width.ts
1761
+ var TABBAR_STATES = ["default", "hover", "active", "disabled"];
1762
+ var OLD_KEY = "--tabbar-bar-indicator-thickness";
1763
+ var FALLBACK = "--border-width-2";
1764
+ var componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth = {
1765
+ id: "2026-05-29-tabbar-indicator-thickness-to-per-state-width",
1766
+ fromVersion: 17,
1767
+ toVersion: 18,
1768
+ appliesTo: "component-config",
1769
+ apply(rawVars, meta) {
1770
+ if (meta.component !== "tabbar") return { ...rawVars };
1771
+ const seed = rawVars[OLD_KEY] ?? FALLBACK;
1772
+ const out = {};
1773
+ for (const [key, value] of Object.entries(rawVars)) {
1774
+ if (key === OLD_KEY) continue;
1775
+ out[key] = value;
1776
+ }
1777
+ for (const state of TABBAR_STATES) {
1778
+ const newKey = `--tabbar-${state}-indicator-border-width`;
1779
+ if (!(newKey in out)) out[newKey] = seed;
1836
1780
  }
1781
+ return out;
1837
1782
  }
1838
- return { against, ratio };
1839
- }
1840
- function pinTextStep(cfg, step, solved) {
1841
- const x = scaleStepToX(step, TEXT_SCALE);
1842
- const seed = cfg.baseColor;
1843
- const yL = Math.max(0, Math.min(200, solved.l / seed.l * 100));
1844
- cfg.scaleCurves.Text.lightness = setCurveAnchor(cfg.scaleCurves.Text.lightness, x, yL).curve;
1845
- if (seed.c > 0) {
1846
- const yC = Math.max(0, Math.min(200, solved.c / seed.c * 100));
1847
- cfg.scaleCurves.Text.saturation = setCurveAnchor(cfg.scaleCurves.Text.saturation, x, yC).curve;
1783
+ };
1784
+
1785
+ // src/editor/core/themes/migrations/2026-05-29-segmentedcontrol-small-divider-rename.ts
1786
+ var RENAMES = {
1787
+ "--segmentedcontrol-divider-small-thickness": "--segmentedcontrol-small-divider-thickness",
1788
+ "--segmentedcontrol-divider-small-inset": "--segmentedcontrol-small-divider-inset"
1789
+ };
1790
+ var componentMigration_2026_05_29_segmentedcontrolSmallDividerRename = {
1791
+ id: "2026-05-29-segmentedcontrol-small-divider-rename",
1792
+ fromVersion: 18,
1793
+ toVersion: 19,
1794
+ appliesTo: "component-config",
1795
+ apply(rawVars, meta) {
1796
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
1797
+ const out = {};
1798
+ for (const [key, value] of Object.entries(rawVars)) {
1799
+ out[RENAMES[key] ?? key] = value;
1800
+ }
1801
+ return out;
1848
1802
  }
1849
- }
1850
- var MAX_CORRECTION_ROUNDS = 3;
1851
- function runContrastGate(configs, scheme) {
1852
- const defs = checkDefs();
1853
- const direction = scheme === "light" ? "darker" : "lighter";
1854
- const corrected = /* @__PURE__ */ new Set();
1855
- for (let round = 0; round < MAX_CORRECTION_ROUNDS; round++) {
1856
- const vars = palettesToVars(configs);
1857
- let anyFixed = false;
1858
- for (const def of defs) {
1859
- const text = cssColorToOklch(vars[def.textVar] ?? "");
1860
- if (!text) continue;
1861
- const textHex = oklchToHexClamped(text.l, text.c, text.h);
1862
- const worst = worstSurface(textHex, vars);
1863
- if (worst.ratio >= def.floor) continue;
1864
- const cfg = configs[def.paletteLabel];
1865
- const seed = cfg.baseColor;
1866
- const solved = findLForContrast({
1867
- against: varToHex(vars[worst.against]) ?? "#000000",
1868
- ratio: def.target,
1869
- direction,
1870
- c: text.c,
1871
- h: seed.h,
1872
- lMax: Math.min(1, 2 * seed.l)
1873
- });
1874
- pinTextStep(cfg, def.step, solved);
1875
- corrected.add(def.textVar);
1876
- anyFixed = true;
1803
+ };
1804
+
1805
+ // src/editor/core/themes/migrations/2026-05-29-toggle-derive-track-from-thumb.ts
1806
+ var componentMigration_2026_05_29_toggleDeriveTrackFromThumb = {
1807
+ id: "2026-05-29-toggle-derive-track-from-thumb",
1808
+ fromVersion: 19,
1809
+ toVersion: 20,
1810
+ appliesTo: "component-config",
1811
+ apply(rawVars, meta) {
1812
+ if (meta.component !== "toggle") return { ...rawVars };
1813
+ const out = {};
1814
+ for (const [key, value] of Object.entries(rawVars)) {
1815
+ if (key === "--toggle-track-width" || key === "--toggle-track-thickness") continue;
1816
+ out[key] = value;
1877
1817
  }
1878
- if (!anyFixed) break;
1818
+ if (!("--toggle-track-padding" in out)) {
1819
+ out["--toggle-track-padding"] = "--space-2";
1820
+ }
1821
+ return out;
1879
1822
  }
1880
- const finalVars = palettesToVars(configs);
1881
- const checks = defs.map((def) => {
1882
- const worst = worstSurface(varToHex(finalVars[def.textVar]) ?? "#000000", finalVars);
1883
- return {
1884
- textVar: def.textVar,
1885
- floor: def.floor,
1886
- against: worst.against,
1887
- ratio: worst.ratio,
1888
- pass: worst.ratio >= def.floor,
1889
- corrected: corrected.has(def.textVar)
1890
- };
1891
- });
1892
- const failures = checks.filter((c) => !c.pass).map((c) => {
1893
- const label = defs.find((d) => d.textVar === c.textVar).paletteLabel;
1894
- 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`;
1895
- return `${c.textVar} reaches ${c.ratio.toFixed(2)}:1 vs ${c.against} (floor ${c.floor}:1) \u2014 ${hint}`;
1896
- });
1897
- return { scheme, checks, failures };
1898
- }
1899
- var ADJACENT_HUE_MAX = 120;
1900
- var hueDist = (a, b) => {
1901
- const d = Math.abs(norm(a) - norm(b));
1902
- return Math.min(d, 360 - d);
1903
1823
  };
1904
- var linear = (variable, angle, from, to) => ({
1905
- variable,
1906
- type: "linear",
1907
- angle,
1908
- stops: [{ position: 0, color: from }, { position: 100, color: to }]
1909
- });
1910
- function recipeGradients(seeds, scheme) {
1911
- return [
1912
- linear("--gradient-1", 90, "--color-brand-400", "--color-brand-700"),
1913
- 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"),
1914
- 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"),
1915
- scheme === "dark" ? linear("--gradient-4", 180, "--color-canvas-600", "--color-canvas-900") : linear("--gradient-4", 180, "--color-canvas-200", "--color-canvas-500")
1916
- ];
1917
- }
1918
- function isStockGradients(gradients) {
1919
- return !gradients || gradients.length === 0 || JSON.stringify(gradients) === JSON.stringify(makeDefaultGradients());
1920
- }
1921
- function applyCanvasGradient(canvas, scheme) {
1922
- const labels = PALETTE_STEPS.map((s) => s.label);
1923
- const anchor = canvas.anchorPlacement.step;
1924
- const sky = scheme === "dark" ? Math.min(anchor + 2, labels.length - 1) : Math.max(anchor - 2, 0);
1925
- if (sky === anchor) {
1926
- 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"}`;
1824
+
1825
+ // src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts
1826
+ var DROPPED = /* @__PURE__ */ new Set([
1827
+ "--badge-trait-radius",
1828
+ "--badge-trait-padding",
1829
+ "--sectiondivider-padding",
1830
+ "--dialog-primary-default-radius",
1831
+ "--dialog-primary-default-padding",
1832
+ "--dialog-primary-hover-radius",
1833
+ "--dialog-primary-hover-padding",
1834
+ "--dialog-secondary-default-radius",
1835
+ "--dialog-secondary-default-padding",
1836
+ "--dialog-secondary-hover-radius",
1837
+ "--dialog-secondary-hover-padding"
1838
+ ]);
1839
+ var colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys = {
1840
+ id: "2026-08-13-drop-legacy-shape-space-keys",
1841
+ fromVersion: 3,
1842
+ toVersion: 4,
1843
+ appliesTo: "colors-and-type",
1844
+ apply(rawVars) {
1845
+ const out = {};
1846
+ for (const [key, value] of Object.entries(rawVars)) {
1847
+ if (DROPPED.has(key)) continue;
1848
+ out[key] = value;
1849
+ }
1850
+ return out;
1927
1851
  }
1928
- canvas.emptyMode = "gradient";
1929
- canvas.gradientStyle = "linear";
1930
- canvas.gradientAngle = 180;
1931
- canvas.gradientReverse = false;
1932
- canvas.gradientStops = [
1933
- { position: 0, paletteLabel: labels[sky] },
1934
- { position: 100, paletteLabel: labels[anchor] }
1935
- ];
1936
- canvas.gradientSize = "window";
1937
- return `on, ${labels[sky]} \u2192 ${labels[anchor]}`;
1938
- }
1939
- var STOCK_SHADOW_GEOMETRY = {
1940
- "--shadow-sm": [1, 1, 2],
1941
- "--shadow-md": [3, 3, 6],
1942
- "--shadow-lg": [5, 5, 9],
1943
- "--shadow-xl": [6, 7, 13],
1944
- "--shadow-2xl": [8, 9, 16]
1945
1852
  };
1946
- var STOCK_SHADOW_COLOR = { spread: 0, hue: 237, saturation: 18, lightness: 3, opacity: 0.9 };
1947
- var SHADOW_OPACITY_DEEP = 0.9;
1948
- var SHADOW_OPACITY_SOFT = 0.2;
1949
- var SHADOW_GROUND_DEEP = 0.5;
1950
- var SHADOW_GROUND_SOFT = 0.9;
1951
- function shadowOpacityForCanvas(canvasL) {
1952
- const t = (canvasL - SHADOW_GROUND_DEEP) / (SHADOW_GROUND_SOFT - SHADOW_GROUND_DEEP);
1953
- const ramp = Math.max(0, Math.min(1, t));
1954
- const opacity = SHADOW_OPACITY_DEEP + ramp * (SHADOW_OPACITY_SOFT - SHADOW_OPACITY_DEEP);
1955
- return Math.round(opacity * 100) / 100;
1956
- }
1957
- function shadowVars(carried, canvas) {
1958
- const opacity = shadowOpacityForCanvas(canvas.l);
1853
+
1854
+ // src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts
1855
+ var RENAMED = {
1856
+ "--line-height-xs": "--line-height-none",
1857
+ "--line-height-sm": "--line-height-tighter",
1858
+ "--line-height-md": "--line-height-normal",
1859
+ "--line-height-lg": "--line-height-relaxed",
1860
+ "--line-height-xl": "--line-height-relaxed"
1861
+ };
1862
+ var REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
1863
+ function renameValues(rawVars) {
1959
1864
  const out = {};
1960
- for (const variable of SHADOW_VAR_NAMES) {
1961
- const [x, y, blur] = STOCK_SHADOW_GEOMETRY[variable];
1962
- const base = parseShadowCss(variable, carried[variable] ?? "") ?? { x, y, blur, ...STOCK_SHADOW_COLOR };
1963
- out[variable] = shadowTokenCss({ ...base, opacity });
1865
+ for (const [key, value] of Object.entries(rawVars)) {
1866
+ out[key] = typeof value === "string" ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
1964
1867
  }
1965
1868
  return out;
1966
1869
  }
1967
- function buildColorsAndTypeFromSeeds(brief, carry = {}, now = (/* @__PURE__ */ new Date()).toISOString()) {
1968
- const { seeds, slug } = validateBrief(brief);
1969
- const configs = {};
1970
- for (const spec of PALETTE_SPECS) {
1971
- configs[spec.label] = defaultPaletteConfig({
1972
- baseColor: seeds[spec.label],
1973
- neutral: spec.neutral,
1974
- scheme: brief.scheme
1975
- });
1870
+ var colorsAndTypeMigration_2026_08_15_lineHeightScaleRename = {
1871
+ id: "2026-08-15-line-height-scale-rename-colors-and-type",
1872
+ fromVersion: 4,
1873
+ toVersion: 5,
1874
+ appliesTo: "colors-and-type",
1875
+ apply: renameValues
1876
+ };
1877
+ var componentMigration_2026_08_15_lineHeightScaleRename = {
1878
+ id: "2026-08-15-line-height-scale-rename-component",
1879
+ fromVersion: 20,
1880
+ toVersion: 21,
1881
+ appliesTo: "component-config",
1882
+ apply: renameValues
1883
+ };
1884
+
1885
+ // src/editor/core/themes/migrations/2026-09-01-scrim-rename.ts
1886
+ var RENAMED2 = {
1887
+ "--overlay-low": "--scrim-low",
1888
+ "--overlay": "--scrim",
1889
+ "--overlay-high": "--scrim-high"
1890
+ };
1891
+ var RENAMED_COMPONENT_KEYS = {
1892
+ "--dialog-overlay-surface": "--dialog-scrim-surface"
1893
+ };
1894
+ var colorsAndTypeMigration_2026_09_01_scrimRename = {
1895
+ id: "2026-09-01-scrim-rename-theme",
1896
+ fromVersion: 5,
1897
+ toVersion: 6,
1898
+ appliesTo: "colors-and-type",
1899
+ apply(rawVars) {
1900
+ const out = {};
1901
+ for (const [key, value] of Object.entries(rawVars)) {
1902
+ out[RENAMED2[key] ?? key] = value;
1903
+ }
1904
+ return out;
1976
1905
  }
1977
- const report = runContrastGate(configs, brief.scheme);
1978
- const canvasGradient = brief.canvasGradient ? applyCanvasGradient(configs.Canvas, brief.scheme) : void 0;
1979
- const gradients = isStockGradients(carry.gradients) ? recipeGradients(seeds, brief.scheme) : carry.gradients;
1980
- const harmonyAxes = [
1981
- { hue: norm(seeds.Brand.h), family: "Brand" },
1982
- { hue: norm(seeds.Accent.h), family: "Accent" },
1983
- { hue: norm(seeds.Canvas.h), family: "Canvas" },
1984
- { hue: norm(seeds.Brand.h + 270), family: null }
1985
- ];
1986
- const owned = new Set(Object.keys(palettesToVars(configs)));
1987
- const cssVariables = Object.fromEntries(
1988
- Object.entries(carry.cssVariables ?? {}).filter(([k]) => !owned.has(k))
1989
- );
1990
- for (const t of gradients) cssVariables[t.variable] = formatGradientValue(t);
1991
- Object.assign(cssVariables, shadowVars(carry.cssVariables ?? {}, seeds.Canvas));
1992
- const colorsAndType = {
1993
- name: brief.name.trim(),
1994
- createdAt: now,
1995
- updatedAt: now,
1996
- editorConfigs: configs,
1997
- cssVariables,
1998
- fontSources: carry.fontSources ?? [],
1999
- fontStacks: carry.fontStacks ?? [],
2000
- gradients,
2001
- harmonyAxes,
2002
- schemaVersion: CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION
2003
- };
2004
- return {
2005
- colorsAndType,
2006
- slug,
2007
- report: {
2008
- ...report,
2009
- gradients: gradients === carry.gradients ? "carried" : "recipes",
2010
- shadows: `opacity ${shadowOpacityForCanvas(seeds.Canvas.l)} for a canvas at L ${seeds.Canvas.l.toFixed(2)}`,
2011
- ...canvasGradient ? { canvasGradient } : {}
1906
+ };
1907
+ var componentMigration_2026_09_01_scrimRename = {
1908
+ id: "2026-09-01-scrim-rename-component",
1909
+ fromVersion: 21,
1910
+ toVersion: 22,
1911
+ appliesTo: "component-config",
1912
+ apply(rawVars) {
1913
+ const out = {};
1914
+ for (const [key, value] of Object.entries(rawVars)) {
1915
+ out[RENAMED_COMPONENT_KEYS[key] ?? key] = RENAMED2[value] ?? value;
2012
1916
  }
2013
- };
2014
- }
1917
+ return out;
1918
+ }
1919
+ };
2015
1920
 
2016
- // vite-plugin/files/dataPaths.ts
2017
- var import_fs = __toESM(require("fs"), 1);
2018
- var import_path = __toESM(require("path"), 1);
2019
- var DEFAULT_DATA_DIR = "src/live-tokens/data";
2020
- var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
2021
- "dataDir",
2022
- "colorsAndTypeDir",
2023
- "componentConfigsDir",
2024
- "themesDir",
2025
- "manifestsDir",
2026
- "tokensCssPath",
2027
- "componentDirs",
2028
- "checks"
1921
+ // src/editor/core/themes/migrations/2026-09-01-tint-rename.ts
1922
+ var RENAMED3 = {
1923
+ "--hover-low": "--tint-low",
1924
+ "--hover": "--tint",
1925
+ "--hover-high": "--tint-high"
1926
+ };
1927
+ var colorsAndTypeMigration_2026_09_01_tintRename = {
1928
+ id: "2026-09-01-tint-rename-theme",
1929
+ fromVersion: 6,
1930
+ toVersion: 7,
1931
+ appliesTo: "colors-and-type",
1932
+ apply(rawVars) {
1933
+ const out = {};
1934
+ for (const [key, value] of Object.entries(rawVars)) out[RENAMED3[key] ?? key] = value;
1935
+ return out;
1936
+ }
1937
+ };
1938
+ var componentMigration_2026_09_01_tintRename = {
1939
+ id: "2026-09-01-tint-rename-component",
1940
+ fromVersion: 22,
1941
+ toVersion: 23,
1942
+ appliesTo: "component-config",
1943
+ apply(rawVars) {
1944
+ const out = {};
1945
+ for (const [key, value] of Object.entries(rawVars)) out[key] = RENAMED3[value] ?? value;
1946
+ return out;
1947
+ }
1948
+ };
1949
+
1950
+ // src/editor/core/themes/migrations/2026-09-01-tabbar-active-tint.ts
1951
+ var componentMigration_2026_09_01_tabbarActiveTint = {
1952
+ id: "2026-09-01-tabbar-active-tint",
1953
+ fromVersion: 23,
1954
+ toVersion: 24,
1955
+ appliesTo: "component-config",
1956
+ apply(rawVars, meta) {
1957
+ if (meta.component !== "tabbar") return { ...rawVars };
1958
+ const out = { ...rawVars };
1959
+ if (out["--tabbar-active-surface"] === "--scrim-low") {
1960
+ out["--tabbar-active-surface"] = "--tint-low";
1961
+ }
1962
+ return out;
1963
+ }
1964
+ };
1965
+
1966
+ // src/editor/core/themes/migrations/2026-09-01-gate-suffix-enabled.ts
1967
+ var RENAMED4 = {
1968
+ "--card-hover-border-active": "--card-hover-border-enabled",
1969
+ "--card-hover-shadow-active": "--card-hover-shadow-enabled",
1970
+ "--image-zoom-hover": "--image-zoom-enabled",
1971
+ "--image-grow-hover": "--image-grow-enabled"
1972
+ };
1973
+ var componentMigration_2026_09_01_gateSuffixEnabled = {
1974
+ id: "2026-09-01-gate-suffix-enabled",
1975
+ fromVersion: 24,
1976
+ toVersion: 25,
1977
+ appliesTo: "component-config",
1978
+ apply(rawVars) {
1979
+ const out = {};
1980
+ for (const [key, value] of Object.entries(rawVars)) out[RENAMED4[key] ?? key] = value;
1981
+ return out;
1982
+ }
1983
+ };
1984
+
1985
+ // src/editor/core/themes/migrations/2026-09-02-sectiondivider-drop-title-outline.ts
1986
+ var DROPPED2 = new Set(
1987
+ ["lg", "md", "sm"].flatMap((v) => [
1988
+ `--sectiondivider-${v}-title-outline-width`,
1989
+ `--sectiondivider-${v}-title-outline-color`
1990
+ ])
1991
+ );
1992
+ var componentMigration_2026_09_02_sectiondividerDropTitleOutline = {
1993
+ id: "2026-09-02-sectiondivider-drop-title-outline",
1994
+ fromVersion: 25,
1995
+ toVersion: 26,
1996
+ appliesTo: "component-config",
1997
+ apply(rawVars, meta) {
1998
+ if (meta.component !== "sectiondivider") return { ...rawVars };
1999
+ const out = {};
2000
+ for (const [key, value] of Object.entries(rawVars)) {
2001
+ if (DROPPED2.has(key)) continue;
2002
+ out[key] = value;
2003
+ }
2004
+ return out;
2005
+ }
2006
+ };
2007
+
2008
+ // src/editor/core/themes/migrations/2026-09-03-drop-legacy-component-keys.ts
2009
+ var DROPPED3 = /* @__PURE__ */ new Set([
2010
+ "--badge-trait-surface",
2011
+ "--badge-trait-text",
2012
+ "--badge-trait-text-font-family",
2013
+ "--badge-trait-text-font-size",
2014
+ "--badge-trait-text-font-weight",
2015
+ "--badge-trait-text-line-height",
2016
+ "--badge-trait-border",
2017
+ "--badge-trait-border-width",
2018
+ "--badge-trait-shadow",
2019
+ "--sectiondivider-title",
2020
+ "--sectiondivider-title-font-family",
2021
+ "--sectiondivider-title-font-size",
2022
+ "--sectiondivider-title-font-weight",
2023
+ "--sectiondivider-title-line-height",
2024
+ "--sectiondivider-title-border-width",
2025
+ "--sectiondivider-title-stroke-color",
2026
+ "--sectiondivider-description",
2027
+ "--sectiondivider-description-font-family",
2028
+ "--sectiondivider-description-font-size",
2029
+ "--sectiondivider-description-font-weight",
2030
+ "--sectiondivider-description-line-height",
2031
+ "--dialog-primary-default-surface",
2032
+ "--dialog-primary-default-text",
2033
+ "--dialog-primary-default-border",
2034
+ "--dialog-primary-default-border-width",
2035
+ "--dialog-primary-hover-surface",
2036
+ "--dialog-primary-hover-text",
2037
+ "--dialog-primary-hover-border",
2038
+ "--dialog-primary-hover-border-width",
2039
+ "--dialog-secondary-default-text",
2040
+ "--dialog-secondary-default-border",
2041
+ "--dialog-secondary-default-border-width",
2042
+ "--dialog-secondary-hover-surface",
2043
+ "--dialog-secondary-hover-text",
2044
+ "--dialog-secondary-hover-border",
2045
+ "--dialog-secondary-hover-border-width"
2029
2046
  ]);
2030
- var cached = null;
2031
- function readLiveTokensConfig() {
2032
- if (cached) return cached;
2033
- try {
2034
- const configPath = import_path.default.resolve("live-tokens.config.json");
2035
- if (!import_fs.default.existsSync(configPath)) return cached = {};
2036
- const parsed = JSON.parse(import_fs.default.readFileSync(configPath, "utf-8"));
2037
- if (!parsed || typeof parsed !== "object") return cached = {};
2038
- const unknown = Object.keys(parsed).filter(
2039
- (k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
2040
- );
2041
- if (unknown.length > 0) {
2042
- console.warn(
2043
- `[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
2044
- );
2047
+ var colorsAndTypeMigration_2026_09_03_dropLegacyComponentKeys = {
2048
+ id: "2026-09-03-drop-legacy-component-keys",
2049
+ fromVersion: 7,
2050
+ toVersion: 8,
2051
+ appliesTo: "colors-and-type",
2052
+ apply(rawVars) {
2053
+ const out = {};
2054
+ for (const [key, value] of Object.entries(rawVars)) {
2055
+ if (DROPPED3.has(key)) continue;
2056
+ out[key] = value;
2045
2057
  }
2046
- cached = parsed;
2047
- return cached;
2048
- } catch {
2049
- return cached = {};
2058
+ return out;
2050
2059
  }
2060
+ };
2061
+
2062
+ // src/editor/core/themes/migrations/index.ts
2063
+ var MIGRATIONS = [
2064
+ colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
2065
+ colorsAndTypeMigration_2026_05_13_primaryToBrand,
2066
+ componentMigration_2026_04_24_prefixAndSuffixRenames,
2067
+ componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
2068
+ componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
2069
+ componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup,
2070
+ componentMigration_2026_05_10_sectiondividerGradientStops,
2071
+ componentMigration_2026_05_13_primaryToBrand,
2072
+ componentMigration_2026_05_19_collapsiblesectionDropFrameSurface,
2073
+ componentMigration_2026_05_19_sectiondividerRichGradient,
2074
+ componentMigration_2026_05_20_sectiondividerSlimVariants,
2075
+ componentMigration_2026_05_21_sectiondividerSpacingToPadding,
2076
+ componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
2077
+ componentMigration_2026_05_24_segmentedcontrolDividerInset,
2078
+ componentMigration_2026_05_24_promoteStateSharedTokens,
2079
+ componentMigration_2026_05_24_progressbarCollapseVariants,
2080
+ componentMigration_2026_05_24_collapsiblesectionDropActiveState,
2081
+ componentMigration_2026_05_25_cornerbadgeFlattenVariants,
2082
+ colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
2083
+ componentMigration_2026_05_26_dropOverlayExtraStops,
2084
+ componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
2085
+ componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
2086
+ componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
2087
+ colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
2088
+ colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
2089
+ componentMigration_2026_08_15_lineHeightScaleRename,
2090
+ colorsAndTypeMigration_2026_09_01_scrimRename,
2091
+ componentMigration_2026_09_01_scrimRename,
2092
+ colorsAndTypeMigration_2026_09_01_tintRename,
2093
+ componentMigration_2026_09_01_tintRename,
2094
+ componentMigration_2026_09_01_tabbarActiveTint,
2095
+ componentMigration_2026_09_01_gateSuffixEnabled,
2096
+ componentMigration_2026_09_02_sectiondividerDropTitleOutline,
2097
+ colorsAndTypeMigration_2026_09_03_dropLegacyComponentKeys
2098
+ ];
2099
+ function countFor(kind) {
2100
+ return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
2051
2101
  }
2052
- function resolveDataDirs(opts = {}) {
2053
- const fileConfig = readLiveTokensConfig();
2054
- const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
2055
- const dataDir = import_path.default.resolve(dataDirRaw);
2056
- const sub = (name) => import_path.default.resolve(dataDir, name);
2057
- return {
2058
- dataDir,
2059
- colorsAndTypeDir: opts.colorsAndTypeDir ? import_path.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
2060
- componentConfigsDir: opts.componentConfigsDir ? import_path.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
2061
- themesDir: opts.themesDir ? import_path.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path.default.resolve(fileConfig.themesDir) : sub("themes"),
2062
- sketchStylesDir: sub("sketch-styles"),
2063
- legacyManifestsDir: fileConfig.manifestsDir ? import_path.default.resolve(fileConfig.manifestsDir) : void 0
2064
- };
2065
- }
2102
+ var CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor("colors-and-type");
2103
+ var CURRENT_COMPONENT_SCHEMA_VERSION = countFor("component-config");
2066
2104
  // Annotate the CommonJS export names for ESM import in node:
2067
2105
  0 && (module.exports = {
2068
2106
  CURRENT_COMPONENT_SCHEMA_VERSION,
2069
- buildColorsAndTypeFromSeeds,
2107
+ buildColors,
2070
2108
  readLiveTokensConfig,
2071
2109
  resolveDataDirs,
2072
2110
  sanitizeFileName