@motion-proto/live-tokens 0.62.0 → 0.64.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 (71) hide show
  1. package/.claude/skills/live-tokens-adjust-geometry/SKILL.md +4 -4
  2. package/.claude/skills/live-tokens-build-page/SKILL.md +21 -3
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +16 -48
  4. package/.claude/skills/live-tokens-create-component/references/fixed-overlays.md +10 -1
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +7 -5
  6. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +1 -1
  7. package/.claude/skills/live-tokens-create-component/references/token-naming.md +50 -0
  8. package/.claude/skills/live-tokens-generate-theme/SKILL.md +16 -9
  9. package/.claude/skills/live-tokens-pair-fonts/SKILL.md +8 -6
  10. package/.claude/skills/live-tokens-pick-component/SKILL.md +19 -5
  11. package/CHANGELOG.md +100 -0
  12. package/bin/migrate.mjs +6 -2
  13. package/dist-plugin/adjust/index.cjs +1 -1
  14. package/dist-plugin/adjust/index.d.cts +1 -1
  15. package/dist-plugin/adjust/index.d.ts +1 -1
  16. package/dist-plugin/adjust/index.js +1 -1
  17. package/dist-plugin/{chunk-232GZGQU.js → chunk-NDJJORKJ.js} +342 -5
  18. package/dist-plugin/{chunk-Y5CNFSSV.js → chunk-RVE3MNKM.js} +1 -1
  19. package/dist-plugin/{chunk-OPYOK2CA.js → chunk-ZHPX7ZYQ.js} +39 -1
  20. package/dist-plugin/{dataPaths-CRfD1LdA.d.ts → dataPaths-DZUzVv8H.d.cts} +3 -3
  21. package/dist-plugin/{dataPaths-CRfD1LdA.d.cts → dataPaths-DZUzVv8H.d.ts} +3 -3
  22. package/dist-plugin/fontPairing/index.cjs +32 -8
  23. package/dist-plugin/fontPairing/index.d.cts +1 -1
  24. package/dist-plugin/fontPairing/index.d.ts +1 -1
  25. package/dist-plugin/fontPairing/index.js +32 -8
  26. package/dist-plugin/generateColorsAndType/index.cjs +1 -1
  27. package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
  28. package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
  29. package/dist-plugin/generateColorsAndType/index.js +1 -1
  30. package/dist-plugin/index.cjs +417 -34
  31. package/dist-plugin/index.d.cts +1 -1
  32. package/dist-plugin/index.d.ts +1 -1
  33. package/dist-plugin/index.js +31 -23
  34. package/dist-plugin/migrateData/index.cjs +350 -9
  35. package/dist-plugin/migrateData/index.d.cts +1 -1
  36. package/dist-plugin/migrateData/index.d.ts +1 -1
  37. package/dist-plugin/migrateData/index.js +9 -5
  38. package/dist-plugin/tokensCssMigrations/index.cjs +39 -1
  39. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  40. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  41. package/dist-plugin/tokensCssMigrations/index.js +2 -2
  42. package/package.json +9 -2
  43. package/src/app/site.css +16 -0
  44. package/src/editor/core/fonts/googleFontsUrl.ts +44 -8
  45. package/src/editor/core/preview/lookPreview.ts +46 -5
  46. package/src/editor/core/productionPulse.ts +6 -2
  47. package/src/editor/core/sketch/index.ts +60 -0
  48. package/src/editor/core/sketch/maskField.ts +5 -5
  49. package/src/editor/core/sketch/sketchLayer.ts +19 -8
  50. package/src/editor/core/sketch/sketchStore.ts +238 -85
  51. package/src/editor/core/sketch/{sketchPresetService.ts → sketchStyleService.ts} +14 -14
  52. package/src/editor/core/sketch/{sketchPresets.ts → sketchStyles.ts} +17 -17
  53. package/src/editor/core/themes/themeDocumentSync.ts +2 -0
  54. package/src/editor/core/themes/themeInit.ts +19 -1
  55. package/src/editor/core/themes/themeService.ts +7 -2
  56. package/src/editor/core/themes/themeTypes.ts +5 -0
  57. package/src/editor/docs/content/editing-tokens.md +1 -1
  58. package/src/editor/docs/content/sketch-mode.md +27 -16
  59. package/src/editor/docs/content/themes-workflow.md +30 -21
  60. package/src/editor/docs/content/where-themes-live.md +9 -5
  61. package/src/editor/docs/content.generated.ts +4 -4
  62. package/src/editor/overlay/LiveTokensRouter.svelte +1 -1
  63. package/src/editor/ui/EditorViewSwitcher.svelte +3 -3
  64. package/src/editor/ui/FontStackEditor.svelte +49 -11
  65. package/src/editor/ui/ProjectFontsSection.svelte +6 -0
  66. package/src/editor/ui/ThemePanel.svelte +47 -1
  67. package/src/editor/ui/sections/textStyles.ts +15 -1
  68. package/src/editor/ui/sketch/SketchPreview.svelte +3 -3
  69. package/src/editor/ui/sketch/SketchTab.svelte +87 -53
  70. package/src/system/components/FloatingTokenTags.css +10 -8
  71. package/src/system/styles/tokens.css +17 -2
