@pixerate/editor 0.240.0 → 0.242.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 (67) hide show
  1. package/dist/animation-editor/controller.d.cts +10 -0
  2. package/dist/animation-editor/controller.d.ts +10 -0
  3. package/dist/animation-editor/effects.d.cts +1 -1
  4. package/dist/animation-editor/effects.d.ts +1 -1
  5. package/dist/animation-editor/index.cjs +195 -146
  6. package/dist/animation-editor/index.js +63 -14
  7. package/dist/{brushstrokeRender-WB67GMUP.js → brushstrokeRender-MOYGEXOC.js} +2 -2
  8. package/dist/{brushstrokeRender-MPOM7BFW.cjs → brushstrokeRender-UKADOV5D.cjs} +5 -5
  9. package/dist/canvas/index.cjs +15 -15
  10. package/dist/canvas/index.js +2 -2
  11. package/dist/{chunk-NKTNLJUJ.cjs → chunk-5BR7LC24.cjs} +99 -11
  12. package/dist/{chunk-ZXNO3ZOX.cjs → chunk-7F4G74UQ.cjs} +35 -35
  13. package/dist/{chunk-A7PQNIBX.cjs → chunk-7V7QMFTI.cjs} +14 -14
  14. package/dist/{chunk-AD7GA3TL.cjs → chunk-AFLMXITL.cjs} +23 -23
  15. package/dist/{chunk-JAOSL334.cjs → chunk-GHCSC2WP.cjs} +38 -16
  16. package/dist/{chunk-PP6BXVRL.cjs → chunk-HGGJ36HR.cjs} +1 -1
  17. package/dist/{chunk-BBUE3UJL.cjs → chunk-HW72ABGR.cjs} +86 -86
  18. package/dist/{chunk-7YGBSFC6.js → chunk-ILM6GYAX.js} +1 -1
  19. package/dist/{chunk-JWCKJNDR.cjs → chunk-K5DS2JTA.cjs} +6 -6
  20. package/dist/{chunk-THXFU3JB.cjs → chunk-KCMV2534.cjs} +2 -2
  21. package/dist/{chunk-WDDUPWVG.js → chunk-L3JFOTBQ.js} +1 -1
  22. package/dist/{chunk-3E36VDMJ.js → chunk-NE6OOKWJ.js} +1 -1
  23. package/dist/{chunk-SIK3LT6M.js → chunk-OFH6Q67U.js} +28 -6
  24. package/dist/{chunk-RV5DKZHU.js → chunk-QP2B3MID.js} +1 -1
  25. package/dist/{chunk-G3RUKJ5C.js → chunk-RXZL4NG5.js} +1 -1
  26. package/dist/{chunk-UUBO6RB5.js → chunk-UDBDYZET.js} +1 -1
  27. package/dist/{chunk-TEFQISBY.js → chunk-X3ZINLIP.js} +1 -1
  28. package/dist/{chunk-PJYG6FCF.js → chunk-XBZK47LV.js} +98 -10
  29. package/dist/{chunk-ZQIWBJGH.cjs → chunk-XNZFVYC2.cjs} +7 -7
  30. package/dist/{chunk-XK4SST43.js → chunk-ZDPLZDTT.js} +1 -1
  31. package/dist/effects/fake.d.cts +4 -0
  32. package/dist/effects/fake.d.ts +4 -0
  33. package/dist/effects/helpers.d.cts +6 -0
  34. package/dist/effects/helpers.d.ts +6 -0
  35. package/dist/effects/index.cjs +222 -94
  36. package/dist/effects/index.js +131 -3
  37. package/dist/effects/types.d.cts +31 -0
  38. package/dist/effects/types.d.ts +31 -0
  39. package/dist/image-editor/index.cjs +788 -788
  40. package/dist/image-editor/index.js +5 -5
  41. package/dist/paint-editor/controller.d.cts +67 -0
  42. package/dist/paint-editor/controller.d.ts +67 -0
  43. package/dist/paint-editor/effect-paint.d.cts +60 -3
  44. package/dist/paint-editor/effect-paint.d.ts +60 -3
  45. package/dist/paint-editor/index.cjs +682 -436
  46. package/dist/paint-editor/index.js +284 -38
  47. package/dist/paint-editor/stickers.d.cts +6 -0
  48. package/dist/paint-editor/stickers.d.ts +6 -0
  49. package/dist/paint-editor/thick.d.cts +4 -0
  50. package/dist/paint-editor/thick.d.ts +4 -0
  51. package/dist/paint-editor/wet.d.cts +8 -0
  52. package/dist/paint-editor/wet.d.ts +8 -0
  53. package/dist/vector/index.cjs +968 -968
  54. package/dist/vector/index.js +5 -5
  55. package/dist/video-editor/controller.d.cts +49 -1
  56. package/dist/video-editor/controller.d.ts +49 -1
  57. package/dist/video-editor/effect-path.d.cts +66 -0
  58. package/dist/video-editor/effect-path.d.ts +66 -0
  59. package/dist/video-editor/index.cjs +616 -427
  60. package/dist/video-editor/index.d.cts +1 -0
  61. package/dist/video-editor/index.d.ts +1 -0
  62. package/dist/video-editor/index.js +193 -4
  63. package/package.json +1 -1
  64. package/skills/pixerate-animation-editor/SKILL.md +1 -1
  65. package/skills/pixerate-paint-editor/SKILL.md +17 -21
  66. package/skills/pixerate-paint-editor/references/effect-paint.md +25 -0
  67. package/skills/pixerate-video-editor/SKILL.md +9 -2
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
- var _chunkZXNO3ZOXcjs = require('../chunk-ZXNO3ZOX.cjs');
3
+ var _chunk7F4G74UQcjs = require('../chunk-7F4G74UQ.cjs');
4
4
 
5
5
 
6
6
 
@@ -16,7 +16,7 @@ var _chunkDGWOGQJ5cjs = require('../chunk-DGWOGQJ5.cjs');
16
16
 
17
17
 
18
18
 
19
- var _chunkJWCKJNDRcjs = require('../chunk-JWCKJNDR.cjs');
19
+ var _chunkK5DS2JTAcjs = require('../chunk-K5DS2JTA.cjs');
20
20
 
21
21
 
22
22
 
@@ -39,8 +39,8 @@ var _chunkJWCKJNDRcjs = require('../chunk-JWCKJNDR.cjs');
39
39
 
40
40
 
41
41
 
42
- var _chunkTHXFU3JBcjs = require('../chunk-THXFU3JB.cjs');
43
- require('../chunk-NKTNLJUJ.cjs');
42
+ var _chunkKCMV2534cjs = require('../chunk-KCMV2534.cjs');
43
+ require('../chunk-5BR7LC24.cjs');
44
44
  require('../chunk-CVFAAZXE.cjs');
45
45
 
46
46
 
@@ -68,7 +68,8 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
68
68
 
69
69
 
70
70
 
71
- var _chunkJAOSL334cjs = require('../chunk-JAOSL334.cjs');
71
+
72
+ var _chunkGHCSC2WPcjs = require('../chunk-GHCSC2WP.cjs');
72
73
  require('../chunk-WOFXZ3XU.cjs');
73
74
  require('../chunk-PQ3H2AAN.cjs');
74
75
  require('../chunk-YQGCPL5X.cjs');
