@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
@@ -13,7 +13,7 @@ import {
13
13
  nextAvailableName,
14
14
  normalizeTheme,
15
15
  versionedFileResourceServer
16
- } from "./chunk-232GZGQU.js";
16
+ } from "./chunk-NDJJORKJ.js";
17
17
  import {
18
18
  CURRENT_COMPONENT_SCHEMA_VERSION
19
19
  } from "./chunk-NE6N66EE.js";
@@ -23,7 +23,7 @@ import {
23
23
  runAdditiveTokensCssMigrations,
24
24
  runTokensCssMigrations,
25
25
  validateTokensCss
26
- } from "./chunk-OPYOK2CA.js";
26
+ } from "./chunk-ZHPX7ZYQ.js";
27
27
  import {
28
28
  hexToOklch,
29
29
  oklchToRgb255,
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunk-7TQQTHI6.js";
32
32
  import {
33
33
  resolveDataDirs
34
- } from "./chunk-Y5CNFSSV.js";
34
+ } from "./chunk-RVE3MNKM.js";
35
35
 
36
36
  // vite-plugin/themeFileApi.ts
37
37
  import fs from "fs";
@@ -220,7 +220,7 @@ function themeFileApi(opts) {
220
220
  const COLORS_AND_TYPE_DIR = dataDirs.colorsAndTypeDir;
221
221
  const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
222
222
  const THEMES_DIR = dataDirs.themesDir;
223
- const SKETCH_PRESETS_DIR = dataDirs.sketchPresetsDir;
223
+ const SKETCH_STYLES_DIR = dataDirs.sketchStylesDir;
224
224
  const CSS_PATH = path.resolve(opts.tokensCssPath);
225
225
  const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? path.resolve(opts.tokensGeneratedCssPath) : path.join(dataDirs.dataDir, "tokens.generated.css");
226
226
  const FONTS_CSS_PATH = opts.fontsCssPath ? path.resolve(opts.fontsCssPath) : path.join(path.dirname(CSS_PATH), "fonts.css");
@@ -278,7 +278,7 @@ function themeFileApi(opts) {
278
278
  dir: THEMES_DIR,
279
279
  packageDir: packageThemesDir
280
280
  });
281
- const sketchPresetsResource = versionedFileResourceServer({ dir: SKETCH_PRESETS_DIR });
281
+ const sketchStylesResource = versionedFileResourceServer({ dir: SKETCH_STYLES_DIR });
282
282
  function ensureColorsAndTypeDir() {
283
283
  colorsAndTypeResource.ensureDir();
284
284
  }
@@ -617,6 +617,13 @@ ${lines.join("\n")}
617
617
  `[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 ${path.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.`
618
618
  );
619
619
  }