@@ -1927,7 +1927,7 @@ function resolveDataDirs(opts = {}) {
1927
1927
  colorsAndTypeDir: opts.colorsAndTypeDir ? import_path.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
1928
1928
  componentConfigsDir: opts.componentConfigsDir ? import_path.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
1929
1929
  themesDir: opts.themesDir ? import_path.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path.default.resolve(fileConfig.themesDir) : sub("themes"),
1930
- sketchPresetsDir: sub("sketch-presets"),
1930
+ sketchStylesDir: sub("sketch-styles"),
1931
1931
  legacyManifestsDir: fileConfig.manifestsDir ? import_path.default.resolve(fileConfig.manifestsDir) : void 0
1932
1932
  };
1933
1933
  }
@@ -1,5 +1,5 @@
1
1
  import { F as FontSource, b as FontStack, G as GradientDiskToken, O as Oklch, H as HarmonyMode, C as ColorsAndType } from '../themeTypes-DSV3Zisf.cjs';
2
- export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-CRfD1LdA.cjs';
2
+ export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.cjs';
3
3
  export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.cjs';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { F as FontSource, b as FontStack, G as GradientDiskToken, O as Oklch, H as HarmonyMode, C as ColorsAndType } from '../themeTypes-DSV3Zisf.js';
2
- export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-CRfD1LdA.js';
2
+ export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.js';
3
3
  export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.js';
4
4
 