@@ -501,11 +502,11 @@ function shotLayersShapeProblems(shot, name) {
501
502
  if (layer.effect === void 0 && layer.subject === void 0) problems.push(`${where} needs an "effect", a "subject" or both.`);
502
503
  if (layer.effect !== void 0 && (typeof layer.effect !== "string" || !layer.effect)) problems.push(`${where}: "effect" must be an effect id.`);
503
504
  if (layer.subject !== void 0) {
504
- const kind = _chunkJWCKJNDRcjs.effectSubjectKind.call(void 0, layer.subject);
505
+ const kind = _chunkK5DS2JTAcjs.effectSubjectKind.call(void 0, layer.subject);
505
506
  if (kind === "video") problems.push(`${where}: an animation layer cannot play a video; use { "image" }, { "svg" }, { "text" } or { "slot" } (the video editor plays video).`);
506
507
  else if (!kind || !String(layer.subject[kind]).trim()) problems.push(`${where}: "subject" must be { "image": url }, { "svg": markup }, { "text": words } or { "slot": name }.`);
507
508
  }
508
- if (layer.role !== void 0 && !_chunkJAOSL334cjs.EFFECT_LAYER_ROLES.includes(layer.role)) problems.push(`${where}: "role" must be one of ${_chunkJAOSL334cjs.EFFECT_LAYER_ROLES.join(", ")}.`);
509
+ if (layer.role !== void 0 && !_chunkGHCSC2WPcjs.EFFECT_LAYER_ROLES.includes(layer.role)) problems.push(`${where}: "role" must be one of ${_chunkGHCSC2WPcjs.EFFECT_LAYER_ROLES.join(", ")}.`);
509
510
  if (layer.rect !== void 0) {
510
511
  const r = layer.rect;
511
512
  if (!isObject(r) || !["x", "y", "width", "height"].every((k) => isNum(r[k])) || !(r.width > 0 && r.height > 0)) problems.push(`${where}: "rect" must be { x, y, width, height } in artwork units, width and height > 0.`);
@@ -697,7 +698,7 @@ function smoothMotionTimes(points, start, duration, pacing = "even") {
697
698
  function motionTextLayout(nodes, id) {
698
699
  const group = _optionalChain([nodes, 'access', _5 => _5.get, 'call', _6 => _6(id), 'optionalAccess', _7 => _7.node]);
699
700
  if (!group || group.type !== "group") return null;
700
- const letters = _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
701
+ const letters = _chunkKCMV2534cjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
701
702
  if (!letters.length) return null;
702
703
  const lines = [];
703
704
  for (const l of [...letters].sort((a, c) => a.b.y + a.b.height / 2 - (c.b.y + c.b.height / 2))) {
@@ -782,21 +783,21 @@ function indexMotionNodes(nodes) {
782
783
  const out = /* @__PURE__ */ new Map();
783
784
  const walk = (list, parentWorld, ancestors) => {
784
785
  for (const node of list) {
785
- const local = _chunkTHXFU3JBcjs.vectorNodeBounds.call(void 0, node);
786
- const bounds = _chunkTHXFU3JBcjs.vectorNodeBounds.call(void 0, node, parentWorld);
786
+ const local = _chunkKCMV2534cjs.vectorNodeBounds.call(void 0, node);
787
+ const bounds = _chunkKCMV2534cjs.vectorNodeBounds.call(void 0, node, parentWorld);
787
788
  const center = local ? { x: local.x + local.width / 2, y: local.y + local.height / 2 } : { x: 0, y: 0 };
788
789
  if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds, box: local });
789
- if (node.type === "group") walk(node.children, _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
790
+ if (node.type === "group") walk(node.children, _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
790
791
  }
791
792
  };
792
- walk(nodes, _chunkTHXFU3JBcjs.IDENTITY_MATRIX, []);
793
+ walk(nodes, _chunkKCMV2534cjs.IDENTITY_MATRIX, []);
793
794
  indexCache.set(nodes, out);
794
795
  return out;
795
796
  }
796
797
  var solid = (paint) => typeof paint === "string" && paint !== "none" ? paint : void 0;
797
798
  function firstPaint(node, key) {
798
799
  if (node.type === "path") return solid(node[key]);
799
- for (const p of _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node)) {
800
+ for (const p of _chunkKCMV2534cjs.collectPathNodes.call(void 0, node)) {
800
801
  const s = solid(p[key]);
801
802
  if (s) return s;
802
803
  }
@@ -804,7 +805,7 @@ function firstPaint(node, key) {
804
805
  }
805
806
  function strokeReach(node) {
806
807
  let reach = 0;
807
- for (const p of node.type === "path" ? [node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node)) {
808
+ for (const p of node.type === "path" ? [node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node)) {
808
809
  if (p.stroke == null || p.stroke === "none") continue;
809
810
  const width = _nullishCoalesce(p.strokeWidth, () => ( 1));
810
811
  reach = Math.max(reach, p.strokeAlign === "outside" ? width : p.strokeAlign === "inside" ? 0 : width / 2);
@@ -874,7 +875,7 @@ function motionRestValue(entry, property, artwork) {
874
875
  case "stroke":
875
876
  return _nullishCoalesce((node && firstPaint(node, property)), () => ( "transparent"));
876
877
  case "strokeWidth": {
877
- const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node)[0] : void 0;
878
+ const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkKCMV2534cjs.collectPathNodes.call(void 0, node)[0] : void 0;
878
879
  return _nullishCoalesce(_optionalChain([path, 'optionalAccess', _14 => _14.strokeWidth]), () => ( 1));
879
880
  }
880
881
  case "shape":
@@ -985,12 +986,12 @@ function resolveMotionCamera(camera, scene) {
985
986
  const r = camera;
986
987
  return { x: r.x, y: r.y, width: r.width, height: r.height };
987
988
  }
988
- function motionPathLength(node, parentWorld = _chunkTHXFU3JBcjs.IDENTITY_MATRIX) {
989
+ function motionPathLength(node, parentWorld = _chunkKCMV2534cjs.IDENTITY_MATRIX) {
989
990
  let longest = 0;
990
- const paths = node.type === "path" ? [node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node);
991
+ const paths = node.type === "path" ? [node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node);
991
992
  for (const p of paths) {
992
993
  try {
993
- longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
994
+ longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
994
995
  } catch (e2) {
995
996
  }
996
997
  }
@@ -1126,9 +1127,9 @@ function compileMotionScene(scene) {
1126
1127
  const start = t;
1127
1128
  let cursor = start;
1128
1129
  const f = motionShotTimeScale(shot);
1129
- const moveIn = shot.camera ? _chunkJAOSL334cjs.cameraMoveParts.call(void 0, shot.camera.in) : void 0;
1130
- const transitionMs = index > 0 && shot.transition ? (_nullishCoalesce(shot.transition.ms, () => ( _chunkJAOSL334cjs.EFFECT_TRANSITION_MS))) * f : 0;
1131
- const moveDuring = shot.camera ? _chunkJAOSL334cjs.cameraMoveParts.call(void 0, shot.camera.during) : void 0;
1130
+ const moveIn = shot.camera ? _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, shot.camera.in) : void 0;
1131
+ const transitionMs = index > 0 && shot.transition ? (_nullishCoalesce(shot.transition.ms, () => ( _chunkGHCSC2WPcjs.EFFECT_TRANSITION_MS))) * f : 0;
1132
+ const moveDuring = shot.camera ? _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, shot.camera.during) : void 0;
1132
1133
  let playsIn = false;
1133
1134
  if (shot.camera) {
1134
1135
  const framed = motionCameraFramed(shot.camera);
@@ -1266,12 +1267,12 @@ function compileMotionScene(scene) {
1266
1267
  const order2 = _nullishCoalesce(o.order, () => ( "together"));
1267
1268
  const pace = _nullishCoalesce(o.pace, () => ( "time"));
1268
1269
  if (order2 === "together" && pace === "time") return null;
1269
- const paths = entry.node.type === "path" ? [entry.node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, entry.node);
1270
+ const paths = entry.node.type === "path" ? [entry.node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, entry.node);
1270
1271
  let list = paths.map((p) => {
1271
1272
  const at = nodes.get(p.id);
1272
1273
  let first = { x: 0, y: 0 };
1273
1274
  try {
1274
- const m = _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _42 => _42.parentWorld]), () => ( _chunkTHXFU3JBcjs.IDENTITY_MATRIX)), { effects: false })[0];
1275
+ const m = _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _42 => _42.parentWorld]), () => ( _chunkKCMV2534cjs.IDENTITY_MATRIX)), { effects: false })[0];
1275
1276
  if (m && m.type === "M") first = { x: m.x, y: m.y };
1276
1277
  } catch (e3) {
1277
1278
  }
@@ -1383,17 +1384,17 @@ function compileMotionScene(scene) {
1383
1384
  let dx = _nullishCoalesce(_optionalChain([command3, 'access', _45 => _45.by, 'optionalAccess', _46 => _46.x]), () => ( 0));
1384
1385
  let dy = _nullishCoalesce(_optionalChain([command3, 'access', _47 => _47.by, 'optionalAccess', _48 => _48.y]), () => ( 0));
1385
1386
  if (command3.to) {
1386
- const inv = _chunkTHXFU3JBcjs.invertMatrix.call(void 0, entry.parentWorld);
1387
- const target = _chunkTHXFU3JBcjs.applyMatrix.call(void 0, inv, command3.to);
1387
+ const inv = _chunkKCMV2534cjs.invertMatrix.call(void 0, entry.parentWorld);
1388
+ const target = _chunkKCMV2534cjs.applyMatrix.call(void 0, inv, command3.to);
1388
1389
  dx = target.x - (entry.center.x + num2("x"));
1389
1390
  dy = target.y - (entry.center.y + num2("y"));
1390
1391
  }
1391
1392
  if (_optionalChain([command3, 'access', _49 => _49.via, 'optionalAccess', _50 => _50.length])) {
1392
- const inv = _chunkTHXFU3JBcjs.invertMatrix.call(void 0, entry.parentWorld);
1393
+ const inv = _chunkKCMV2534cjs.invertMatrix.call(void 0, entry.parentWorld);
1393
1394
  const x0 = num2("x");
1394
1395
  const y0 = num2("y");
1395
1396
  const add = command3.blend === "add";
1396
- const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkTHXFU3JBcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1397
+ const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkKCMV2534cjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1397
1398
  const times = _optionalChain([command3, 'access', _51 => _51.times, 'optionalAccess', _52 => _52.length]) === command3.via.length ? [start, ...command3.times.map((f) => start + f * (end - start)), end] : smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(command3.pacing, () => ( "even")));
1398
1399
  for (const axis of ["x", "y"]) {
1399
1400
  const base = add ? 0 : axis === "x" ? x0 : y0;
@@ -1497,7 +1498,7 @@ function motionShotAt(timeline, time) {
1497
1498
  // src/animation-editor/camera.ts
1498
1499
  var windowCache = /* @__PURE__ */ new WeakMap();
1499
1500
  function motionShotCameraMove(shot, role) {
1500
- return _chunkJAOSL334cjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _55 => _55.camera, 'optionalAccess', _56 => _56[role === "transition" ? "in" : "during"]]));
1501
+ return _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _55 => _55.camera, 'optionalAccess', _56 => _56[role === "transition" ? "in" : "during"]]));
1501
1502
  }
1502
1503
  var motionCameraStage = (scene) => ({ width: scene.artwork.width, height: scene.artwork.height });
1503
1504
  var effectsPlayCamera = (provider) => !!provider && provider.capabilities.supportsCamera === true && typeof provider.cameraView === "function";
@@ -1519,7 +1520,7 @@ function motionCameraWindows(scene, provider) {
1519
1520
  const track = timeline.tracks.get(motionTrackKey("", "camera"));
1520
1521
  const boxView = (t) => {
1521
1522
  const b = trackValue(track, t);
1522
- return _chunkJAOSL334cjs.cameraViewOfBox.call(void 0, Array.isArray(b) ? { x: b[0], y: b[1], width: b[2], height: b[3] } : full, stage);
1523
+ return _chunkGHCSC2WPcjs.cameraViewOfBox.call(void 0, Array.isArray(b) ? { x: b[0], y: b[1], width: b[2], height: b[3] } : full, stage);
1523
1524
  };
1524
1525
  const view = (move, values, from, to, u, ms2) => {
1525
1526
  try {
@@ -1535,7 +1536,7 @@ function motionCameraWindows(scene, provider) {
1535
1536
  const eases = timing.commandsStart > timing.start && !!_optionalChain([track, 'optionalAccess', _57 => _57.some, 'call', _58 => _58((seg) => seg.shot === timing.id)]);
1536
1537
  const framed = !!_optionalChain([track, 'optionalAccess', _59 => _59.some, 'call', _60 => _60((seg) => seg.shot === timing.id)]);
1537
1538
  if (timing.cameraIn && timing.commandsStart > timing.start) {
1538
- const spec = _chunkJAOSL334cjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _61 => _61.camera, 'optionalAccess', _62 => _62.in]));
1539
+ const spec = _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _61 => _61.camera, 'optionalAccess', _62 => _62.in]));
1539
1540
  const from = _nullishCoalesce(carry, () => ( boxView(timing.start)));
1540
1541
  const to = boxView(timing.commandsStart);
1541
1542
  if (view(spec.move, spec.values, from, to, 0, timing.commandsStart - timing.start)) {
@@ -1547,7 +1548,7 @@ function motionCameraWindows(scene, provider) {
1547
1548
  carry = null;
1548
1549
  } else if (framed) carry = null;
1549
1550
  if (timing.cameraDuring && timing.end > timing.commandsEnd) {
1550
- const spec = _chunkJAOSL334cjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _63 => _63.camera, 'optionalAccess', _64 => _64.during]));
1551
+ const spec = _chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'access', _63 => _63.camera, 'optionalAccess', _64 => _64.during]));
1551
1552
  const from = _nullishCoalesce(carry, () => ( boxView(timing.commandsEnd)));
1552
1553
  const ms2 = timing.end - timing.commandsEnd;
1553
1554
  const last = view(spec.move, spec.values, from, from, 1, ms2);
@@ -1564,8 +1565,8 @@ var lerp = (a, b, t) => a + (b - a) * t;
1564
1565
  var smooth = (t) => t * t * (3 - 2 * t);