620
+ function warnOnUnmigratedSketchStyles(warn) {
621
+ const legacyDir = path.join(dataDirs.dataDir, "sketch-presets");
622
+ if (!fs.existsSync(legacyDir)) return;
623
+ warn(
624
+ `[live-tokens] Saved sketchstyles still live under the retired ${path.basename(legacyDir)}/ directory name. Run \`npx live-tokens migrate\` to rename it to ${path.basename(SKETCH_STYLES_DIR)}/; until then they will not show up in the Sketchstyle view.`
625
+ );
626
+ }
620
627
  const diskThemeResolvers = {
621
628
  readColorsAndType: (name) => colorsAndTypeResource.readJson(sanitizeFileName(name)),
622
629
  readComponentConfig: (comp, name) => readComponentConfig(comp, sanitizeFileName(name)),
@@ -856,8 +863,8 @@ ${lines.join("\n")}
856
863
  const THEME_EXPORT_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)/export$`);
857
864
  const THEME_IMPORT_ROUTE = `${API_BASE}/themes/import`;
858
865
  const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
859
- const SKETCH_PRESETS_ROUTE = `${API_BASE}/sketch-presets`;
860
- const SKETCH_PRESET_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-presets/([a-z0-9\\-_]+)$`);
866
+ const SKETCH_STYLES_ROUTE = `${API_BASE}/sketch-styles`;
867
+ const SKETCH_STYLE_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-styles/([a-z0-9\\-_]+)$`);
861
868
  const PRODUCTION_ROUTE = `${API_BASE}/production`;
862
869
  async function handleListColorsAndType(_ctx) {
863
870
  const files = colorsAndTypeResource.listNames().map((fileName) => {
@@ -1389,11 +1396,11 @@ ${lines.join("\n")}
1389
1396
  }
1390
1397
  });
1391
1398
  }
1392
- async function handleListSketchPresets({ res }) {
1393
- const files = sketchPresetsResource.listNames().map((fileName) => {
1399
+ async function handleListSketchStyles({ res }) {
1400
+ const files = sketchStylesResource.listNames().map((fileName) => {
1394
1401
  let data = null;
1395
1402
  try {
1396
- data = sketchPresetsResource.readJson(fileName);
1403
+ data = sketchStylesResource.readJson(fileName);
1397
1404
  } catch {
1398
1405
  }
1399
1406
  return {
@@ -1404,12 +1411,12 @@ ${lines.join("\n")}
1404
1411
  });
1405
1412
  jsonResponse(res, 200, { files });
1406
1413
  }
1407
- async function handleSketchPresetByName({ params, req, res }) {
1414
+ async function handleSketchStyleByName({ params, req, res }) {
1408
1415
  const [fileName] = params;
1409
1416
  if (rejectReservedName(res, fileName)) return;
1410
- const filePath = sketchPresetsResource.filePath(fileName);
1417
+ const filePath = sketchStylesResource.filePath(fileName);
1411
1418
  if (req.method === "GET") {
1412
- const raw = sketchPresetsResource.readJson(fileName);
1419
+ const raw = sketchStylesResource.readJson(fileName);
1413
1420
  if (!raw) {
1414
1421
  jsonResponse(res, 404, { error: "Not found" });
1415
1422
  return;
@@ -1420,7 +1427,7 @@ ${lines.join("\n")}
1420
1427
  if (req.method === "PUT") {
1421
1428
  const body = JSON.parse(await readBody(req));
1422
1429
  if (!body || typeof body !== "object" || !body.settings || typeof body.settings !== "object") {
1423
- jsonResponse(res, 400, { error: "A sketch preset needs a settings object" });
1430
+ jsonResponse(res, 400, { error: "A sketchstyle needs a settings object" });
1424
1431
  return;
1425
1432
  }
1426
1433
  body.name = String(body.name || fileName);
@@ -1433,7 +1440,7 @@ ${lines.join("\n")}
1433
1440
  }
1434
1441
  }
1435
1442
  if (!body.createdAt) body.createdAt = body.updatedAt;
1436
- sketchPresetsResource.ensureDir();
1443
+ sketchStylesResource.ensureDir();
1437
1444
  fs.writeFileSync(filePath, JSON.stringify(body, null, 2));
1438
1445
  jsonResponse(res, 200, { ok: true, fileName });
1439
1446
  return;
@@ -1520,14 +1527,14 @@ ${lines.join("\n")}
1520
1527
  { method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
1521
1528
  { method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
1522
1529
  // Production — the whole-look adopt door
1523
- { method: "GET", pattern: SKETCH_PRESETS_ROUTE, handler: handleListSketchPresets },
1524
- { method: "PUT", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
1525
- { method: "POST", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
1526
- { method: "DELETE", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
1527
- { method: "GET", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
1528
- { method: "PUT", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
1529
- { method: "DELETE", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
1530
- { method: "POST", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: methodNotAllowed },
1530
+ { method: "GET", pattern: SKETCH_STYLES_ROUTE, handler: handleListSketchStyles },
1531
+ { method: "PUT", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
1532
+ { method: "POST", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
1533
+ { method: "DELETE", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
1534
+ { method: "GET", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
1535
+ { method: "PUT", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
1536
+ { method: "DELETE", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
1537
+ { method: "POST", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: methodNotAllowed },
1531
1538
  { method: "PUT", pattern: PRODUCTION_ROUTE, handler: handleAdoptLook },
1532
1539
  { method: "GET", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
1533
1540
  { method: "POST", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
@@ -1567,6 +1574,7 @@ ${lines.join("\n")}
1567
1574
  productionPointerHeld,
1568
1575
  (msg) => server.config.logger.warn(msg)
1569
1576
  );
1577
+ warnOnUnmigratedSketchStyles((msg) => server.config.logger.warn(msg));
1570
1578
  }
1571
1579
  server.middlewares.use(async (req, res, next) => {
1572
1580
  if (legacyLayout && req.method !== "GET" && (req.url ?? "").startsWith(API_BASE)) {
@@ -1053,6 +1053,340 @@ var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
1053
1053
  "--sectiondivider-sm-color-family"
1054
1054
  ]);
1055
1055
 
1056
+ // src/editor/core/sketch/sketchStyles.ts
1057
+ var base = {
1058
+ label: "",
1059
+ blurb: "",
1060
+ fillTravel: 1.5,
1061
+ strokeTravel: 1.5,
1062
+ wobble: 45,
1063
+ roughness: 3,
1064
+ borderWavelength: 1,
1065
+ waveform: 1,
1066
+ strokeWidth: 1.5,
1067
+ doubleStroke: false,
1068
+ retraceOffset: 1.2,
1069
+ retracePass: "copy",
1070
+ fillStyle: "solid",
1071
+ hatchInk: 0.4,
1072
+ strokeStyle: "solid",
1073
+ pressure: 0.25,
1074
+ pressureMod: 0.35,
1075
+ pooling: 1.2,
1076
+ strokeInk: 1,
1077
+ maskOn: true,
1078
+ maskBlob: 100,
1079
+ maskOutputMin: 0.45,
1080
+ maskOutputMax: 1,
1081
+ maskOctaves: 2,
1082
+ maskGrain: "fractal",
1083
+ maskPosterize: 1,
1084
+ maskSoftness: 1.5,
1085
+ jitterX: 2.5,
1086
+ jitterY: 2.5,
1087
+ jitterRot: 0.6,
1088
+ jitterScale: 0.035,
1089
+ cornerSpread: 10,
1090
+ cornerTravel: 8,
1091
+ iconTravel: 1.25,
1092
+ iconWavelength: 0.625,
1093
+ iconMaskOn: true,
1094
+ iconMaskScale: 1
1095
+ };
1096
+ var SKETCH_STYLES = {
1097
+ pencil: {
1098
+ ...base,
1099
+ label: "Pencil",
1100
+ 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.",
1101
+ fillTravel: 0.75,
1102
+ strokeTravel: 1.25,
1103
+ wobble: 30,
1104
+ roughness: 3,
1105
+ waveform: 1,
1106
+ strokeWidth: 1.25,
1107
+ doubleStroke: true,
1108
+ retracePass: "reseeded",
1109
+ retraceOffset: 1.5,
1110
+ strokeInk: 0.85,
1111
+ maskBlob: 40,
1112
+ maskOutputMin: 0.62,
1113
+ maskOutputMax: 1,
1114
+ maskOctaves: 3,
1115
+ maskPosterize: 1,
1116
+ maskSoftness: 0,
1117
+ jitterX: 1.5,
1118
+ jitterY: 1.5,
1119
+ jitterRot: 0.35,
1120
+ jitterScale: 0.022,
1121
+ cornerSpread: 6,
1122
+ cornerTravel: 4.5,
1123
+ pressure: 0.15,
1124
+ pressureMod: 0.3,
1125
+ pooling: 0,
1126
+ iconTravel: 0.75
1127
+ },
1128
+ marker: {
1129
+ ...base,
1130
+ label: "Marker",
1131
+ blurb: "Broad translucent nib gone round twice on the same line, so the overlap darkens and the ink pools where it slows.",
1132
+ fillTravel: 2,
1133
+ strokeTravel: 1.5,
1134
+ wobble: 56,
1135
+ waveform: 1.4,
1136
+ borderWavelength: 1.3,
1137
+ strokeWidth: 4,
1138
+ doubleStroke: true,
1139
+ retracePass: "copy",
1140
+ strokeInk: 0.52,
1141
+ retraceOffset: 2.2,
1142
+ maskBlob: 115,
1143
+ maskOutputMin: 0.42,
1144
+ maskOutputMax: 1,
1145
+ maskOctaves: 3,
1146
+ maskPosterize: 4,
1147
+ maskSoftness: 4,
1148
+ jitterX: 3,
1149
+ jitterY: 3,
1150
+ jitterRot: 0.8,
1151
+ jitterScale: 0.045,
1152
+ cornerSpread: 10,
1153
+ cornerTravel: 8,
1154
+ pressure: 0.2,
1155
+ pressureMod: 0.25,
1156
+ pooling: 2,
1157
+ iconTravel: 1.25,
1158
+ iconMaskScale: 4
1159
+ },
1160
+ whiteboard: {
1161
+ ...base,
1162
+ label: "Whiteboard",
1163
+ blurb: "The fattest nib on glass. One long smooth undulation, and a veined mask that streaks the fill like a half-wiped board.",
1164
+ fillTravel: 2.5,
1165
+ strokeTravel: 2.5,
1166
+ wobble: 90,
1167
+ roughness: 1,
1168
+ waveform: 1,
1169
+ borderWavelength: 1.5,
1170
+ strokeWidth: 5.5,
1171
+ doubleStroke: true,
1172
+ retracePass: "copy",
1173
+ strokeInk: 0.66,
1174
+ retraceOffset: 3,
1175
+ maskGrain: "turbulence",
1176
+ maskBlob: 180,
1177
+ maskOutputMin: 0.42,
1178
+ maskOutputMax: 1,
1179
+ maskOctaves: 1,
1180
+ maskPosterize: 3,
1181
+ maskSoftness: 8,
1182
+ jitterX: 4.5,
1183
+ jitterY: 4.5,
1184
+ jitterRot: 1.2,
1185
+ jitterScale: 0.07,
1186
+ cornerSpread: 14,
1187
+ cornerTravel: 11,
1188
+ pressure: 0.15,
1189
+ pressureMod: 0.15,
1190
+ pooling: 3.5,
1191
+ iconTravel: 1.75,
1192
+ iconMaskScale: 1.5
1193
+ },
1194
+ hatched: {
1195
+ ...base,
1196
+ label: "Hatched",
1197
+ 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.",
1198
+ fillTravel: 1.25,
1199
+ strokeTravel: 1.5,
1200
+ wobble: 24,
1201
+ roughness: 3,
1202
+ waveform: 3,
1203
+ strokeWidth: 1.5,
1204
+ fillStyle: "hatched",
1205
+ hatchInk: 0.5,
1206
+ doubleStroke: false,
1207
+ maskOn: false,
1208
+ iconMaskOn: false,
1209
+ jitterX: 1.5,
1210
+ jitterY: 1.5,
1211
+ jitterRot: 0.4,
1212
+ jitterScale: 0.03,
1213
+ cornerSpread: 6,
1214
+ cornerTravel: 6,
1215
+ pressure: 0.3,
1216
+ pressureMod: 0.45,
1217
+ pooling: 0.8,
1218
+ iconTravel: 1.25,
1219
+ iconWavelength: 0.5
1220
+ },
1221
+ dashed: {
1222
+ ...base,
1223
+ label: "Dashed",
1224
+ blurb: "A drafting outline. One slow drift along the ruler, broken into strokes, with jitter, mask and pressure all off. The clean pole.",
1225
+ strokeStyle: "dashed",
1226
+ strokeTravel: 1,
1227
+ fillTravel: 0.5,
1228
+ wobble: 120,
1229
+ roughness: 1,
1230
+ waveform: 1,
1231
+ strokeWidth: 1.5,
1232
+ doubleStroke: false,
1233
+ maskOn: false,
1234
+ iconMaskOn: false,
1235
+ jitterX: 0,
1236
+ jitterY: 0,
1237
+ jitterRot: 0,
1238
+ jitterScale: 0,
1239
+ cornerSpread: 4,
1240
+ cornerTravel: 3,
1241
+ pressure: 0,
1242
+ pressureMod: 0,
1243
+ pooling: 0,
1244
+ iconTravel: 0
1245
+ },
1246
+ napkin: {
1247
+ ...base,
1248
+ label: "Napkin",
1249
+ 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.",
1250
+ fillTravel: 3,
1251
+ strokeTravel: 2.25,
1252
+ wobble: 50,
1253
+ roughness: 3,
1254
+ waveform: 2.5,
1255
+ strokeWidth: 2.25,
1256
+ doubleStroke: true,
1257
+ retracePass: "reseeded",
1258
+ retraceOffset: 4,
1259
+ strokeInk: 1,
1260
+ maskBlob: 150,
1261
+ maskOutputMin: 0.43,
1262
+ maskOutputMax: 0.95,
1263
+ maskOctaves: 2,
1264
+ maskPosterize: 2,
1265
+ maskSoftness: 10,
1266
+ jitterX: 6,
1267
+ jitterY: 6,
1268
+ jitterRot: 1.8,
1269
+ jitterScale: 0.1,
1270
+ cornerSpread: 20,
1271
+ cornerTravel: 17,
1272
+ pressure: 0.45,
1273
+ pressureMod: 0.6,
1274
+ pooling: 2.5,
1275
+ iconTravel: 2.25,
1276
+ iconMaskScale: 3.6
1277
+ },
1278
+ dry: {
1279
+ ...base,
1280
+ label: "Dry marker",
1281
+ 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.",
1282
+ fillTravel: 2.25,
1283
+ strokeTravel: 1.75,
1284
+ wobble: 50,
1285
+ waveform: 2,
1286
+ borderWavelength: 0.5,
1287
+ strokeWidth: 3.5,
1288
+ doubleStroke: false,
1289
+ strokeInk: 0.4,
1290
+ maskBlob: 150,
1291
+ maskOutputMin: 0.24,
1292
+ maskOutputMax: 0.91,
1293
+ maskOctaves: 2,
1294
+ maskPosterize: 4,
1295
+ maskSoftness: 1.75,
1296
+ jitterX: 5,
1297
+ jitterY: 5,
1298
+ jitterRot: 1.4,
1299
+ jitterScale: 0.08,
1300
+ cornerSpread: 16,
1301
+ cornerTravel: 13,
1302
+ pressure: 0.4,
1303
+ pressureMod: 0.8,
1304
+ pooling: 1.5,
1305
+ iconTravel: 1.75,
1306
+ iconMaskScale: 3.8
1307
+ }
1308
+ };
1309
+ var DEFAULT_SKETCH_STYLE = "marker";
1310
+ function hydrateSketchStyle(raw) {
1311
+ const base2 = SKETCH_STYLES[DEFAULT_SKETCH_STYLE];
1312
+ const stored = raw ?? {};
1313
+ const out = { ...base2 };
1314
+ for (const key of Object.keys(base2)) {
1315
+ if (stored[key] !== void 0) out[key] = stored[key];
1316
+ }
1317
+ if (out.fillStyle === "none") out.fillStyle = base2.fillStyle;
1318
+ convertTiledMask(stored, out);
1319
+ convertCutToLevels(stored, out);
1320
+ carryLevelsToOutput(stored, out);
1321
+ halveSwingDials(stored, out);
1322
+ convertCyclesToWavelength(stored, out);
1323
+ convertIconTileToScale(stored, out);
1324
+ restoreDerivedRetrace(stored, out);
1325
+ return out;
1326
+ }
1327
+ function restoreDerivedRetrace(stored, out) {
1328
+ if (stored.retraceOffset === void 0) {
1329
+ out.retraceOffset = Number(Math.max(1.2, out.strokeWidth * 0.55).toFixed(2));
1330
+ }
1331
+ }
1332
+ var SWING_DIALS = {
1333
+ fillScale: "fillTravel",
1334
+ strokeScale: "strokeTravel",
1335
+ iconScale: "iconTravel",
1336
+ cornerShift: "cornerTravel"
1337
+ };
1338
+ function convertCyclesToWavelength(stored, out) {
1339
+ const cycles = stored.frequency;
1340
+ if (typeof cycles === "number" && cycles > 0) out.wobble = Math.round(1 / cycles);
1341
+ for (const [legacy, key] of [
1342
+ ["borderFrequency", "borderWavelength"],
1343
+ ["iconFrequency", "iconWavelength"]
1344
+ ]) {
1345
+ const multiple = stored[legacy];
1346
+ if (typeof multiple === "number" && multiple > 0) {
1347
+ out[key] = Number((1 / multiple).toFixed(3));
1348
+ }
1349
+ }
1350
+ const layers = stored.octaves;
1351
+ if (typeof layers === "number") out.roughness = Math.min(3, Math.max(1, layers));
1352
+ }
1353
+ function convertIconTileToScale(stored, out) {
1354
+ const tile = stored.iconMaskTile;
1355
+ if (typeof tile !== "number") return;
1356
+ out.iconMaskScale = Math.min(5, Math.max(0.5, Number((tile / 90).toFixed(2))));
1357
+ }
1358
+ function halveSwingDials(stored, out) {
1359
+ for (const [legacy, key] of Object.entries(SWING_DIALS)) {
1360
+ const value = stored[legacy];
1361
+ if (typeof value === "number") out[key] = value / 2;
1362
+ }
1363
+ }
1364
+ function convertTiledMask(stored, out) {
1365
+ const scale = stored.maskScale;
1366
+ if (typeof scale !== "number") return;
1367
+ const freq = stored.maskFrequency;
1368
+ if (typeof freq === "number") out.maskBlob = Math.round(scale / (freq * LEGACY_TILE));
1369
+ const soft = stored.maskSoftness;
1370
+ if (typeof soft === "number") out.maskSoftness = Number((soft * scale / LEGACY_TILE).toFixed(1));
1371
+ }
1372
+ function convertCutToLevels(stored, out) {
1373
+ const contrast = stored.maskContrast;
1374
+ const coverage = stored.maskCoverage;
1375
+ if (typeof contrast !== "number" || typeof coverage !== "number") return;
1376
+ const veined = out.maskGrain === "turbulence";
1377
+ const [lo, hi] = veined ? LEGACY_RANGE.turbulence : LEGACY_RANGE.fractal;
1378
+ const pivot = veined ? 0.55 - 0.5 * coverage : 0.8 - 0.6 * coverage;
1379
+ const level = (raw) => Math.min(1, Math.max(0, (raw - lo) / (hi - lo)));
1380
+ out.maskOutputMin = Number(level(pivot - 0.5 / contrast).toFixed(2));
1381
+ out.maskOutputMax = Number(Math.max(out.maskOutputMin + 0.02, level(pivot + 0.5 / contrast)).toFixed(2));
1382
+ }
1383
+ function carryLevelsToOutput(stored, out) {
1384
+ if (typeof stored.maskLevelMin === "number") out.maskOutputMin = stored.maskLevelMin;
1385
+ if (typeof stored.maskLevelMax === "number") out.maskOutputMax = stored.maskLevelMax;
1386
+ }
1387
+ var LEGACY_RANGE = { fractal: [0.24, 0.77], turbulence: [0.02, 0.6] };
1388
+ var LEGACY_TILE = 600;
1389
+
1056
1390
  // vite-plugin/themes/normalizeTheme.ts
1057
1391
  function asObject(value) {
1058
1392
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1144,12 +1478,12 @@ function normalizeTheme(raw, resolvers) {
1144
1478
  }
1145
1479
  const filled = { components: [], aliases: 0, orphans: 0 };
1146
1480
  for (const comp of resolvers.listComponentNames()) {
1147
- const base = asObject(resolvers.readComponentConfig(comp, "default"));
1148
- const baseAliases = base ? asObject(base.aliases) : null;
1149
- if (!base || !baseAliases) continue;
1481
+ const base2 = asObject(resolvers.readComponentConfig(comp, "default"));
1482
+ const baseAliases = base2 ? asObject(base2.aliases) : null;
1483
+ if (!base2 || !baseAliases) continue;
1150
1484
  const entry = componentConfigs[comp];
1151
1485
  if (!entry) {
1152
- const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base);
1486
+ const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base2);
1153
1487
  componentConfigs[comp] = structuredClone(rest);
1154
1488
  filled.components.push(comp);
1155
1489
  continue;
@@ -1165,6 +1499,8 @@ function normalizeTheme(raw, resolvers) {
1165
1499
  if (!(key in baseAliases)) filled.orphans++;
1166
1500
  }
1167
1501
  }
1502
+ const embeddedSketchStyle = asObject(src.sketchStyle);
1503
+ const sketchStyle = embeddedSketchStyle ? hydrateSketchStyle(embeddedSketchStyle) : void 0;
1168
1504
  return {
1169
1505
  theme: {
1170
1506
  name: asString(src.name, "Untitled"),
@@ -1173,7 +1509,8 @@ function normalizeTheme(raw, resolvers) {
1173
1509
  schemaVersion: THEME_SCHEMA_VERSION,
1174
1510
  colorsAndType,
1175
1511
  componentConfigs,
1176
- componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
1512
+ componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
1513
+ ...sketchStyle ? { sketchStyle } : {}
1177
1514
  },
1178
1515
  dropped,
1179
1516
  migrated,
@@ -1356,8 +1693,12 @@ function migrateData(opts) {
1356
1693
  configuredManifestsDir: opts.legacyManifestsDir
1357
1694
  };
1358
1695
  const legacyLayout = detectLegacyLayout(layoutInput);
1359
- const renames = legacyLayout ? planLegacyRenames(legacyLayout, layoutInput) : [];
1360
- if (legacyLayout && !check) applyLegacyRenames(renames);
1696
+ const legacyRenames = legacyLayout ? planLegacyRenames(legacyLayout, layoutInput) : [];
1697
+ const sketchStylesFrom = import_path3.default.join(opts.dataDir, "sketch-presets");
1698
+ const sketchStylesTo = import_path3.default.join(opts.dataDir, "sketch-styles");
1699
+ const sketchStylesRenames = import_fs3.default.existsSync(sketchStylesFrom) ? [{ from: sketchStylesFrom, to: sketchStylesTo }] : [];
1700
+ const renames = [...legacyRenames, ...sketchStylesRenames];
1701
+ if (!check) applyLegacyRenames(renames);
1361
1702
  const planningLegacy = legacyLayout !== null && check;
1362
1703
  const colorsAndTypeDir = planningLegacy ? opts.themesDir : opts.colorsAndTypeDir;
1363
1704
  const themesDir = planningLegacy ? legacyLayout.manifestsDir : opts.themesDir;
@@ -1414,7 +1755,7 @@ function migrateData(opts) {
1414
1755
  upgradedThemes: []
1415
1756
  };
1416
1757
  if (legacyPointers.length === 0) {
1417
- if (!legacyLayout) return empty;
1758
+ if (!legacyLayout && renames.length === 0) return empty;
1418
1759
  return { ...empty, status: check ? "planned" : "healed" };
1419
1760
  }
1420
1761
  const resolvers = {
@@ -1659,7 +2000,7 @@ function resolveDataDirs(opts = {}) {
1659
2000
  colorsAndTypeDir: opts.colorsAndTypeDir ? import_path4.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path4.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
1660
2001
  componentConfigsDir: opts.componentConfigsDir ? import_path4.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path4.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
1661
2002
  themesDir: opts.themesDir ? import_path4.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path4.default.resolve(fileConfig.themesDir) : sub("themes"),
1662
- sketchPresetsDir: sub("sketch-presets"),
2003
+ sketchStylesDir: sub("sketch-styles"),
1663
2004
  legacyManifestsDir: fileConfig.manifestsDir ? import_path4.default.resolve(fileConfig.manifestsDir) : void 0
1664
2005
  };
1665
2006
  }
@@ -1,4 +1,4 @@
1
- export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-CRfD1LdA.cjs';
1
+ export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.cjs';
2
2
 
3
3
  interface LegacyRename {
4
4
  from: string;
@@ -1,4 +1,4 @@
1
- export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-CRfD1LdA.js';
1
+ export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.js';
2
2
 
3
3
  interface LegacyRename {
4
4
  from: string;
@@ -7,14 +7,14 @@ import {
7
7
  normalizeTheme,
8
8
  planLegacyRenames,
9
9
  versionedFileResourceServer
10
- } from "../chunk-232GZGQU.js";
10
+ } from "../chunk-NDJJORKJ.js";
11
11
  import {
12
12
  CURRENT_COMPONENT_SCHEMA_VERSION
13
13
  } from "../chunk-NE6N66EE.js";
14
14
  import {
15
15
  readLiveTokensConfig,
16
16
  resolveDataDirs
17
- } from "../chunk-Y5CNFSSV.js";
17
+ } from "../chunk-RVE3MNKM.js";
18
18
 
19
19
  // vite-plugin/migrateData/migrateData.ts
20
20
  import fs from "fs";
@@ -90,8 +90,12 @@ function migrateData(opts) {
90
90
  configuredManifestsDir: opts.legacyManifestsDir
91
91
  };
92
92
  const legacyLayout = detectLegacyLayout(layoutInput);
93
- const renames = legacyLayout ? planLegacyRenames(legacyLayout, layoutInput) : [];
94
- if (legacyLayout && !check) applyLegacyRenames(renames);
93
+ const legacyRenames = legacyLayout ? planLegacyRenames(legacyLayout, layoutInput) : [];
94
+ const sketchStylesFrom = path.join(opts.dataDir, "sketch-presets");
95
+ const sketchStylesTo = path.join(opts.dataDir, "sketch-styles");
96
+ const sketchStylesRenames = fs.existsSync(sketchStylesFrom) ? [{ from: sketchStylesFrom, to: sketchStylesTo }] : [];
97
+ const renames = [...legacyRenames, ...sketchStylesRenames];
98
+ if (!check) applyLegacyRenames(renames);
95
99
  const planningLegacy = legacyLayout !== null && check;
96
100
  const colorsAndTypeDir = planningLegacy ? opts.themesDir : opts.colorsAndTypeDir;
97
101
  const themesDir = planningLegacy ? legacyLayout.manifestsDir : opts.themesDir;
@@ -148,7 +152,7 @@ function migrateData(opts) {
148
152
  upgradedThemes: []
149
153
  };
150
154
  if (legacyPointers.length === 0) {
151
- if (!legacyLayout) return empty;
155
+ if (!legacyLayout && renames.length === 0) return empty;
152
156
  return { ...empty, status: check ? "planned" : "healed" };
153
157
  }
154
158
  const resolvers = {
@@ -566,6 +566,43 @@ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
566
566
  }
567
567
  };
568
568
 
569
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-large-steps.ts
570
+ var BUNDLE3 = [
571
+ { name: "--editorial-xl-font-family", value: "var(--font-editorial)" },
572
+ { name: "--editorial-xl-font-size", value: "var(--font-size-xl)" },
573
+ { name: "--editorial-xl-font-weight", value: "var(--font-weight-normal)" },
574
+ { name: "--editorial-xl-line-height", value: "var(--line-height-tighter)" },
575
+ { name: "--editorial-xl-letter-spacing", value: "var(--letter-spacing-normal)" },
576
+ { name: "--editorial-lg-font-family", value: "var(--font-editorial)" },
577
+ { name: "--editorial-lg-font-size", value: "var(--font-size-lg)" },
578
+ { name: "--editorial-lg-font-weight", value: "var(--font-weight-normal)" },
579
+ { name: "--editorial-lg-line-height", value: "var(--line-height-tight)" },
580
+ { name: "--editorial-lg-letter-spacing", value: "var(--letter-spacing-normal)" }
581
+ ];
582
+ var tokensCssMigration_2026_08_27_editorialLargeSteps = {
583
+ id: "2026-08-27-editorial-large-steps",
584
+ kind: "additive",
585
+ description: "Add the --editorial-lg-* and --editorial-xl-* steps above the reading size",
586
+ apply(css) {
587
+ return ensureScale(css, {
588
+ sectionComment: "Editorial \u2014 the steps above the reading size",
589
+ anchorPrefixes: [
590
+ "--editorial-",
591
+ "--eyebrow-",
592
+ "--code-",
593
+ "--body-",
594
+ "--heading-",
595
+ "--letter-spacing-",
596
+ "--line-height-",
597
+ "--font-weight-",
598
+ "--font-size-",
599
+ "--font-"
600
+ ],
601
+ entries: BUNDLE3
602
+ });
603
+ }
604
+ };
605
+
569
606
  // vite-plugin/files/dataPaths.ts
570
607
  var import_fs = __toESM(require("fs"), 1);
571
608
  var import_path = __toESM(require("path"), 1);
@@ -613,7 +650,8 @@ var TOKENS_CSS_MIGRATIONS = [
613
650
  tokensCssMigration_2026_08_25_editorialTypeRole,
614
651
  tokensCssMigration_2026_08_26_gradientStops,
615
652
  tokensCssMigration_2026_08_27_backdropPolarity,
616
- tokensCssMigration_2026_08_27_editorialSizeSteps
653
+ tokensCssMigration_2026_08_27_editorialSizeSteps,
654
+ tokensCssMigration_2026_08_27_editorialLargeSteps
617
655
  ];
618
656
  function runTokensCssMigrations(css) {
619
657
  return foldMigrations(css, () => true);
@@ -1,4 +1,4 @@
1
- export { r as readLiveTokensConfig } from '../dataPaths-CRfD1LdA.cjs';
1
+ export { r as readLiveTokensConfig } from '../dataPaths-DZUzVv8H.cjs';
2
2
 
3
3
  /**
4
4
  * A `tokens-css` migration: a pure, idempotent transform on the text of a
@@ -1,4 +1,4 @@
1
- export { r as readLiveTokensConfig } from '../dataPaths-CRfD1LdA.js';
1
+ export { r as readLiveTokensConfig } from '../dataPaths-DZUzVv8H.js';
2
2
 
3
3
  /**
4
4
  * A `tokens-css` migration: a pure, idempotent transform on the text of a