5
5
  /**
@@ -30,7 +30,7 @@ import {
30
30
  import {
31
31
  readLiveTokensConfig,
32
32
  resolveDataDirs
33
- } from "../chunk-Y5CNFSSV.js";
33
+ } from "../chunk-RVE3MNKM.js";
34
34
 
35
35
  // src/editor/core/store/editorCore.ts
36
36
  import { writable, derived, get } from "svelte/store";
@@ -95,8 +95,8 @@ function formatRadialShape(v) {
95
95
  if (ax === 1 && ay === 1) {
96
96
  return v.radius && v.radius > 0 ? `circle ${v.radius}px` : "circle";
97
97
  }
98
- const base = v.radius && v.radius > 0 ? v.radius : RADIAL_BASE_PX;
99
- return `ellipse ${(base * ax).toFixed(2)}px ${(base * ay).toFixed(2)}px`;
98
+ const base2 = v.radius && v.radius > 0 ? v.radius : RADIAL_BASE_PX;
99
+ return `ellipse ${(base2 * ax).toFixed(2)}px ${(base2 * ay).toFixed(2)}px`;
100
100
  }
101
101
  function formatGradientValue(v) {
102
102
  if (v.type === "none") return "transparent";
@@ -486,14 +486,14 @@ function scaleStepToX(step, scale) {
486
486
  function serializeDerivedValue(value) {
487
487
  return value.kind === "raw" ? value.css : oklchToCss(value.l, value.c, value.h);
488
488
  }
489
- function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset, hueCurve) {
490
- const { c: baseC } = base;
489
+ function computePaletteOklch(index, base2, lightnessCurve, saturationCurve, curveOffset, hueCurve) {
490
+ const { c: baseC } = base2;
491
491
  const xPos = stepIndexToX(index);
492
492
  const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset.lightness ?? 0))) / 100;
493
493
  const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset.saturation ?? 0)) / 100));
494
494
  const targetC = baseC * satMul;
495
495
  const hueDelta = (hueCurve ? sampleCurve(hueCurve, xPos) : 0) + (curveOffset.hue ?? 0);
496
- const h = hueDelta === 0 ? base.h : wrapHue(base.h + hueDelta);
496
+ const h = hueDelta === 0 ? base2.h : wrapHue(base2.h + hueDelta);
497
497
  return gamutClamp(targetL, targetC, h);
498
498
  }
499
499
  function nearestPaletteStep(lightnessCurve, baseL) {
@@ -617,7 +617,7 @@ function syncBaseAnchor(cfg) {
617
617
  priorHueEndpoints: h ? prev?.priorHueEndpoints ?? h.priorEndpoints : void 0
618
618
  };
619
619
  }
620
- function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
620
+ function computeDerivedOklch(step, base2, scaleTitle, scaleCurves, curveOffset) {
621
621
  const scale = SCALES.find((s) => s.title === scaleTitle);
622
622
  const xPos = scaleStepToX(step, scale);
623
623
  const defs = defaultScaleCurves[scaleTitle];
@@ -627,7 +627,7 @@ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
627
627
  const lOff = curveOffset[`${scaleTitle}-lightness`] ?? 0;
628
628
  const sOff = curveOffset[`${scaleTitle}-saturation`] ?? 0;
629
629
  const hOff = curveOffset[`${scaleTitle}-hue`] ?? 0;
630
- const { l: baseL, c: baseC, h: baseH } = base;
630
+ const { l: baseL, c: baseC, h: baseH } = base2;
631
631
  let targetL;
632
632
  if (scale.isText) {
633
633
  const lMul = Math.max(0, Math.min(2, (sampleCurve(lCurve, xPos) + lOff) / 100));
@@ -1904,6 +1904,340 @@ var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
1904
1904
  "--sectiondivider-sm-color-family"
1905
1905
  ]);
1906
1906
 
1907
+ // src/editor/core/sketch/sketchStyles.ts
1908
+ var base = {
1909
+ label: "",
1910
+ blurb: "",
1911
+ fillTravel: 1.5,
1912
+ strokeTravel: 1.5,
1913
+ wobble: 45,
1914
+ roughness: 3,
1915
+ borderWavelength: 1,
1916
+ waveform: 1,
1917
+ strokeWidth: 1.5,
1918
+ doubleStroke: false,
1919
+ retraceOffset: 1.2,
1920
+ retracePass: "copy",
1921
+ fillStyle: "solid",
1922
+ hatchInk: 0.4,
1923
+ strokeStyle: "solid",
1924
+ pressure: 0.25,
1925
+ pressureMod: 0.35,
1926
+ pooling: 1.2,
1927
+ strokeInk: 1,
1928
+ maskOn: true,
1929
+ maskBlob: 100,
1930
+ maskOutputMin: 0.45,
1931
+ maskOutputMax: 1,
1932
+ maskOctaves: 2,
1933
+ maskGrain: "fractal",
1934
+ maskPosterize: 1,
1935
+ maskSoftness: 1.5,
1936
+ jitterX: 2.5,
1937
+ jitterY: 2.5,
1938
+ jitterRot: 0.6,
1939
+ jitterScale: 0.035,
1940
+ cornerSpread: 10,
1941
+ cornerTravel: 8,
1942
+ iconTravel: 1.25,
1943
+ iconWavelength: 0.625,
1944
+ iconMaskOn: true,
1945
+ iconMaskScale: 1
1946
+ };
1947
+ var SKETCH_STYLES = {
1948
+ pencil: {
1949
+ ...base,
1950
+ label: "Pencil",
1951
+ blurb: "Two graphite passes on their own seeds, so the outline disagrees with itself the way a hand coming back round does. Tight grain, little else.",
1952
+ fillTravel: 0.75,
1953
+ strokeTravel: 1.25,
1954
+ wobble: 30,
1955
+ roughness: 3,
1956
+ waveform: 1,
1957
+ strokeWidth: 1.25,
1958
+ doubleStroke: true,
1959
+ retracePass: "reseeded",
1960
+ retraceOffset: 1.5,
1961
+ strokeInk: 0.85,
1962
+ maskBlob: 40,
1963
+ maskOutputMin: 0.62,
1964
+ maskOutputMax: 1,
1965
+ maskOctaves: 3,
1966
+ maskPosterize: 1,
1967
+ maskSoftness: 0,
1968
+ jitterX: 1.5,
1969
+ jitterY: 1.5,
1970
+ jitterRot: 0.35,
1971
+ jitterScale: 0.022,
1972
+ cornerSpread: 6,
1973
+ cornerTravel: 4.5,
1974
+ pressure: 0.15,
1975
+ pressureMod: 0.3,
1976
+ pooling: 0,
1977
+ iconTravel: 0.75
1978
+ },
1979
+ marker: {
1980
+ ...base,
1981
+ label: "Marker",
1982
+ blurb: "Broad translucent nib gone round twice on the same line, so the overlap darkens and the ink pools where it slows.",
1983
+ fillTravel: 2,
1984
+ strokeTravel: 1.5,
1985
+ wobble: 56,
1986
+ waveform: 1.4,
1987
+ borderWavelength: 1.3,
1988
+ strokeWidth: 4,
1989
+ doubleStroke: true,
1990
+ retracePass: "copy",
1991
+ strokeInk: 0.52,
1992
+ retraceOffset: 2.2,
1993
+ maskBlob: 115,
1994
+ maskOutputMin: 0.42,
1995
+ maskOutputMax: 1,
1996
+ maskOctaves: 3,
1997
+ maskPosterize: 4,
1998
+ maskSoftness: 4,
1999
+ jitterX: 3,
2000
+ jitterY: 3,
2001
+ jitterRot: 0.8,
2002
+ jitterScale: 0.045,
2003
+ cornerSpread: 10,
2004
+ cornerTravel: 8,
2005
+ pressure: 0.2,
2006
+ pressureMod: 0.25,
2007
+ pooling: 2,
2008
+ iconTravel: 1.25,
2009
+ iconMaskScale: 4
2010
+ },
2011
+ whiteboard: {
2012
+ ...base,
2013
+ label: "Whiteboard",
2014
+ blurb: "The fattest nib on glass. One long smooth undulation, and a veined mask that streaks the fill like a half-wiped board.",
2015
+ fillTravel: 2.5,
2016
+ strokeTravel: 2.5,
2017
+ wobble: 90,
2018
+ roughness: 1,
2019
+ waveform: 1,
2020
+ borderWavelength: 1.5,
2021
+ strokeWidth: 5.5,
2022
+ doubleStroke: true,
2023
+ retracePass: "copy",
2024
+ strokeInk: 0.66,
2025
+ retraceOffset: 3,
2026
+ maskGrain: "turbulence",
2027
+ maskBlob: 180,
2028
+ maskOutputMin: 0.42,
2029
+ maskOutputMax: 1,
2030
+ maskOctaves: 1,
2031
+ maskPosterize: 3,
2032
+ maskSoftness: 8,
2033
+ jitterX: 4.5,
2034
+ jitterY: 4.5,
2035
+ jitterRot: 1.2,
2036
+ jitterScale: 0.07,
2037
+ cornerSpread: 14,
2038
+ cornerTravel: 11,
2039
+ pressure: 0.15,
2040
+ pressureMod: 0.15,
2041
+ pooling: 3.5,
2042
+ iconTravel: 1.75,
2043
+ iconMaskScale: 1.5
2044
+ },
2045
+ hatched: {
2046
+ ...base,
2047
+ label: "Hatched",
2048
+ blurb: "An etching. The fill is angled shading, the outline a single hard-edged scratch that chatters along its length. No mask: the hatch is the texture.",
2049
+ fillTravel: 1.25,
2050
+ strokeTravel: 1.5,
2051
+ wobble: 24,
2052
+ roughness: 3,
2053
+ waveform: 3,
2054
+ strokeWidth: 1.5,
2055
+ fillStyle: "hatched",
2056
+ hatchInk: 0.5,
2057
+ doubleStroke: false,
2058
+ maskOn: false,
2059
+ iconMaskOn: false,
2060
+ jitterX: 1.5,
2061
+ jitterY: 1.5,
2062
+ jitterRot: 0.4,
2063
+ jitterScale: 0.03,
2064
+ cornerSpread: 6,
2065
+ cornerTravel: 6,
2066
+ pressure: 0.3,
2067
+ pressureMod: 0.45,
2068
+ pooling: 0.8,
2069
+ iconTravel: 1.25,
2070
+ iconWavelength: 0.5
2071
+ },
2072
+ dashed: {
2073
+ ...base,
2074
+ label: "Dashed",
2075
+ blurb: "A drafting outline. One slow drift along the ruler, broken into strokes, with jitter, mask and pressure all off. The clean pole.",
2076
+ strokeStyle: "dashed",
2077
+ strokeTravel: 1,
2078
+ fillTravel: 0.5,
2079
+ wobble: 120,
2080
+ roughness: 1,
2081
+ waveform: 1,
2082
+ strokeWidth: 1.5,
2083
+ doubleStroke: false,
2084
+ maskOn: false,
2085
+ iconMaskOn: false,
2086
+ jitterX: 0,
2087
+ jitterY: 0,
2088
+ jitterRot: 0,
2089
+ jitterScale: 0,
2090
+ cornerSpread: 4,
2091
+ cornerTravel: 3,
2092
+ pressure: 0,
2093
+ pressureMod: 0,
2094
+ pooling: 0,
2095
+ iconTravel: 0
2096
+ },
2097
+ napkin: {
2098
+ ...base,
2099
+ label: "Napkin",
2100
+ blurb: "Ballpoint in a hurry. Everything loose at once: a square wave sends every edge to full travel, and the second pass lands wherever it lands.",
2101
+ fillTravel: 3,
2102
+ strokeTravel: 2.25,
2103
+ wobble: 50,
2104
+ roughness: 3,
2105
+ waveform: 2.5,
2106
+ strokeWidth: 2.25,
2107
+ doubleStroke: true,
2108
+ retracePass: "reseeded",
2109
+ retraceOffset: 4,
2110
+ strokeInk: 1,
2111
+ maskBlob: 150,
2112
+ maskOutputMin: 0.43,
2113
+ maskOutputMax: 0.95,
2114
+ maskOctaves: 2,
2115
+ maskPosterize: 2,
2116
+ maskSoftness: 10,
2117
+ jitterX: 6,
2118
+ jitterY: 6,
2119
+ jitterRot: 1.8,
2120
+ jitterScale: 0.1,
2121
+ cornerSpread: 20,
2122
+ cornerTravel: 17,
2123
+ pressure: 0.45,
2124
+ pressureMod: 0.6,
2125
+ pooling: 2.5,
2126
+ iconTravel: 2.25,
2127
+ iconMaskScale: 3.6
2128
+ },
2129
+ dry: {
2130
+ ...base,
2131
+ label: "Dry marker",
2132
+ blurb: "Ink that ran out. One scratchy pass that breaks up along its length, over a fill the mask has worn nearly through in patches.",
2133
+ fillTravel: 2.25,
2134
+ strokeTravel: 1.75,
2135
+ wobble: 50,
2136
+ waveform: 2,
2137
+ borderWavelength: 0.5,
2138
+ strokeWidth: 3.5,
2139
+ doubleStroke: false,
2140
+ strokeInk: 0.4,
2141
+ maskBlob: 150,
2142
+ maskOutputMin: 0.24,
2143
+ maskOutputMax: 0.91,
2144
+ maskOctaves: 2,
2145
+ maskPosterize: 4,
2146
+ maskSoftness: 1.75,
2147
+ jitterX: 5,
2148
+ jitterY: 5,
2149
+ jitterRot: 1.4,
2150
+ jitterScale: 0.08,
2151
+ cornerSpread: 16,
2152
+ cornerTravel: 13,
2153
+ pressure: 0.4,
2154
+ pressureMod: 0.8,
2155
+ pooling: 1.5,
2156
+ iconTravel: 1.75,
2157
+ iconMaskScale: 3.8
2158
+ }
2159
+ };
2160
+ var DEFAULT_SKETCH_STYLE = "marker";
2161
+ function hydrateSketchStyle(raw) {
2162
+ const base2 = SKETCH_STYLES[DEFAULT_SKETCH_STYLE];
2163
+ const stored = raw ?? {};
2164
+ const out = { ...base2 };
2165
+ for (const key of Object.keys(base2)) {
2166
+ if (stored[key] !== void 0) out[key] = stored[key];
2167
+ }
2168
+ if (out.fillStyle === "none") out.fillStyle = base2.fillStyle;
2169
+ convertTiledMask(stored, out);
2170
+ convertCutToLevels(stored, out);
2171
+ carryLevelsToOutput(stored, out);
2172
+ halveSwingDials(stored, out);
2173
+ convertCyclesToWavelength(stored, out);
2174
+ convertIconTileToScale(stored, out);
2175
+ restoreDerivedRetrace(stored, out);
2176
+ return out;
2177
+ }
2178
+ function restoreDerivedRetrace(stored, out) {
2179
+ if (stored.retraceOffset === void 0) {
2180
+ out.retraceOffset = Number(Math.max(1.2, out.strokeWidth * 0.55).toFixed(2));
2181
+ }
2182
+ }
2183
+ var SWING_DIALS = {
2184
+ fillScale: "fillTravel",
2185
+ strokeScale: "strokeTravel",
2186
+ iconScale: "iconTravel",
2187
+ cornerShift: "cornerTravel"
2188
+ };
2189
+ function convertCyclesToWavelength(stored, out) {
2190
+ const cycles = stored.frequency;
2191
+ if (typeof cycles === "number" && cycles > 0) out.wobble = Math.round(1 / cycles);
2192
+ for (const [legacy, key] of [
2193
+ ["borderFrequency", "borderWavelength"],
2194
+ ["iconFrequency", "iconWavelength"]
2195
+ ]) {
2196
+ const multiple = stored[legacy];
2197
+ if (typeof multiple === "number" && multiple > 0) {
2198
+ out[key] = Number((1 / multiple).toFixed(3));
2199
+ }
2200
+ }
2201
+ const layers = stored.octaves;
2202
+ if (typeof layers === "number") out.roughness = Math.min(3, Math.max(1, layers));
2203
+ }
2204
+ function convertIconTileToScale(stored, out) {
2205
+ const tile = stored.iconMaskTile;
2206
+ if (typeof tile !== "number") return;
2207
+ out.iconMaskScale = Math.min(5, Math.max(0.5, Number((tile / 90).toFixed(2))));
2208
+ }
2209
+ function halveSwingDials(stored, out) {
2210
+ for (const [legacy, key] of Object.entries(SWING_DIALS)) {
2211
+ const value = stored[legacy];
2212
+ if (typeof value === "number") out[key] = value / 2;
2213
+ }
2214
+ }
2215
+ function convertTiledMask(stored, out) {
2216
+ const scale = stored.maskScale;
2217
+ if (typeof scale !== "number") return;
2218
+ const freq = stored.maskFrequency;
2219
+ if (typeof freq === "number") out.maskBlob = Math.round(scale / (freq * LEGACY_TILE));
2220
+ const soft = stored.maskSoftness;
2221
+ if (typeof soft === "number") out.maskSoftness = Number((soft * scale / LEGACY_TILE).toFixed(1));
2222
+ }
2223
+ function convertCutToLevels(stored, out) {
2224
+ const contrast = stored.maskContrast;
2225
+ const coverage = stored.maskCoverage;
2226
+ if (typeof contrast !== "number" || typeof coverage !== "number") return;
2227
+ const veined = out.maskGrain === "turbulence";
2228
+ const [lo, hi] = veined ? LEGACY_RANGE.turbulence : LEGACY_RANGE.fractal;
2229
+ const pivot = veined ? 0.55 - 0.5 * coverage : 0.8 - 0.6 * coverage;
2230
+ const level = (raw) => Math.min(1, Math.max(0, (raw - lo) / (hi - lo)));
2231
+ out.maskOutputMin = Number(level(pivot - 0.5 / contrast).toFixed(2));
2232
+ out.maskOutputMax = Number(Math.max(out.maskOutputMin + 0.02, level(pivot + 0.5 / contrast)).toFixed(2));
2233
+ }
2234
+ function carryLevelsToOutput(stored, out) {
2235
+ if (typeof stored.maskLevelMin === "number") out.maskOutputMin = stored.maskLevelMin;
2236
+ if (typeof stored.maskLevelMax === "number") out.maskOutputMax = stored.maskLevelMax;
2237
+ }
2238
+ var LEGACY_RANGE = { fractal: [0.24, 0.77], turbulence: [0.02, 0.6] };
2239
+ var LEGACY_TILE = 600;
2240
+
1907
2241
  // vite-plugin/themes/normalizeTheme.ts
1908
2242
  function asObject(value) {
1909
2243
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1995,12 +2329,12 @@ function normalizeTheme(raw, resolvers) {
1995
2329
  }
1996
2330
  const filled = { components: [], aliases: 0, orphans: 0 };
1997
2331
  for (const comp of resolvers.listComponentNames()) {
1998
- const base = asObject(resolvers.readComponentConfig(comp, "default"));
1999
- const baseAliases = base ? asObject(base.aliases) : null;
2000
- if (!base || !baseAliases) continue;
2332
+ const base2 = asObject(resolvers.readComponentConfig(comp, "default"));
2333
+ const baseAliases = base2 ? asObject(base2.aliases) : null;
2334
+ if (!base2 || !baseAliases) continue;
2001
2335
  const entry = componentConfigs[comp];
2002
2336
  if (!entry) {
2003
- const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base);
2337
+ const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base2);
2004
2338
  componentConfigs[comp] = structuredClone(rest);
2005
2339
  filled.components.push(comp);
2006
2340
  continue;
@@ -2016,6 +2350,8 @@ function normalizeTheme(raw, resolvers) {
2016
2350
  if (!(key in baseAliases)) filled.orphans++;
2017
2351
  }
2018
2352
  }
2353
+ const embeddedSketchStyle = asObject(src.sketchStyle);
2354
+ const sketchStyle = embeddedSketchStyle ? hydrateSketchStyle(embeddedSketchStyle) : void 0;
2019
2355
  return {
2020
2356
  theme: {
2021
2357
  name: asString(src.name, "Untitled"),
@@ -2024,7 +2360,8 @@ function normalizeTheme(raw, resolvers) {
2024
2360
  schemaVersion: THEME_SCHEMA_VERSION,
2025
2361
  colorsAndType,
2026
2362
  componentConfigs,
2027
- componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
2363
+ componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
2364
+ ...sketchStyle ? { sketchStyle } : {}
2028
2365
  },
2029
2366
  dropped,
2030
2367
  migrated,
@@ -2086,7 +2423,7 @@ function resolveDataDirs(opts = {}) {
2086
2423
  colorsAndTypeDir: opts.colorsAndTypeDir ? import_path2.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path2.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
2087
2424
  componentConfigsDir: opts.componentConfigsDir ? import_path2.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path2.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
2088
2425
  themesDir: opts.themesDir ? import_path2.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path2.default.resolve(fileConfig.themesDir) : sub("themes"),
2089
- sketchPresetsDir: sub("sketch-presets"),
2426
+ sketchStylesDir: sub("sketch-styles"),
2090
2427
  legacyManifestsDir: fileConfig.manifestsDir ? import_path2.default.resolve(fileConfig.manifestsDir) : void 0
2091
2428
  };
2092
2429
  }
@@ -2612,6 +2949,43 @@ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
2612
2949
  }
2613
2950
  };
2614
2951
 
2952
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-large-steps.ts
2953
+ var BUNDLE3 = [
2954
+ { name: "--editorial-xl-font-family", value: "var(--font-editorial)" },
2955
+ { name: "--editorial-xl-font-size", value: "var(--font-size-xl)" },
2956
+ { name: "--editorial-xl-font-weight", value: "var(--font-weight-normal)" },
2957
+ { name: "--editorial-xl-line-height", value: "var(--line-height-tighter)" },
2958
+ { name: "--editorial-xl-letter-spacing", value: "var(--letter-spacing-normal)" },
2959
+ { name: "--editorial-lg-font-family", value: "var(--font-editorial)" },
2960
+ { name: "--editorial-lg-font-size", value: "var(--font-size-lg)" },
2961
+ { name: "--editorial-lg-font-weight", value: "var(--font-weight-normal)" },
2962
+ { name: "--editorial-lg-line-height", value: "var(--line-height-tight)" },
2963
+ { name: "--editorial-lg-letter-spacing", value: "var(--letter-spacing-normal)" }
2964
+ ];
2965
+ var tokensCssMigration_2026_08_27_editorialLargeSteps = {
2966
+ id: "2026-08-27-editorial-large-steps",
2967
+ kind: "additive",
2968
+ description: "Add the --editorial-lg-* and --editorial-xl-* steps above the reading size",
2969
+ apply(css) {
2970
+ return ensureScale(css, {
2971
+ sectionComment: "Editorial \u2014 the steps above the reading size",
2972
+ anchorPrefixes: [
2973
+ "--editorial-",
2974
+ "--eyebrow-",
2975
+ "--code-",
2976
+ "--body-",
2977
+ "--heading-",
2978
+ "--letter-spacing-",
2979
+ "--line-height-",
2980
+ "--font-weight-",
2981
+ "--font-size-",
2982
+ "--font-"
2983
+ ],
2984
+ entries: BUNDLE3
2985
+ });
2986
+ }
2987
+ };
2988
+
2615
2989
  // vite-plugin/tokensCssMigrations/index.ts
2616
2990
  var TOKENS_CSS_MIGRATIONS = [
2617
2991
  tokensCssMigration_2026_05_29_typographyScaleAdditions,
@@ -2625,7 +2999,8 @@ var TOKENS_CSS_MIGRATIONS = [
2625
2999
  tokensCssMigration_2026_08_25_editorialTypeRole,
2626
3000
  tokensCssMigration_2026_08_26_gradientStops,
2627
3001
  tokensCssMigration_2026_08_27_backdropPolarity,
2628
- tokensCssMigration_2026_08_27_editorialSizeSteps
3002
+ tokensCssMigration_2026_08_27_editorialSizeSteps,
3003
+ tokensCssMigration_2026_08_27_editorialLargeSteps
2629
3004
  ];
2630
3005
  function runTokensCssMigrations(css) {
2631
3006
  return foldMigrations(css, () => true);
@@ -2726,7 +3101,7 @@ function themeFileApi(opts) {
2726
3101
  const COLORS_AND_TYPE_DIR = dataDirs.colorsAndTypeDir;
2727
3102
  const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
2728
3103
  const THEMES_DIR = dataDirs.themesDir;
2729
- const SKETCH_PRESETS_DIR = dataDirs.sketchPresetsDir;
3104
+ const SKETCH_STYLES_DIR = dataDirs.sketchStylesDir;
2730
3105
  const CSS_PATH = import_path4.default.resolve(opts.tokensCssPath);
2731
3106
  const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? import_path4.default.resolve(opts.tokensGeneratedCssPath) : import_path4.default.join(dataDirs.dataDir, "tokens.generated.css");
2732
3107
  const FONTS_CSS_PATH = opts.fontsCssPath ? import_path4.default.resolve(opts.fontsCssPath) : import_path4.default.join(import_path4.default.dirname(CSS_PATH), "fonts.css");
@@ -2784,7 +3159,7 @@ function themeFileApi(opts) {
2784
3159
  dir: THEMES_DIR,
2785
3160
  packageDir: packageThemesDir
2786
3161
  });
2787
- const sketchPresetsResource = versionedFileResourceServer({ dir: SKETCH_PRESETS_DIR });
3162
+ const sketchStylesResource = versionedFileResourceServer({ dir: SKETCH_STYLES_DIR });
2788
3163
  function ensureColorsAndTypeDir() {
2789
3164
  colorsAndTypeResource.ensureDir();
2790
3165
  }
@@ -3123,6 +3498,13 @@ ${lines.join("\n")}
3123
3498
  `[live-tokens] This project still uses the data layout from 0.47 and earlier: ${evidence}. Since 0.48 the whole-look theme files live in \`themes/\` and the colors and type live in \`colors-and-type/\`. Nothing in the data directory was written, the editor cannot save, and ${import_path4.default.basename(GENERATED_CSS_PATH)} is left exactly as it is. Run \`npx live-tokens migrate\` to move the directories and heal the tree, then restart the dev server.`
3124
3499
  );
3125
3500
  }
3501
+ function warnOnUnmigratedSketchStyles(warn) {
3502
+ const legacyDir = import_path4.default.join(dataDirs.dataDir, "sketch-presets");
3503
+ if (!import_fs4.default.existsSync(legacyDir)) return;
3504
+ warn(
3505
+ `[live-tokens] Saved sketchstyles still live under the retired ${import_path4.default.basename(legacyDir)}/ directory name. Run \`npx live-tokens migrate\` to rename it to ${import_path4.default.basename(SKETCH_STYLES_DIR)}/; until then they will not show up in the Sketchstyle view.`
3506
+ );
3507
+ }
3126
3508
  const diskThemeResolvers = {
3127
3509
  readColorsAndType: (name) => colorsAndTypeResource.readJson(sanitizeFileName(name)),
3128
3510
  readComponentConfig: (comp, name) => readComponentConfig(comp, sanitizeFileName(name)),
@@ -3362,8 +3744,8 @@ ${lines.join("\n")}
3362
3744
  const THEME_EXPORT_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)/export$`);
3363
3745
  const THEME_IMPORT_ROUTE = `${API_BASE}/themes/import`;
3364
3746
  const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
3365
- const SKETCH_PRESETS_ROUTE = `${API_BASE}/sketch-presets`;
3366
- const SKETCH_PRESET_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-presets/([a-z0-9\\-_]+)$`);
3747
+ const SKETCH_STYLES_ROUTE = `${API_BASE}/sketch-styles`;
3748
+ const SKETCH_STYLE_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-styles/([a-z0-9\\-_]+)$`);
3367
3749
  const PRODUCTION_ROUTE = `${API_BASE}/production`;
3368
3750
  async function handleListColorsAndType(_ctx) {
3369
3751
  const files = colorsAndTypeResource.listNames().map((fileName) => {
@@ -3895,11 +4277,11 @@ ${lines.join("\n")}
3895
4277
  }
3896
4278
  });
3897
4279
  }
3898
- async function handleListSketchPresets({ res }) {
3899
- const files = sketchPresetsResource.listNames().map((fileName) => {
4280
+ async function handleListSketchStyles({ res }) {
4281
+ const files = sketchStylesResource.listNames().map((fileName) => {
3900
4282
  let data = null;
3901
4283
  try {
3902
- data = sketchPresetsResource.readJson(fileName);
4284
+ data = sketchStylesResource.readJson(fileName);
3903
4285
  } catch {
3904
4286
  }
3905
4287
  return {
@@ -3910,12 +4292,12 @@ ${lines.join("\n")}
3910
4292
  });
3911
4293
  jsonResponse(res, 200, { files });
3912
4294
  }
3913
- async function handleSketchPresetByName({ params, req, res }) {
4295
+ async function handleSketchStyleByName({ params, req, res }) {
3914
4296
  const [fileName] = params;
3915
4297
  if (rejectReservedName(res, fileName)) return;
3916
- const filePath = sketchPresetsResource.filePath(fileName);
4298
+ const filePath = sketchStylesResource.filePath(fileName);
3917
4299
  if (req.method === "GET") {
3918
- const raw = sketchPresetsResource.readJson(fileName);
4300
+ const raw = sketchStylesResource.readJson(fileName);
3919
4301
  if (!raw) {
3920
4302
  jsonResponse(res, 404, { error: "Not found" });
3921
4303
  return;
@@ -3926,7 +4308,7 @@ ${lines.join("\n")}
3926
4308
  if (req.method === "PUT") {
3927
4309
  const body = JSON.parse(await readBody(req));
3928
4310
  if (!body || typeof body !== "object" || !body.settings || typeof body.settings !== "object") {
3929
- jsonResponse(res, 400, { error: "A sketch preset needs a settings object" });
4311
+ jsonResponse(res, 400, { error: "A sketchstyle needs a settings object" });
3930
4312
  return;
3931
4313
  }
3932
4314
  body.name = String(body.name || fileName);
@@ -3939,7 +4321,7 @@ ${lines.join("\n")}
3939
4321
  }
3940
4322
  }
3941
4323
  if (!body.createdAt) body.createdAt = body.updatedAt;
3942
- sketchPresetsResource.ensureDir();
4324
+ sketchStylesResource.ensureDir();
3943
4325
  import_fs4.default.writeFileSync(filePath, JSON.stringify(body, null, 2));
3944
4326
  jsonResponse(res, 200, { ok: true, fileName });
3945
4327
  return;
@@ -4026,14 +4408,14 @@ ${lines.join("\n")}
4026
4408
  { method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
4027
4409
  { method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
4028
4410
  // Production — the whole-look adopt door
4029
- { method: "GET", pattern: SKETCH_PRESETS_ROUTE, handler: handleListSketchPresets },
4030
- { method: "PUT", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4031
- { method: "POST", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4032
- { method: "DELETE", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4033
- { method: "GET", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4034
- { method: "PUT", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4035
- { method: "DELETE", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4036
- { method: "POST", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: methodNotAllowed },
4411
+ { method: "GET", pattern: SKETCH_STYLES_ROUTE, handler: handleListSketchStyles },
4412
+ { method: "PUT", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4413
+ { method: "POST", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4414
+ { method: "DELETE", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4415
+ { method: "GET", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4416
+ { method: "PUT", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4417
+ { method: "DELETE", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4418
+ { method: "POST", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: methodNotAllowed },
4037
4419
  { method: "PUT", pattern: PRODUCTION_ROUTE, handler: handleAdoptLook },
4038
4420
  { method: "GET", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
4039
4421
  { method: "POST", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
@@ -4073,6 +4455,7 @@ ${lines.join("\n")}
4073
4455
  productionPointerHeld,
4074
4456
  (msg) => server.config.logger.warn(msg)
4075
4457
  );
4458
+ warnOnUnmigratedSketchStyles((msg) => server.config.logger.warn(msg));
4076
4459
  }
4077
4460
  server.middlewares.use(async (req, res, next) => {
4078
4461
  if (legacyLayout && req.method !== "GET" && (req.url ?? "").startsWith(API_BASE)) {
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
2
  export { ComponentSource, MissingToken, RunResult, TOKENS_CSS_MIGRATIONS, TokensCssMigration, ValidateInput, runTokensCssMigrations, validateTokensCss } from './tokensCssMigrations/index.cjs';
3
- import './dataPaths-CRfD1LdA.cjs';
3
+ import './dataPaths-DZUzVv8H.cjs';
4
4
 
5
5
  interface ThemeFileApiOptions {
6
6
  tokensCssPath: string;
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
2
  export { ComponentSource, MissingToken, RunResult, TOKENS_CSS_MIGRATIONS, TokensCssMigration, ValidateInput, runTokensCssMigrations, validateTokensCss } from './tokensCssMigrations/index.js';
3
- import './dataPaths-CRfD1LdA.js';
3
+ import './dataPaths-DZUzVv8H.js';
4
4
 
5
5
  interface ThemeFileApiOptions {
6
6
  tokensCssPath: string;