1565
1566
  function easeViews(from, to, u, stage) {
1566
1567
  const k = smooth(Math.min(1, Math.max(0, u)));
1567
- const a = _chunkJAOSL334cjs.cameraBoxOfView.call(void 0, from, stage);
1568
- const b = _chunkJAOSL334cjs.cameraBoxOfView.call(void 0, to, stage);
1568
+ const a = _chunkGHCSC2WPcjs.cameraBoxOfView.call(void 0, from, stage);
1569
+ const b = _chunkGHCSC2WPcjs.cameraBoxOfView.call(void 0, to, stage);
1569
1570
  const zoom = from.zoom * Math.pow(to.zoom / from.zoom, k);
1570
1571
  const cx = lerp(a.x + a.width / 2, b.x + b.width / 2, k);
1571
1572
  const cy = lerp(a.y + a.height / 2, b.y + b.height / 2, k);
@@ -1597,7 +1598,7 @@ function motionCameraViewAt(scene, time, provider) {
1597
1598
  return retaken ? null : before.after;
1598
1599
  }
1599
1600
  function motionCameraBox(view, scene) {
1600
- return _chunkJAOSL334cjs.cameraBoxOfView.call(void 0, view, motionCameraStage(scene));
1601
+ return _chunkGHCSC2WPcjs.cameraBoxOfView.call(void 0, view, motionCameraStage(scene));
1601
1602
  }
1602
1603
  function motionCameraTransform(view, width) {
1603
1604
  if (!view || !view.tilt && !view.turn) return "";
@@ -1638,7 +1639,7 @@ async function checkMotionCameraMoves(scene, provider) {
1638
1639
  const spec = shot.camera[field];
1639
1640
  if (spec === void 0) continue;
1640
1641
  try {
1641
- await _chunkJAOSL334cjs.resolveCameraMoveSpec.call(void 0, provider, spec, role);
1642
+ await _chunkGHCSC2WPcjs.resolveCameraMoveSpec.call(void 0, provider, spec, role);
1642
1643
  } catch (error) {
1643
1644
  const code = error.code === "invalid_values" || /preset/.test(error.message) ? "camera-move-values" : "camera-move-unknown";
1644
1645
  issues.push(_chunkDGWOGQJ5cjs.motionIssue.call(void 0, code, error.message, { shot: shot.id }));
@@ -1666,7 +1667,7 @@ function motionLayerSpans(scene) {
1666
1667
  (_nullishCoalesce(shot.layers, () => ( []))).forEach((layer, index) => {
1667
1668
  const start = at(shotIndex2, layer.from, shots[shotIndex2].start);
1668
1669
  const end = Math.max(start, at(shotIndex2, _nullishCoalesce(layer.until, () => ( { shots: 1 })), total));
1669
- out.push({ layer, shot: shot.id, shotIndex: shotIndex2, index, role: _chunkJWCKJNDRcjs.effectLayerRole.call(void 0, layer), start, end });
1670
+ out.push({ layer, shot: shot.id, shotIndex: shotIndex2, index, role: _chunkK5DS2JTAcjs.effectLayerRole.call(void 0, layer), start, end });
1670
1671
  });
1671
1672
  });
1672
1673
  spanCache.set(scene, out);
@@ -1761,7 +1762,7 @@ var MotionLayersEngine = (_class = class {
1761
1762
  __init6() {this.generation = 0}
1762
1763
 
1763
1764
  constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);
1764
- this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkJAOSL334cjs.EffectsSlot)()));
1765
+ this.slot = _nullishCoalesce(options.slot, () => ( new (0, _chunkGHCSC2WPcjs.EffectsSlot)()));
1765
1766
  this.host = _nullishCoalesce(options.host, () => ( null));
1766
1767
  this.frameSvg = options.frameSvg;
1767
1768
  this.options = { scale: _nullishCoalesce(options.scale, () => ( 1)), maxSize: _nullishCoalesce(options.maxSize, () => ( 1280)), fps: _nullishCoalesce(options.fps, () => ( 30)), maxEntries: _nullishCoalesce(options.maxEntries, () => ( 160)) };
@@ -1881,8 +1882,8 @@ var MotionLayersEngine = (_class = class {
1881
1882
  const effect = layer.effect;
1882
1883
  this.request(key, { layer: layer.id }, async () => {
1883
1884
  const d = await this.describe(effect);
1884
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, layer.values);
1885
- const input = _chunkJWCKJNDRcjs.effectLayerInput.call(void 0, d);
1885
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, layer.values);
1886
+ const input = _chunkK5DS2JTAcjs.effectLayerInput.call(void 0, d);
1886
1887
  const inputs = layer.subject && input ? { [input]: await this.subjectPixels(layer.subject, size) } : void 0;
1887
1888
  const pixels = await this.pool.render(provider, effect, size, { time, values, ...inputs ? { inputs } : {} });
1888
1889
  return host.encode(pixels);
@@ -1903,7 +1904,7 @@ var MotionLayersEngine = (_class = class {
1903
1904
  const fromKey = `from:${sceneId(scene)}:${active.shot}:${size.width}x${size.height}`;
1904
1905
  this.request(key, { transition: active.shot }, async () => {
1905
1906
  const d = await this.describe(t.effect);
1906
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, t.values);
1907
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, t.values);
1907
1908
  frameSvg(scene, Math.max(0, active.start - 1e-3));
1908
1909
  frameSvg(scene, at);
1909
1910
  await this.idleExcept(key);
@@ -2016,13 +2017,13 @@ function morphBetween(a, b) {
2016
2017
  let inner = morphCache.get(a);
2017
2018
  if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
2018
2019
  let morph = inner.get(b);
2019
- if (!morph) inner.set(b, morph = _chunkZXNO3ZOXcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
2020
+ if (!morph) inner.set(b, morph = _chunk7F4G74UQcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
2020
2021
  return morph;
2021
2022
  }
2022
2023
  function shapeIn(entry, shape) {
2023
2024
  if (shape === entry) return entry.node;
2024
- const m = _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkTHXFU3JBcjs.invertMatrix.call(void 0, entry.parentWorld));
2025
- return { ...shape.node, ..._chunkTHXFU3JBcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
2025
+ const m = _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkKCMV2534cjs.invertMatrix.call(void 0, entry.parentWorld));
2026
+ return { ...shape.node, ..._chunkKCMV2534cjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
2026
2027
  }
2027
2028
  function shapeAt(entry, timeline, nodes, time) {
2028
2029
  const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
@@ -2042,7 +2043,7 @@ function shapeAt(entry, timeline, nodes, time) {
2042
2043
  function motionFollowRoute(entry, path) {
2043
2044
  if (!path || path.node.type !== "path") return null;
2044
2045
  try {
2045
- return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkTHXFU3JBcjs.invertMatrix.call(void 0, entry.parentWorld));
2046
+ return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkKCMV2534cjs.invertMatrix.call(void 0, entry.parentWorld));
2046
2047
  } catch (e6) {
2047
2048
  return null;
2048
2049
  }
@@ -2076,9 +2077,9 @@ function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry
2076
2077
  const scaleX = read("scaleX", 1);
2077
2078
  const scaleY = read("scaleY", 1);
2078
2079
  const c = entry.center;
2079
- let matrix = _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkTHXFU3JBcjs.rotateMatrix.call(void 0, rotation, c)), _chunkTHXFU3JBcjs.translateMatrix.call(void 0, dx, dy));
2080
+ let matrix = _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkKCMV2534cjs.rotateMatrix.call(void 0, rotation, c)), _chunkKCMV2534cjs.translateMatrix.call(void 0, dx, dy));
2080
2081
  const along = follow ? followAt(entry, timeline, nodes, time) : null;
2081
- if (along) matrix = _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, matrix, _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkTHXFU3JBcjs.rotateMatrix.call(void 0, along.angle)), _chunkTHXFU3JBcjs.translateMatrix.call(void 0, along.x, along.y)));
2082
+ if (along) matrix = _chunkKCMV2534cjs.multiplyMatrices.call(void 0, matrix, _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkKCMV2534cjs.rotateMatrix.call(void 0, along.angle)), _chunkKCMV2534cjs.translateMatrix.call(void 0, along.x, along.y)));
2082
2083
  return { matrix, dx, dy, rotation, scaleX, scaleY, follow: along };
2083
2084
  }
2084
2085
  function motionNodeClips(id, timeline, time) {
@@ -2145,7 +2146,7 @@ function motionFrameAt(scene, time, options = {}) {
2145
2146
  const start = Math.min(1, Math.max(0, typeof drawStart === "number" ? drawStart : 0));
2146
2147
  const end = Math.min(1, Math.max(0, typeof drawEnd === "number" ? drawEnd : 1));
2147
2148
  if (start > 0 || end < 1) {
2148
- const trim = _chunkTHXFU3JBcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
2149
+ const trim = _chunkKCMV2534cjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
2149
2150
  p = { ...p, effects: [trim, ...(_nullishCoalesce(p.effects, () => ( []))).filter((e) => e.id !== MOTION_DRAW_EFFECT_ID)] };
2150
2151
  }
2151
2152
  }
@@ -2159,8 +2160,8 @@ function motionFrameAt(scene, time, options = {}) {
2159
2160
  if (o >= 1) delete out.opacity;
2160
2161
  }
2161
2162
  const offset = options.offsets === false ? null : motionNodeOffset(entry, timeline, time, nodes);
2162
- if (offset && !_chunkTHXFU3JBcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
2163
- const m = _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
2163
+ if (offset && !_chunkKCMV2534cjs.isIdentityMatrix.call(void 0, offset.matrix)) {
2164
+ const m = _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _chunkKCMV2534cjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
2164
2165
  out = { ...out, transform: m };
2165
2166
  }
2166
2167
  return out;
@@ -2181,8 +2182,8 @@ function motionFrameToSvg(scene, time, options = {}) {
2181
2182
  const wrap = { ...options.wrap };
2182
2183
  for (const [id, clips] of Object.entries(frame.clips))
2183
2184
  wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
2184
- if (!motionSceneHasLayers(scene)) return withCameraViewEffects(withViewBox(_chunkTHXFU3JBcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera), frame.view, frame.camera, prefix);
2185
- const art = _chunkTHXFU3JBcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap, background: false });
2185
+ if (!motionSceneHasLayers(scene)) return withCameraViewEffects(withViewBox(_chunkKCMV2534cjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera), frame.view, frame.camera, prefix);
2186
+ const art = _chunkKCMV2534cjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap, background: false });
2186
2187
  let svg = withViewBox(withMotionShotLayers(art, scene, time, frame.camera, options.layers, options.background !== false), frame.camera);
2187
2188
  const transition = options.transitions === false ? null : motionTransitionAt(scene, time);
2188
2189
  if (transition) {
@@ -2373,8 +2374,8 @@ function visibleAt(timeline, id, time, node) {
2373
2374
  if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
2374
2375
  const circle = clip("clipCircle");
2375
2376
  if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
2376
- const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
2377
- const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node).some((p) => {
2377
+ const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
2378
+ const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkKCMV2534cjs.collectPathNodes.call(void 0, node).length === 0 || _chunkKCMV2534cjs.collectPathNodes.call(void 0, node).some((p) => {
2378
2379
  const v = trackValue(timeline.tracks.get(motionTrackKey(p.id, "drawEnd")), time);
2379
2380
  return typeof v !== "number" || v > 0.01;
2380
2381
  }));
@@ -2461,7 +2462,7 @@ function checkMotionScene(scene) {
2461
2462
  }
2462
2463
  for (const id of targets) {
2463
2464
  const node = nodes.get(id).node;
2464
- const paths = node.type === "path" ? [node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node);
2465
+ const paths = node.type === "path" ? [node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node);
2465
2466
  if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
2466
2467
  issues.push(_chunkDGWOGQJ5cjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
2467
2468
  }
@@ -2474,7 +2475,7 @@ function checkMotionScene(scene) {
2474
2475
  else
2475
2476
  for (const id of targets) {
2476
2477
  const node = nodes.get(id).node;
2477
- const paths = node.type === "path" ? [node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node);
2478
+ const paths = node.type === "path" ? [node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node);
2478
2479
  if (paths.some((p) => typeof p[key] !== "string"))
2479
2480
  issues.push(_chunkDGWOGQJ5cjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient or no ${key}, so a colour pulse cannot tint it; give it a solid ${key} or pulse the ${key === "fill" ? "stroke" : "fill"}.`, { ...where, ids: [id] }));
2480
2481
  }
@@ -2919,7 +2920,7 @@ function motionNodePose(scene, id, time) {
2919
2920
  if (!entry) throw new Error(`There is no element ${_chunkDGWOGQJ5cjs.namedWithSuggestion.call(void 0, id, [...indexMotionNodes(scene.artwork.nodes).keys()])} in the artwork.`);
2920
2921
  const timeline = compileMotionScene(scene);
2921
2922
  const drawn = indexMotionNodes(motionFrameAt(scene, time).document.nodes).get(id);
2922
- const centre = _chunkTHXFU3JBcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2923
+ const centre = _chunkKCMV2534cjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2923
2924
  const paint = (property) => _nullishCoalesce(trackValue(timeline.tracks.get(motionTrackKey(id, property)), time), () => ( motionRestValue(entry, property, scene.artwork)));
2924
2925
  const fill = paint("fill");
2925
2926
  const stroke = paint("stroke");
@@ -3266,7 +3267,7 @@ function toFlairSvgMotion(scene, options = {}) {
3266
3267
  raw: (t) => transformAt(t, true)
3267
3268
  });
3268
3269
  }
3269
- const paths = node.type === "path" ? [node] : _chunkTHXFU3JBcjs.collectPathNodes.call(void 0, node);
3270
+ const paths = node.type === "path" ? [node] : _chunkKCMV2534cjs.collectPathNodes.call(void 0, node);
3270
3271
  for (const path of paths) {
3271
3272
  if (pathsSeen.has(path.id)) continue;
3272
3273
  pathsSeen.add(path.id);
@@ -3288,7 +3289,7 @@ function toFlairSvgMotion(scene, options = {}) {
3288
3289
  if (shapeSegments.length) {
3289
3290
  if (node.type !== "path") notes.push(`"${id}" is a group: its morph or effect animation is not exported (Flair tweens one path's "d").`);
3290
3291
  else {
3291
- const inverse = _chunkTHXFU3JBcjs.invertMatrix.call(void 0, _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, node));
3292
+ const inverse = _chunkKCMV2534cjs.invertMatrix.call(void 0, _chunkKCMV2534cjs.nodeMatrix.call(void 0, node));
3292
3293
  channels.push({
3293
3294
  id,
3294
3295
  kind: "attr",
@@ -3297,9 +3298,9 @@ function toFlairSvgMotion(scene, options = {}) {
3297
3298
  exact: () => false,
3298
3299
  value: (t) => {
3299
3300
  const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
3300
- const now = _chunkTHXFU3JBcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _151 => _151(frame.document.nodes), 'access', _152 => _152.get, 'call', _153 => _153(id), 'optionalAccess', _154 => _154.node]));
3301
+ const now = _chunkKCMV2534cjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _151 => _151(frame.document.nodes), 'access', _152 => _152.get, 'call', _153 => _153(id), 'optionalAccess', _154 => _154.node]));
3301
3302
  if (!now || now.type !== "path") return "";
3302
- const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, now, _chunkTHXFU3JBcjs.IDENTITY_MATRIX, { effects: false }), inverse);
3303
+ const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, now, _chunkKCMV2534cjs.IDENTITY_MATRIX, { effects: false }), inverse);
3303
3304
  return _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
3304
3305
  }
