@energy8platform/golem 0.6.0 → 0.8.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 (73) hide show
  1. package/README.md +14 -0
  2. package/dist/editor.css +3 -4
  3. package/dist/editor.js +202 -101
  4. package/dist/lib/cli.js +225 -118
  5. package/dist/lib/cli.js.map +4 -4
  6. package/dist/lib/e8/agent.d.ts +35 -0
  7. package/dist/lib/e8/host.d.ts +22 -0
  8. package/dist/lib/e8/node.d.ts +66 -0
  9. package/dist/lib/e8/runtime.d.ts +10 -0
  10. package/dist/lib/e8/schema.d.ts +3 -0
  11. package/dist/lib/e8/types.d.ts +80 -0
  12. package/dist/lib/e8-agent.js +6865 -0
  13. package/dist/lib/e8-agent.js.map +7 -0
  14. package/dist/lib/e8-client.js +116 -0
  15. package/dist/lib/e8-host.js +7005 -0
  16. package/dist/lib/e8-host.js.map +7 -0
  17. package/dist/lib/e8-runtime.js +2079 -0
  18. package/dist/lib/e8-runtime.js.map +7 -0
  19. package/dist/lib/e8-schema.js +7 -0
  20. package/dist/lib/e8-schema.js.map +7 -0
  21. package/dist/lib/editor/api.d.ts +1 -0
  22. package/dist/lib/editor/embed.d.ts +9 -0
  23. package/dist/lib/editor/server.d.ts +23 -1
  24. package/dist/lib/editor/store.d.ts +34 -32
  25. package/dist/lib/editor/timeline.d.ts +15 -0
  26. package/dist/lib/editor-entry.d.ts +1 -1
  27. package/dist/lib/editor-entry.js +226 -118
  28. package/dist/lib/editor-entry.js.map +4 -4
  29. package/dist/lib/harness.js +54 -1
  30. package/dist/lib/interactive-editor.js.map +1 -1
  31. package/dist/lib/rig-check.d.ts +11 -0
  32. package/dist/lib/rig-control-qa.d.ts +8 -8
  33. package/dist/lib/rig-format.d.ts +184 -184
  34. package/dist/lib/rig-import-layers.d.ts +2 -0
  35. package/dist/lib/rig-symbol.d.ts +5 -2
  36. package/dist/lib/rig-tools.d.ts +2 -1
  37. package/dist/lib/rig-version.d.ts +12 -0
  38. package/dist/lib/runtime.js +60 -3
  39. package/dist/lib/runtime.js.map +3 -3
  40. package/dist/lib/tool-schema.d.ts +3 -0
  41. package/dist/lib/tools.d.ts +2 -0
  42. package/dist/lib/tools.js +179 -58
  43. package/dist/lib/tools.js.map +4 -4
  44. package/editor.html +2 -2
  45. package/package.json +38 -3
  46. package/skills/e8-golem/SKILL.md +71 -0
  47. package/skills/golem-symbol-animation/SKILL.md +87 -0
  48. package/skills/golem-symbol-animation/agents/openai.yaml +4 -0
  49. package/skills/golem-symbol-animation/references/facial-controls.md +48 -0
  50. package/skills/golem-symbol-animation/references/game-engine-integration.md +133 -0
  51. package/skills/golem-symbol-animation/references/golem-authoring.md +138 -0
  52. package/skills/golem-symbol-animation/references/interactive-editor.md +17 -0
  53. package/skills/golem-symbol-animation/references/motion-craft.md +116 -0
  54. package/skills/golem-symbol-animation/references/packed-delivery.md +88 -0
  55. package/skills/golem-symbol-animation/references/quantitative-qa.md +109 -0
  56. package/skills/golem-symbol-animation/references/spine-rive-study.md +87 -0
  57. package/skills/golem-symbol-animation/scripts/atlas_parts.py +87 -0
  58. package/skills/golem-symbol-animation/scripts/check_package.py +71 -0
  59. package/skills/golem-symbol-animation/scripts/image_gates.py +143 -0
  60. package/skills/golem-symbol-cutting/SKILL.md +70 -0
  61. package/skills/golem-symbol-cutting/agents/openai.yaml +4 -0
  62. package/skills/golem-symbol-cutting/assets/h1/h1.atlas.png +0 -0
  63. package/skills/golem-symbol-cutting/assets/h1/h1.png +0 -0
  64. package/skills/golem-symbol-cutting/references/cutting-workflow.md +92 -0
  65. package/skills/golem-symbol-cutting/references/facial-layers.md +44 -0
  66. package/skills/golem-symbol-cutting/references/generation-workflow.md +109 -0
  67. package/skills/golem-symbol-cutting/references/golem-handoff.md +62 -0
  68. package/skills/golem-symbol-cutting/references/h1-example.md +46 -0
  69. package/skills/golem-symbol-cutting/references/hybrid-workflow.md +119 -0
  70. package/skills/golem-symbol-cutting/references/registration-and-motion.md +89 -0
  71. package/skills/golem-symbol-cutting/references/spine-rive-construction.md +73 -0
  72. package/skills/golem-symbol-cutting/scripts/atlas_parts.py +87 -0
  73. package/skills/golem-symbol-cutting/scripts/hybrid_parts.py +279 -0
package/dist/editor.js CHANGED
@@ -43308,7 +43308,7 @@ var require_gifenc = __commonJS({
43308
43308
  bins[nb.fw].bk = nb.bk;
43309
43309
  nb.mtm = bincountMinusOne;
43310
43310
  }
43311
- let palette = [];
43311
+ let palette2 = [];
43312
43312
  var k4 = 0;
43313
43313
  for (i6 = 0; ; ++k4) {
43314
43314
  let r5 = clamp3(Math.round(bins[i6].rc), 0, 255);
@@ -43327,17 +43327,17 @@ var require_gifenc = __commonJS({
43327
43327
  }
43328
43328
  }
43329
43329
  const color = hasAlpha ? [r5, g4, b4, a5] : [r5, g4, b4];
43330
- const exists = existsInPalette(palette, color);
43330
+ const exists = existsInPalette(palette2, color);
43331
43331
  if (!exists)
43332
- palette.push(color);
43332
+ palette2.push(color);
43333
43333
  if ((i6 = bins[i6].fw) == 0)
43334
43334
  break;
43335
43335
  }
43336
- return palette;
43336
+ return palette2;
43337
43337
  }