3305
3306
  });
@@ -3320,7 +3321,7 @@ function toFlairSvgMotion(scene, options = {}) {
3320
3321
  if (w) return `${w.move}@${w.shot}`;
3321
3322
  const seg = camera.find((x) => t >= x.start - 1e-6 && t < Math.max(x.end, x.start + 1e-3));
3322
3323
  const shot = seg ? scene.shots.find((x) => x.id === seg.shot) : void 0;
3323
- const move = _optionalChain([_chunkJAOSL334cjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _155 => _155.camera, 'optionalAccess', _156 => _156.in])), 'optionalAccess', _157 => _157.move]);
3324
+ const move = _optionalChain([_chunkGHCSC2WPcjs.cameraMoveParts.call(void 0, _optionalChain([shot, 'optionalAccess', _155 => _155.camera, 'optionalAccess', _156 => _156.in])), 'optionalAccess', _157 => _157.move]);
3324
3325
  return move && shot ? `${move}@${shot.id}` : void 0;
3325
3326
  };
3326
3327
  const unplayed = scene.shots.filter((x) => x.camera && (x.camera.in !== void 0 || x.camera.during !== void 0) && !windows.some((w) => w.shot === x.id));
@@ -3439,7 +3440,7 @@ function toFlairSvgMotion(scene, options = {}) {
3439
3440
  }
3440
3441
  if (scene.motionBlur) notes.push("Motion blur is drawn on the stage only; Flair plays the scene sharp.");
3441
3442
  if (trigger && (_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") notes.push(`The scene plays on ${trigger}, so its loop does not apply in Flair.`);
3442
- let svg = _chunkTHXFU3JBcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkTHXFU3JBcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
3443
+ let svg = _chunkKCMV2534cjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkKCMV2534cjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
3443
3444
  if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
3444
3445
  let motion = { svg, animate };
3445
3446
  if (_optionalChain([scene, 'access', _160 => _160.controls, 'optionalAccess', _161 => _161.length])) {
@@ -3537,14 +3538,14 @@ function easingOf(ease, fallback) {
3537
3538
  return fallback;
3538
3539
  }
3539
3540
  function poseOf(value, entry) {
3540
- const t = _chunkTHXFU3JBcjs.parseSvgTransform.call(void 0, String(value));
3541
- const o = _chunkTHXFU3JBcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkTHXFU3JBcjs.invertMatrix.call(void 0, _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
3541
+ const t = _chunkKCMV2534cjs.parseSvgTransform.call(void 0, String(value));
3542
+ const o = _chunkKCMV2534cjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkKCMV2534cjs.invertMatrix.call(void 0, _chunkKCMV2534cjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
3542
3543
  const sx = Math.hypot(o[0], o[1]);
3543
3544
  if (!(sx > 1e-9)) return null;
3544
3545
  const sy = (o[0] * o[3] - o[1] * o[2]) / sx;
3545
3546
  if (Math.abs(o[2] + o[1] / sx * sy) > 1e-6 || Math.abs(o[3] - o[0] / sx * sy) > 1e-6) return null;
3546
3547
  const c = entry.center;
3547
- const moved = _chunkTHXFU3JBcjs.applyMatrix.call(void 0, o, c);
3548
+ const moved = _chunkKCMV2534cjs.applyMatrix.call(void 0, o, c);
3548
3549
  return { dx: moved.x - c.x, dy: moved.y - c.y, rotation: Math.atan2(o[1], o[0]) * 180 / Math.PI, sx, sy };
3549
3550
  }
3550
3551
  var near = (a, b, eps = 1e-6) => Math.abs(a - b) < eps;
@@ -3629,7 +3630,7 @@ function fromFlairSvgMotion(input, options = {}) {
3629
3630
  const notes = [];
3630
3631
  if (!input || typeof input.svg !== "string") throw new Error('Give a Flair SvgMotion: { svg: "<svg \u2026>", animate: [ \u2026 ] }.');
3631
3632
  const { motion, controls } = resolvePlaceholders(input, notes);
3632
- const artwork = _chunkTHXFU3JBcjs.parseVectorSvg.call(void 0, motion.svg);
3633
+ const artwork = _chunkKCMV2534cjs.parseVectorSvg.call(void 0, motion.svg);
3633
3634
  const nodes = indexMotionNodes(artwork.nodes);
3634
3635
  const byStep = /* @__PURE__ */ new Map();
3635
3636
  for (const anim of _nullishCoalesce(motion.animate, () => ( []))) {
@@ -3876,9 +3877,9 @@ function toLottie(scene, options = {}) {
3876
3877
  const items = [];
3877
3878
  const shapeSegments = [...timeline.tracks.entries()].filter(([k]) => k.startsWith(`${path.id}\0`) && (k.endsWith("\0shape") || k.includes("\0effect:"))).flatMap(([, v]) => v);
3878
3879
  const geometryAt = (t) => {
3879
- if (!shapeSegments.length) return _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, path);
3880
+ if (!shapeSegments.length) return _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, path);
3880
3881
  const now = _optionalChain([indexMotionNodes, 'call', _170 => _170(motionFrameAt(scene, t, { draw: false, offsets: false }).document.nodes), 'access', _171 => _171.get, 'call', _172 => _172(path.id), 'optionalAccess', _173 => _173.node]);
3881
- return now && now.type === "path" ? _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, _chunkTHXFU3JBcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkTHXFU3JBcjs.vectorPathWorldBezier.call(void 0, path);
3882
+ return now && now.type === "path" ? _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, _chunkKCMV2534cjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, path);
3882
3883
  };
3883
3884
  const rest = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(0)), round4);
3884
3885
  rest.forEach((contour, n2) => {
@@ -3951,13 +3952,13 @@ function toLottie(scene, options = {}) {
3951
3952
  const innerTr = STATIC_TR();
3952
3953
  if (node.type === "path") inner = [...pathShapes(node)];
3953
3954
  else if (node.type === "text" || node.type === "instance") {
3954
- const drawn = _chunkTHXFU3JBcjs.expandVectorAppearance.call(void 0, node);
3955
+ const drawn = _chunkKCMV2534cjs.expandVectorAppearance.call(void 0, node);
3955
3956
  inner = drawn.type === "path" ? [...pathShapes(drawn)] : drawn.children.filter((c) => c.type === "path").reverse().flatMap((c) => [...pathShapes(c)]);
3956
- notes.push(`"${node.id}": text is exported as its outlines${_chunkTHXFU3JBcjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3957
+ notes.push(`"${node.id}": text is exported as its outlines${_chunkKCMV2534cjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3957
3958
  } else {
3958
3959
  inner = shown(node.children).reverse().map(nodeGroup);
3959
- const m = _chunkTHXFU3JBcjs.nodeMatrix.call(void 0, node);
3960
- if (m !== _chunkTHXFU3JBcjs.IDENTITY_MATRIX) {
3960
+ const m = _chunkKCMV2534cjs.nodeMatrix.call(void 0, node);
3961
+ if (m !== _chunkKCMV2534cjs.IDENTITY_MATRIX) {
3961
3962
  const parts = staticParts(m);
3962
3963
  if (!parts) notes.push(`"${node.id}": its transform skews, which is not exported; it is drawn without the skew.`);
3963
3964
  else {
@@ -3970,7 +3971,7 @@ function toLottie(scene, options = {}) {
3970
3971
  const body = { ty: "gr", nm: `${node.id} (own)`, it: [...inner, innerTr] };
3971
3972
  return { ty: "gr", nm: _nullishCoalesce(node.name, () => ( node.id)), it: [body, poseTransform(entry)] };
3972
3973
  };
3973
- const artwork = { ...scene.artwork, nodes: _chunkTHXFU3JBcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3974
+ const artwork = { ...scene.artwork, nodes: _chunkKCMV2534cjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3974
3975
  const content = shown(artwork.nodes).reverse().map(nodeGroup);
3975
3976
  if (artwork.background && rgba(artwork.background))
3976
3977
  content.push({ ty: "gr", nm: "Background", it: [{ ty: "rc", nm: "Background", p: { a: 0, k: [artwork.width / 2, artwork.height / 2] }, s: { a: 0, k: [artwork.width, artwork.height] }, r: { a: 0, k: 0 } }, { ty: "fl", c: { a: 0, k: rgba(artwork.background).map(round4) }, o: { a: 0, k: 100 }, r: 1 }, STATIC_TR()] });
@@ -4069,11 +4070,11 @@ function preset(prst, w, h) {
4069
4070
  const poly = (pts) => [{ closed: true, anchors: pts.map(([x, y]) => ({ x, y })) }];
4070
4071
  switch (prst) {
4071
4072
  case "rect":
4072
- return [_chunkTHXFU3JBcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4073
+ return [_chunkKCMV2534cjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4073
4074
  case "roundRect":
4074
- return [_chunkTHXFU3JBcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
4075
+ return [_chunkKCMV2534cjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
4075
4076
  case "ellipse":
4076
- return [_chunkTHXFU3JBcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4077
+ return [_chunkKCMV2534cjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4077
4078
  case "triangle":
4078
4079
  return poly([[w / 2, 0], [w, h], [0, h]]);
4079
4080
  case "rtTriangle":
@@ -4181,7 +4182,7 @@ function shapes(ctx, tree, map) {
4181
4182
  let subpaths = cust ? custom(cust, w, h) : prst ? preset(prst, w, h) : null;
4182
4183
  if (!subpaths) {
4183
4184
  if (prst) ctx.notes.push(`"${name}" is a ${prst}, drawn as its bounding rectangle.`);
4184
- subpaths = [_chunkTHXFU3JBcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4185
+ subpaths = [_chunkKCMV2534cjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4185
4186
  }
4186
4187
  const style = kid(el, "style");
4187
4188
  const fill = kid(spPr, "noFill") ? null : _nullishCoalesce(colour(ctx, kid(spPr, "solidFill")), () => ( (el.localName === "cxnSp" ? null : colour(ctx, kid(style, "fillRef")))));
@@ -4424,7 +4425,7 @@ var kindHint = (d) => {
4424
4425
  function withPreset(d, preset2, values) {
4425
4426
  if (preset2 === void 0) return values;
4426
4427
  const p = d.presets.find((x) => x.name === preset2);
4427
- if (!p) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" has no preset "${preset2}"; ${d.presets.length ? `its presets are ${d.presets.map((x) => `"${x.name}"`).join(", ")}` : "it has no presets"}.`, d.id);
4428
+ if (!p) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" has no preset "${preset2}"; ${d.presets.length ? `its presets are ${d.presets.map((x) => `"${x.name}"`).join(", ")}` : "it has no presets"}.`, d.id);
4428
4429
  return { ...p.values, ..._nullishCoalesce(values, () => ( {})) };
4429
4430
  }
4430
4431
  async function resolveMotionShotLayer(provider, layer) {
@@ -4434,27 +4435,27 @@ async function resolveMotionShotLayer(provider, layer) {
4434
4435
  const { provider: _p, name: _n, ...rest } = layer;
4435
4436
  return rest;
4436
4437
  }
4437
- if (!provider) throw new (0, _chunkJAOSL334cjs.NoEffectsProviderError)();
4438
+ if (!provider) throw new (0, _chunkGHCSC2WPcjs.NoEffectsProviderError)();
4438
4439
  const d = await provider.describe(layer.effect);
4439
- if (!_chunkJWCKJNDRcjs.effectLayerOffered.call(void 0, d)) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) cannot be a layer; ${kindHint(d)}. A layer's effect is a generator, filter, overlay or title (search_effects with use "generator", "filter", "overlay" or "title").`, d.id);
4440
- const input = _chunkJWCKJNDRcjs.effectLayerInput.call(void 0, d);
4441
- if (layer.subject && !input) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) draws its own picture and takes no subject; leave "subject" out, or pick a filter to change the subject.`, d.id);
4442
- if (!layer.subject && input && _optionalChain([d, 'access', _198 => _198.inputs, 'access', _199 => _199.find, 'call', _200 => _200((i) => i.name === input), 'optionalAccess', _201 => _201.required])) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) changes a picture; give a "subject": { "image": url }, { "svg": markup }, { "text": words } or { "slot": name }.`, d.id);
4440
+ if (!_chunkK5DS2JTAcjs.effectLayerOffered.call(void 0, d)) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) cannot be a layer; ${kindHint(d)}. A layer's effect is a generator, filter, overlay or title (search_effects with use "generator", "filter", "overlay" or "title").`, d.id);
4441
+ const input = _chunkK5DS2JTAcjs.effectLayerInput.call(void 0, d);
4442
+ if (layer.subject && !input) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) draws its own picture and takes no subject; leave "subject" out, or pick a filter to change the subject.`, d.id);
4443
+ if (!layer.subject && input && _optionalChain([d, 'access', _198 => _198.inputs, 'access', _199 => _199.find, 'call', _200 => _200((i) => i.name === input), 'optionalAccess', _201 => _201.required])) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) changes a picture; give a "subject": { "image": url }, { "svg": markup }, { "text": words } or { "slot": name }.`, d.id);
4443
4444
  const values = withPreset(d, layer.preset, layer.values);
4444
- _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, values);
4445
+ _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, values);
4445
4446
  const out = { ...layer, provider: provider.id, name: d.name };
4446
4447
  if (values && Object.keys(values).length) out.values = values;
4447
4448
  else delete out.values;
4448
4449
  return out;
4449
4450
  }
4450
4451
  async function resolveMotionShotTransition(provider, transition) {
4451
- if (!provider) throw new (0, _chunkJAOSL334cjs.NoEffectsProviderError)();
4452
+ if (!provider) throw new (0, _chunkGHCSC2WPcjs.NoEffectsProviderError)();
4452
4453
  const d = await provider.describe(transition.effect);
4453
- if (!d.uses.includes("transition") || d.kind === "camera") throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is not a transition (${kindHint(d)}); search_effects with use "transition" lists them.`, d.id);
4454
+ if (!d.uses.includes("transition") || d.kind === "camera") throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is not a transition (${kindHint(d)}); search_effects with use "transition" lists them.`, d.id);
4454
4455
  if (transition.ms !== void 0 && !(transition.ms > 0 && transition.ms <= 6e4)) throw new Error(`A transition's "ms" is from 1 to 60000; got ${transition.ms}.`);
4455
4456
  const values = withPreset(d, transition.preset, transition.values);
4456
- _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, values);
4457
- const out = { ...transition, ms: _nullishCoalesce(transition.ms, () => ( _chunkJAOSL334cjs.EFFECT_TRANSITION_MS)), provider: provider.id, name: d.name };
4457
+ _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, values);
4458
+ const out = { ...transition, ms: _nullishCoalesce(transition.ms, () => ( _chunkGHCSC2WPcjs.EFFECT_TRANSITION_MS)), provider: provider.id, name: d.name };
4458
4459
  if (values && Object.keys(values).length) out.values = values;
4459
4460
  else delete out.values;
4460
4461
  return out;
@@ -4570,7 +4571,7 @@ function nextMotionEffectInstance(scene) {
4570
4571
  walk(scene.artwork.nodes);
4571
4572
  for (let i = 1; ; i++) if (!used.has(`fx${i}`)) return `fx${i}`;
4572
4573
  }
4573
- var motionArtworkSvg = (artwork) => _chunkTHXFU3JBcjs.vectorDocumentToSvg.call(void 0, artwork);
4574
+ var motionArtworkSvg = (artwork) => _chunkKCMV2534cjs.vectorDocumentToSvg.call(void 0, artwork);
4574
4575
  var tag = (commands, source) => commands.map((c) => c.type === "wait" ? c : { ...c, source });
4575
4576
  function motionCommandsFromEffect(artwork, motion, source) {
4576
4577
  const imported = fromFlairSvgMotion({ svg: motionArtworkSvg(artwork), animate: [..._nullishCoalesce(motion.animate, () => ( []))] });
@@ -4606,9 +4607,19 @@ function motionPartsFromVectorEffect(artwork, motion, source, box2 = { x: 0, y:
4606
4607
  const art = imported.scene.artwork;
4607
4608
  const prefix = `${source.instance}-`;
4608
4609
  const { nodes, shots } = prefixed(art.nodes, imported.scene.shots, prefix);
4609
- const k = Math.min(box2.width / art.width, box2.height / art.height);
4610
- const dx = box2.x + (box2.width - art.width * k) / 2;
4611
- const dy = box2.y + (box2.height - art.height * k) / 2;
4610
+ let k;
4611
+ let dx;
4612
+ let dy;
4613
+ if (box2 === "viewBox") {
4614
+ const vb = _nullishCoalesce(_optionalChain([/viewBox\s*=\s*["']([^"']+)["']/, 'access', _215 => _215.exec, 'call', _216 => _216(motion.svg), 'optionalAccess', _217 => _217[1], 'access', _218 => _218.trim, 'call', _219 => _219(), 'access', _220 => _220.split, 'call', _221 => _221(/[\s,]+/), 'access', _222 => _222.map, 'call', _223 => _223(Number)]), () => ( []));
4615
+ k = 1;
4616
+ dx = vb.length === 4 && Number.isFinite(vb[0]) ? vb[0] : 0;
4617
+ dy = vb.length === 4 && Number.isFinite(vb[1]) ? vb[1] : 0;
4618
+ } else {
4619
+ k = Math.min(box2.width / art.width, box2.height / art.height);
4620
+ dx = box2.x + (box2.width - art.width * k) / 2;
4621
+ dy = box2.y + (box2.height - art.height * k) / 2;
4622
+ }
4612
4623
  const group = { type: "group", id: source.instance, name: _nullishCoalesce(source.name, () => ( source.effect)), children: nodes, transform: [k, 0, 0, k, dx, dy] };
4613
4624
  const tagged = shots.map((s, i) => ({ ...s, id: i === 0 ? source.instance + "-shot" : `${source.instance}-shot-${i + 1}`, run: tag(s.run, source) }));
4614
4625
  return { group, shots: tagged.map((s) => s.hold === 0 ? (({ hold: _h, ...rest }) => rest)(s) : s), notes: imported.notes };
@@ -4619,7 +4630,7 @@ function withoutMotionEffect(scene, instance) {
4619
4630
  const shots = [];
4620
4631
  for (const shot of scene.shots) {
4621
4632
  const run = shot.run.filter((c, i) => {
4622
- const mine = _optionalChain([sourceOf, 'call', _215 => _215(c), 'optionalAccess', _216 => _216.instance]) === instance;
4633
+ const mine = _optionalChain([sourceOf, 'call', _224 => _224(c), 'optionalAccess', _225 => _225.instance]) === instance;
4623
4634
  if (mine && !place) place = { shot: shot.id, index: i };
4624
4635
  return !mine;
4625
4636
  });
@@ -4639,7 +4650,7 @@ var AnimationEditorController = (_class2 = class {
4639
4650
 
4640
4651
 
4641
4652
  /** The effects provider slot (see `setEffectsProvider`). */
4642
- __init9() {this.effects = new (0, _chunkJAOSL334cjs.EffectsSlot)()}
4653
+ __init9() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
4643
4654
  /** Renders shot layer and transition pictures for frames (see `MotionLayersEngine`). */
4644
4655
 
4645
4656
 
@@ -4714,7 +4725,7 @@ var AnimationEditorController = (_class2 = class {
4714
4725
  time: p.time,
4715
4726
  playing: p.playing,
4716
4727
  loop: p.loop,
4717
- currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _217 => _217(timeline, p.time), 'optionalAccess', _218 => _218.id]), () => ( null)),
4728
+ currentShot: _nullishCoalesce(_optionalChain([motionShotAt, 'call', _226 => _226(timeline, p.time), 'optionalAccess', _227 => _227.id]), () => ( null)),
4718
4729
  selection: this.selection,
4719
4730
  readOnly: this.readOnly,
4720
4731
  error: this.error,
@@ -4763,7 +4774,7 @@ var AnimationEditorController = (_class2 = class {
4763
4774
  this.applying = false;
4764
4775
  }
4765
4776
  this.notify();
4766
- _optionalChain([this, 'access', _219 => _219.onChange, 'optionalCall', _220 => _220(scene)]);
4777
+ _optionalChain([this, 'access', _228 => _228.onChange, 'optionalCall', _229 => _229(scene)]);
4767
4778
  }
4768
4779
  commit(label, next, merge) {
4769
4780
  const before = this.scene;
@@ -4833,7 +4844,7 @@ var AnimationEditorController = (_class2 = class {
4833
4844
  try {
4834
4845
  plan = await work();
4835
4846
  } catch (error) {
4836
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
4847
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
4837
4848
  throw error;
4838
4849
  }
4839
4850
  const r = this.apply({ op: "replace_scene", scene: plan.scene }, plan.label, { merge });
@@ -4844,11 +4855,11 @@ var AnimationEditorController = (_class2 = class {
4844
4855
  }
4845
4856
  async describeFor(effect, kinds) {
4846
4857
  const provider = this.effects.require();
4847
- if (!provider.applyVectorEffect) throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
4858
+ if (!provider.applyVectorEffect) throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
4848
4859
  const d = await provider.describe(effect);
4849
4860
  if (!kinds.includes(d.kind)) {
4850
4861
  const hint = d.kind === "motion" ? "apply it to nodes with apply_effect" : d.kind === "vector" ? "add it with add_vector_effect" : "it draws pixels, which scenes cannot hold";
4851
- throw new (0, _chunkJAOSL334cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
4862
+ throw new (0, _chunkGHCSC2WPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
4852
4863
  }
4853
4864
  return d;
4854
4865
  }
@@ -4869,7 +4880,7 @@ var AnimationEditorController = (_class2 = class {
4869
4880
  return this.effectEdit(async () => {
4870
4881
  this.knownNodes(targets);
4871
4882
  const d = await this.describeFor(effect, ["motion"]);
4872
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, options.values);
4883
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, options.values);
4873
4884
  const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
4874
4885
  const motion = await this.effects.require().applyVectorEffect(d.id, { svg: motionArtworkSvg(this.scene.artwork), nodeIds: [...targets] }, values);
4875
4886
  const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
@@ -4891,11 +4902,34 @@ var AnimationEditorController = (_class2 = class {
4891
4902
  addVectorEffect(effect, options = {}) {
4892
4903
  return this.effectEdit(async () => {
4893
4904
  const d = await this.describeFor(effect, ["vector"]);
4894
- const values = _chunkJAOSL334cjs.resolveEffectValues.call(void 0, d, options.values);
4905
+ let given = options.values;
4906
+ let place = options.box;
4907
+ if (options.path) {
4908
+ const controls = _chunkGHCSC2WPcjs.pathControlsOf.call(void 0, d);
4909
+ if (!controls.length) throw new Error(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"] (kind vector).`);
4910
+ const control = _nullishCoalesce(options.control, () => ( (controls.length === 1 ? controls[0] : void 0)));
4911
+ if (!control) throw new Error(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4912
+ if (!controls.includes(control)) throw new Error(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4913
+ let value;
4914
+ if ("node" in options.path) {
4915
+ const entry = indexMotionNodes(this.scene.artwork.nodes).get(options.path.node);
4916
+ if (!entry) throw new Error(`There is no node "${options.path.node}"; find_animation_elements lists the artwork's nodes.`);
4917
+ if (entry.node.type !== "path") throw new Error(`Node "${options.path.node}" is a ${entry.node.type}, not a path; pass a path node (find_animation_elements shows each node's type).`);
4918
+ value = _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, _chunkKCMV2534cjs.vectorPathWorldBezier.call(void 0, entry.node, entry.parentWorld, { effects: false }));
4919
+ place ??= "viewBox";
4920
+ } else {
4921
+ const provider = this.effects.require();
4922
+ if (!provider.pathFromText) throw new Error(`The effects provider "${provider.id}" cannot write words as a path; pass a path node instead.`);
4923
+ if (typeof options.path.text !== "string" || !options.path.text.trim()) throw new Error("text is empty; pass the words to write.");
4924
+ value = await provider.pathFromText(options.path.text, { ...options.path.font ? { font: options.path.font } : {}, ...options.path.align ? { align: options.path.align } : {} });
4925
+ }
4926
+ given = { ..._nullishCoalesce(given, () => ( {})), [control]: value };
4927
+ }
4928
+ const values = _chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, d, given);
4895
4929
  const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
4896
4930
  const motion = await this.effects.require().applyVectorEffect(d.id, motionArtworkSvg(this.scene.artwork), values);
4897
4931
  const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
4898
- const { group, shots, notes } = motionPartsFromVectorEffect(this.scene.artwork, motion, source, options.box);
4932
+ const { group, shots, notes } = motionPartsFromVectorEffect(this.scene.artwork, motion, source, place);
4899
4933
  return { scene: { ...this.scene, artwork: { ...this.scene.artwork, nodes: [...this.scene.artwork.nodes, group] }, shots: [...this.scene.shots, ...shots] }, label: `Add ${d.name}`, instance, notes };
4900
4934
  });
4901
4935
  }
@@ -4915,7 +4949,7 @@ var AnimationEditorController = (_class2 = class {
4915
4949
  else if (k in d.controls.properties) base[k] = d.defaults[k];
4916
4950
  else throw new Error(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
4917
4951
  }
4918
- const merged = { ...base, ..._chunkJAOSL334cjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
4952
+ const merged = { ...base, ..._chunkGHCSC2WPcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
4919
4953
  const { scene: bare, place } = withoutMotionEffect(this.scene, instance);
4920
4954
  const provider = this.effects.require();
4921
4955
  const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
@@ -4925,7 +4959,7 @@ var AnimationEditorController = (_class2 = class {
4925
4959
  const { group, shots: shots2, notes: notes2 } = motionPartsFromVectorEffect(bare.artwork, motion2, source);
4926
4960
  const index = this.scene.artwork.nodes.findIndex((n2) => n2.id === instance);
4927
4961
  const nodes = [...bare.artwork.nodes];
4928
- nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess', _221 => _221.transform]) ? { ...group, transform: old.transform } : group);
4962
+ nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess', _230 => _230.transform]) ? { ...group, transform: old.transform } : group);
4929
4963
  const at = this.scene.shots.findIndex((s) => was.shots.includes(s.id));
4930
4964
  const kept = bare.shots;
4931
4965
  const nextShots = [...kept.slice(0, Math.max(0, at)), ...shots2, ...kept.slice(Math.max(0, at))];
@@ -4936,7 +4970,7 @@ var AnimationEditorController = (_class2 = class {
4936
4970
  let shots = bare.shots;
4937
4971
  if (place && shots.some((s) => s.id === place.shot)) shots = shots.map((s) => s.id === place.shot ? { ...s, run: [...s.run.slice(0, place.index), ...commands, ...s.run.slice(place.index)] } : s);
4938
4972
  else {
4939
- const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess', _222 => _222.shot]));
4973
+ const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess', _231 => _231.shot]));
4940
4974
  shots = [...shots.slice(0, Math.max(0, at)), { id: instance, label: d.name, run: commands }, ...shots.slice(Math.max(0, at))];
4941
4975
  }
4942
4976
  return { scene: { ...bare, shots }, label: `Change ${d.name}`, instance, notes };
@@ -4970,12 +5004,12 @@ var AnimationEditorController = (_class2 = class {
4970
5004
  if (!found) return this.refuse(`There is no shot "${shot}"; the shots are ${this.scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
4971
5005
  let resolved;
4972
5006
  try {
4973
- resolved = await _chunkJAOSL334cjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
5007
+ resolved = await _chunkGHCSC2WPcjs.resolveCameraMoveSpec.call(void 0, this.effects.require(), spec, role);
4974
5008
  } catch (error) {
4975
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5009
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
4976
5010
  throw error;
4977
5011
  }
4978
- const field = _chunkJAOSL334cjs.cameraMoveField.call(void 0, role);
5012
+ const field = _chunkGHCSC2WPcjs.cameraMoveField.call(void 0, role);
4979
5013
  const current = this.scene.shots.find((s) => s.id === shot);
4980
5014
  if (!current) return this.refuse(`Shot "${shot}" was removed while the move was checked.`);
4981
5015
  const parts = role === "transition" && resolved.spec.ms === void 0 ? { ...resolved.spec, ms: resolved.description.camera.durationMs } : resolved.spec;
@@ -4989,8 +5023,8 @@ var AnimationEditorController = (_class2 = class {
4989
5023
  clearShotCameraMove(shot, role) {
4990
5024
  const found = this.scene.shots.find((s) => s.id === shot);
4991
5025
  if (!found) return this.refuse(`There is no shot "${shot}"; the shots are ${this.scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
4992
- const field = _chunkJAOSL334cjs.cameraMoveField.call(void 0, role);
4993
- if (_optionalChain([found, 'access', _223 => _223.camera, 'optionalAccess', _224 => _224[field]]) === void 0) return this.refuse(`Shot "${shot}" has no camera "${field}" move to clear${_optionalChain([found, 'access', _225 => _225.camera, 'optionalAccess', _226 => _226[field === "in" ? "during" : "in"]]) !== void 0 ? `; it has a "${field === "in" ? "during" : "in"}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
5026
+ const field = _chunkGHCSC2WPcjs.cameraMoveField.call(void 0, role);
5027
+ if (_optionalChain([found, 'access', _232 => _232.camera, 'optionalAccess', _233 => _233[field]]) === void 0) return this.refuse(`Shot "${shot}" has no camera "${field}" move to clear${_optionalChain([found, 'access', _234 => _234.camera, 'optionalAccess', _235 => _235[field === "in" ? "during" : "in"]]) !== void 0 ? `; it has a "${field === "in" ? "during" : "in"}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
4994
5028
  const rest = { ...found.camera };
4995
5029
  delete rest[field];
4996
5030
  const keep = motionCameraFramed(rest) || rest.in !== void 0 || rest.during !== void 0;
@@ -5000,7 +5034,7 @@ var AnimationEditorController = (_class2 = class {
5000
5034
  }
5001
5035
  cameraMoveResult(shot, role, move) {
5002
5036
  const timing = compileMotionScene(this.scene).shots.find((s) => s.id === shot);
5003
- const camera = _nullishCoalesce(_optionalChain([this, 'access', _227 => _227.scene, 'access', _228 => _228.shots, 'access', _229 => _229.find, 'call', _230 => _230((s) => s.id === shot), 'optionalAccess', _231 => _231.camera]), () => ( null));
5037
+ const camera = _nullishCoalesce(_optionalChain([this, 'access', _236 => _236.scene, 'access', _237 => _237.shots, 'access', _238 => _238.find, 'call', _239 => _239((s) => s.id === shot), 'optionalAccess', _240 => _240.camera]), () => ( null));
5004
5038
  const window = role === "transition" ? { start: timing.start, end: timing.commandsStart } : { start: timing.commandsEnd, end: timing.end };
5005
5039
  const notes = [];
5006
5040
  if (move && role === "transition" && timing.index === 0) notes.push('This is the first shot, which cuts to its framing, so its "in" move does not play; it plays from the second shot on.');
@@ -5071,7 +5105,7 @@ var AnimationEditorController = (_class2 = class {
5071
5105
  viewScene() {
5072
5106
  const r = this.recording;
5073
5107
  if (!r) return this.scene;
5074
- if (_optionalChain([r, 'access', _232 => _232.preview, 'optionalAccess', _233 => _233.count]) === r.samples.length) return r.preview.scene;
5108
+ if (_optionalChain([r, 'access', _241 => _241.preview, 'optionalAccess', _242 => _242.count]) === r.samples.length) return r.preview.scene;
5075
5109
  let scene = this.scene;
5076
5110
  if (r.samples.length) {
5077
5111
  try {
@@ -5131,7 +5165,7 @@ var AnimationEditorController = (_class2 = class {
5131
5165
  try {
5132
5166
  plan = await work();
5133
5167
  } catch (error) {
5134
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5168
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5135
5169
  throw error;
5136
5170
  }
5137
5171
  const id = this.scene.shots[plan.shot].id;
@@ -5213,14 +5247,14 @@ var AnimationEditorController = (_class2 = class {
5213
5247
  const { provider: _p, name: _n, ...given } = transition;
5214
5248
  resolved = await resolveMotionShotTransition(this.effects.provider, given);
5215
5249
  } catch (error) {
5216
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5250
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5217
5251
  throw error;
5218
5252
  }
5219
5253
  if (!this.scene.shots.some((s) => s.id === shot)) return this.refuse(`Shot "${shot}" was removed while the transition was checked.`);
5220
5254
  const r = this.apply({ op: "update_shot", shot, set: { transition: resolved } }, `Transition ${_nullishCoalesce(resolved.name, () => ( resolved.effect))}`, { merge: options.merge });
5221
5255
  if (!r.ok) return r;
5222
5256
  const camera = this.scene.shots.find((s) => s.id === shot).camera;
5223
- return this.layerResult(shot, void 0, _optionalChain([camera, 'optionalAccess', _234 => _234.in]) === void 0 ? ["With no camera move in, the camera cuts to this shot's framing and the transition does the move."] : []);
5257
+ return this.layerResult(shot, void 0, _optionalChain([camera, 'optionalAccess', _243 => _243.in]) === void 0 ? ["With no camera move in, the camera cuts to this shot's framing and the transition does the move."] : []);
5224
5258
  }
5225
5259
  /** Removes a shot's transition. One undo step. Works without a provider. */
5226
5260
  clearShotTransition(shot) {
@@ -5245,9 +5279,9 @@ var AnimationEditorController = (_class2 = class {
5245
5279
  const mode = _nullishCoalesce(options.mode, () => ( "replace"));
5246
5280
  let filled;
5247
5281
  try {
5248
- filled = await _chunkJWCKJNDRcjs.fillEffectTemplate.call(void 0, this.effects.provider, template, values, options.name ? { name: options.name } : {});
5282
+ filled = await _chunkK5DS2JTAcjs.fillEffectTemplate.call(void 0, this.effects.provider, template, values, options.name ? { name: options.name } : {});
5249
5283
  } catch (error) {
5250
- if (_chunkJAOSL334cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5284
+ if (_chunkGHCSC2WPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
5251
5285
  throw error;
5252
5286
  }
5253
5287
  const provider = this.effects.provider.id;
@@ -5334,13 +5368,13 @@ var AnimationEditorController = (_class2 = class {
5334
5368
  }
5335
5369
  /** Records the drag's pose with the pointer at `point` (document units). */
5336
5370
  updateRecordGesture(point) {
5337
- const g = _optionalChain([this, 'access', _235 => _235.recording, 'optionalAccess', _236 => _236.gesture]);
5371
+ const g = _optionalChain([this, 'access', _244 => _244.recording, 'optionalAccess', _245 => _245.gesture]);
5338
5372
  if (g) this.recordGesture(g.pose, point);
5339
5373
  }
5340
5374
  /** Ends the stage drag (the take keeps recording). */
5341
5375
  endRecordGesture() {
5342
5376
  const r = this.recording;
5343
- if (!_optionalChain([r, 'optionalAccess', _237 => _237.gesture])) return;
5377
+ if (!_optionalChain([r, 'optionalAccess', _246 => _246.gesture])) return;
5344
5378
  r.gesture = null;
5345
5379
  this.notify();
5346
5380
  }
@@ -5354,7 +5388,7 @@ var AnimationEditorController = (_class2 = class {
5354
5388
  this.recordSample(g.node, { scaleX: Math.max(0.01, pose.scaleX * f), scaleY: Math.max(0.01, pose.scaleY * f) });
5355
5389
  } else {
5356
5390
  const turn = (Math.atan2(point.y - c.y, point.x - c.x) - Math.atan2(g.from.y - c.y, g.from.x - c.x)) * (180 / Math.PI);
5357
- const was = _nullishCoalesce(_optionalChain([this, 'access', _238 => _238.recording, 'access', _239 => _239.samples, 'access', _240 => _240.filter, 'call', _241 => _241((s) => s.node === g.node && s.rotation !== void 0), 'access', _242 => _242.at, 'call', _243 => _243(-1), 'optionalAccess', _244 => _244.rotation]), () => ( pose.rotation));
5391
+ const was = _nullishCoalesce(_optionalChain([this, 'access', _247 => _247.recording, 'access', _248 => _248.samples, 'access', _249 => _249.filter, 'call', _250 => _250((s) => s.node === g.node && s.rotation !== void 0), 'access', _251 => _251.at, 'call', _252 => _252(-1), 'optionalAccess', _253 => _253.rotation]), () => ( pose.rotation));
5358
5392
  let next = pose.rotation + turn;
5359
5393
  next += 360 * Math.round((was - next) / 360);
5360
5394
  this.recordSample(g.node, { rotation: next });
@@ -5448,7 +5482,7 @@ function elementsOf(args) {
5448
5482
  if (Array.isArray(args.ops)) {
5449
5483
  for (const op of args.ops) {
5450
5484
  fromShot(op);
5451
- if (Array.isArray(_optionalChain([op, 'optionalAccess', _245 => _245.shots]))) op.shots.forEach(fromShot);
5485
+ if (Array.isArray(_optionalChain([op, 'optionalAccess', _254 => _254.shots]))) op.shots.forEach(fromShot);
5452
5486
  }
5453
5487
  }
5454
5488
  return out.slice(0, 4);
@@ -5630,7 +5664,7 @@ var MOTION_COMMAND_SCHEMA = {
5630
5664
  oneOf: MOTION_COMMAND_TYPES.map((type) => MOTION_COMMAND_TYPE_SCHEMAS[type])
5631
5665
  };
5632
5666
  var REF2 = (name, description) => ({ $ref: `#/$defs/${name}`, ...description ? { description } : {} });
5633
- var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _246 => _246.exec, 'call', _247 => _247(text), 'optionalAccess', _248 => _248[0]]), () => ( text));
5667
+ var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _255 => _255.exec, 'call', _256 => _256(text), 'optionalAccess', _257 => _257[0]]), () => ( text));
5634
5668
  var COMMAND_TYPE_LINES = MOTION_COMMAND_TYPES.map((type) => `${type}: ${firstSentence(_nullishCoalesce(MOTION_COMMAND_TYPE_SCHEMAS[type].description, () => ( "")))}`);
5635
5669
  var EASE_COMPACT = {
5636
5670
  description: `Easing: a preset, or a curve { "type": "cubic-bezier", x1, y1, x2, y2 }, { "type": "spring", stiffness, damping, mass, velocity } (spring presets are Figma's; with no "duration" it lasts until it settles) or { "type": "elastic", amplitude, period, mode }. Default: ease-out for entrances, ease-in-out for moves.`,
@@ -6039,9 +6073,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6039
6073
  handler: ({ from = 0, to, limit = 200 }) => {
6040
6074
  const s = scene();
6041
6075
  const timeline = compileMotionScene(s);
6042
- const words = _nullishCoalesce(_optionalChain([s, 'access', _249 => _249.narration, 'optionalAccess', _250 => _250.words]), () => ( []));
6076
+ const words = _nullishCoalesce(_optionalChain([s, 'access', _258 => _258.narration, 'optionalAccess', _259 => _259.words]), () => ( []));
6043
6077
  const end = _nullishCoalesce(to, () => ( Math.max(timeline.duration, words.length ? _nullishCoalesce(words[words.length - 1].end, () => ( words[words.length - 1].start)) : 0)));
6044
- const shotAt = (ms2) => _optionalChain([timeline, 'access', _251 => _251.shots, 'access', _252 => _252.find, 'call', _253 => _253((x) => ms2 >= x.start && ms2 < x.end), 'optionalAccess', _254 => _254.id]);
6078
+ const shotAt = (ms2) => _optionalChain([timeline, 'access', _260 => _260.shots, 'access', _261 => _261.find, 'call', _262 => _262((x) => ms2 >= x.start && ms2 < x.end), 'optionalAccess', _263 => _263.id]);
6045
6079
  const beats = [];
6046
6080
  if (s.beat && s.beat.bpm > 0) {
6047
6081
  const first = Math.max(0, Math.ceil(motionBeatAt(s.beat, from).beat - 1e-9));
@@ -6142,7 +6176,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6142
6176
  handler: ({ svg }) => {
6143
6177
  let artwork;
6144
6178
  try {
6145
- artwork = _chunkTHXFU3JBcjs.parseVectorSvg.call(void 0, svg);
6179
+ artwork = _chunkKCMV2534cjs.parseVectorSvg.call(void 0, svg);
6146
6180
  } catch (error) {
6147
6181
  throw new Error(`The SVG could not be read: ${error.message}. Nothing was changed.`);
6148
6182
  }
@@ -6417,7 +6451,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6417
6451
  inputSchema: object({ shot: SHOT_ID, commands: { type: "array", items: REF2("command"), minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the run (default: the end)." } }, ["shot", "commands"]),
6418
6452
  annotations: { title: "Add commands to a shot", ...WRITE },
6419
6453
  handler: ({ shot, commands, at }) => {
6420
- const before = _nullishCoalesce(_optionalChain([scene, 'call', _255 => _255(), 'access', _256 => _256.shots, 'access', _257 => _257.find, 'call', _258 => _258((s) => s.id === shot), 'optionalAccess', _259 => _259.run, 'access', _260 => _260.length]), () => ( 0));
6454
+ const before = _nullishCoalesce(_optionalChain([scene, 'call', _264 => _264(), 'access', _265 => _265.shots, 'access', _266 => _266.find, 'call', _267 => _267((s) => s.id === shot), 'optionalAccess', _268 => _268.run, 'access', _269 => _269.length]), () => ( 0));
6421
6455
  const first = _nullishCoalesce(at, () => ( before));
6422
6456
  return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
6423
6457
  const shots = describeMotionShots(s);
@@ -6618,7 +6652,7 @@ var TIMING = /* @__PURE__ */ new Set(["duration", "delay", "stagger", "with", "e
6618
6652
  var COLORS = /* @__PURE__ */ new Set(["fill", "stroke", "color"]);
6619
6653
  var NODES = /* @__PURE__ */ new Set(["into", "path"]);
6620
6654
  function branch(type) {
6621
- return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _261 => _261.properties, 'optionalAccess', _262 => _262.type, 'optionalAccess', _263 => _263.const]) === type);
6655
+ return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _270 => _270.properties, 'optionalAccess', _271 => _271.type, 'optionalAccess', _272 => _272.const]) === type);
6622
6656
  }
6623
6657
  function unitOf(type, name) {
6624
6658
  if (name === "duration" || name === "delay" || name === "stagger") return "ms";
@@ -6653,7 +6687,7 @@ function kindOf(name, schema) {
6653
6687
  }
6654
6688
  function motionCommandFields(type) {
6655
6689
  const schema = branch(type);
6656
- if (!_optionalChain([schema, 'optionalAccess', _264 => _264.properties])) return [];
6690
+ if (!_optionalChain([schema, 'optionalAccess', _273 => _273.properties])) return [];
6657
6691
  const required = new Set(_nullishCoalesce(schema.required, () => ( [])));
6658
6692
  const fields2 = Object.entries(schema.properties).filter(([name]) => name !== "type").map(([name, s]) => {
6659
6693
  const kind = kindOf(name, s);
@@ -6710,7 +6744,7 @@ function defaultMotionCommand(type, targets, scene) {
6710
6744
  if (type === "wait") return { type: "wait", duration: 500 };
6711
6745
  if (!targets.length) return { error: "Pick a target first: click an element on the stage." };
6712
6746
  const nodes = [...indexMotionNodes(scene.artwork.nodes).values()];
6713
- const other = (pred) => _optionalChain([nodes, 'access', _265 => _265.find, 'call', _266 => _266((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _267 => _267.node, 'access', _268 => _268.id]);
6747
+ const other = (pred) => _optionalChain([nodes, 'access', _274 => _274.find, 'call', _275 => _275((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _276 => _276.node, 'access', _277 => _277.id]);
6714
6748
  const base = { targets: [...targets] };
6715
6749
  switch (type) {
6716
6750
  case "scale":
@@ -6741,8 +6775,8 @@ function defaultMotionCommand(type, targets, scene) {
6741
6775
  }
6742
6776
  case "effect": {
6743
6777
  for (const id of targets) {
6744
- const node = _optionalChain([nodes, 'access', _269 => _269.find, 'call', _270 => _270((e) => e.node.id === id), 'optionalAccess', _271 => _271.node]);
6745
- for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _272 => _272.effects]), () => ( []))) {
6778
+ const node = _optionalChain([nodes, 'access', _278 => _278.find, 'call', _279 => _279((e) => e.node.id === id), 'optionalAccess', _280 => _280.node]);
6779
+ for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _281 => _281.effects]), () => ( []))) {
6746
6780
  const param = Object.entries(effect.params).find(([, v]) => typeof v === "number");
6747
6781
  if (param) return { type, ...base, effect: effect.id, param: param[0], to: param[1] + 1 };
6748
6782
  }
@@ -6767,11 +6801,11 @@ function motionCommandRows(scene, shotId) {
6767
6801
  return scene.shots[index].run.map((command3, i) => {
6768
6802
  const t = timeline.commands.find((c) => c.shotIndex === index && c.command === i);
6769
6803
  const primitive = motionFlairPrimitive(command3);
6770
- return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _273 => _273.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _274 => _274.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
6804
+ return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _282 => _282.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _283 => _283.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
6771
6805
  });
6772
6806
  }
6773
6807
  function duplicateMotionCommandEdit(scene, shot, command3) {
6774
- const run = _nullishCoalesce(_optionalChain([scene, 'access', _275 => _275.shots, 'access', _276 => _276.find, 'call', _277 => _277((s) => s.id === shot), 'optionalAccess', _278 => _278.run]), () => ( []));
6808
+ const run = _nullishCoalesce(_optionalChain([scene, 'access', _284 => _284.shots, 'access', _285 => _285.find, 'call', _286 => _286((s) => s.id === shot), 'optionalAccess', _287 => _287.run]), () => ( []));
6775
6809
  return { op: "add_commands", shot, commands: run[command3] ? [structuredClone(run[command3])] : [], at: command3 + 1 };
6776
6810
  }
6777
6811
  var MOTION_EASE_CHOICES = [
@@ -6856,7 +6890,7 @@ function motionCueFromKey(key) {
6856
6890
  function motionCueChoices(scene, limit = 256) {
6857
6891
  const choices = [];
6858
6892
  const s = (ms2) => `${(ms2 / 1e3).toFixed(2)} s`;
6859
- const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _279 => _279.narration, 'optionalAccess', _280 => _280.words, 'access', _281 => _281.map, 'call', _282 => _282((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
6893
+ const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _288 => _288.narration, 'optionalAccess', _289 => _289.words, 'access', _290 => _290.map, 'call', _291 => _291((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
6860
6894
  if (scene.beat && scene.beat.bpm > 0) {
6861
6895
  for (let beat = 0; choices.length < limit; beat++) {
6862
6896
  const time = motionBeatTime(scene.beat, beat);
@@ -6866,7 +6900,7 @@ function motionCueChoices(scene, limit = 256) {
6866
6900
  choices.push({ value: `beat:${beat}`, label: `Beat ${beat} (bar ${at.bar}.${at.beatInBar}) \xB7 ${s(time)}`, time });
6867
6901
  }
6868
6902
  }
6869
- _optionalChain([scene, 'access', _283 => _283.narration, 'optionalAccess', _284 => _284.words, 'access', _285 => _285.forEach, 'call', _286 => _286((w, i) => {
6903
+ _optionalChain([scene, 'access', _292 => _292.narration, 'optionalAccess', _293 => _293.words, 'access', _294 => _294.forEach, 'call', _295 => _295((w, i) => {
6870
6904
  if (choices.length < limit * 2) choices.push({ value: `word:${i}`, label: `Word ${i} \u201C${w.text}\u201D \xB7 ${s(w.start)}`, time: w.start });
6871
6905
  })]);
6872
6906
  return choices;
@@ -6875,7 +6909,7 @@ function motionShotCueTime(scene, cue) {
6875
6909
  return cue ? motionCueTime(scene, cue) : void 0;
6876
6910
  }
6877
6911
  function formatMotionNarration(narration) {
6878
- return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _287 => _287.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
6912
+ return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _296 => _296.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
6879
6913
  }
6880
6914
  function parseMotionNarration(text) {
6881
6915
  const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
@@ -6918,7 +6952,7 @@ var ROLE = {
6918
6952
  enum: ["transition", "hold"],
6919
6953
  description: `transition: the move the camera gets into the shot with (its camera "in": a glide, whip pan, punch zoom, cut). hold: the move it makes while the shot holds (its camera "during": a Ken Burns drift, a crash zoom), played across the shot's hold.`
6920
6954
  };
6921
- var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {}, ..._optionalChain([e, 'access', _288 => _288.tags, 'optionalAccess', _289 => _289.length]) ? { tags: e.tags } : {} });
6955
+ var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {}, ..._optionalChain([e, 'access', _297 => _297.tags, 'optionalAccess', _298 => _298.length]) ? { tags: e.tags } : {} });
6922
6956
  var done = (r) => {
6923
6957
  if (!r.ok) throw new Error(r.error);
6924
6958
  return { shot: r.shot, camera: r.camera, ...r.window ? { window: r.window } : {}, ...r.notes.length ? { notes: r.notes } : {} };
@@ -6947,7 +6981,7 @@ function animationCameraMoveTools(controller, ctx) {
6947
6981
  shot: { type: "string", minLength: 1, description: "A shot id from get_animation." },
6948
6982
  role: ROLE,
6949
6983
  move: { type: "string", minLength: 1, description: "A camera move id of that role from list_camera_moves." },
6950
- ms: { type: "number", minimum: 0, maximum: _chunkJAOSL334cjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (0\u2013${_chunkJAOSL334cjs.CAMERA_MOVE_MAX_MS}; default the move's durationMs). Not for a hold, which plays across the shot's hold.` },
6984
+ ms: { type: "number", minimum: 0, maximum: _chunkGHCSC2WPcjs.CAMERA_MOVE_MAX_MS, description: `How long a transition takes, ms (0\u2013${_chunkGHCSC2WPcjs.CAMERA_MOVE_MAX_MS}; default the move's durationMs). Not for a hold, which plays across the shot's hold.` },
6951
6985
  preset: { type: "string", minLength: 1, description: "A preset of the move by name, from describe_effect; its values are written out on the shot." },
6952
6986
  values: ctx.valuesSchema("Control values over the move's defaults (and the preset's), from describe_effect")
6953
6987
  },
@@ -7020,7 +7054,7 @@ var fields = (ctx) => ({
7020
7054
  preset: { type: "string", minLength: 1, description: "A preset of the effect by name, from describe_effect; its values are written out on the layer." },
7021
7055
  values: ctx.valuesSchema("Control values over the effect's defaults (and the preset's), from describe_effect"),
7022
7056
  subject: SUBJECT,
7023
- role: { type: "string", enum: [..._chunkJAOSL334cjs.EFFECT_LAYER_ROLES], description: "background: under the artwork; subject: over the artwork; overlay: over everything. Default subject with a rect, else background." },
7057
+ role: { type: "string", enum: [..._chunkGHCSC2WPcjs.EFFECT_LAYER_ROLES], description: "background: under the artwork; subject: over the artwork; overlay: over everything. Default subject with a rect, else background." },
7024
7058
  rect: RECT,
7025
7059
  from: TIME("starts", "0: as its shot starts"),
7026
7060
  until: TIME("stops", '{ "shots": 1 }: as the next shot starts'),
@@ -7110,7 +7144,7 @@ function animationShotLayerTools(controller, ctx) {
7110
7144
  properties: {
7111
7145
  shot: { ...SHOT2, description: "A shot id from get_animation (not the first shot)." },
7112
7146
  effect: { ...ctx.effectIdSchema(["transition"]), description: "A transition effect id from search_effects (use transition)." },
7113
- ms: { type: "number", exclusiveMinimum: 0, maximum: 6e4, description: `How long it takes, ms (default ${_chunkJAOSL334cjs.EFFECT_TRANSITION_MS}).` },
7147
+ ms: { type: "number", exclusiveMinimum: 0, maximum: 6e4, description: `How long it takes, ms (default ${_chunkGHCSC2WPcjs.EFFECT_TRANSITION_MS}).` },
7114
7148
  preset: { type: "string", minLength: 1, description: "A preset of the transition by name, from describe_effect." },
7115
7149
  values: ctx.valuesSchema("Control values over the transition's defaults (and the preset's)")
7116
7150
  },
@@ -7146,7 +7180,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7146
7180
  if (!r.ok) throw new Error(r.error);
7147
7181
  return { target, effect: info(r.effect), effects: controller.appliedEffects().filter((e) => e.targets.includes(target)).map(info), ...r.notes.length ? { notes: r.notes } : {} };
7148
7182
  };
7149
- return withAnimationPlayback(_chunkJAOSL334cjs.createEffectToolProvider.call(void 0, {
7183
+ return withAnimationPlayback(_chunkGHCSC2WPcjs.createEffectToolProvider.call(void 0, {
7150
7184
  id: _nullishCoalesce(options.id, () => ( "animation-effects")),
7151
7185
  namespace: options.namespace,
7152
7186
  title: "Animation effects",
@@ -7181,7 +7215,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7181
7215
  extraTools: (ctx) => [
7182
7216
  ...animationCameraMoveTools(controller, ctx),
7183
7217
  ...animationShotLayerTools(controller, ctx),
7184
- ..._chunkJWCKJNDRcjs.effectTemplateTools.call(void 0,
7218
+ ..._chunkK5DS2JTAcjs.effectTemplateTools.call(void 0,
7185
7219
  {
7186
7220
  provider: () => controller.effectsProvider,
7187
7221
  fillDetails: "mode replace (default) makes a new scene from the template's shots, the size of its stage; mode append adds its shots after the current ones, scaled to the artwork. Each shot keeps its framing and camera moves, its layers and its transition; its title and caption become overlay word layers. Returns { template, mode, shots (new shot ids), layers (new layer ids), openSlots, notes }. Check the result with render_animation_frame.",
@@ -7198,7 +7232,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7198
7232
  {
7199
7233
  name: "add_vector_effect",
7200
7234
  title: "Add a vector effect",
7201
- description: "Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.",
7235
+ description: 'Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. For an effect that draws along a path (search_effects accepts ["path"]: a signature, a route), pass path: { node } to run it along a path node (its outline with every transform applied; the picture then lands on the node at scale 1 unless box is given) or { text } for words the provider writes. Use it instead of follow or draw-on when the effect itself should trace the path. The path is copied when added; add it again after reshaping the node. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.',
7202
7236
  inputSchema: {
7203
7237
  type: "object",
7204
7238
  properties: {
@@ -7214,8 +7248,21 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7214
7248
  },
7215
7249
  required: ["x", "y", "width", "height"],
7216
7250
  additionalProperties: false,
7217
- description: "Where the picture goes in the artwork, fitted keeping its proportions (default the whole artwork)."
7218
- }
7251
+ description: "Where the picture goes in the artwork, fitted keeping its proportions (default the whole artwork; with path { node }, on the node at scale 1)."
7252
+ },
7253
+ path: {
7254
+ type: "object",
7255
+ description: "The path the effect draws along (only for effects with a path control): { node } or { text }.",
7256
+ properties: {
7257
+ node: { type: "string", minLength: 1, description: "A path node id (find_animation_elements)." },
7258
+ text: { type: "string", minLength: 1, description: "Words the provider writes as a single-stroke path." },
7259
+ font: { type: "string", minLength: 1, description: "With text: a single-stroke font the provider offers (default its first)." },
7260
+ align: { type: "string", enum: ["start", "middle", "end"], description: "With text: where the line sits (default start)." }
7261
+ },
7262
+ oneOf: [{ required: ["node"] }, { required: ["text"] }],
7263
+ additionalProperties: false
7264
+ },
7265
+ control: { type: "string", minLength: 1, description: "Which path control takes the path (default the effect's only one; describe_effect pathControls lists them)." }
7219
7266
  },
7220
7267
  required: ["effect"],
7221
7268
  additionalProperties: false
@@ -7223,7 +7270,9 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7223
7270
  annotations: { title: "Add a vector effect", ...ctx.annotations.write },
7224
7271
  handler: async (args) => {
7225
7272
  ctx.requireProvider();
7226
- const r = await controller.addVectorEffect(args.effect, { values: args.values, box: args.box });
7273
+ const path = args.path ? args.path.node !== void 0 ? { node: args.path.node } : { text: args.path.text, font: args.path.font, align: args.path.align } : void 0;
7274
+ if (args.path && args.path.node !== void 0 && args.path.text !== void 0) throw new Error("Pass path as { node } or { text }, not both.");
7275
+ const r = await controller.addVectorEffect(args.effect, { values: args.values, box: args.box, path, control: args.control });
7227
7276
  if (!r.ok) throw new Error(r.error);
7228
7277
  return { instance: r.effect.instance, group: r.effect.group, effect: info(r.effect), ...r.notes.length ? { notes: r.notes } : {} };
7229
7278
  }