43338
- function existsInPalette(palette, color) {
43339
- for (let i6 = 0; i6 < palette.length; i6++) {
43340
- const p6 = palette[i6];
43338
+ function existsInPalette(palette2, color) {
43339
+ for (let i6 = 0; i6 < palette2.length; i6++) {
43340
+ const p6 = palette2[i6];
43341
43341
  let matchesRGB = p6[0] === color[0] && p6[1] === color[1] && p6[2] === color[2];
43342
43342
  let matchesAlpha = p6.length >= 4 && color.length >= 4 ? p6[3] === color[3] : true;
43343
43343
  if (matchesRGB && matchesAlpha)
@@ -43376,14 +43376,14 @@ var require_gifenc = __commonJS({
43376
43376
  data[i6] = a5 << 24 | b4 << 16 | g4 << 8 | r5 << 0;
43377
43377
  }
43378
43378
  }
43379
- function applyPalette2(rgba, palette, format = "rgb565") {
43379
+ function applyPalette2(rgba, palette2, format = "rgb565") {
43380
43380
  if (!rgba || !rgba.buffer) {
43381
43381
  throw new Error("quantize() expected RGBA Uint8Array data");
43382
43382
  }
43383
43383
  if (!(rgba instanceof Uint8Array) && !(rgba instanceof Uint8ClampedArray)) {
43384
43384
  throw new Error("quantize() expected RGBA Uint8Array data");
43385
43385
  }
43386
- if (palette.length > 256) {
43386
+ if (palette2.length > 256) {
43387
43387
  throw new Error("applyPalette() only works with 256 colors or less");
43388
43388
  }
43389
43389
  const data = new Uint32Array(rgba.buffer);
@@ -43400,7 +43400,7 @@ var require_gifenc = __commonJS({
43400
43400
  const g4 = color >> 8 & 255;
43401
43401
  const r5 = color & 255;
43402
43402
  const key = rgba8888_to_rgba4444(r5, g4, b4, a5);
43403
- const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGBA(r5, g4, b4, a5, palette);
43403
+ const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGBA(r5, g4, b4, a5, palette2);
43404
43404
  index[i6] = idx;
43405
43405
  }
43406
43406
  } else {
@@ -43411,17 +43411,17 @@ var require_gifenc = __commonJS({
43411
43411
  const g4 = color >> 8 & 255;
43412
43412
  const r5 = color & 255;
43413
43413
  const key = rgb888_to_key(r5, g4, b4);
43414
- const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGB(r5, g4, b4, palette);
43414
+ const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGB(r5, g4, b4, palette2);
43415
43415
  index[i6] = idx;
43416
43416
  }
43417
43417
  }
43418
43418
  return index;
43419
43419
  }
43420
- function nearestColorIndexRGBA(r5, g4, b4, a5, palette) {
43420
+ function nearestColorIndexRGBA(r5, g4, b4, a5, palette2) {
43421
43421
  let k4 = 0;
43422
43422
  let mindist = 1e100;
43423
- for (let i6 = 0; i6 < palette.length; i6++) {
43424
- const px2 = palette[i6];
43423
+ for (let i6 = 0; i6 < palette2.length; i6++) {
43424
+ const px2 = palette2[i6];
43425
43425
  const a22 = px2[3];
43426
43426
  let curdist = sqr2(a22 - a5);
43427
43427
  if (curdist > mindist)
@@ -43443,11 +43443,11 @@ var require_gifenc = __commonJS({
43443
43443
  }
43444
43444
  return k4;
43445
43445
  }
43446
- function nearestColorIndexRGB(r5, g4, b4, palette) {
43446
+ function nearestColorIndexRGB(r5, g4, b4, palette2) {
43447
43447
  let k4 = 0;
43448
43448
  let mindist = 1e100;
43449
- for (let i6 = 0; i6 < palette.length; i6++) {
43450
- const px2 = palette[i6];
43449
+ for (let i6 = 0; i6 < palette2.length; i6++) {
43450
+ const px2 = palette2[i6];
43451
43451
  const r22 = px2[0];
43452
43452
  let curdist = sqr2(r22 - r5);
43453
43453
  if (curdist > mindist)
@@ -43465,12 +43465,12 @@ var require_gifenc = __commonJS({
43465
43465
  }
43466
43466
  return k4;
43467
43467
  }
43468
- function snapColorsToPalette(palette, knownColors, threshold = 5) {
43469
- if (!palette.length || !knownColors.length)
43468
+ function snapColorsToPalette(palette2, knownColors, threshold = 5) {
43469
+ if (!palette2.length || !knownColors.length)
43470
43470
  return;
43471
- const paletteRGB = palette.map((p6) => p6.slice(0, 3));
43471
+ const paletteRGB = palette2.map((p6) => p6.slice(0, 3));
43472
43472
  const thresholdSq = threshold * threshold;
43473
- const dim2 = palette[0].length;
43473
+ const dim2 = palette2[0].length;
43474
43474
  for (let i6 = 0; i6 < knownColors.length; i6++) {
43475
43475
  let color = knownColors[i6];
43476
43476
  if (color.length < dim2) {
@@ -43484,7 +43484,7 @@ var require_gifenc = __commonJS({
43484
43484
  const idx = r5[0];
43485
43485
  const distanceSq = r5[1];
43486
43486
  if (distanceSq > 0 && distanceSq <= thresholdSq) {
43487
- palette[idx] = color;
43487
+ palette2[idx] = color;
43488
43488
  }
43489
43489
  }
43490
43490
  }
@@ -43554,7 +43554,7 @@ var require_gifenc = __commonJS({
43554
43554
  transparent = false,
43555
43555
  transparentIndex = 0,
43556
43556
  delay = 0,
43557
- palette = null,
43557
+ palette: palette2 = null,
43558
43558
  repeat = 0,
43559
43559
  colorDepth = 8,
43560
43560
  dispose = -1
@@ -43572,21 +43572,21 @@ var require_gifenc = __commonJS({
43572
43572
  width = Math.max(0, Math.floor(width));
43573
43573
  height = Math.max(0, Math.floor(height));
43574
43574
  if (first) {
43575
- if (!palette) {
43575
+ if (!palette2) {
43576
43576
  throw new Error("First frame must include a { palette } option");
43577
43577
  }
43578
- encodeLogicalScreenDescriptor(stream, width, height, palette, colorDepth);
43579
- encodeColorTable(stream, palette);
43578
+ encodeLogicalScreenDescriptor(stream, width, height, palette2, colorDepth);
43579
+ encodeColorTable(stream, palette2);
43580
43580
  if (repeat >= 0) {
43581
43581
  encodeNetscapeExt(stream, repeat);
43582
43582
  }
43583
43583
  }
43584
43584
  const delayTime = Math.round(delay / 10);
43585
43585
  encodeGraphicControlExt(stream, dispose, delayTime, transparent, transparentIndex);
43586
- const useLocalColorTable = Boolean(palette) && !first;
43587
- encodeImageDescriptor(stream, width, height, useLocalColorTable ? palette : null);
43586
+ const useLocalColorTable = Boolean(palette2) && !first;
43587
+ encodeImageDescriptor(stream, width, height, useLocalColorTable ? palette2 : null);
43588
43588
  if (useLocalColorTable)
43589
- encodeColorTable(stream, palette);
43589
+ encodeColorTable(stream, palette2);
43590
43590
  encodePixels(stream, index, width, height, colorDepth, accum, htab, codetab);
43591
43591
  }
43592
43592
  };
@@ -43620,10 +43620,10 @@ var require_gifenc = __commonJS({
43620
43620
  stream.writeByte(transparentIndex || 0);
43621
43621
  stream.writeByte(0);
43622
43622
  }
43623
- function encodeLogicalScreenDescriptor(stream, width, height, palette, colorDepth = 8) {
43623
+ function encodeLogicalScreenDescriptor(stream, width, height, palette2, colorDepth = 8) {
43624
43624
  const globalColorTableFlag = 1;
43625
43625
  const sortFlag = 0;
43626
- const globalColorTableSize = colorTableSize(palette.length) - 1;
43626
+ const globalColorTableSize = colorTableSize(palette2.length) - 1;
43627
43627
  const fields = globalColorTableFlag << 7 | colorDepth - 1 << 4 | sortFlag << 3 | globalColorTableSize;
43628
43628
  const backgroundColorIndex = 0;
43629
43629
  const pixelAspectRatio = 0;
@@ -43641,12 +43641,12 @@ var require_gifenc = __commonJS({
43641
43641
  writeUInt16(stream, repeat);
43642
43642
  stream.writeByte(0);
43643
43643
  }
43644
- function encodeColorTable(stream, palette) {
43645
- const colorTableLength = 1 << colorTableSize(palette.length);
43644
+ function encodeColorTable(stream, palette2) {
43645
+ const colorTableLength = 1 << colorTableSize(palette2.length);
43646
43646
  for (let i6 = 0; i6 < colorTableLength; i6++) {
43647
43647
  let color = [0, 0, 0];
43648
- if (i6 < palette.length) {
43649
- color = palette[i6];
43648
+ if (i6 < palette2.length) {
43649
+ color = palette2[i6];
43650
43650
  }
43651
43651
  stream.writeByte(color[0]);
43652
43652
  stream.writeByte(color[1]);
@@ -48944,7 +48944,7 @@ var Key = external_exports.object({
48944
48944
  /** Optional independent easing for numeric-array components (for example Spine RGBA curves). */
48945
48945
  componentEase: external_exports.array(Ease).min(1).optional()
48946
48946
  });
48947
- var Interpolation = { interpolation: external_exports.enum(["segment", "pchip"]).optional() };
48947
+ var Interpolation = { interpolation: external_exports.enum(["segment", "pchip", "spline"]).optional() };
48948
48948
  var Track = external_exports.discriminatedUnion("target", [
48949
48949
  external_exports.object({ target: external_exports.literal("control"), id: Id, prop: external_exports.literal("value"), ...Interpolation, keys: external_exports.array(Key).min(1) }),
48950
48950
  external_exports.object({ target: external_exports.literal("bone"), id: Id, prop: BoneProp, ...Interpolation, keys: external_exports.array(Key).min(1) }),
@@ -49210,8 +49210,8 @@ function validate(doc2) {
49210
49210
  if (tracks.has(tid)) errs.push(`animation "${a5.id}": duplicate track ${tid}`);
49211
49211
  tracks.add(tid);
49212
49212
  if (driven.has(tid)) errs.push(`animation "${a5.id}": ${tid} is controlled by a binding; animate its control instead`);
49213
- const known = t5.target === "bone" ? bones.has(t5.id) : t5.target === "slot" ? slots.has(t5.id) : t5.target === "deform" ? attachments.has(t5.id) : t5.target === "ik" ? iks.has(t5.id) : t5.target === "transform" ? transforms.has(t5.id) : t5.target === "path" ? paths.has(t5.id) : t5.target === "control" ? controls.has(t5.id) : true;
49214
- if (!known) errs.push(`animation "${a5.id}": unknown ${t5.target} "${t5.id}"`);
49213
+ const known2 = t5.target === "bone" ? bones.has(t5.id) : t5.target === "slot" ? slots.has(t5.id) : t5.target === "deform" ? attachments.has(t5.id) : t5.target === "ik" ? iks.has(t5.id) : t5.target === "transform" ? transforms.has(t5.id) : t5.target === "path" ? paths.has(t5.id) : t5.target === "control" ? controls.has(t5.id) : true;
49214
+ if (!known2) errs.push(`animation "${a5.id}": unknown ${t5.target} "${t5.id}"`);
49215
49215
  const bound = t5.target === "deform" ? DEFORM_BOUNDS[t5.prop] : void 0;
49216
49216
  const att = t5.target === "deform" ? attachments.get(t5.id) : void 0;
49217
49217
  let prev = -1;
@@ -49365,6 +49365,57 @@ function smoothValue(track, i6, t5, component, loop2) {
49365
49365
  const u6 = (t5 - k4[i6].t) / h6(i6), u22 = u6 * u6, u32 = u22 * u6;
49366
49366
  return (2 * u32 - 3 * u22 + 1) * v6(i6) + (u32 - 2 * u22 + u6) * h6(i6) * tangent(i6) + (-2 * u32 + 3 * u22) * v6(i6 + 1) + (u32 - u22) * h6(i6) * tangent(i6 + 1);
49367
49367
  }
49368
+ function tridiagonal(a5, b4, c5, r5) {
49369
+ const n4 = b4.length, cp = [], x4 = [];
49370
+ let beta = b4[0];
49371
+ x4[0] = r5[0] / beta;
49372
+ for (let i6 = 1; i6 < n4; i6++) {
49373
+ cp[i6] = c5[i6 - 1] / beta;
49374
+ beta = b4[i6] - a5[i6] * cp[i6];
49375
+ x4[i6] = (r5[i6] - a5[i6] * x4[i6 - 1]) / beta;
49376
+ }
49377
+ for (let i6 = n4 - 2; i6 >= 0; i6--) x4[i6] -= cp[i6 + 1] * x4[i6 + 1];
49378
+ return x4;
49379
+ }
49380
+ function splineMoments(t5, v6, periodic) {
49381
+ const n4 = t5.length, h6 = (j5) => t5[j5 + 1] - t5[j5], d6 = (j5) => (v6[j5 + 1] - v6[j5]) / h6(j5);
49382
+ if (!periodic) {
49383
+ const a6 = [], b5 = [], c6 = [], r7 = [];
49384
+ for (let i6 = 0; i6 < n4; i6++) {
49385
+ const hp = i6 > 0 ? h6(i6 - 1) : 0, hn = i6 < n4 - 1 ? h6(i6) : 0;
49386
+ a6.push(hp);
49387
+ b5.push(2 * (hp + hn));
49388
+ c6.push(hn);
49389
+ r7.push(6 * ((i6 < n4 - 1 ? d6(i6) : 0) - (i6 > 0 ? d6(i6 - 1) : 0)));
49390
+ }
49391
+ return tridiagonal(a6, b5, c6, r7);
49392
+ }
49393
+ const m5 = n4 - 1, a5 = [], b4 = [], c5 = [], r5 = [];
49394
+ for (let i6 = 0; i6 < m5; i6++) {
49395
+ const p6 = (i6 + m5 - 1) % m5;
49396
+ a5.push(h6(p6));
49397
+ b4.push(2 * (h6(p6) + h6(i6)));
49398
+ c5.push(h6(i6));
49399
+ r5.push(6 * (d6(i6) - d6(p6)));
49400
+ }
49401
+ const top = a5[0], bottom = c5[m5 - 1], gamma = -b4[0];
49402
+ const bb = [...b4];
49403
+ bb[0] -= gamma;
49404
+ bb[m5 - 1] -= bottom * top / gamma;
49405
+ const x4 = tridiagonal(a5, bb, c5, r5), u6 = new Array(m5).fill(0);
49406
+ u6[0] = gamma;
49407
+ u6[m5 - 1] = bottom;
49408
+ const z3 = tridiagonal(a5, bb, c5, u6);
49409
+ const f6 = (x4[0] + top * x4[m5 - 1] / gamma) / (1 + z3[0] + top * z3[m5 - 1] / gamma);
49410
+ const M2 = x4.map((xi, i6) => xi - f6 * z3[i6]);
49411
+ return [...M2, M2[0]];
49412
+ }
49413
+ function splineValue(track, i6, t5, component, loop2) {
49414
+ const k4 = track.keys, ts = k4.map((x4) => x4.t), vs = k4.map((x4) => component === void 0 ? x4.v : x4.v[component]);
49415
+ const M2 = splineMoments(ts, vs, loop2 && k4.length > 3 && vs[0] === vs[k4.length - 1]);
49416
+ const H3 = ts[i6 + 1] - ts[i6], A3 = (ts[i6 + 1] - t5) / H3, B3 = (t5 - ts[i6]) / H3;
49417
+ return A3 * vs[i6] + B3 * vs[i6 + 1] + ((A3 ** 3 - A3) * M2[i6] + (B3 ** 3 - B3) * M2[i6 + 1]) * H3 * H3 / 6;
49418
+ }
49368
49419
  function sample(track, t5, loop2 = false) {
49369
49420
  const keys = track.keys;
49370
49421
  if (t5 <= keys[0].t) return keys[0].v;
@@ -49376,11 +49427,13 @@ function sample(track, t5, loop2 = false) {
49376
49427
  if (a5.ease === "step") return a5.v;
49377
49428
  if (typeof a5.v === "number" && typeof b4.v === "number") {
49378
49429
  if (track.interpolation === "pchip") return smoothValue(track, i6, t5, void 0, loop2);
49430
+ if (track.interpolation === "spline") return splineValue(track, i6, t5, void 0, loop2);
49379
49431
  const u6 = ease(a5.ease)((t5 - a5.t) / (b4.t - a5.t));
49380
49432
  return a5.v + (b4.v - a5.v) * u6;
49381
49433
  }
49382
49434
  if (Array.isArray(a5.v) && Array.isArray(b4.v) && typeof a5.v[0] === "number") {
49383
49435
  if (track.interpolation === "pchip") return a5.v.map((_4, j5) => smoothValue(track, i6, t5, j5, loop2));
49436
+ if (track.interpolation === "spline") return a5.v.map((_4, j5) => splineValue(track, i6, t5, j5, loop2));
49384
49437
  const phase = (t5 - a5.t) / (b4.t - a5.t), av = a5.v, bv = b4.v;
49385
49438
  return av.map((v6, k4) => v6 + ((bv[k4] ?? v6) - v6) * ease(a5.componentEase?.[k4] ?? a5.ease)(phase));
49386
49439
  }
@@ -50260,13 +50313,13 @@ function motionQuality(doc2, anim, opts = {}) {
50260
50313
  const before = delta(values(k4.v), values(p6.v)), after = delta(values(n4.v), values(k4.v));
50261
50314
  const pass = before.some((v6, j5) => v6 * after[j5] > 1e-6);
50262
50315
  const speed = Math.max(magnitude(before) / (k4.t - p6.t), magnitude(after) / (n4.t - k4.t));
50263
- if (pass && Math.max(magnitude(left), magnitude(right)) < speed * 0.02) report("pass_key_stop", id, `motion stops at a pass-through key; use track interpolation pchip or matched tangents`, k4.t);
50316
+ if (pass && Math.max(magnitude(left), magnitude(right)) < speed * 0.02) report("pass_key_stop", id, `motion stops at a pass-through key; use track interpolation pchip or spline, or matched tangents`, k4.t);
50264
50317
  const jump = magnitude(delta(left, right));
50265
50318
  if (jump > Math.max(0.1, speed * 0.1)) report("velocity_jump", id, `velocity jumps ${jump.toFixed(3)} units/s across this key`, k4.t);
50266
50319
  const acceleration = (a5, b4, c5) => values(at(b4)).map((v6, j5) => (values(at(c5))[j5] - 2 * v6 + values(at(a5))[j5]) / (h6 * h6));
50267
50320
  const al = acceleration(k4.t - 2 * h6, k4.t - h6, k4.t), ar = acceleration(k4.t, k4.t + h6, k4.t + 2 * h6);
50268
50321
  const aj = magnitude(delta(al, ar));
50269
- if (aj > Math.max(1, speed / Math.min(k4.t - p6.t, n4.t - k4.t) * 2)) report("acceleration_jump", id, `acceleration changes by ${aj.toFixed(2)} units/s\xB2 at this key; PCHIP guarantees velocity, not acceleration continuity`, k4.t, "info");
50322
+ if (aj > Math.max(1, speed / Math.min(k4.t - p6.t, n4.t - k4.t) * 2)) report("acceleration_jump", id, `acceleration changes by ${aj.toFixed(2)} units/s\xB2 at this key; PCHIP guarantees velocity, not acceleration continuity \u2014 spline does both`, k4.t, "info");
50270
50323
  }
50271
50324
  }
50272
50325
  const steps = Math.max(2, Math.ceil(D3 * 60));
@@ -50958,12 +51011,12 @@ var json = async (res) => {
50958
51011
  return body;
50959
51012
  };
50960
51013
  async function getDoc(rig) {
50961
- const r5 = await json(await fetch(`/api/doc?rig=${encodeURIComponent(rig)}`));
51014
+ const r5 = await json(await fetch(`api/doc?rig=${encodeURIComponent(rig)}`));
50962
51015
  if (r5.isError) throw new Error(String(r5.text).replace(/^ERROR: /, ""));
50963
51016
  return r5;
50964
51017
  }
50965
51018
  async function callTool(rig, name, args, baseVersion) {
50966
- const res = await fetch(`/api/tool/${encodeURIComponent(name)}`, {
51019
+ const res = await fetch(`api/tool/${encodeURIComponent(name)}`, {
50967
51020
  method: "POST",
50968
51021
  headers: { "content-type": "application/json" },
50969
51022
  body: JSON.stringify({ rig, args, baseVersion })
@@ -50971,25 +51024,25 @@ async function callTool(rig, name, args, baseVersion) {
50971
51024
  return { ...await json(res), status: res.status };
50972
51025
  }
50973
51026
  function subscribe(rig, onChanged, onState) {
50974
- const es = new EventSource(`/api/events?rig=${encodeURIComponent(rig)}`);
51027
+ const es = new EventSource(`api/events?rig=${encodeURIComponent(rig)}`);
50975
51028
  es.addEventListener("changed", (e5) => onChanged(JSON.parse(e5.data).version));
50976
51029
  es.onopen = () => onState(true);
50977
51030
  es.onerror = () => onState(false);
50978
51031
  return () => es.close();
50979
51032
  }
50980
- var assetUrl = (rigDir2, src) => `/rig/${rigDir2 ? rigDir2 + "/" : ""}${src}`;
51033
+ var assetUrl = (rigDir2, src) => `rig/${rigDir2 ? rigDir2 + "/" : ""}${src}`;
50981
51034
  async function listRigs() {
50982
- return json(await fetch("/api/rigs"));
51035
+ return json(await fetch("api/rigs"));
50983
51036
  }
50984
51037
  async function createRig(rig, name, width, height) {
50985
- const res = await fetch("/api/rigs", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ rig, name, width, height }) });
51038
+ const res = await fetch("api/rigs", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ rig, name, width, height }) });
50986
51039
  return { ...await json(res), status: res.status };
50987
51040
  }
50988
51041
  async function listFiles(rig) {
50989
- return json(await fetch(`/api/files?rig=${encodeURIComponent(rig)}`));
51042
+ return json(await fetch(`api/files?rig=${encodeURIComponent(rig)}`));
50990
51043
  }
50991
51044
  async function upload(rig, file) {
50992
- const res = await fetch(`/api/upload?rig=${encodeURIComponent(rig)}&name=${encodeURIComponent(file.name)}`, { method: "POST", headers: { "content-type": "image/png" }, body: file });
51045
+ const res = await fetch(`api/upload?rig=${encodeURIComponent(rig)}&name=${encodeURIComponent(file.name)}`, { method: "POST", headers: { "content-type": "image/png" }, body: file });
50993
51046
  const r5 = await json(res);
50994
51047
  if (r5.isError) throw new Error(String(r5.text).replace(/^ERROR: /, ""));
50995
51048
  return r5;
@@ -51004,19 +51057,20 @@ var requireSlot = (doc2, id) => {
51004
51057
  if (!s6) throw new Error(`unknown slot "${id}"`);
51005
51058
  return s6;
51006
51059
  };
51007
- function sampled(duration, n4, f6, ease2 = "linear") {
51060
+ function sampled(duration, n4, f6) {
51008
51061
  const keys = [];
51009
51062
  for (let i6 = 0; i6 <= n4; i6++) {
51010
51063
  const t5 = +(duration * i6 / n4).toFixed(4);
51011
- keys.push({ t: t5, v: +f6(t5).toFixed(4) + 0, ease: ease2 });
51064
+ keys.push({ t: t5, v: +f6(t5).toFixed(4) + 0, ease: "linear" });
51012
51065
  }
51013
51066
  return keys;
51014
51067
  }
51015
- function boneTrack(bone, prop, keys) {
51016
- return { target: "bone", id: bone.id, prop, keys };
51068
+ var smooth = "spline";
51069
+ function boneTrack(bone, prop, keys, interpolation) {
51070
+ return { target: "bone", id: bone.id, prop, keys, ...interpolation && { interpolation } };
51017
51071
  }
51018
- function deformTrack(slot, prop, keys) {
51019
- return slot.attachment ? { target: "deform", id: slot.attachment, prop, keys } : void 0;
51072
+ function deformTrack(slot, prop, keys, interpolation) {
51073
+ return slot.attachment ? { target: "deform", id: slot.attachment, prop, keys, ...interpolation && { interpolation } } : void 0;
51020
51074
  }
51021
51075
  var pushTrack = (tracks, t5) => {
51022
51076
  if (t5) tracks.push(t5);
@@ -51040,18 +51094,18 @@ var idleBreathing = {
51040
51094
  const armsR = byRole(doc2, "arm_r", "arm_upper_r");
51041
51095
  const chest = slotOfBone(doc2, torso);
51042
51096
  if (chest?.attachment) {
51043
- pushTrack(tracks, deformTrack(chest, "bulge", sampled(T4, 8, (t5) => p6.amplitude * Math.sin(w5 * t5), "ease_in_out")));
51097
+ pushTrack(tracks, deformTrack(chest, "bulge", sampled(T4, 8, (t5) => p6.amplitude * Math.sin(w5 * t5)), smooth));
51044
51098
  } else {
51045
51099
  const r5 = torso.transform;
51046
- tracks.push(boneTrack(torso, "scaleY", sampled(T4, 8, (t5) => r5.scaleY + p6.amplitude * Math.sin(w5 * t5), "ease_in_out")));
51047
- tracks.push(boneTrack(torso, "scaleX", sampled(T4, 8, (t5) => r5.scaleX - p6.amplitude * 0.4 * Math.sin(w5 * t5), "ease_in_out")));
51100
+ tracks.push(boneTrack(torso, "scaleY", sampled(T4, 8, (t5) => r5.scaleY + p6.amplitude * Math.sin(w5 * t5)), smooth));
51101
+ tracks.push(boneTrack(torso, "scaleX", sampled(T4, 8, (t5) => r5.scaleX - p6.amplitude * 0.4 * Math.sin(w5 * t5)), smooth));
51048
51102
  }
51049
51103
  for (const h6 of heads)
51050
- tracks.push(boneTrack(h6, "y", sampled(T4, 8, (t5) => h6.transform.y - p6.headBob * Math.sin(w5 * t5 + 0.4), "ease_in_out")));
51104
+ tracks.push(boneTrack(h6, "y", sampled(T4, 8, (t5) => h6.transform.y - p6.headBob * Math.sin(w5 * t5 + 0.4)), smooth));
51051
51105
  for (const a5 of armsL)
51052
- tracks.push(boneTrack(a5, "rotation", sampled(T4, 8, (t5) => a5.transform.rotation + p6.armSway * Math.sin(w5 * t5 + 0.8), "ease_in_out")));
51106
+ tracks.push(boneTrack(a5, "rotation", sampled(T4, 8, (t5) => a5.transform.rotation + p6.armSway * Math.sin(w5 * t5 + 0.8)), smooth));
51053
51107
  for (const a5 of armsR)
51054
- tracks.push(boneTrack(a5, "rotation", sampled(T4, 8, (t5) => a5.transform.rotation - p6.armSway * Math.sin(w5 * t5 + 0.8), "ease_in_out")));
51108
+ tracks.push(boneTrack(a5, "rotation", sampled(T4, 8, (t5) => a5.transform.rotation - p6.armSway * Math.sin(w5 * t5 + 0.8)), smooth));
51055
51109
  return finish(this.name, p6.id, T4, true, tracks, p6);
51056
51110
  }
51057
51111
  };
@@ -51060,22 +51114,20 @@ var winBounce = {
51060
51114
  defaults: { id: "win", duration: 1.2, height: 40, bounces: 2, squash: 0.15 },
51061
51115
  build(doc2, p6) {
51062
51116
  const b4 = root(doc2), r5 = b4.transform, tracks = [];
51063
- const yK = [[0, r5.y, "ease_out"]];
51064
- const sxK = [[0, r5.scaleX, "ease_out"]];
51065
- const syK = [[0, r5.scaleY, "ease_out"]];
51117
+ const yK = [[0, r5.y]], sxK = [[0, r5.scaleX]], syK = [[0, r5.scaleY]];
51066
51118
  const per = p6.duration / p6.bounces;
51067
51119
  for (let i6 = 0; i6 < p6.bounces; i6++) {
51068
51120
  const t0 = i6 * per, h6 = p6.height * 0.55 ** i6, s6 = p6.squash * 0.7 ** i6;
51069
- sxK.push([t0 + per * 0.08, r5.scaleX * (1 + s6), "ease_out"], [t0 + per * 0.5, r5.scaleX * (1 - s6 * 0.6), "ease_in"], [t0 + per * 0.95, r5.scaleX * (1 + s6), "ease_out"]);
51070
- syK.push([t0 + per * 0.08, r5.scaleY * (1 - s6), "ease_out"], [t0 + per * 0.5, r5.scaleY * (1 + s6 * 0.6), "ease_in"], [t0 + per * 0.95, r5.scaleY * (1 - s6), "ease_out"]);
51071
- yK.push([t0 + per * 0.08, r5.y, "ease_out"], [t0 + per * 0.5, r5.y - h6, "ease_in"], [t0 + per * 0.95, r5.y, "ease_out"]);
51121
+ sxK.push([t0 + per * 0.08, r5.scaleX * (1 + s6)], [t0 + per * 0.5, r5.scaleX * (1 - s6 * 0.6)], [t0 + per * 0.95, r5.scaleX * (1 + s6)]);
51122
+ syK.push([t0 + per * 0.08, r5.scaleY * (1 - s6)], [t0 + per * 0.5, r5.scaleY * (1 + s6 * 0.6)], [t0 + per * 0.95, r5.scaleY * (1 - s6)]);
51123
+ yK.push([t0 + per * 0.08, r5.y], [t0 + per * 0.5, r5.y - h6], [t0 + per * 0.95, r5.y]);
51072
51124
  }
51073
51125
  yK.push([p6.duration, r5.y]);
51074
51126
  sxK.push([p6.duration, r5.scaleX]);
51075
51127
  syK.push([p6.duration, r5.scaleY]);
51076
- tracks.push(boneTrack(b4, "y", K2(...yK)), boneTrack(b4, "scaleX", K2(...sxK)), boneTrack(b4, "scaleY", K2(...syK)));
51128
+ tracks.push(boneTrack(b4, "y", K2(...yK), "pchip"), boneTrack(b4, "scaleX", K2(...sxK), smooth), boneTrack(b4, "scaleY", K2(...syK), smooth));
51077
51129
  for (const h6 of byRole(doc2, "head"))
51078
- tracks.push(boneTrack(h6, "rotation", K2([0, h6.transform.rotation], [p6.duration * 0.25, h6.transform.rotation - 6, "back_out"], [p6.duration * 0.6, h6.transform.rotation + 4], [p6.duration, h6.transform.rotation])));
51130
+ tracks.push(boneTrack(h6, "rotation", K2([0, h6.transform.rotation], [p6.duration * 0.25, h6.transform.rotation - 6], [p6.duration * 0.6, h6.transform.rotation + 4], [p6.duration, h6.transform.rotation]), smooth));
51079
51131
  const anim = finish(this.name, p6.id, p6.duration, false, tracks, p6);
51080
51132
  anim.events.push({ t: 0, name: "win_start" }, { t: per * 0.95, name: "land" });
51081
51133
  return anim;
@@ -51088,8 +51140,8 @@ var anticipationShake = {
51088
51140
  const b4 = root(doc2), r5 = b4.transform, tracks = [];
51089
51141
  const n4 = Math.ceil(p6.duration * p6.frequency * 4);
51090
51142
  const env = (t5) => p6.grow ? t5 / p6.duration : 1;
51091
- tracks.push(boneTrack(b4, "x", sampled(p6.duration, n4, (t5) => r5.x + p6.amplitude * env(t5) * Math.sin(2 * Math.PI * p6.frequency * t5), "linear")));
51092
- tracks.push(boneTrack(b4, "rotation", sampled(p6.duration, n4, (t5) => r5.rotation + 0.6 * p6.amplitude * env(t5) * Math.sin(2 * Math.PI * p6.frequency * t5 + 1.2), "linear")));
51143
+ tracks.push(boneTrack(b4, "x", sampled(p6.duration, n4, (t5) => r5.x + p6.amplitude * env(t5) * Math.sin(2 * Math.PI * p6.frequency * t5)), smooth));
51144
+ tracks.push(boneTrack(b4, "rotation", sampled(p6.duration, n4, (t5) => r5.rotation + 0.6 * p6.amplitude * env(t5) * Math.sin(2 * Math.PI * p6.frequency * t5 + 1.2)), smooth));
51093
51145
  tracks.push(boneTrack(b4, "scaleX", K2([0, r5.scaleX, "ease_in"], [p6.duration, r5.scaleX * p6.scaleUp])));
51094
51146
  tracks.push(boneTrack(b4, "scaleY", K2([0, r5.scaleY, "ease_in"], [p6.duration, r5.scaleY * p6.scaleUp])));
51095
51147
  return finish(this.name, p6.id, p6.duration, false, tracks, p6);
@@ -51114,6 +51166,7 @@ var mouthTalk = {
51114
51166
  if (!p6.frames.length) throw new Error("mouth_talk: frames must not be empty");
51115
51167
  const n4 = Math.max(1, Math.round(p6.duration * p6.rate));
51116
51168
  const keys = S3(...Array.from({ length: n4 }, (_4, i6) => [+(i6 / p6.rate).toFixed(4), p6.frames[i6 % p6.frames.length]]));
51169
+ if (keys.at(-1).t < p6.duration && keys.at(-1).v !== keys[0].v) keys.push(...S3([p6.duration, keys[0].v]));
51117
51170
  return finish(this.name, p6.id, p6.duration, true, [slotTrack(slot, "attachment", keys)], p6);
51118
51171
  }
51119
51172
  };
@@ -51131,10 +51184,10 @@ var symbolIdle = {
51131
51184
  build(doc2, p6) {
51132
51185
  const b4 = root(doc2), r5 = b4.transform, T4 = p6.period, w5 = 2 * Math.PI / T4, tracks = [];
51133
51186
  const rise = (t5) => 0.5 - 0.5 * Math.cos(w5 * t5);
51134
- tracks.push(boneTrack(b4, "y", sampled(T4, 8, (t5) => r5.y - p6.float * rise(t5), "ease_in_out")));
51135
- if (p6.tilt) tracks.push(boneTrack(b4, "rotation", sampled(T4, 8, (t5) => r5.rotation + p6.tilt * Math.sin(w5 * t5), "ease_in_out")));
51187
+ tracks.push(boneTrack(b4, "y", sampled(T4, 8, (t5) => r5.y - p6.float * rise(t5)), smooth));
51188
+ if (p6.tilt) tracks.push(boneTrack(b4, "rotation", sampled(T4, 8, (t5) => r5.rotation + p6.tilt * Math.sin(w5 * t5)), smooth));
51136
51189
  if (p6.pulse) for (const s6 of doc2.slots.filter((s7) => s7.bone === b4.id && s7.attachment))
51137
- pushTrack(tracks, deformTrack(s6, "bulge", sampled(T4, 8, (t5) => p6.pulse * rise(t5), "ease_in_out")));
51190
+ pushTrack(tracks, deformTrack(s6, "bulge", sampled(T4, 8, (t5) => p6.pulse * rise(t5)), smooth));
51138
51191
  return finish(this.name, p6.id, T4, true, tracks, p6);
51139
51192
  }
51140
51193
  };
@@ -51144,12 +51197,12 @@ var symbolWin = {
51144
51197
  build(doc2, p6) {
51145
51198
  const b4 = root(doc2), r5 = b4.transform, d6 = p6.duration, tracks = [];
51146
51199
  for (const [prop, rest] of [["scaleX", r5.scaleX], ["scaleY", r5.scaleY]])
51147
- tracks.push(boneTrack(b4, prop, K2([0, rest, "ease_out"], [d6 * 0.2, rest * (1 + p6.pop), "ease_in_out"], [d6 * 0.5, rest * (1 - p6.pop * 0.3), "ease_out"], [d6, rest])));
51200
+ tracks.push(boneTrack(b4, prop, K2([0, rest], [d6 * 0.2, rest * (1 + p6.pop)], [d6 * 0.5, rest * (1 - p6.pop * 0.3)], [d6, rest]), smooth));
51148
51201
  if (p6.wobble) {
51149
51202
  const n4 = Math.max(8, p6.wobbles * 4);
51150
- const keys = sampled(d6, n4, (t5) => p6.wobble * Math.exp(-3 * t5 / d6) * Math.sin(2 * Math.PI * p6.wobbles * t5 / d6), "ease_in_out");
51203
+ const keys = sampled(d6, n4, (t5) => p6.wobble * Math.exp(-3 * t5 / d6) * Math.sin(2 * Math.PI * p6.wobbles * t5 / d6));
51151
51204
  keys[keys.length - 1].v = 0;
51152
- for (const s6 of doc2.slots.filter((s7) => s7.bone === b4.id && s7.attachment)) pushTrack(tracks, deformTrack(s6, "sway", keys));
51205
+ for (const s6 of doc2.slots.filter((s7) => s7.bone === b4.id && s7.attachment)) pushTrack(tracks, deformTrack(s6, "sway", keys, smooth));
51153
51206
  }
51154
51207
  const anim = finish(this.name, p6.id, d6, false, tracks, p6);
51155
51208
  anim.events.push({ t: 0, name: "win_start" });
@@ -51163,11 +51216,11 @@ var weightShift = {
51163
51216
  const T4 = p6.period, w5 = 2 * Math.PI / T4, N3 = 16, tracks = [];
51164
51217
  const hips = byRole(doc2, "hips")[0] ?? root(doc2), hr = hips.transform;
51165
51218
  const s6 = (t5) => Math.sin(w5 * t5);
51166
- tracks.push(boneTrack(hips, "x", sampled(T4, N3, (t5) => hr.x + p6.shift * s6(t5))));
51167
- if (p6.dip) tracks.push(boneTrack(hips, "y", sampled(T4, N3, (t5) => hr.y + p6.dip * s6(t5) ** 2)));
51219
+ tracks.push(boneTrack(hips, "x", sampled(T4, N3, (t5) => hr.x + p6.shift * s6(t5)), smooth));
51220
+ if (p6.dip) tracks.push(boneTrack(hips, "y", sampled(T4, N3, (t5) => hr.y + p6.dip * s6(t5) ** 2), smooth));
51168
51221
  const torso = byRole(doc2, "torso", "body")[0];
51169
- if (torso && torso !== hips) tracks.push(boneTrack(torso, "rotation", sampled(T4, N3, (t5) => torso.transform.rotation - p6.lean * s6(t5))));
51170
- for (const h6 of byRole(doc2, "head")) tracks.push(boneTrack(h6, "rotation", sampled(T4, N3, (t5) => h6.transform.rotation + p6.lean / 2 * s6(t5))));
51222
+ if (torso && torso !== hips) tracks.push(boneTrack(torso, "rotation", sampled(T4, N3, (t5) => torso.transform.rotation - p6.lean * s6(t5)), smooth));
51223
+ for (const h6 of byRole(doc2, "head")) tracks.push(boneTrack(h6, "rotation", sampled(T4, N3, (t5) => h6.transform.rotation + p6.lean / 2 * s6(t5)), smooth));
51171
51224
  for (const leg of byRole(doc2, "leg_l", "leg_r")) {
51172
51225
  const slot = slotOfBone(doc2, leg), att = slot && doc2.attachments.find((a5) => a5.id === slot.attachment && a5.type === "region");
51173
51226
  const asset = att && att.type === "region" ? doc2.assets.find((a5) => a5.id === att.asset) : void 0;
@@ -51177,8 +51230,8 @@ var weightShift = {
51177
51230
  length2 = Math.max(...[[0, -h6 / 2], [w6 / 2, 0], [0, h6 / 2], [-w6 / 2, 0]].map(([x4, y5]) => Math.hypot(...apply(m5, x4, y5))));
51178
51231
  }
51179
51232
  if (!(length2 > p6.shift)) continue;
51180
- tracks.push(boneTrack(leg, "rotation", sampled(T4, N3, (t5) => leg.transform.rotation + Math.asin(p6.shift * s6(t5) / length2) * 180 / Math.PI)));
51181
- if (p6.dip) tracks.push(boneTrack(leg, "y", sampled(T4, N3, (t5) => leg.transform.y - p6.dip * s6(t5) ** 2)));
51233
+ tracks.push(boneTrack(leg, "rotation", sampled(T4, N3, (t5) => leg.transform.rotation + Math.asin(p6.shift * s6(t5) / length2) * 180 / Math.PI), smooth));
51234
+ if (p6.dip) tracks.push(boneTrack(leg, "y", sampled(T4, N3, (t5) => leg.transform.y - p6.dip * s6(t5) ** 2), smooth));
51182
51235
  }
51183
51236
  return finish(this.name, p6.id, T4, true, tracks, p6);
51184
51237
  }
@@ -51378,7 +51431,8 @@ function adjustTrack(doc2, animId2, track, adj) {
51378
51431
  return { ...k4, t: r42(adj.timeScale ? k4.t * adj.timeScale : k4.t), v: r42(v6) };
51379
51432
  });
51380
51433
  const duration = Math.max(anim.duration, keys[keys.length - 1].t);
51381
- const next = { ...anim, duration, tracks: anim.tracks.map((t5) => same2(t5) ? { ...t5, keys } : t5), preset: void 0 };
51434
+ const interpolation = track.interpolation ?? tr.interpolation;
51435
+ const next = { ...anim, duration, tracks: anim.tracks.map((t5) => same2(t5) ? { ...t5, keys, ...interpolation && { interpolation } } : t5), preset: void 0 };
51382
51436
  return { ...doc2, animations: doc2.animations.map((a5) => a5.id === animId2 ? next : a5) };
51383
51437
  }
51384
51438
 
@@ -51409,6 +51463,7 @@ __export(store_exports, {
51409
51463
  drawOrderFront: () => drawOrderFront,
51410
51464
  drivenBy: () => drivenBy,
51411
51465
  editable: () => editable,
51466
+ embedded: () => embedded,
51412
51467
  ensureTemplate: () => ensureTemplate,
51413
51468
  externalChange: () => externalChange,
51414
51469
  files: () => files,
@@ -51595,6 +51650,7 @@ function hitMesh(v6, tri, px, py) {
51595
51650
  var params = new URLSearchParams(typeof location === "undefined" ? "" : location.search);
51596
51651
  var rigPath = params.get("rig") || "examples/hero/rig.json";
51597
51652
  var rigDir = rigPath.slice(0, Math.max(0, rigPath.lastIndexOf("/")));
51653
+ var embedded = params.get("embed") === "1";
51598
51654
  var doc = y3(void 0);
51599
51655
  var draft = y3(void 0);
51600
51656
  var shown = g2(() => draft.value ?? doc.value);
@@ -52992,7 +53048,7 @@ function TrackSliders() {
52992
53048
  {
52993
53049
  label: "interpolation",
52994
53050
  value: tr.interpolation ?? "segment",
52995
- options: [["segment", "per-key easing"], ["pchip", "smooth through keys"]],
53051
+ options: [["segment", "per-key easing"], ["pchip", "smooth through keys"], ["spline", "smooth, continuous acceleration"]],
52996
53052
  onCommit: (v6) => void commit("rig_set_keys", { animation: a5.id, ...ref, interpolation: v6, keys: tr.keys })
52997
53053
  }
52998
53054
  );
@@ -53116,7 +53172,7 @@ function KeyEase() {
53116
53172
  const tr = a5.tracks.find((k4) => k4.target === track.target && k4.id === track.id && k4.prop === track.prop);
53117
53173
  const key = tr?.keys.find((k4) => Math.abs(k4.t - times3[0]) < 1e-6);
53118
53174
  if (!key) return null;
53119
- if (tr?.interpolation === "pchip") return /* @__PURE__ */ u4(S, { children: [
53175
+ if (tr?.interpolation === "pchip" || tr?.interpolation === "spline") return /* @__PURE__ */ u4(S, { children: [
53120
53176
  /* @__PURE__ */ u4("h4", { children: [
53121
53177
  "key ",
53122
53178
  fmt2(key.t),
@@ -58880,8 +58936,8 @@ var Stage = class {
58880
58936
  void p6.play(anim.id, { loop: false, mix: 0 });
58881
58937
  p6.tick(i6 / fps);
58882
58938
  const { pixels } = this.app.renderer.extract.pixels({ target: this.camera, frame });
58883
- const palette = (0, import_gifenc.quantize)(pixels, 256);
58884
- gif.writeFrame((0, import_gifenc.applyPalette)(pixels, palette), w5, h6, { palette, delay: 1e3 / fps });
58939
+ const palette2 = (0, import_gifenc.quantize)(pixels, 256);
58940
+ gif.writeFrame((0, import_gifenc.applyPalette)(pixels, palette2), w5, h6, { palette: palette2, delay: 1e3 / fps });
58885
58941
  setStatus(`gif: frame ${i6 + 1}/${n4}`);
58886
58942
  await new Promise((r5) => setTimeout(r5));
58887
58943
  }
@@ -59695,9 +59751,9 @@ var KEY_HIT = 5;
59695
59751
  var times2 = (ts) => [...new Set(ts.flatMap((t5) => t5.keys.map((k4) => k4.t)))].sort((a5, b4) => a5 - b4);
59696
59752
  function rows(doc2, anim) {
59697
59753
  const out2 = [{ kind: "all", label: "all keys", keys: times2(anim.tracks), depth: 0 }];
59698
- const push = (target, known) => {
59754
+ const push = (target, known2) => {
59699
59755
  const mine = anim.tracks.filter((t5) => t5.target === target);
59700
- const ids = [.../* @__PURE__ */ new Set([...known.filter((id) => mine.some((t5) => t5.id === id)), ...mine.map((t5) => t5.id)])];
59756
+ const ids = [.../* @__PURE__ */ new Set([...known2.filter((id) => mine.some((t5) => t5.id === id)), ...mine.map((t5) => t5.id)])];
59701
59757
  for (const id of ids) {
59702
59758
  const own = mine.filter((t5) => t5.id === id);
59703
59759
  out2.push({ kind: "group", label: id, keys: times2(own), depth: 0 });
@@ -59763,14 +59819,19 @@ function clampDuration(requested, lastKeyOrEventTime, fps) {
59763
59819
  }
59764
59820
 
59765
59821
  // src/editor/timeline.ts
59766
- var PANEL = "#181818";
59767
- var ALT = "#1E1E1E";
59768
- var LINE = "#2B2B2B";
59769
- var CTL_LINE = "#3C3C3C";
59770
- var ACCENT4 = "#0078D4";
59771
- var FG = "#CCCCCC";
59772
- var FG2 = "#9D9D9D";
59773
- var ERR = "#F14C4C";
59822
+ var TOKENS = {
59823
+ PANEL: ["--chrome", "#181818"],
59824
+ ALT: ["--bg", "#1E1E1E"],
59825
+ LINE: ["--line", "#2B2B2B"],
59826
+ CTL_LINE: ["--ctl-line", "#3C3C3C"],
59827
+ ACCENT: ["--accent", "#0078D4"],
59828
+ FG: ["--fg", "#CCCCCC"],
59829
+ FG2: ["--fg2", "#9D9D9D"],
59830
+ ERR: ["--err", "#F14C4C"]
59831
+ };
59832
+ function palette(style) {
59833
+ return Object.fromEntries(Object.entries(TOKENS).map(([k4, [token, fallback]]) => [k4, style.getPropertyValue(token).trim() || fallback]));
59834
+ }
59774
59835
  var LEFT = 220;
59775
59836
  var ROW_H = 20;
59776
59837
  var HEADER_H = 24;
@@ -59800,6 +59861,9 @@ var Timeline = class {
59800
59861
  selectedKeys.value;
59801
59862
  f3(() => this.draw());
59802
59863
  }));
59864
+ const retheme = () => f3(() => this.draw());
59865
+ window.addEventListener("golem:theme", retheme);
59866
+ this.dispose.push(() => window.removeEventListener("golem:theme", retheme));
59803
59867
  this.bindPointer();
59804
59868
  this.resize();
59805
59869
  }
@@ -59870,6 +59934,7 @@ var Timeline = class {
59870
59934
  g4.fill();
59871
59935
  }
59872
59936
  draw() {
59937
+ const { PANEL, ALT, LINE, CTL_LINE, ACCENT: ACCENT4, FG, FG2, ERR } = palette(getComputedStyle(document.documentElement));
59873
59938
  const g4 = this.g, w5 = this.w, h6 = this.h, l6 = this.layout();
59874
59939
  const anim = currentAnim.value, rs = this.rowsNow(), d6 = this.drag;
59875
59940
  const dur = d6?.kind === "duration" ? d6.duration : anim?.duration ?? 0;
@@ -60300,6 +60365,41 @@ function ControlForms() {
60300
60365
  ] });
60301
60366
  }
60302
60367
 
60368
+ // src/editor/embed.ts
60369
+ var THEME_TOKENS = [
60370
+ "--bg",
60371
+ "--panel",
60372
+ "--chrome",
60373
+ "--line",
60374
+ "--accent",
60375
+ "--accent-hover",
60376
+ "--fg",
60377
+ "--fg2",
60378
+ "--ctl",
60379
+ "--ctl-hover",
60380
+ "--ctl-line",
60381
+ "--err",
60382
+ "--warn",
60383
+ "--font",
60384
+ "--size"
60385
+ ];
60386
+ var known = new Set(THEME_TOKENS);
60387
+ function themeVars(data) {
60388
+ if (!data || typeof data !== "object" || data.type !== "golem:theme") return [];
60389
+ const vars = data.vars;
60390
+ if (!vars || typeof vars !== "object") return [];
60391
+ return Object.entries(vars).filter((e5) => known.has(e5[0]) && typeof e5[1] === "string");
60392
+ }
60393
+ function listenForTheme(win = window) {
60394
+ const on = (e5) => {
60395
+ if (e5.origin !== win.location.origin) return;
60396
+ for (const [name, value] of themeVars(e5.data)) win.document.documentElement.style.setProperty(name, value);
60397
+ win.dispatchEvent(new Event("golem:theme"));
60398
+ };
60399
+ win.addEventListener("message", on);
60400
+ return () => win.removeEventListener("message", on);
60401
+ }
60402
+
60303
60403
  // src/editor/app.tsx
60304
60404
  var stage;
60305
60405
  var timeline;
@@ -60461,7 +60561,7 @@ function OpenList() {
60461
60561
  const body = rigsLoading.value ? /* @__PURE__ */ u4("div", { class: "rig", children: "loading\u2026" }) : rigsError.value ? /* @__PURE__ */ u4("div", { class: "rig error", children: [
60462
60562
  "open: ",
60463
60563
  rigsError.value
60464
- ] }) : rigs.value.length ? rigs.value.map((r5) => /* @__PURE__ */ u4("a", { class: "rig", "data-rig": r5.rig, href: `/editor.html?rig=${encodeURIComponent(r5.rig)}`, children: [
60564
+ ] }) : rigs.value.length ? rigs.value.map((r5) => /* @__PURE__ */ u4("a", { class: "rig", "data-rig": r5.rig, href: `editor.html?rig=${encodeURIComponent(r5.rig)}`, children: [
60465
60565
  /* @__PURE__ */ u4("b", { children: r5.name }),
60466
60566
  " ",
60467
60567
  /* @__PURE__ */ u4("span", { class: "path", children: r5.rig }),
@@ -60493,7 +60593,7 @@ function NewForm() {
60493
60593
  setStatus(String(r5.text).replace(/^ERROR: /, ""), "error");
60494
60594
  return;
60495
60595
  }
60496
- location.href = `/editor.html?rig=${encodeURIComponent(`${dir}/rig.json`)}`;
60596
+ location.href = `editor.html?rig=${encodeURIComponent(`${dir}/rig.json`)}`;
60497
60597
  } catch (e5) {
60498
60598
  setStatus(`new: ${e5.message}`, "error");
60499
60599
  }
@@ -60633,8 +60733,8 @@ function TopBar() {
60633
60733
  /* @__PURE__ */ u4("input", { class: "lock", type: "checkbox", checked: lockImages.value, onChange: (e5) => lockImages.value = e5.target.checked }),
60634
60734
  "lock images"
60635
60735
  ] }),
60636
- /* @__PURE__ */ u4("button", { class: "new", onClick: click(() => popover.value = popover.peek() === "new" ? void 0 : "new"), children: "new" }),
60637
- /* @__PURE__ */ u4("button", { class: "open", onClick: click(() => {
60736
+ !embedded && /* @__PURE__ */ u4("button", { class: "new", onClick: click(() => popover.value = popover.peek() === "new" ? void 0 : "new"), children: "new" }),
60737
+ !embedded && /* @__PURE__ */ u4("button", { class: "open", onClick: click(() => {
60638
60738
  if (popover.peek() === "open") {
60639
60739
  closePopover();
60640
60740
  return;
@@ -60894,6 +60994,7 @@ function App() {
60894
60994
  /* @__PURE__ */ u4(Splitter, { edge: "tl" })
60895
60995
  ] });
60896
60996
  }
60997
+ if (embedded) listenForTheme();
60897
60998
  restoreLayout();
60898
60999
  R(/* @__PURE__ */ u4(App, {}), document.getElementById("app"));
60899
61000
  await reload();