@pixerate/editor 0.275.0 → 0.276.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 (72) hide show
  1. package/dist/animation-editor/index.cjs +62 -62
  2. package/dist/animation-editor/index.js +6 -6
  3. package/dist/brushes/index.cjs +81 -70
  4. package/dist/brushes/index.js +17 -6
  5. package/dist/brushes/patch.d.cts +1 -1
  6. package/dist/brushes/patch.d.ts +1 -1
  7. package/dist/brushes/profiles.d.cts +2 -0
  8. package/dist/brushes/profiles.d.ts +2 -0
  9. package/dist/brushes/schema.d.cts +1 -0
  10. package/dist/brushes/schema.d.ts +1 -0
  11. package/dist/brushes/types.d.cts +22 -1
  12. package/dist/brushes/types.d.ts +22 -1
  13. package/dist/{brushstrokeRender-WGY4DZHF.js → brushstrokeRender-FK3ASUUJ.js} +5 -5
  14. package/dist/{brushstrokeRender-2RQL46WB.cjs → brushstrokeRender-I6MYFCOU.cjs} +21 -21
  15. package/dist/canvas/index.cjs +13 -13
  16. package/dist/canvas/index.js +1 -1
  17. package/dist/chart/contract.d.cts +3 -1
  18. package/dist/chart/contract.d.ts +3 -1
  19. package/dist/{chunk-Y2ISSVPH.js → chunk-4EM5NGCL.js} +167 -9
  20. package/dist/{chunk-Y354ETAE.cjs → chunk-5HR5CSLC.cjs} +49 -49
  21. package/dist/{chunk-LMG57L5A.js → chunk-CTHWXW5M.js} +121 -8
  22. package/dist/{chunk-43XJC3PP.js → chunk-CVBTJVRN.js} +1 -1
  23. package/dist/{chunk-RJGW3RQS.js → chunk-GHYJAMMS.js} +1 -1
  24. package/dist/{chunk-NIBFKXMD.cjs → chunk-IFWLZZCW.cjs} +619 -2
  25. package/dist/{chunk-G5TCMKX5.js → chunk-IJ6NSWKM.js} +2 -2
  26. package/dist/{chunk-C6VB7CPY.cjs → chunk-ISCAJBPQ.cjs} +1 -1
  27. package/dist/{chunk-W6JDUXP3.js → chunk-J23JOHPR.js} +1 -1
  28. package/dist/{chunk-IEEY5RJV.js → chunk-JNMNM3SL.js} +1 -1
  29. package/dist/{chunk-HVO6XCI4.js → chunk-JPB65KQ6.js} +1 -1
  30. package/dist/{chunk-ACTHSQOI.js → chunk-LDZOXESA.js} +618 -1
  31. package/dist/{chunk-DHC4E2DU.cjs → chunk-MITQGHN3.cjs} +121 -8
  32. package/dist/{chunk-STLTOISW.cjs → chunk-NPPMKMCU.cjs} +17 -17
  33. package/dist/{chunk-75SYKUOT.js → chunk-OS6OG7DN.js} +1 -1
  34. package/dist/{chunk-OLZXXAER.cjs → chunk-OY24XRYF.cjs} +408 -250
  35. package/dist/{chunk-6QNDGMK7.cjs → chunk-Q33V5PEF.cjs} +123 -42
  36. package/dist/{chunk-JDXWLCXF.cjs → chunk-QNNZA3V5.cjs} +2 -2
  37. package/dist/{chunk-T6KNJVBP.cjs → chunk-U26LUXCJ.cjs} +35 -35
  38. package/dist/{chunk-62MFUHSI.cjs → chunk-UQXULAMQ.cjs} +16 -16
  39. package/dist/{chunk-RAPNRK4R.cjs → chunk-X7XBEX3O.cjs} +88 -88
  40. package/dist/{chunk-MSWLJI4G.js → chunk-XMSH66VU.js} +2 -2
  41. package/dist/{chunk-ZM7IKQ4X.js → chunk-XVPQNX7O.js} +89 -8
  42. package/dist/{chunk-YYZC2EQO.cjs → chunk-ZIE6EJGR.cjs} +23 -23
  43. package/dist/image-editor/index.cjs +880 -852
  44. package/dist/image-editor/index.js +36 -8
  45. package/dist/paint/index.cjs +33 -5
  46. package/dist/paint/index.d.cts +1 -0
  47. package/dist/paint/index.d.ts +1 -0
  48. package/dist/paint/index.js +32 -4
  49. package/dist/paint/live-patterns.d.cts +149 -0
  50. package/dist/paint/live-patterns.d.ts +149 -0
  51. package/dist/paint/wet/world.d.cts +13 -0
  52. package/dist/paint/wet/world.d.ts +13 -0
  53. package/dist/paint-editor/brush-model.d.cts +7 -1
  54. package/dist/paint-editor/brush-model.d.ts +7 -1
  55. package/dist/paint-editor/controller.d.cts +52 -0
  56. package/dist/paint-editor/controller.d.ts +52 -0
  57. package/dist/paint-editor/index.cjs +850 -510
  58. package/dist/paint-editor/index.js +355 -15
  59. package/dist/paint-editor/ui.d.cts +5 -1
  60. package/dist/paint-editor/ui.d.ts +5 -1
  61. package/dist/paint-editor/wet-tools.d.cts +42 -0
  62. package/dist/paint-editor/wet-tools.d.ts +42 -0
  63. package/dist/paint-editor/wet.d.cts +22 -1
  64. package/dist/paint-editor/wet.d.ts +22 -1
  65. package/dist/vector/index.cjs +1002 -1002
  66. package/dist/vector/index.js +7 -7
  67. package/package.json +1 -1
  68. package/skills/pixerate-brushes/SKILL.md +1 -0
  69. package/skills/pixerate-paint-editor/SKILL.md +7 -1
  70. package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
  71. package/skills/pixerate-paint-editor/references/live-patterns.md +41 -0
  72. package/skills/pixerate-paint-watercolour/SKILL.md +8 -0
@@ -8,7 +8,7 @@
8
8
 
9
9
 
10
10
 
11
- var _chunk6QNDGMK7cjs = require('./chunk-6QNDGMK7.cjs');
11
+ var _chunkQ33V5PEFcjs = require('./chunk-Q33V5PEF.cjs');
12
12
 
13
13
 
14
14
 
@@ -74,13 +74,13 @@ var _chunkJBZRVLXVcjs = require('./chunk-JBZRVLXV.cjs');
74
74
 
75
75
 
76
76
 
77
- var _chunkDHC4E2DUcjs = require('./chunk-DHC4E2DU.cjs');
77
+ var _chunkMITQGHN3cjs = require('./chunk-MITQGHN3.cjs');
78
78
 
79
79
 
80
80
 
81
81
 
82
82
 
83
- var _chunkSTLTOISWcjs = require('./chunk-STLTOISW.cjs');
83
+ var _chunkNPPMKMCUcjs = require('./chunk-NPPMKMCU.cjs');
84
84
 
85
85
 
86
86
 
@@ -102,7 +102,10 @@ var _chunkSTLTOISWcjs = require('./chunk-STLTOISW.cjs');
102
102
 
103
103
 
104
104
 
105
- var _chunkNIBFKXMDcjs = require('./chunk-NIBFKXMD.cjs');
105
+
106
+
107
+
108
+ var _chunkIFWLZZCWcjs = require('./chunk-IFWLZZCW.cjs');
106
109
 
107
110
 
108
111
 
@@ -2793,7 +2796,7 @@ function effectDabField(img, rect, cov, centre, mixed, field, steps = 0, dab = n
2793
2796
  var samplers = /* @__PURE__ */ new WeakMap();
2794
2797
  function stampSampler(ref, art, hardness = 1) {
2795
2798
  const sampler = baseSampler(ref, art);
2796
- if (!sampler || hardness >= 1 || !_chunk6QNDGMK7cjs.isBrushSourceRef.call(void 0, ref)) return sampler;
2799
+ if (!sampler || hardness >= 1 || !_chunkQ33V5PEFcjs.isBrushSourceRef.call(void 0, ref)) return sampler;
2797
2800
  const h = Math.max(0, hardness);
2798
2801
  return (u, v2, seed) => {
2799
2802
  const r = Math.hypot(u, v2) / Math.SQRT2;
@@ -2868,7 +2871,7 @@ function rasterizeStampDab(d, sample, seed, rect, out) {
2868
2871
  }
2869
2872
  function brushStickerRefs(brush) {
2870
2873
  const refs = brush.engine === "sticker" ? [...brush.sticker.stamps] : brush.engine === "particle" ? [...brush.particle.dotTextures] : brush.engine === "dab" && brush.stamp ? [brush.stamp] : [];
2871
- return [...new Set(refs.filter((r) => r.includes(":") && !r.startsWith("editor:") && !_chunk6QNDGMK7cjs.isBrushSourceRef.call(void 0, r)))];
2874
+ return [...new Set(refs.filter((r) => r.includes(":") && !r.startsWith("editor:") && !_chunkQ33V5PEFcjs.isBrushSourceRef.call(void 0, r)))];
2872
2875
  }
2873
2876
  function sprayDroplets(d, spray, seed) {
2874
2877
  const count = 1 + Math.round(spray.density * 31);
@@ -2950,7 +2953,7 @@ function normalizePaper(raw = {}, base) {
2950
2953
  preset: typeof r.preset === "string" && r.preset ? r.preset : b.preset,
2951
2954
  name: typeof r.name === "string" && r.name.trim() ? r.name.trim() : b.name,
2952
2955
  family: PAPER_FAMILIES.includes(r.family) ? r.family : b.family,
2953
- pattern: _chunkNIBFKXMDcjs.GRAIN_PATTERNS.includes(r.pattern) ? r.pattern : b.pattern,
2956
+ pattern: _chunkIFWLZZCWcjs.GRAIN_PATTERNS.includes(r.pattern) ? r.pattern : b.pattern,
2954
2957
  seed: typeof r.seed === "number" && Number.isFinite(r.seed) ? Math.round(Math.abs(r.seed)) % 2147483647 : b.seed,
2955
2958
  color: typeof r.color === "string" && HEX.test(r.color) ? r.color.toLowerCase() : b.color,
2956
2959
  scale: clampNum(r.scale, 0.25, 8, b.scale),
@@ -2972,7 +2975,7 @@ function hexToRgb8(hex) {
2972
2975
  const n = parseInt(hex.slice(1, 7), 16);
2973
2976
  return [n >> 16 & 255, n >> 8 & 255, n & 255];
2974
2977
  }
2975
- function renderPaper(paper, rect, grain = new (0, _chunkNIBFKXMDcjs.PaperGrain)(paper), light) {
2978
+ function renderPaper(paper, rect, grain = new (0, _chunkIFWLZZCWcjs.PaperGrain)(paper), light) {
2976
2979
  const [r, g, b] = hexToRgb8(paper.color);
2977
2980
  const out = new Uint8ClampedArray(rect.width * rect.height * 4);
2978
2981
  const shade = grain.flat ? 0 : paper.shading * 0.16;
@@ -3059,10 +3062,10 @@ var TipGrain = class _TipGrain {
3059
3062
  */
3060
3063
  static create(settings, art) {
3061
3064
  if (!settings || settings.depth <= 0) return null;
3062
- if (_chunkNIBFKXMDcjs.GRAIN_PATTERNS.includes(settings.source)) {
3065
+ if (_chunkIFWLZZCWcjs.GRAIN_PATTERNS.includes(settings.source)) {
3063
3066
  if (settings.source === "smooth") return null;
3064
3067
  const tuning2 = { contrast: settings.contrast, invert: settings.invert };
3065
- const paper = new (0, _chunkNIBFKXMDcjs.PaperGrain)({ pattern: settings.source, seed: 0, scale: settings.scale, tiling: "repeat", dry: tuning2, wet: tuning2 });
3068
+ const paper = new (0, _chunkIFWLZZCWcjs.PaperGrain)({ pattern: settings.source, seed: 0, scale: settings.scale, tiling: "repeat", dry: tuning2, wet: tuning2 });
3066
3069
  return new _TipGrain(paper, settings);
3067
3070
  }
3068
3071
  const a = _optionalChain([art, 'optionalCall', _62 => _62(settings.source)]);
@@ -3332,7 +3335,7 @@ var DryStroke = (_class3 = class {
3332
3335
  }
3333
3336
 
3334
3337
 
3335
- __init12() {this.coverage = new (0, _chunkNIBFKXMDcjs.CoverageMap)()}
3338
+ __init12() {this.coverage = new (0, _chunkIFWLZZCWcjs.CoverageMap)()}
3336
3339
  __init13() {this.dabCount = 0}
3337
3340
 
3338
3341
 
@@ -3383,18 +3386,18 @@ var DryStroke = (_class3 = class {
3383
3386
  mark(m, d, rects) {
3384
3387
  const hardness = this.brush.tip.hardness;
3385
3388
  const grain = this.options.grain;
3386
- const rect = this.stamp ? stampDabRect(m) : _chunkNIBFKXMDcjs.dabRect.call(void 0, m, hardness);
3389
+ const rect = this.stamp ? stampDabRect(m) : _chunkIFWLZZCWcjs.dabRect.call(void 0, m, hardness);
3387
3390
  const n = rect.width * rect.height;
3388
3391
  if (this.buf.length < n) this.buf = new Float32Array(n);
3389
3392
  const vals = this.buf.subarray(0, n);
3390
3393
  if (this.stamp) rasterizeStampDab(m, this.stamp, d.index, rect, vals);
3391
- else _chunkNIBFKXMDcjs.rasterizeDab.call(void 0, m, hardness, rect, vals);
3394
+ else _chunkIFWLZZCWcjs.rasterizeDab.call(void 0, m, hardness, rect, vals);
3392
3395
  _optionalChain([this, 'access', _65 => _65.tipGrain, 'optionalAccess', _66 => _66.apply, 'call', _67 => _67(vals, rect, { x: m.x, y: m.y, angle: m.angle, travel: d.travel })]);
3393
3396
  if (this.depth > 0 && grain) {
3394
3397
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
3395
3398
  const y = rect.y + yy + 0.5;
3396
3399
  for (let xx = 0; xx < rect.width; xx++, k++) {
3397
- if (vals[k] > 0) vals[k] *= _chunkNIBFKXMDcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure);
3400
+ if (vals[k] > 0) vals[k] *= _chunkIFWLZZCWcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure);
3398
3401
  }
3399
3402
  }
3400
3403
  }
@@ -3476,21 +3479,21 @@ var PaintDabStroke = (_class4 = class {
3476
3479
  this.smoother = new PenSmoother(brush.tip.smoothing, brush.pressureSmoothing);
3477
3480
  this.copies = _optionalChain([options, 'access', _68 => _68.copies, 'optionalAccess', _69 => _69.length]) ? options.copies : [IDENTITY_COPY];
3478
3481
  const exchanging = brush.engine === "mixer" || brush.engine === "dab";
3479
- const rates = brush.engine === "mixer" ? _chunkNIBFKXMDcjs.mixerRates.call(void 0, brush.mixer) : _chunkNIBFKXMDcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
3482
+ const rates = brush.engine === "mixer" ? _chunkIFWLZZCWcjs.mixerRates.call(void 0, brush.mixer) : _chunkIFWLZZCWcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
3480
3483
  this.mixing = brush.engine === "mixer" ? brush.mixer.mixing : brush.behavior.mixing;
3481
3484
  this.states = this.copies.map((c, i) => ({
3482
3485
  walker: new PenDabWalker(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
3483
- exchange: exchanging ? new (0, _chunkNIBFKXMDcjs.PaintExchange)(rates, options.load) : null,
3484
- smudge: brush.engine === "smudge" ? new (0, _chunkNIBFKXMDcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
3486
+ exchange: exchanging ? new (0, _chunkIFWLZZCWcjs.PaintExchange)(rates, options.load) : null,
3487
+ smudge: brush.engine === "smudge" ? new (0, _chunkIFWLZZCWcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
3485
3488
  }));
3486
- this.medium = new (0, _chunkNIBFKXMDcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
3489
+ this.medium = new (0, _chunkIFWLZZCWcjs.TileMedium)(options.target, brush.engine === "dab" ? { blend: brush.tip.blend } : {});
3487
3490
  this.depth = options.grain && !options.grain.flat ? Math.min(1, Math.max(0, options.paperDepth * brush.grain)) : 0;
3488
- this.coverage = brush.engine === "dab" ? new (0, _chunkNIBFKXMDcjs.CoverageMap)() : null;
3489
- this.sampler = exchanging && options.paint ? new (0, _chunkNIBFKXMDcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
3491
+ this.coverage = brush.engine === "dab" ? new (0, _chunkIFWLZZCWcjs.CoverageMap)() : null;
3492
+ this.sampler = exchanging && options.paint ? new (0, _chunkIFWLZZCWcjs.PaintGradientSampler)(options.paint, _nullishCoalesce(options.seed, () => ( 0))) : null;
3490
3493
  const table = _optionalChain([this, 'access', _70 => _70.sampler, 'optionalAccess', _71 => _71.acrossTip]) ? this.sampler.tipTable(GRADIENT_STEPS) : null;
3491
3494
  this.gradient = table ? table.map((e) => e.rgb) : null;
3492
3495
  this.gradientAlpha = table && table.some((e) => e.alpha < 1) ? table.map((e) => e.alpha) : null;
3493
- this.scratch = brush.engine === "blender" ? _chunkNIBFKXMDcjs.createBlenderScratch.call(void 0, ) : null;
3496
+ this.scratch = brush.engine === "blender" ? _chunkIFWLZZCWcjs.createBlenderScratch.call(void 0, ) : null;
3494
3497
  }
3495
3498
 
3496
3499
 
@@ -3554,7 +3557,7 @@ var PaintDabStroke = (_class4 = class {
3554
3557
  paintDabs(copy, dabs, rects) {
3555
3558
  const spray = this.brush.engine === "dab" ? this.brush.spray : null;
3556
3559
  for (const d of spray ? dabs.flatMap((dab) => sprayDroplets(dab, spray, (_nullishCoalesce(this.options.seed, () => ( 0))) + copy * 7919)) : dabs) {
3557
- const rect = this.stamp ? stampDabRect(d) : _chunkNIBFKXMDcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
3560
+ const rect = this.stamp ? stampDabRect(d) : _chunkIFWLZZCWcjs.dabRect.call(void 0, d, this.brush.tip.hardness);
3558
3561
  if (rect.width <= 0 || rect.height <= 0) continue;
3559
3562
  this.dab(copy, d, rect);
3560
3563
  rects.push(rect);
@@ -3571,14 +3574,14 @@ var PaintDabStroke = (_class4 = class {
3571
3574
  const tip = this.tip.subarray(0, n);
3572
3575
  tip.fill(0);
3573
3576
  if (this.stamp) rasterizeStampDab({ ...d, alpha: 1 }, this.stamp, d.index, rect, tip);
3574
- else _chunkNIBFKXMDcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
3577
+ else _chunkIFWLZZCWcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.brush.tip.hardness, rect, tip);
3575
3578
  _optionalChain([this, 'access', _76 => _76.tipGrain, 'optionalAccess', _77 => _77.apply, 'call', _78 => _78(tip, rect, d)]);
3576
3579
  if (!(this.depth > 0 && this.options.grain)) return { tip, cov: tip };
3577
3580
  const cov = this.cov.subarray(0, n);
3578
3581
  const grain = this.options.grain;
3579
3582
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
3580
3583
  const y = rect.y + yy + 0.5;
3581
- for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkNIBFKXMDcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
3584
+ for (let xx = 0; xx < rect.width; xx++, k++) cov[k] = tip[k] > 0 ? tip[k] * _chunkIFWLZZCWcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, y), this.depth, d.pressure) : 0;
3582
3585
  }
3583
3586
  return { tip, cov };
3584
3587
  }
@@ -3587,7 +3590,7 @@ var PaintDabStroke = (_class4 = class {
3587
3590
  const { tip, cov } = this.rasterize(d, rect);
3588
3591
  const st = this.states[copy];
3589
3592
  if (brush.engine === "blender") {
3590
- _chunkNIBFKXMDcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
3593
+ _chunkIFWLZZCWcjs.blenderDab.call(void 0, this.medium, rect, cov, d.opacity * d.alpha * brush.tip.opacity, d.radius, brush.blender, this.scratch);
3591
3594
  return;
3592
3595
  }
3593
3596
  if (brush.engine === "smudge") {
@@ -3703,7 +3706,7 @@ var PaintDabStroke = (_class4 = class {
3703
3706
 
3704
3707
  // src/paint-editor/wet.ts
3705
3708
  var STROKE_WATER = 0.9;
3706
- var STROKE_MASS = _chunkDHC4E2DUcjs.PIGMENT_UNIT * 2.5;
3709
+ var STROKE_MASS = _chunkMITQGHN3cjs.PIGMENT_UNIT * 2.5;
3707
3710
  var STROKE_LIGHT = 1.5;
3708
3711
  var COVERAGE_STEPS = 4096;
3709
3712
  function union(a, b) {
@@ -3713,7 +3716,7 @@ function union(a, b) {
3713
3716
  return { x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y };
3714
3717
  }
3715
3718
  function wetPaperInput(paper) {
3716
- const grain = new (0, _chunkNIBFKXMDcjs.PaperGrain)(paper, "wet");
3719
+ const grain = new (0, _chunkIFWLZZCWcjs.PaperGrain)(paper, "wet");
3717
3720
  const flat = grain.flat;
3718
3721
  return {
3719
3722
  absorption: paper.absorption,
@@ -3734,27 +3737,27 @@ var WetStrokeDriver = (_class5 = class {
3734
3737
  const perDab = Math.min(1, spacing * 1.2);
3735
3738
  const thin = wet.thinner;
3736
3739
  const body = wet.body * (1 - thin);
3737
- this.medium = new (0, _chunkDHC4E2DUcjs.WetMedium)(init.world, init.laneId, {
3740
+ this.medium = new (0, _chunkMITQGHN3cjs.WetMedium)(init.world, init.laneId, {
3738
3741
  water: STROKE_WATER * Math.min(1, wet.water * (1 + thin)) * perDab,
3739
3742
  mass: STROKE_MASS * wet.pigment * (1 - 0.6 * thin) * perDab,
3740
3743
  body,
3741
3744
  light: 0
3742
3745
  });
3743
3746
  if (wet.tool === "paint" && brush.ghost && wet.pigment > 0) {
3744
- const one = _chunkDHC4E2DUcjs.pigmentOf.call(void 0, init.color, body);
3747
+ const one = _chunkMITQGHN3cjs.pigmentOf.call(void 0, init.color, body);
3745
3748
  init.world.startGhost(init.laneId, [one[0], one[1], one[2], one[3]], brush.ghost.linger, _nullishCoalesce(init.speed, () => ( 120)), _nullishCoalesce(brush.ghost.trigger, () => ( "immediate")));
3746
3749
  }
3747
3750
  this.lightBase = wet.tool === "paint" ? STROKE_LIGHT * brush.light.amount * (1 - 0.6 * thin) * perDab : 0;
3748
- const rates = _chunkNIBFKXMDcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
3751
+ const rates = _chunkIFWLZZCWcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
3749
3752
  this.states = copies.map((c, i) => ({
3750
3753
  walker: new PenDabWalker(brush, init.seed + i * 7919 | 0, c.linear),
3751
- exchange: wet.tool === "paint" ? new (0, _chunkNIBFKXMDcjs.PaintExchange)(rates, init.load) : null,
3754
+ exchange: wet.tool === "paint" ? new (0, _chunkIFWLZZCWcjs.PaintExchange)(rates, init.load) : null,
3752
3755
  last: null
3753
3756
  }));
3754
3757
  this.copies = copies;
3755
3758
  this.depth = init.grain && !init.grain.flat ? Math.min(1, Math.max(0, init.paperDepth * brush.grain)) : 0;
3756
3759
  const g = _nullishCoalesce(init.paint, () => ( null));
3757
- this.sampler = g ? new (0, _chunkNIBFKXMDcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
3760
+ this.sampler = g ? new (0, _chunkIFWLZZCWcjs.PaintGradientSampler)(g.map.by === "across-tip" ? { ...g, map: { by: "distance", length: 300, repeat: "mirror" } } : g, init.seed) : null;
3758
3761
  }
3759
3762
 
3760
3763
  __init28() {this.dabCount = 0}
@@ -3828,7 +3831,7 @@ var WetStrokeDriver = (_class5 = class {
3828
3831
  }
3829
3832
  applyDabs(copy, dabs, rects) {
3830
3833
  for (const d of dabs) {
3831
- const rect = _chunkNIBFKXMDcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
3834
+ const rect = _chunkIFWLZZCWcjs.dabRect.call(void 0, d, this.init.brush.tip.hardness);
3832
3835
  if (rect.width <= 0 || rect.height <= 0) continue;
3833
3836
  this.dab(copy, d, rect);
3834
3837
  rects.push(rect);
@@ -3845,7 +3848,7 @@ var WetStrokeDriver = (_class5 = class {
3845
3848
  const tip = this.tip.subarray(0, n);
3846
3849
  const cov = this.cov.subarray(0, n);
3847
3850
  tip.fill(0);
3848
- _chunkNIBFKXMDcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
3851
+ _chunkIFWLZZCWcjs.rasterizeDab.call(void 0, { ...d, alpha: 1 }, this.init.brush.tip.hardness, rect, tip);
3849
3852
  const grain = this.depth > 0 ? this.init.grain : null;
3850
3853
  const mask = this.init.mask;
3851
3854
  for (let yy = 0, k = 0; yy < rect.height; yy++) {
@@ -3856,7 +3859,7 @@ var WetStrokeDriver = (_class5 = class {
3856
3859
  tip[k] *= mx >= 0 && my >= 0 && mx < mask.width && my < mask.height ? mask.data[my * mask.width + mx] / 255 : 0;
3857
3860
  }
3858
3861
  let v2 = tip[k];
3859
- if (v2 > 0 && grain) v2 *= _chunkNIBFKXMDcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
3862
+ if (v2 > 0 && grain) v2 *= _chunkIFWLZZCWcjs.grainCatch.call(void 0, grain.at(rect.x + xx + 0.5, rect.y + yy + 0.5), this.depth, d.pressure);
3860
3863
  tip[k] = Math.round(tip[k] * COVERAGE_STEPS) / COVERAGE_STEPS;
3861
3864
  cov[k] = Math.round(v2 * COVERAGE_STEPS) / COVERAGE_STEPS;
3862
3865
  }
@@ -3914,6 +3917,17 @@ var WetStrokeDriver = (_class5 = class {
3914
3917
  } else world.paint(laneId, rect, cov, this.medium.options.water * k, null);
3915
3918
  ex.drain();
3916
3919
  if (wet.rewet > 0) world.rewet(laneId, rect, cov, wet.rewet * k * 0.15, this.init.paperColor);
3920
+ if (brush.livePatterns) {
3921
+ world.seedLivePatterns(
3922
+ laneId,
3923
+ d.x,
3924
+ d.y,
3925
+ Math.max(2, d.radius),
3926
+ this.init.seed + this.dabCount * 131 + copy * 997 | 0,
3927
+ Math.max(0.65, d.pressure),
3928
+ brush.livePatterns
3929
+ );
3930
+ }
3917
3931
  break;
3918
3932
  }
3919
3933
  case "water": {
@@ -3953,7 +3967,7 @@ var WET_GPU_MODES = ["auto", "off"];
3953
3967
  var GPU_LEAD = 16;
3954
3968
  var DISPLAY_TILES_PER_TICK = 24;
3955
3969
  var PaintWetLayers = (_class6 = class {
3956
- constructor(host, options = {}) {;_class6.prototype.__init41.call(this);_class6.prototype.__init42.call(this);_class6.prototype.__init43.call(this);_class6.prototype.__init44.call(this);_class6.prototype.__init45.call(this);_class6.prototype.__init46.call(this);_class6.prototype.__init47.call(this);_class6.prototype.__init48.call(this);_class6.prototype.__init49.call(this);_class6.prototype.__init50.call(this);_class6.prototype.__init51.call(this);_class6.prototype.__init52.call(this);_class6.prototype.__init53.call(this);_class6.prototype.__init54.call(this);_class6.prototype.__init55.call(this);_class6.prototype.__init56.call(this);
3970
+ constructor(host, options = {}) {;_class6.prototype.__init41.call(this);_class6.prototype.__init42.call(this);_class6.prototype.__init43.call(this);_class6.prototype.__init44.call(this);_class6.prototype.__init45.call(this);_class6.prototype.__init46.call(this);_class6.prototype.__init47.call(this);_class6.prototype.__init48.call(this);_class6.prototype.__init49.call(this);_class6.prototype.__init50.call(this);_class6.prototype.__init51.call(this);_class6.prototype.__init52.call(this);_class6.prototype.__init53.call(this);_class6.prototype.__init54.call(this);_class6.prototype.__init55.call(this);_class6.prototype.__init56.call(this);_class6.prototype.__init57.call(this);
3957
3971
  this.host = host;
3958
3972
  this.options = options;
3959
3973
  this.speed = Math.max(1, Math.min(2e3, _nullishCoalesce(options.speed, () => ( 120))));
@@ -3964,32 +3978,33 @@ var PaintWetLayers = (_class6 = class {
3964
3978
 
3965
3979
 
3966
3980
  __init41() {this.world = null}
3967
- __init42() {this.tilt = { ..._chunkDHC4E2DUcjs.FLAT }}
3981
+ __init42() {this.tilt = { ..._chunkMITQGHN3cjs.FLAT }}
3968
3982
  __init43() {this.settings = /* @__PURE__ */ new Map()}
3969
- __init44() {this.paused = false}
3983
+ __init44() {this.patterns = /* @__PURE__ */ new Map()}
3984
+ __init45() {this.paused = false}
3970
3985
  /** Wet strokes dry as soon as they end (one undo step with the stroke). */
3971
- __init45() {this.instantDry = false}
3986
+ __init46() {this.instantDry = false}
3972
3987
 
3973
- __init46() {this.overlay = false}
3988
+ __init47() {this.overlay = false}
3974
3989
 
3975
3990
  /** The live wet stroke, if any. */
3976
- __init47() {this.driver = null}
3977
- __init48() {this.lastTick = null}
3978
- __init49() {this.ticking = null}
3979
- __init50() {this.stepsOwed = 0}
3980
- __init51() {this.displaying = null}
3981
- __init52() {this.leadAt = 0}
3991
+ __init48() {this.driver = null}
3992
+ __init49() {this.lastTick = null}
3993
+ __init50() {this.ticking = null}
3994
+ __init51() {this.stepsOwed = 0}
3995
+ __init52() {this.displaying = null}
3996
+ __init53() {this.leadAt = 0}
3982
3997
 
3983
3998
 
3984
- __init53() {this.gpu = null}
3985
- __init54() {this.gpuSupport = null}
3986
- __init55() {this.gpuStarting = null}
3999
+ __init54() {this.gpu = null}
4000
+ __init55() {this.gpuSupport = null}
4001
+ __init56() {this.gpuStarting = null}
3987
4002
  // --- Engine B ------------------------------------------------------------------
3988
4003
  /** Starts the GPU engine for the world (once; it may turn out unavailable). */
3989
4004
  startGpu() {
3990
4005
  if (this.gpuMode === "off" || this.gpu || this.gpuStarting || this.gpuSupport) return;
3991
- const provider = this.options.gpuProvider === void 0 ? _chunkDHC4E2DUcjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
3992
- this.gpuStarting = _chunkDHC4E2DUcjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
4006
+ const provider = this.options.gpuProvider === void 0 ? _chunkMITQGHN3cjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
4007
+ this.gpuStarting = _chunkMITQGHN3cjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
3993
4008
  this.gpuSupport = support;
3994
4009
  if (!engine) return;
3995
4010
  if (this.gpuMode === "off" || !this.world) {
@@ -4048,7 +4063,7 @@ var PaintWetLayers = (_class6 = class {
4048
4063
  return this.world;
4049
4064
  }
4050
4065
  makeWorld(width, height, paper) {
4051
- const world = new (0, _chunkDHC4E2DUcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
4066
+ const world = new (0, _chunkMITQGHN3cjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
4052
4067
  world.setTilt(this.tilt);
4053
4068
  world.gpuMinTiles = this.gpuMinTiles;
4054
4069
  if (this.gpu) world.attachGpu(this.gpu);
@@ -4060,7 +4075,7 @@ var PaintWetLayers = (_class6 = class {
4060
4075
  * sides: the shift has to be whole wet tiles (256 px), and no wet stroke may be live.
4061
4076
  */
4062
4077
  canExtend(left2, top) {
4063
- return left2 % _chunkDHC4E2DUcjs.WET_TILE === 0 && top % _chunkDHC4E2DUcjs.WET_TILE === 0 && !this.driver;
4078
+ return left2 % _chunkMITQGHN3cjs.WET_TILE === 0 && top % _chunkMITQGHN3cjs.WET_TILE === 0 && !this.driver;
4064
4079
  }
4065
4080
  /**
4066
4081
  * Keeps the wet paint while the canvas grows to `width`×`height` by `left` / `top` on those
@@ -4072,22 +4087,31 @@ var PaintWetLayers = (_class6 = class {
4072
4087
  extend(width, height, left2, top, paper) {
4073
4088
  if (!this.canExtend(left2, top)) throw new Error("Wet paint only moves by whole 256 px tiles, between strokes.");
4074
4089
  for (const [id, s] of this.settings) if (s.flow.center) this.settings.set(id, { ...s, flow: { ...s.flow, center: { x: s.flow.center.x + left2, y: s.flow.center.y + top } } });
4090
+ const tx0 = left2 / _chunkMITQGHN3cjs.WET_TILE;
4091
+ const ty0 = top / _chunkMITQGHN3cjs.WET_TILE;
4092
+ for (const [id, f] of this.patterns) {
4093
+ const moved2 = _chunkIFWLZZCWcjs.moveLivePatternSnapshot.call(void 0, f.snapshot(), { width, height }, tx0, ty0);
4094
+ const next = new (0, _chunkIFWLZZCWcjs.LivePatternField)(width, height);
4095
+ next.restore(moved2);
4096
+ this.patterns.set(id, next);
4097
+ }
4075
4098
  const old = this.world;
4076
4099
  const snap = _optionalChain([old, 'optionalAccess', _101 => _101.laneIds, 'call', _102 => _102(), 'access', _103 => _103.length]) ? old.snapshot() : null;
4077
4100
  this.dropWorld();
4078
4101
  this.lastTick = null;
4079
4102
  this.stepsOwed = 0;
4080
4103
  if (!old || !snap) return;
4081
- const moved = _chunkDHC4E2DUcjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left2, top, (l) => {
4104
+ const moved = _chunkMITQGHN3cjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left2, top, (l) => {
4082
4105
  const flow = _optionalChain([this, 'access', _104 => _104.settings, 'access', _105 => _105.get, 'call', _106 => _106(l.id), 'optionalAccess', _107 => _107.flow]);
4083
4106
  return {
4084
4107
  base: _chunk474IQG74cjs.translateSurface.call(void 0, l.base, left2, top),
4085
4108
  ...l.light ? { light: _chunk474IQG74cjs.translateSurface.call(void 0, l.light, left2, top) } : {},
4086
- flow: l.flow && flow && flow.kind !== "none" ? _chunkDHC4E2DUcjs.flowField.call(void 0, flow, width, height) : l.flow
4109
+ flow: l.flow && flow && flow.kind !== "none" ? _chunkMITQGHN3cjs.flowField.call(void 0, flow, width, height) : l.flow
4087
4110
  };
4088
4111
  });
4089
4112
  this.world = this.makeWorld(width, height, paper);
4090
4113
  this.world.restore(moved);
4114
+ for (const id of this.world.laneIds()) this.patterns.set(id, this.world.livePatternField(id));
4091
4115
  }
4092
4116
  /** Whether any layer (or `layerId`) has wet paint. */
4093
4117
  isWet(layerId) {
@@ -4111,73 +4135,152 @@ var PaintWetLayers = (_class6 = class {
4111
4135
  settingsOf(layerId, medium = "watercolor") {
4112
4136
  let s = this.settings.get(layerId);
4113
4137
  if (!s) {
4114
- s = { params: _chunkDHC4E2DUcjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkDHC4E2DUcjs.DEFAULT_WET_PARAMS), flow: { ..._chunkDHC4E2DUcjs.DEFAULT_FLOW } };
4138
+ s = { params: _chunkMITQGHN3cjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkMITQGHN3cjs.DEFAULT_WET_PARAMS), flow: { ..._chunkMITQGHN3cjs.DEFAULT_FLOW }, livePatterns: null };
4115
4139
  this.settings.set(layerId, s);
4116
4140
  }
4117
4141
  return s;
4118
4142
  }
4143
+ patternFieldOf(layerId) {
4144
+ const { width, height } = this.host.canvas();
4145
+ let f = this.patterns.get(layerId);
4146
+ if (!f) {
4147
+ f = new (0, _chunkIFWLZZCWcjs.LivePatternField)(width, height);
4148
+ const s = _optionalChain([this, 'access', _113 => _113.settings, 'access', _114 => _114.get, 'call', _115 => _115(layerId), 'optionalAccess', _116 => _116.livePatterns]);
4149
+ if (s) f.configure(s);
4150
+ this.patterns.set(layerId, f);
4151
+ } else if (f.width !== width || f.height !== height) {
4152
+ f.resize(width, height);
4153
+ }
4154
+ return f;
4155
+ }
4119
4156
  /** Puts a layer in the world (its current pixels become the base under the wet paint). */
4120
4157
  ensureLane(layerId, medium) {
4121
4158
  const w = this.ensureWorld();
4159
+ const lp = this.patternFieldOf(layerId);
4122
4160
  if (!w.hasLane(layerId)) {
4123
4161
  const base = _nullishCoalesce(this.host.layerSurface(layerId), () => ( new (0, _chunk474IQG74cjs.TiledSurface)(4, /* @__PURE__ */ new Map(), 0)));
4124
4162
  const s = this.settingsOf(layerId, medium);
4125
- w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId), ghost: s.ghost });
4163
+ w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId), ghost: s.ghost, livePatterns: lp });
4126
4164
  const { width, height } = this.host.canvas();
4127
- if (s.flow.kind !== "none") w.setFlow(layerId, _chunkDHC4E2DUcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
4165
+ if (s.flow.kind !== "none") w.setFlow(layerId, _chunkMITQGHN3cjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
4128
4166
  }
4129
4167
  return w;
4130
4168
  }
4131
4169
  setParams(layerId, update) {
4132
4170
  const s = this.settingsOf(layerId);
4133
- s.params = _chunkDHC4E2DUcjs.normalizeWetParams.call(void 0, update, s.params);
4134
- if (_optionalChain([this, 'access', _113 => _113.world, 'optionalAccess', _114 => _114.hasLane, 'call', _115 => _115(layerId)])) this.world.setParams(layerId, s.params);
4171
+ s.params = _chunkMITQGHN3cjs.normalizeWetParams.call(void 0, update, s.params);
4172
+ if (_optionalChain([this, 'access', _117 => _117.world, 'optionalAccess', _118 => _118.hasLane, 'call', _119 => _119(layerId)])) this.world.setParams(layerId, s.params);
4135
4173
  return { ...s.params };
4136
4174
  }
4137
4175
  setFlow(layerId, update) {
4138
4176
  const s = this.settingsOf(layerId);
4139
- s.flow = _chunkDHC4E2DUcjs.normalizeFlow.call(void 0, update, s.flow);
4140
- if (_optionalChain([this, 'access', _116 => _116.world, 'optionalAccess', _117 => _117.hasLane, 'call', _118 => _118(layerId)])) {
4177
+ s.flow = _chunkMITQGHN3cjs.normalizeFlow.call(void 0, update, s.flow);
4178
+ if (_optionalChain([this, 'access', _120 => _120.world, 'optionalAccess', _121 => _121.hasLane, 'call', _122 => _122(layerId)])) {
4141
4179
  const { width, height } = this.host.canvas();
4142
- this.world.setFlow(layerId, _chunkDHC4E2DUcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
4180
+ this.world.setFlow(layerId, _chunkMITQGHN3cjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
4143
4181
  }
4144
4182
  return { ...s.flow };
4145
4183
  }
4184
+ setLivePatterns(layerId, update) {
4185
+ const s = this.settingsOf(layerId);
4186
+ const f = this.patternFieldOf(layerId);
4187
+ if (update === null) {
4188
+ f.clear();
4189
+ s.livePatterns = null;
4190
+ if (_optionalChain([this, 'access', _123 => _123.world, 'optionalAccess', _124 => _124.hasLane, 'call', _125 => _125(layerId)])) this.syncDisplays();
4191
+ return null;
4192
+ }
4193
+ const next = _optionalChain([this, 'access', _126 => _126.world, 'optionalAccess', _127 => _127.hasLane, 'call', _128 => _128(layerId)]) ? this.world.setLivePatterns(layerId, update) : f.configure(update);
4194
+ s.livePatterns = { ...next };
4195
+ this.syncDisplays();
4196
+ return { ...next };
4197
+ }
4198
+ seedLivePatterns(layerId, points, radius, seed = 1, settings) {
4199
+ const s = this.settingsOf(layerId);
4200
+ const f = this.patternFieldOf(layerId);
4201
+ if (settings) {
4202
+ const next = _optionalChain([this, 'access', _129 => _129.world, 'optionalAccess', _130 => _130.hasLane, 'call', _131 => _131(layerId)]) ? this.world.setLivePatterns(layerId, settings) : f.configure(settings);
4203
+ s.livePatterns = { ...next };
4204
+ } else if (!f.enabled) {
4205
+ const next = _optionalChain([this, 'access', _132 => _132.world, 'optionalAccess', _133 => _133.hasLane, 'call', _134 => _134(layerId)]) ? this.world.setLivePatterns(layerId, _nullishCoalesce(s.livePatterns, () => ( {}))) : f.configure(_nullishCoalesce(s.livePatterns, () => ( {})));
4206
+ s.livePatterns = { ...next };
4207
+ }
4208
+ let seededCells = 0;
4209
+ const hasLane = Boolean(_optionalChain([this, 'access', _135 => _135.world, 'optionalAccess', _136 => _136.hasLane, 'call', _137 => _137(layerId)]));
4210
+ for (let i = 0; i < points.length; i++) {
4211
+ const p = points[i];
4212
+ const str = _nullishCoalesce(p.strength, () => ( 1));
4213
+ const ptSeed = seed + i * 7919 | 0;
4214
+ if (hasLane) {
4215
+ seededCells += this.world.seedLivePatterns(layerId, p.x, p.y, radius, ptSeed, str);
4216
+ } else {
4217
+ seededCells += f.seedDisc(p.x, p.y, radius, ptSeed, str);
4218
+ }
4219
+ }
4220
+ this.syncDisplays();
4221
+ return { seededCells, stats: this.livePatternStats(layerId) };
4222
+ }
4223
+ livePatternStats(layerId) {
4224
+ const f = this.patterns.get(layerId);
4225
+ if (_optionalChain([f, 'optionalAccess', _138 => _138.enabled])) {
4226
+ const s = this.settingsOf(layerId);
4227
+ if (!s.livePatterns) s.livePatterns = { ...f.settings };
4228
+ }
4229
+ if (_optionalChain([this, 'access', _139 => _139.world, 'optionalAccess', _140 => _140.hasLane, 'call', _141 => _141(layerId)])) return this.world.livePatternStats(layerId);
4230
+ if (f) return f.stats(() => false);
4231
+ const cfg = _nullishCoalesce(_optionalChain([this, 'access', _142 => _142.settings, 'access', _143 => _143.get, 'call', _144 => _144(layerId), 'optionalAccess', _145 => _145.livePatterns]), () => ( null));
4232
+ return {
4233
+ enabled: Boolean(cfg),
4234
+ settings: _chunkIFWLZZCWcjs.normalizeLivePatterns.call(void 0, _nullishCoalesce(cfg, () => ( {}))),
4235
+ activeTiles: 0,
4236
+ patternCells: 0,
4237
+ wetPatternCells: 0,
4238
+ meanV: 0,
4239
+ maxV: 0,
4240
+ bounds: null
4241
+ };
4242
+ }
4146
4243
  setTilt(update) {
4147
- this.tilt = _chunkDHC4E2DUcjs.normalizeTilt.call(void 0, update, this.tilt);
4148
- _optionalChain([this, 'access', _119 => _119.world, 'optionalAccess', _120 => _120.setTilt, 'call', _121 => _121(this.tilt)]);
4244
+ this.tilt = _chunkMITQGHN3cjs.normalizeTilt.call(void 0, update, this.tilt);
4245
+ _optionalChain([this, 'access', _146 => _146.world, 'optionalAccess', _147 => _147.setTilt, 'call', _148 => _148(this.tilt)]);
4149
4246
  return { ...this.tilt };
4150
4247
  }
4151
4248
  /** The paper changed. */
4152
4249
  paperChanged() {
4153
- _optionalChain([this, 'access', _122 => _122.world, 'optionalAccess', _123 => _123.setPaper, 'call', _124 => _124(wetPaperInput(this.host.paper()))]);
4250
+ _optionalChain([this, 'access', _149 => _149.world, 'optionalAccess', _150 => _150.setPaper, 'call', _151 => _151(wetPaperInput(this.host.paper()))]);
4154
4251
  }
4155
4252
  /** A layer as tools describe it. */
4156
4253
  info(layerId) {
4157
4254
  const s = this.settingsOf(layerId);
4158
- const st = _optionalChain([this, 'access', _125 => _125.world, 'optionalAccess', _126 => _126.hasLane, 'call', _127 => _127(layerId)]) ? this.world.stats(layerId) : null;
4159
- const g = _optionalChain([this, 'access', _128 => _128.world, 'optionalAccess', _129 => _129.hasLane, 'call', _130 => _130(layerId)]) ? this.world.getGhost(layerId) : _nullishCoalesce(s.ghost, () => ( null));
4255
+ const f = this.patterns.get(layerId);
4256
+ if (_optionalChain([f, 'optionalAccess', _152 => _152.enabled]) && !s.livePatterns) s.livePatterns = { ...f.settings };
4257
+ const st = _optionalChain([this, 'access', _153 => _153.world, 'optionalAccess', _154 => _154.hasLane, 'call', _155 => _155(layerId)]) ? this.world.stats(layerId) : null;
4258
+ const g = _optionalChain([this, 'access', _156 => _156.world, 'optionalAccess', _157 => _157.hasLane, 'call', _158 => _158(layerId)]) ? this.world.getGhost(layerId) : _nullishCoalesce(s.ghost, () => ( null));
4160
4259
  return {
4161
4260
  layerId,
4162
4261
  wet: Boolean(st && st.wetCells > 0),
4163
- wetCells: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _131 => _131.wetCells]), () => ( 0)),
4164
- wetBounds: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _132 => _132.wetBounds]), () => ( null)),
4165
- activeTiles: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _133 => _133.activeTiles]), () => ( 0)),
4262
+ wetCells: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _159 => _159.wetCells]), () => ( 0)),
4263
+ wetBounds: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _160 => _160.wetBounds]), () => ( null)),
4264
+ activeTiles: _nullishCoalesce(_optionalChain([st, 'optionalAccess', _161 => _161.activeTiles]), () => ( 0)),
4166
4265
  params: { ...s.params },
4167
4266
  flow: { ...s.flow },
4168
- ...g ? { ghost: { remaining: Math.round(g.remaining * _chunkDHC4E2DUcjs.FREE_INTERVAL / this.speed * 100) / 100 } } : {}
4267
+ livePatterns: s.livePatterns ? { ...s.livePatterns } : null,
4268
+ ...g ? { ghost: { remaining: Math.round(g.remaining * _chunkMITQGHN3cjs.FREE_INTERVAL / this.speed * 100) / 100 } } : {}
4169
4269
  };
4170
4270
  }
4171
4271
  backend() {
4172
- return _nullishCoalesce(_optionalChain([this, 'access', _134 => _134.world, 'optionalAccess', _135 => _135.backend, 'call', _136 => _136()]), () => ( null));
4272
+ return _nullishCoalesce(_optionalChain([this, 'access', _162 => _162.world, 'optionalAccess', _163 => _163.backend, 'call', _164 => _164()]), () => ( null));
4173
4273
  }
4174
4274
  /** Shows the current wet pixels (at most `maxTiles` reshaded per layer). */
4175
4275
  syncDisplays(maxTiles = Infinity) {
4176
4276
  const w = this.world;
4277
+ this.syncHeights();
4177
4278
  if (!w) return [];
4178
4279
  const surfaces = /* @__PURE__ */ new Map();
4179
4280
  const rects = [];
4180
4281
  for (const id of w.laneIds()) {
4282
+ const f = this.patterns.get(id);
4283
+ if (_optionalChain([f, 'optionalAccess', _165 => _165.enabled])) this.settingsOf(id).livePatterns = { ...f.settings };
4181
4284
  const d = w.display(id, maxTiles);
4182
4285
  if (this.host.layerSurface(id) !== d.surface) surfaces.set(id, d.surface);
4183
4286
  rects.push(...d.changed);
@@ -4189,10 +4292,13 @@ var PaintWetLayers = (_class6 = class {
4189
4292
  /** Like `syncDisplays`, shading on the GPU when Engine B is active (all stale tiles at once). */
4190
4293
  async syncDisplaysGpu(maxCpuTiles, lead = false) {
4191
4294
  const w = this.world;
4295
+ this.syncHeights();
4192
4296
  if (!w) return [];
4193
4297
  const surfaces = /* @__PURE__ */ new Map();
4194
4298
  const rects = [];
4195
4299
  for (const id of w.laneIds()) {
4300
+ const f = this.patterns.get(id);
4301
+ if (_optionalChain([f, 'optionalAccess', _166 => _166.enabled])) this.settingsOf(id).livePatterns = { ...f.settings };
4196
4302
  const d = await w.displayGpu(id, maxCpuTiles, lead);
4197
4303
  if (!w.hasLane(id)) continue;
4198
4304
  if (this.host.layerSurface(id) !== d.surface) surfaces.set(id, d.surface);
@@ -4202,6 +4308,18 @@ var PaintWetLayers = (_class6 = class {
4202
4308
  if (surfaces.size) this.host.updateSurfaces(surfaces, rects);
4203
4309
  return rects;
4204
4310
  }
4311
+ /** Updates thick height maps for any layers with live pattern relief (`relief > 0`). */
4312
+ syncHeights() {
4313
+ if (!this.host.layerHeight || !this.host.updateHeights) return;
4314
+ const heights = /* @__PURE__ */ new Map();
4315
+ for (const [id, f] of this.patterns) {
4316
+ if (!f.enabled || !(f.settings.relief > 0) || f.tiles.size === 0) continue;
4317
+ const cur = _nullishCoalesce(this.host.layerHeight(id), () => ( new (0, _chunk474IQG74cjs.TiledSurface)(1, /* @__PURE__ */ new Map(), 0)));
4318
+ const next = f.applyReliefHeight(cur);
4319
+ if (next !== cur) heights.set(id, next);
4320
+ }
4321
+ if (heights.size) this.host.updateHeights(heights);
4322
+ }
4205
4323
  /** Shows each wet layer's live light paint (the light under it with the wet light shaded in). */
4206
4324
  syncLights() {
4207
4325
  const w = this.world;
@@ -4218,12 +4336,12 @@ var PaintWetLayers = (_class6 = class {
4218
4336
  const w = this.world;
4219
4337
  if (!w) return;
4220
4338
  for (const id of w.laneIds()) {
4221
- if (w.isActive(id) || _optionalChain([this, 'access', _137 => _137.driver, 'optionalAccess', _138 => _138.init, 'access', _139 => _139.laneId]) === id) continue;
4339
+ if (w.isActive(id) || _optionalChain([this, 'access', _167 => _167.driver, 'optionalAccess', _168 => _168.init, 'access', _169 => _169.laneId]) === id) continue;
4222
4340
  const base = w.getBase(id);
4223
4341
  const light = w.isLit(id) ? w.getLight(id) : null;
4224
4342
  w.removeLane(id);
4225
4343
  const s = this.settings.get(id);
4226
- if (_optionalChain([s, 'optionalAccess', _140 => _140.ghost])) delete s.ghost;
4344
+ if (_optionalChain([s, 'optionalAccess', _170 => _170.ghost])) delete s.ghost;
4227
4345
  if (light && this.host.layerLight(id) !== light) this.host.updateLights(/* @__PURE__ */ new Map([[id, light]]));
4228
4346
  this.host.updateSurfaces(/* @__PURE__ */ new Map([[id, base]]), []);
4229
4347
  }
@@ -4302,10 +4420,10 @@ var PaintWetLayers = (_class6 = class {
4302
4420
  if (!d || !this.world) return;
4303
4421
  const rects = d.flush();
4304
4422
  if (rects.length) this.syncDisplays(DISPLAY_TILES_PER_TICK);
4305
- if (d.done) _optionalChain([this, 'access', _141 => _141.onDriverDone, 'optionalCall', _142 => _142(d)]);
4423
+ if (d.done) _optionalChain([this, 'access', _171 => _171.onDriverDone, 'optionalCall', _172 => _172(d)]);
4306
4424
  }
4307
4425
  /** Called when a live stroke that ended mid-batch has finished applying. */
4308
- __init56() {this.onDriverDone = null}
4426
+ __init57() {this.onDriverDone = null}
4309
4427
  /** Steps `steps` times now (agents, tests). Returns the steps run. */
4310
4428
  async advance(steps) {
4311
4429
  await this.idle();
@@ -4346,61 +4464,101 @@ var PaintWetLayers = (_class6 = class {
4346
4464
  /** Starts the fade countdown of an agent-triggered ghost on `layerId`. */
4347
4465
  releaseGhost(layerId, linger) {
4348
4466
  const w = this.world;
4349
- if (_optionalChain([w, 'optionalAccess', _143 => _143.hasLane, 'call', _144 => _144(layerId)])) w.releaseGhost(layerId, linger, this.speed);
4467
+ if (_optionalChain([w, 'optionalAccess', _173 => _173.hasLane, 'call', _174 => _174(layerId)])) w.releaseGhost(layerId, linger, this.speed);
4350
4468
  const s = this.settings.get(layerId);
4351
- if (_optionalChain([s, 'optionalAccess', _145 => _145.ghost, 'optionalAccess', _146 => _146.trigger]) === "agent") {
4469
+ if (_optionalChain([s, 'optionalAccess', _175 => _175.ghost, 'optionalAccess', _176 => _176.trigger]) === "agent") {
4352
4470
  const sec = linger !== void 0 ? Math.max(0.5, Math.min(60, linger)) : s.ghost.linger;
4353
- const total = Math.max(1, Math.round(sec * this.speed / _chunkDHC4E2DUcjs.FREE_INTERVAL));
4471
+ const total = Math.max(1, Math.round(sec * this.speed / _chunkMITQGHN3cjs.FREE_INTERVAL));
4354
4472
  s.ghost = { ...s.ghost, linger: sec, total, remaining: total, trigger: void 0 };
4355
4473
  }
4356
4474
  }
4357
4475
  /** Keeps an unclaimed agent-triggered ghost on `layerId` as ordinary wet paint. */
4358
4476
  keepGhost(layerId) {
4359
4477
  const w = this.world;
4360
- if (_optionalChain([w, 'optionalAccess', _147 => _147.hasLane, 'call', _148 => _148(layerId)])) w.keepGhost(layerId);
4478
+ if (_optionalChain([w, 'optionalAccess', _177 => _177.hasLane, 'call', _178 => _178(layerId)])) w.keepGhost(layerId);
4361
4479
  const s = this.settings.get(layerId);
4362
- if (_optionalChain([s, 'optionalAccess', _149 => _149.ghost])) delete s.ghost;
4480
+ if (_optionalChain([s, 'optionalAccess', _179 => _179.ghost])) delete s.ghost;
4363
4481
  }
4364
4482
  /** The layer's light paint with all its wet paint dried (`null` without a wet layer or light), without changing anything. */
4365
4483
  bakedLight(layerId) {
4366
4484
  const w = this.world;
4367
- if (!_optionalChain([w, 'optionalAccess', _150 => _150.hasLane, 'call', _151 => _151(layerId)]) || !w.isLit(layerId)) return null;
4485
+ if (!_optionalChain([w, 'optionalAccess', _180 => _180.hasLane, 'call', _181 => _181(layerId)]) || !w.isLit(layerId)) return null;
4368
4486
  return w.bakedLight(layerId);
4369
4487
  }
4370
4488
  /** The layer's pixels with all its wet paint dried (deterministic), without changing anything. */
4371
4489
  bakedSurface(layerId) {
4372
4490
  const w = this.world;
4373
- if (!_optionalChain([w, 'optionalAccess', _152 => _152.hasLane, 'call', _153 => _153(layerId)])) return null;
4491
+ if (!_optionalChain([w, 'optionalAccess', _182 => _182.hasLane, 'call', _183 => _183(layerId)])) return null;
4374
4492
  return w.bakedSurface(layerId);
4375
4493
  }
4376
4494
  /** A snapshot of the world for undo (`null` when there is none). */
4377
4495
  snapshot() {
4378
4496
  const w = this.world;
4379
- if (!w || !w.laneIds().length) return null;
4380
- return w.snapshot();
4497
+ const patterns = /* @__PURE__ */ new Map();
4498
+ let patternBytes = 0;
4499
+ for (const [id, f] of this.patterns) {
4500
+ if (!f.enabled && f.tiles.size === 0) continue;
4501
+ const ps = f.snapshot();
4502
+ patterns.set(id, ps);
4503
+ patternBytes += ps.bytes;
4504
+ }
4505
+ if (!w || !w.laneIds().length) {
4506
+ if (!patterns.size) return null;
4507
+ return {
4508
+ clock: _nullishCoalesce(_optionalChain([w, 'optionalAccess', _184 => _184.clock]), () => ( 0)),
4509
+ tilt: { ...this.tilt },
4510
+ lanes: [],
4511
+ slots: /* @__PURE__ */ new Map(),
4512
+ patterns,
4513
+ bytes: patternBytes
4514
+ };
4515
+ }
4516
+ const snap = w.snapshot();
4517
+ return patterns.size ? { ...snap, patterns } : snap;
4381
4518
  }
4382
4519
  /** Puts a snapshot back (`null`: no wet layers). Returns the layer surfaces it implies. */
4383
4520
  restore(snap) {
4521
+ this.patterns.clear();
4522
+ for (const [, s] of this.settings) s.livePatterns = null;
4384
4523
  if (!snap) {
4385
4524
  if (this.world) for (const id of this.world.laneIds()) this.world.removeLane(id);
4386
4525
  return;
4387
4526
  }
4388
4527
  const { width, height } = this.host.canvas();
4389
4528
  if (this.world && (this.world.width !== width || this.world.height !== height)) this.dropWorld();
4390
- this.ensureWorld().restore(snap);
4529
+ if (snap.patterns) {
4530
+ for (const [id, ps] of snap.patterns) {
4531
+ const f = new (0, _chunkIFWLZZCWcjs.LivePatternField)(width, height);
4532
+ f.restore(ps);
4533
+ this.patterns.set(id, f);
4534
+ this.settingsOf(id).livePatterns = f.enabled ? { ...f.settings } : null;
4535
+ }
4536
+ }
4537
+ if (snap.lanes.length) {
4538
+ const w = this.ensureWorld();
4539
+ w.restore(snap);
4540
+ for (const id of w.laneIds()) {
4541
+ const f = w.livePatternField(id);
4542
+ this.patterns.set(id, f);
4543
+ this.settingsOf(id).livePatterns = f.enabled ? { ...f.settings } : null;
4544
+ }
4545
+ } else if (this.world) {
4546
+ for (const id of this.world.laneIds()) this.world.removeLane(id);
4547
+ }
4391
4548
  this.syncDisplays();
4392
4549
  }
4393
4550
  dropWorld() {
4394
- _optionalChain([this, 'access', _154 => _154.world, 'optionalAccess', _155 => _155.destroy, 'call', _156 => _156()]);
4551
+ _optionalChain([this, 'access', _185 => _185.world, 'optionalAccess', _186 => _186.destroy, 'call', _187 => _187()]);
4395
4552
  this.world = null;
4396
4553
  this.driver = null;
4397
4554
  }
4398
4555
  /** Forgets everything wet (a new canvas, a resize, opening a document). */
4399
4556
  reset() {
4400
- _optionalChain([this, 'access', _157 => _157.world, 'optionalAccess', _158 => _158.destroy, 'call', _159 => _159()]);
4557
+ _optionalChain([this, 'access', _188 => _188.world, 'optionalAccess', _189 => _189.destroy, 'call', _190 => _190()]);
4401
4558
  this.world = null;
4402
4559
  this.driver = null;
4403
4560
  this.settings.clear();
4561
+ this.patterns.clear();
4404
4562
  this.lastTick = null;
4405
4563
  this.stepsOwed = 0;
4406
4564
  }
@@ -4427,15 +4585,15 @@ var PaintWetLayers = (_class6 = class {
4427
4585
  return out;
4428
4586
  }
4429
4587
  destroy() {
4430
- _optionalChain([this, 'access', _160 => _160.world, 'optionalAccess', _161 => _161.destroy, 'call', _162 => _162()]);
4588
+ _optionalChain([this, 'access', _191 => _191.world, 'optionalAccess', _192 => _192.destroy, 'call', _193 => _193()]);
4431
4589
  this.world = null;
4432
- _optionalChain([this, 'access', _163 => _163.gpu, 'optionalAccess', _164 => _164.destroy, 'call', _165 => _165()]);
4590
+ _optionalChain([this, 'access', _194 => _194.gpu, 'optionalAccess', _195 => _195.destroy, 'call', _196 => _196()]);
4433
4591
  this.gpu = null;
4434
4592
  }
4435
4593
  }, _class6);
4436
4594
  function wetPigmentOf(hex, body) {
4437
4595
  const [r, g, b] = hexToRgb8(hex);
4438
- return Array.from(_chunkDHC4E2DUcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
4596
+ return Array.from(_chunkMITQGHN3cjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
4439
4597
  }
4440
4598
 
4441
4599
  // src/vector/brushstrokeMedia.ts
@@ -4447,7 +4605,7 @@ function vectorMediaEngine(brush) {
4447
4605
  var usesVectorBackdrop = (engine) => engine === "mixer" || engine === "smudge" || engine === "blender";
4448
4606
  var finite2 = (v2) => typeof v2 === "number" && Number.isFinite(v2);
4449
4607
  function place(input, brush, options, pad = 0) {
4450
- const samples = _chunkSTLTOISWcjs.brushstrokeSamples.call(void 0, input);
4608
+ const samples = _chunkNPPMKMCUcjs.brushstrokeSamples.call(void 0, input);
4451
4609
  if (!samples.length) return null;
4452
4610
  for (const s of samples) if (!finite2(s.x) || !finite2(s.y)) throw new Error("Brushstroke samples need finite x and y.");
4453
4611
  let scale3 = finite2(options.scale) && options.scale > 0 ? Math.min(_chunkYQGCPL5Xcjs.BRUSHSTROKE_MAX_SCALE, Math.max(_chunkYQGCPL5Xcjs.BRUSHSTROKE_MIN_SCALE, options.scale)) : 1;
@@ -4471,8 +4629,8 @@ function place(input, brush, options, pad = 0) {
4471
4629
  const [r, g, b, a] = options.color;
4472
4630
  const hex = "#" + [r, g, b].map((v2) => Math.round(Math.min(255, Math.max(0, v2))).toString(16).padStart(2, "0")).join("");
4473
4631
  const source = _nullishCoalesce(options.paint, () => ( null));
4474
- const paint = _optionalChain([source, 'optionalAccess', _166 => _166.type]) === "gradient" ? _chunkNIBFKXMDcjs.resolvePaintGradient.call(void 0, _chunkNIBFKXMDcjs.scalePaintGradient.call(void 0, source, scale3), { paint: hex, secondary: "#ffffff" }) : null;
4475
- const color2 = _optionalChain([source, 'optionalAccess', _167 => _167.type]) === "color" ? hexRgb(source.color) : [r / 255, g / 255, b / 255];
4632
+ const paint = _optionalChain([source, 'optionalAccess', _197 => _197.type]) === "gradient" ? _chunkIFWLZZCWcjs.resolvePaintGradient.call(void 0, _chunkIFWLZZCWcjs.scalePaintGradient.call(void 0, source, scale3), { paint: hex, secondary: "#ffffff" }) : null;
4633
+ const color2 = _optionalChain([source, 'optionalAccess', _198 => _198.type]) === "color" ? hexRgb(source.color) : [r / 255, g / 255, b / 255];
4476
4634
  return { points, brush: sized, rect, scale: scale3, color: color2, alpha: Math.min(1, Math.max(0, a / 255)), paint };
4477
4635
  }
4478
4636
  function hexRgb(hex) {
@@ -4512,7 +4670,7 @@ function cropped(data, placed, dabs, keep) {
4512
4670
  return { image: { width: cw, height: ch, data: out }, bounds: { x: (placed.rect.x + cx0) / s, y: (placed.rect.y + cy0) / s, width: cw / s, height: ch / s }, scale: s, dabs };
4513
4671
  }
4514
4672
  var WetBrushstrokeJob = (_class7 = class {
4515
- constructor(input, brush, options, steps = VECTOR_WET_STEPS) {;_class7.prototype.__init57.call(this);_class7.prototype.__init58.call(this);
4673
+ constructor(input, brush, options, steps = VECTOR_WET_STEPS) {;_class7.prototype.__init58.call(this);_class7.prototype.__init59.call(this);
4516
4674
  this.steps = steps;
4517
4675
  if (vectorMediaEngine(brush) !== "wet") throw new Error(`'${brush.name}' is not a wet paint brush.`);
4518
4676
  this.placed = place(input, brush, options, brush.tip.size * 0.25);
@@ -4523,7 +4681,7 @@ var WetBrushstrokeJob = (_class7 = class {
4523
4681
  return;
4524
4682
  }
4525
4683
  const { rect, points } = this.placed;
4526
- this.world = new (0, _chunkDHC4E2DUcjs.WetWorld)(rect.width, rect.height, wetPaperInput(DEFAULT_PAPER), { kernel: "typescript", threads: 0 });
4684
+ this.world = new (0, _chunkMITQGHN3cjs.WetWorld)(rect.width, rect.height, wetPaperInput(DEFAULT_PAPER), { kernel: "typescript", threads: 0 });
4527
4685
  const medium = _nullishCoalesce(this.placed.brush.wet.medium, () => ( "watercolor"));
4528
4686
  this.world.ensureLane("s", { params: _nullishCoalesce(WET_MEDIUM_PARAMS[medium], () => ( {})) });
4529
4687
  const color2 = this.placed.color;
@@ -4548,8 +4706,8 @@ var WetBrushstrokeJob = (_class7 = class {
4548
4706
 
4549
4707
 
4550
4708
 
4551
- __init57() {this.done = 0}
4552
- __init58() {this.final = null}
4709
+ __init58() {this.done = 0}
4710
+ __init59() {this.final = null}
4553
4711
  /** Steps run so far. */
4554
4712
  get progress() {
4555
4713
  return this.done;
@@ -4582,7 +4740,7 @@ var WetBrushstrokeJob = (_class7 = class {
4582
4740
  return this.final;
4583
4741
  }
4584
4742
  destroy() {
4585
- _optionalChain([this, 'access', _168 => _168.world, 'optionalAccess', _169 => _169.destroy, 'call', _170 => _170()]);
4743
+ _optionalChain([this, 'access', _199 => _199.world, 'optionalAccess', _200 => _200.destroy, 'call', _201 => _201()]);
4586
4744
  }
4587
4745
  bake() {
4588
4746
  if (!this.world || !this.placed) return EMPTY;
@@ -4607,8 +4765,8 @@ function renderBackdropBrushstroke(input, brush, options) {
4607
4765
  const area = { x: 0, y: 0, width: rect.width, height: rect.height };
4608
4766
  const before = options.backdrop ? options.backdrop(rect, placed.scale) : new Uint8ClampedArray(rect.width * rect.height * 4);
4609
4767
  if (before.length !== rect.width * rect.height * 4) throw new Error(`The backdrop must be ${rect.width}\xD7${rect.height} RGBA pixels.`);
4610
- const cached = _optionalChain([options, 'access', _171 => _171.cache, 'optionalCall', _172 => _172(before)]);
4611
- const hit = _optionalChain([cached, 'optionalAccess', _173 => _173.get, 'call', _174 => _174()]);
4768
+ const cached = _optionalChain([options, 'access', _202 => _202.cache, 'optionalCall', _203 => _203(before)]);
4769
+ const hit = _optionalChain([cached, 'optionalAccess', _204 => _204.get, 'call', _205 => _205()]);
4612
4770
  if (hit) return hit;
4613
4771
  const base = _chunk474IQG74cjs.writeRegion.call(void 0, _chunk474IQG74cjs.emptySurface.call(void 0, 4), area, before);
4614
4772
  const live = /* @__PURE__ */ new Map();
@@ -4616,7 +4774,7 @@ function renderBackdropBrushstroke(input, brush, options) {
4616
4774
  offset: { x: 0, y: 0 },
4617
4775
  lockTransparency: false,
4618
4776
  selection: null,
4619
- readTile: (tx, ty) => _nullishCoalesce(_nullishCoalesce(live.get(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), () => ( _optionalChain([base, 'access', _175 => _175.tiles, 'access', _176 => _176.get, 'call', _177 => _177(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), 'optionalAccess', _178 => _178.data]))), () => ( null)),
4777
+ readTile: (tx, ty) => _nullishCoalesce(_nullishCoalesce(live.get(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), () => ( _optionalChain([base, 'access', _206 => _206.tiles, 'access', _207 => _207.get, 'call', _208 => _208(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), 'optionalAccess', _209 => _209.data]))), () => ( null)),
4620
4778
  writeTile: (tx, ty) => {
4621
4779
  const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
4622
4780
  let t = live.get(key);
@@ -4625,7 +4783,7 @@ function renderBackdropBrushstroke(input, brush, options) {
4625
4783
  }
4626
4784
  };
4627
4785
  const color2 = placed.color;
4628
- const load = placed.brush.engine === "mixer" && placed.brush.loadsColor ? _chunkNIBFKXMDcjs.loadMixer.call(void 0, _chunkNIBFKXMDcjs.EMPTY_MIXER_LOAD, color2) : _chunkNIBFKXMDcjs.EMPTY_MIXER_LOAD;
4786
+ const load = placed.brush.engine === "mixer" && placed.brush.loadsColor ? _chunkIFWLZZCWcjs.loadMixer.call(void 0, _chunkIFWLZZCWcjs.EMPTY_MIXER_LOAD, color2) : _chunkIFWLZZCWcjs.EMPTY_MIXER_LOAD;
4629
4787
  const stroke = new PaintDabStroke(placed.brush, { target, color: color2, secondary: [1, 1, 1], load, grain: null, paperDepth: 0, seed: _nullishCoalesce(options.seed, () => ( 0)), paint: placed.paint });
4630
4788
  stroke.push(placed.points);
4631
4789
  stroke.finish();
@@ -4634,29 +4792,29 @@ function renderBackdropBrushstroke(input, brush, options) {
4634
4792
  for (const [key, data] of live) tiles.set(key, { data, uniform: null });
4635
4793
  _chunk474IQG74cjs.readRegion.call(void 0, new (0, _chunk474IQG74cjs.TiledSurface)(4, tiles), area, after);
4636
4794
  const result = cropped(after, placed, stroke.dabCount, (i) => after[i] !== before[i] || after[i + 1] !== before[i + 1] || after[i + 2] !== before[i + 2] || after[i + 3] !== before[i + 3]);
4637
- _optionalChain([cached, 'optionalAccess', _179 => _179.set, 'call', _180 => _180(result)]);
4795
+ _optionalChain([cached, 'optionalAccess', _210 => _210.set, 'call', _211 => _211(result)]);
4638
4796
  return result;
4639
4797
  }
4640
4798
 
4641
4799
  // src/vector/brushstroke.ts
4642
4800
  var VECTOR_BRUSHSTROKE_SCALE = 2;
4643
- var PRESETS = _chunk6QNDGMK7cjs.listPresets.call(void 0, _chunk6QNDGMK7cjs.VECTOR_PROFILE).map((spec) => _chunk6QNDGMK7cjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id));
4801
+ var PRESETS = _chunkQ33V5PEFcjs.listPresets.call(void 0, _chunkQ33V5PEFcjs.VECTOR_PROFILE).map((spec) => _chunkQ33V5PEFcjs.BUILTIN_BRUSHES.find((b) => b.id === spec.id));
4644
4802
  function admitted(spec) {
4645
4803
  try {
4646
- const brush = _chunk6QNDGMK7cjs.normalizeBrushSpec.call(void 0, spec);
4647
- return _chunk6QNDGMK7cjs.checkBrush.call(void 0, brush, _chunk6QNDGMK7cjs.VECTOR_PROFILE).ok && isVectorBrushstrokeEngine(_chunk6QNDGMK7cjs.resolveBrush.call(void 0, brush)) ? brush : null;
4804
+ const brush = _chunkQ33V5PEFcjs.normalizeBrushSpec.call(void 0, spec);
4805
+ return _chunkQ33V5PEFcjs.checkBrush.call(void 0, brush, _chunkQ33V5PEFcjs.VECTOR_PROFILE).ok && isVectorBrushstrokeEngine(_chunkQ33V5PEFcjs.resolveBrush.call(void 0, brush)) ? brush : null;
4648
4806
  } catch (e6) {
4649
4807
  return null;
4650
4808
  }
4651
4809
  }
4652
4810
  function isVectorBrushstrokeEngine(brush) {
4653
- return brush.engine === "dab" && _chunkSTLTOISWcjs.isBrushstrokeBrush.call(void 0, brush) || vectorMediaEngine(brush) !== null;
4811
+ return brush.engine === "dab" && _chunkNPPMKMCUcjs.isBrushstrokeBrush.call(void 0, brush) || vectorMediaEngine(brush) !== null;
4654
4812
  }
4655
4813
  function vectorBrushstrokeBrushes(user = []) {
4656
4814
  const out = [...PRESETS];
4657
4815
  for (const raw of user) {
4658
4816
  const brush = admitted(raw);
4659
- if (brush && !out.some((b) => b.id === brush.id)) out.push(_chunk6QNDGMK7cjs.resolveBrush.call(void 0, brush));
4817
+ if (brush && !out.some((b) => b.id === brush.id)) out.push(_chunkQ33V5PEFcjs.resolveBrush.call(void 0, brush));
4660
4818
  }
4661
4819
  return out;
4662
4820
  }
@@ -4666,7 +4824,7 @@ function vectorBrushstrokeBrush(id) {
4666
4824
  function vectorBrushstrokeBrushOf(brush) {
4667
4825
  if (brush.spec) {
4668
4826
  const saved = admitted(brush.spec);
4669
- return saved && saved.id === brush.brushId ? _chunk6QNDGMK7cjs.resolveBrush.call(void 0, saved) : null;
4827
+ return saved && saved.id === brush.brushId ? _chunkQ33V5PEFcjs.resolveBrush.call(void 0, saved) : null;
4670
4828
  }
4671
4829
  return vectorBrushstrokeBrush(brush.brushId);
4672
4830
  }
@@ -4674,15 +4832,15 @@ function vectorBrushstrokeBrushError(id, user = []) {
4674
4832
  if (vectorBrushstrokeBrush(id)) return null;
4675
4833
  const saved = user.find((b) => b.id === id);
4676
4834
  const ids = vectorBrushstrokeBrushes(user).map((b) => b.id);
4677
- const reasons = (b) => _chunk6QNDGMK7cjs.checkBrush.call(void 0, b, _chunk6QNDGMK7cjs.VECTOR_PROFILE).issues.filter((i) => i.severity === "error").map((i) => `${i.reason} ${i.fix}`).join(" ") || "its engine does not paint brushstrokes.";
4835
+ const reasons = (b) => _chunkQ33V5PEFcjs.checkBrush.call(void 0, b, _chunkQ33V5PEFcjs.VECTOR_PROFILE).issues.filter((i) => i.severity === "error").map((i) => `${i.reason} ${i.fix}`).join(" ") || "its engine does not paint brushstrokes.";
4678
4836
  if (saved) return admitted(saved) ? null : `Brush "${id}" (${saved.name}) can't paint a brushstroke: ${reasons(saved)} Use one of: ${ids.join(", ")}.`;
4679
- const preset2 = _chunk6QNDGMK7cjs.BRUSH_PRESETS.find((b) => b.id === id);
4837
+ const preset2 = _chunkQ33V5PEFcjs.BRUSH_PRESETS.find((b) => b.id === id);
4680
4838
  if (preset2) return `Brush "${id}" (${preset2.name}) can't paint a brushstroke: ${reasons(preset2)} Use one of: ${ids.join(", ")}.`;
4681
- return `Unknown brush "${id}". ${_chunk6QNDGMK7cjs.closest.call(void 0, id, ids)}Use one of: ${ids.join(", ")} (vector.listBrushes lists them).`;
4839
+ return `Unknown brush "${id}". ${_chunkQ33V5PEFcjs.closest.call(void 0, id, ids)}Use one of: ${ids.join(", ")} (vector.listBrushes lists them).`;
4682
4840
  }
4683
4841
  function vectorBrushstrokeDefaultColour(id, user = [], scheme = "light") {
4684
- const brush = _nullishCoalesce(_chunk6QNDGMK7cjs.BRUSH_PRESETS.find((b) => b.id === id), () => ( user.find((b) => b.id === id)));
4685
- return brush ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, _optionalChain([brush, 'access', _181 => _181.colour, 'optionalAccess', _182 => _182.default]), scheme) : null;
4842
+ const brush = _nullishCoalesce(_chunkQ33V5PEFcjs.BRUSH_PRESETS.find((b) => b.id === id), () => ( user.find((b) => b.id === id)));
4843
+ return brush ? _chunkJBZRVLXVcjs.brushColourHex.call(void 0, _optionalChain([brush, 'access', _212 => _212.colour, 'optionalAccess', _213 => _213.default]), scheme) : null;
4686
4844
  }
4687
4845
  function sanitizeVectorBrushstroke(value, user = []) {
4688
4846
  if (!value || typeof value !== "object") return null;
@@ -4714,7 +4872,7 @@ var TIMED_MAPPINGS = ["velocity", "time"];
4714
4872
  function vectorBrushstrokePaintError(paint) {
4715
4873
  let source;
4716
4874
  try {
4717
- source = _chunkNIBFKXMDcjs.parsePaintSource.call(void 0, paint, "paint");
4875
+ source = _chunkIFWLZZCWcjs.parsePaintSource.call(void 0, paint, "paint");
4718
4876
  } catch (e) {
4719
4877
  return e.message;
4720
4878
  }
@@ -4723,7 +4881,7 @@ function vectorBrushstrokePaintError(paint) {
4723
4881
  }
4724
4882
  function readVectorBrushstrokePaint(value) {
4725
4883
  if (value === void 0 || value === null || vectorBrushstrokePaintError(value)) return null;
4726
- return _chunkNIBFKXMDcjs.readPaintSource.call(void 0, value);
4884
+ return _chunkIFWLZZCWcjs.readPaintSource.call(void 0, value);
4727
4885
  }
4728
4886
  var VECTOR_BRUSHSTROKE_MAX_SEED = 2147483647;
4729
4887
  var finite3 = (v2) => typeof v2 === "number" && Number.isFinite(v2);
@@ -4732,7 +4890,7 @@ function sanitizeVectorBrushstrokePaper(value) {
4732
4890
  if (!value || typeof value !== "object") return null;
4733
4891
  const r = value;
4734
4892
  const out = {};
4735
- if (typeof r.pattern === "string" && _chunkNIBFKXMDcjs.GRAIN_PATTERNS.includes(r.pattern)) out.pattern = r.pattern;
4893
+ if (typeof r.pattern === "string" && _chunkIFWLZZCWcjs.GRAIN_PATTERNS.includes(r.pattern)) out.pattern = r.pattern;
4736
4894
  const seed = sanitizeSeed(r.seed);
4737
4895
  if (seed !== void 0) out.seed = seed;
4738
4896
  if (finite3(r.scale) && r.scale > 0) out.scale = Math.min(8, Math.max(0.25, r.scale));
@@ -4747,7 +4905,7 @@ function vectorBrushstrokeCharacterError(brush) {
4747
4905
  const r = paper;
4748
4906
  const extra = Object.keys(r).filter((k) => !["pattern", "seed", "scale", "depth"].includes(k));
4749
4907
  if (extra.length) return `paper has unknown field ${extra.map((k) => `"${k}"`).join(", ")}: use pattern, seed, scale, depth.`;
4750
- if (r.pattern !== void 0 && !_chunkNIBFKXMDcjs.GRAIN_PATTERNS.includes(r.pattern)) return `Unknown paper pattern "${String(r.pattern)}": use one of ${_chunkNIBFKXMDcjs.GRAIN_PATTERNS.join(", ")}.`;
4908
+ if (r.pattern !== void 0 && !_chunkIFWLZZCWcjs.GRAIN_PATTERNS.includes(r.pattern)) return `Unknown paper pattern "${String(r.pattern)}": use one of ${_chunkIFWLZZCWcjs.GRAIN_PATTERNS.join(", ")}.`;
4751
4909
  if (r.seed !== void 0 && !(Number.isInteger(r.seed) && r.seed >= 0 && r.seed <= VECTOR_BRUSHSTROKE_MAX_SEED)) return `paper.seed must be an integer from 0 to ${VECTOR_BRUSHSTROKE_MAX_SEED}.`;
4752
4910
  if (r.scale !== void 0 && !(finite3(r.scale) && r.scale >= 0.25 && r.scale <= 8)) return "paper.scale must be from 0.25 to 8 (1 is the pattern's natural size).";
4753
4911
  if (r.depth !== void 0 && !(finite3(r.depth) && r.depth >= 0 && r.depth <= 1)) return "paper.depth must be from 0 to 1.";
@@ -4806,7 +4964,7 @@ function strokePaintOf(node, layer, brush, length2) {
4806
4964
  const color2 = [c[0] * 255, c[1] * 255, c[2] * 255, c[3] * 255].map(Math.round);
4807
4965
  if (layer.brush.paint) return { color: color2, paint: layer.brush.paint, within: null };
4808
4966
  const g = layer.paint;
4809
- if (isVectorGradient(g) && _optionalChain([g, 'access', _183 => _183.stops, 'optionalAccess', _184 => _184.length])) {
4967
+ if (isVectorGradient(g) && _optionalChain([g, 'access', _214 => _214.stops, 'optionalAccess', _215 => _215.length])) {
4810
4968
  const mode = _nullishCoalesce(g.strokeMode, () => ( "within"));
4811
4969
  if (mode === "along") return { color: [color2[0], color2[1], color2[2], 255], paint: gradientPaint(g, { by: "distance", length: Math.max(1, length2), repeat: REPEAT[_nullishCoalesce(g.spread, () => ( "pad"))], unit: "px" }), within: null };
4812
4970
  if (mode === "across") return { color: [color2[0], color2[1], color2[2], 255], paint: gradientPaint(g, { by: "across-tip" }), within: null };
@@ -4859,11 +5017,11 @@ function mediaKey(input, brush, options) {
4859
5017
  return `${hash(path).toString(16)}:${path.length}:${hash(JSON.stringify([brush, options])).toString(16)}`;
4860
5018
  }
4861
5019
  var Lru = (_class8 = class {
4862
- constructor(capacity) {;_class8.prototype.__init59.call(this);
5020
+ constructor(capacity) {;_class8.prototype.__init60.call(this);
4863
5021
  this.capacity = capacity;
4864
5022
  }
4865
5023
 
4866
- __init59() {this.map = /* @__PURE__ */ new Map()}
5024
+ __init60() {this.map = /* @__PURE__ */ new Map()}
4867
5025
  get(key) {
4868
5026
  const v2 = this.map.get(key);
4869
5027
  if (v2 !== void 0) {
@@ -4946,7 +5104,7 @@ function wetImage(input, brush, options, settle, pending) {
4946
5104
  pending.push(key);
4947
5105
  return _nullishCoalesce(wetInstant.get(key), () => ( job.image()));
4948
5106
  }
4949
- var cache = new (0, _chunkSTLTOISWcjs.BrushstrokeCache)(256);
5107
+ var cache = new (0, _chunkNPPMKMCUcjs.BrushstrokeCache)(256);
4950
5108
  var backdropResults = new Lru(64);
4951
5109
  var urls = /* @__PURE__ */ new WeakMap();
4952
5110
  var layerCache = /* @__PURE__ */ new WeakMap();
@@ -4961,7 +5119,7 @@ function vectorBrushstrokeImages(node, layer, context = {}) {
4961
5119
  const source = usesVectorBackdrop(engine) && backdropSource ? backdropSource(document2, node, Math.max(0, index), settle) : null;
4962
5120
  const deps = source ? [...source.deps, wetGeneration] : null;
4963
5121
  let byLayer = layerCache.get(node);
4964
- const hit = _optionalChain([byLayer, 'optionalAccess', _185 => _185.get, 'call', _186 => _186(layer)]);
5122
+ const hit = _optionalChain([byLayer, 'optionalAccess', _216 => _216.get, 'call', _217 => _217(layer)]);
4965
5123
  const stale = hit && (hit.pending.length && hit.pending.some((k) => wetSettled.has(k)) || settle === "now" && !hit.settled);
4966
5124
  if (hit && sameDeps(hit.deps, deps) && !stale) return hit.images;
4967
5125
  const brush = layer.brush.size ? { ...preset2, tip: { ...preset2.tip, size: layer.brush.size } } : preset2;
@@ -4986,7 +5144,7 @@ function vectorBrushstrokeImages(node, layer, context = {}) {
4986
5144
  const key = mediaKey(input, brush, options);
4987
5145
  stroke = renderBackdropBrushstroke(input, brush, {
4988
5146
  ...options,
4989
- backdrop: _nullishCoalesce(_optionalChain([source, 'optionalAccess', _187 => _187.backdrop]), () => ( null)),
5147
+ backdrop: _nullishCoalesce(_optionalChain([source, 'optionalAccess', _218 => _218.backdrop]), () => ( null)),
4990
5148
  cache: (bytes) => {
4991
5149
  const k = `${key}:${hashBytes(bytes).toString(16)}`;
4992
5150
  return { get: () => backdropResults.get(k), set: (img) => backdropResults.set(k, img) };
@@ -4999,7 +5157,7 @@ function vectorBrushstrokeImages(node, layer, context = {}) {
4999
5157
  if (sp2.within) stroke = recoloured(stroke, sp2.within);
5000
5158
  if (!stroke.bounds) continue;
5001
5159
  let href = urls.get(stroke);
5002
- if (!href) urls.set(stroke, href = _chunkSTLTOISWcjs.brushstrokeDataUrl.call(void 0, stroke));
5160
+ if (!href) urls.set(stroke, href = _chunkNPPMKMCUcjs.brushstrokeDataUrl.call(void 0, stroke));
5003
5161
  out.push({ href, ...stroke.bounds });
5004
5162
  }
5005
5163
  }
@@ -5090,7 +5248,7 @@ function withVectorFills(node, fills) {
5090
5248
  const next = { ...node };
5091
5249
  if (fills.length === 0 || fills.length === 1 && isPlainVectorPaintLayer(fills[0])) {
5092
5250
  delete next.fills;
5093
- next.fill = _nullishCoalesce(_optionalChain([fills, 'access', _188 => _188[0], 'optionalAccess', _189 => _189.paint]), () => ( null));
5251
+ next.fill = _nullishCoalesce(_optionalChain([fills, 'access', _219 => _219[0], 'optionalAccess', _220 => _220.paint]), () => ( null));
5094
5252
  return next;
5095
5253
  }
5096
5254
  next.fills = fills.map((l) => ({ ...l }));
@@ -5115,8 +5273,8 @@ function withVectorStrokes(node, strokes) {
5115
5273
  var json = (v2) => JSON.stringify(_nullishCoalesce(v2, () => ( null)));
5116
5274
  function strokeShorthandDiff(node, top) {
5117
5275
  const out = [];
5118
- if (json(node.stroke) !== json(_optionalChain([top, 'optionalAccess', _190 => _190.paint]))) out.push("stroke");
5119
- for (const key of VECTOR_STROKE_SETTING_KEYS) if (json(node[key]) !== json(_optionalChain([top, 'optionalAccess', _191 => _191[key]]))) out.push(key);
5276
+ if (json(node.stroke) !== json(_optionalChain([top, 'optionalAccess', _221 => _221.paint]))) out.push("stroke");
5277
+ for (const key of VECTOR_STROKE_SETTING_KEYS) if (json(node[key]) !== json(_optionalChain([top, 'optionalAccess', _222 => _222[key]]))) out.push(key);
5120
5278
  return out;
5121
5279
  }
5122
5280
  var checked = /* @__PURE__ */ new WeakSet();
@@ -5133,7 +5291,7 @@ function normalizeVectorPaintStacks(node, prefer = "shorthand") {
5133
5291
  if (Array.isArray(node.fills)) {
5134
5292
  let fills = node.fills;
5135
5293
  const top = fills[fills.length - 1];
5136
- if (prefer === "shorthand" && json(node.fill) !== json(_optionalChain([top, 'optionalAccess', _192 => _192.paint]))) {
5294
+ if (prefer === "shorthand" && json(node.fill) !== json(_optionalChain([top, 'optionalAccess', _223 => _223.paint]))) {
5137
5295
  if (!draws(node.fill)) fills = [];
5138
5296
  else fills = top ? [...fills.slice(0, -1), { ...top, paint: node.fill }] : [{ paint: node.fill }];
5139
5297
  }
@@ -5349,8 +5507,8 @@ var Measured = class {
5349
5507
  append(sa, sb, out) {
5350
5508
  for (const piece of _chunkGF2RBSDMcjs.trimSegments.call(void 0, this.segs, sa, sb, this.lens)) {
5351
5509
  if (degenerate(piece)) continue;
5352
- const last = _optionalChain([out, 'access', _193 => _193[out.length - 1], 'optionalAccess', _194 => _194.segs]);
5353
- const end = _optionalChain([last, 'optionalAccess', _195 => _195[last.length - 1], 'optionalAccess', _196 => _196.at, 'call', _197 => _197(-1)]);
5510
+ const last = _optionalChain([out, 'access', _224 => _224[out.length - 1], 'optionalAccess', _225 => _225.segs]);
5511
+ const end = _optionalChain([last, 'optionalAccess', _226 => _226[last.length - 1], 'optionalAccess', _227 => _227.at, 'call', _228 => _228(-1)]);
5354
5512
  if (!end || Math.hypot(end[0] - piece[0][0], end[1] - piece[0][1]) > 1e-6) out.push({ segs: [piece], closed: false });
5355
5513
  else last.push(piece);
5356
5514
  }
@@ -5662,9 +5820,9 @@ function vectorRepeaterCopies(r, pivot) {
5662
5820
  for (let i = 0; i < n; i++) {
5663
5821
  const k = i + offset;
5664
5822
  let m = translateMatrix(-pivot.x, -pivot.y);
5665
- m = multiplyMatrices(m, scaleMatrix(Math.pow((_nullishCoalesce(_optionalChain([r, 'access', _198 => _198.scale, 'optionalAccess', _199 => _199.x]), () => ( 100))) / 100, k), Math.pow((_nullishCoalesce(_optionalChain([r, 'access', _200 => _200.scale, 'optionalAccess', _201 => _201.y]), () => ( 100))) / 100, k)));
5823
+ m = multiplyMatrices(m, scaleMatrix(Math.pow((_nullishCoalesce(_optionalChain([r, 'access', _229 => _229.scale, 'optionalAccess', _230 => _230.x]), () => ( 100))) / 100, k), Math.pow((_nullishCoalesce(_optionalChain([r, 'access', _231 => _231.scale, 'optionalAccess', _232 => _232.y]), () => ( 100))) / 100, k)));
5666
5824
  m = multiplyMatrices(m, rotateMatrix((_nullishCoalesce(r.rotation, () => ( 0))) * k));
5667
- m = multiplyMatrices(m, translateMatrix(pivot.x + (_nullishCoalesce(_optionalChain([r, 'access', _202 => _202.position, 'optionalAccess', _203 => _203.x]), () => ( 0))) * k, pivot.y + (_nullishCoalesce(_optionalChain([r, 'access', _204 => _204.position, 'optionalAccess', _205 => _205.y]), () => ( 0))) * k));
5825
+ m = multiplyMatrices(m, translateMatrix(pivot.x + (_nullishCoalesce(_optionalChain([r, 'access', _233 => _233.position, 'optionalAccess', _234 => _234.x]), () => ( 0))) * k, pivot.y + (_nullishCoalesce(_optionalChain([r, 'access', _235 => _235.position, 'optionalAccess', _236 => _236.y]), () => ( 0))) * k));
5668
5826
  const t = n > 1 ? i / (n - 1) : 0;
5669
5827
  const partial = i + 1 === n && fract > 0 ? fract : 1;
5670
5828
  out.push({ index: i, matrix: m, opacity: Math.min(1, Math.max(0, (so + (eo - so) * t) * partial)) });
@@ -5828,7 +5986,7 @@ function mapBezierPath(path, f, tolerance = 0.1, options = {}) {
5828
5986
 
5829
5987
  // src/vector/frames.ts
5830
5988
  function isVectorFrame(node) {
5831
- return _optionalChain([node, 'optionalAccess', _206 => _206.type]) === "group" && !!node.frame && !node.blend && !node.liveBoolean && !node.mask;
5989
+ return _optionalChain([node, 'optionalAccess', _237 => _237.type]) === "group" && !!node.frame && !node.blend && !node.liveBoolean && !node.mask;
5832
5990
  }
5833
5991
  function vectorFrameRectPath(frame) {
5834
5992
  const { x, y, width: w, height: h } = frame;
@@ -5873,8 +6031,8 @@ function placeSpan(rule, a0, a1, f0, f1, g0, g1) {
5873
6031
  }
5874
6032
  }
5875
6033
  function vectorFrameChildMatrix(resizing, box, from, to) {
5876
- const [x0, x1] = placeSpan(_nullishCoalesce(H[_nullishCoalesce(_optionalChain([resizing, 'optionalAccess', _207 => _207.horizontal]), () => ( "left"))], () => ( "start")), box.x, box.x + box.width, from.x, from.x + from.width, to.x, to.x + to.width);
5877
- const [y0, y1] = placeSpan(_nullishCoalesce(V[_nullishCoalesce(_optionalChain([resizing, 'optionalAccess', _208 => _208.vertical]), () => ( "top"))], () => ( "start")), box.y, box.y + box.height, from.y, from.y + from.height, to.y, to.y + to.height);
6034
+ const [x0, x1] = placeSpan(_nullishCoalesce(H[_nullishCoalesce(_optionalChain([resizing, 'optionalAccess', _238 => _238.horizontal]), () => ( "left"))], () => ( "start")), box.x, box.x + box.width, from.x, from.x + from.width, to.x, to.x + to.width);
6035
+ const [y0, y1] = placeSpan(_nullishCoalesce(V[_nullishCoalesce(_optionalChain([resizing, 'optionalAccess', _239 => _239.vertical]), () => ( "top"))], () => ( "start")), box.y, box.y + box.height, from.y, from.y + from.height, to.y, to.y + to.height);
5878
6036
  const sx = box.width > 1e-9 ? (x1 - x0) / box.width : 1;
5879
6037
  const sy = box.height > 1e-9 ? (y1 - y0) / box.height : 1;
5880
6038
  return [sx, 0, 0, sy, x0 - sx * box.x, y0 - sy * box.y];
@@ -5930,7 +6088,7 @@ function vectorFrameDocument(doc, id, find) {
5930
6088
  height,
5931
6089
  ...doc.background ? { background: doc.background } : {},
5932
6090
  nodes: [placed],
5933
- ..._optionalChain([doc, 'access', _209 => _209.symbols, 'optionalAccess', _210 => _210.length]) ? { symbols: doc.symbols } : {}
6091
+ ..._optionalChain([doc, 'access', _240 => _240.symbols, 'optionalAccess', _241 => _241.length]) ? { symbols: doc.symbols } : {}
5934
6092
  };
5935
6093
  }
5936
6094
  function getVectorFramePanel(state) {
@@ -5950,7 +6108,7 @@ function getVectorFramePanel(state) {
5950
6108
  const one = (values) => values.every((v2) => v2 === values[0]) ? values[0] : "mixed";
5951
6109
  return {
5952
6110
  frame: f ? { id: f.id, name: _nullishCoalesce(f.name, () => ( "Frame")), artboard: parents.get(f.id) === null, frame: f.frame } : null,
5953
- resizing: children.length ? { ids: children.map((c) => c.id), horizontal: one(children.map((c) => _nullishCoalesce(_optionalChain([c, 'access', _211 => _211.resizing, 'optionalAccess', _212 => _212.horizontal]), () => ( "left")))), vertical: one(children.map((c) => _nullishCoalesce(_optionalChain([c, 'access', _213 => _213.resizing, 'optionalAccess', _214 => _214.vertical]), () => ( "top")))) } : null
6111
+ resizing: children.length ? { ids: children.map((c) => c.id), horizontal: one(children.map((c) => _nullishCoalesce(_optionalChain([c, 'access', _242 => _242.resizing, 'optionalAccess', _243 => _243.horizontal]), () => ( "left")))), vertical: one(children.map((c) => _nullishCoalesce(_optionalChain([c, 'access', _244 => _244.resizing, 'optionalAccess', _245 => _245.vertical]), () => ( "top")))) } : null
5954
6112
  };
5955
6113
  }
5956
6114
 
@@ -6336,7 +6494,7 @@ function normalizeVectorFilterParams(type, params, base) {
6336
6494
  if (!isVectorFilterType(type)) return null;
6337
6495
  const out = { ...VECTOR_FILTER_DEFAULTS[type], ..._nullishCoalesce(base, () => ( {})) };
6338
6496
  for (const spec of VECTOR_FILTER_PARAM_SPECS[type]) {
6339
- const v2 = _optionalChain([params, 'optionalAccess', _215 => _215[spec.key]]);
6497
+ const v2 = _optionalChain([params, 'optionalAccess', _246 => _246[spec.key]]);
6340
6498
  if (v2 === void 0) continue;
6341
6499
  if (spec.kind === "number" && typeof v2 === "number" && Number.isFinite(v2)) out[spec.key] = Math.min(_nullishCoalesce(spec.max, () => ( Infinity)), Math.max(_nullishCoalesce(spec.min, () => ( -Infinity)), v2));
6342
6500
  else if (spec.kind === "color" && typeof v2 === "string" && v2.trim()) out[spec.key] = v2.trim();
@@ -6468,7 +6626,7 @@ function vectorFilterSvg(filters, id, bounds) {
6468
6626
  primitives.push(fe("feGaussianBlur", { in: body, stdDeviation: round(f.params.radius / 2), result: name("body") }));
6469
6627
  body = name("body");
6470
6628
  }
6471
- const lastResult = _optionalChain([primitives, 'access', _216 => _216[primitives.length - 1], 'optionalAccess', _217 => _217.attrs, 'access', _218 => _218.result]);
6629
+ const lastResult = _optionalChain([primitives, 'access', _247 => _247[primitives.length - 1], 'optionalAccess', _248 => _248.attrs, 'access', _249 => _249.result]);
6472
6630
  if (lastResult !== body) primitives.push(fe("feMerge", {}, [fe("feMergeNode", { in: body })]));
6473
6631
  const pad = vectorFilterReach(active) + 2;
6474
6632
  return {
@@ -6483,7 +6641,7 @@ function vectorFilterSvg(filters, id, bounds) {
6483
6641
  var escapeAttr = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
6484
6642
  function primitiveMarkup(p) {
6485
6643
  const attrs = Object.entries(p.attrs).map(([k, v2]) => ` ${k}="${escapeAttr(String(v2))}"`).join("");
6486
- return _optionalChain([p, 'access', _219 => _219.children, 'optionalAccess', _220 => _220.length]) ? `<${p.tag}${attrs}>${p.children.map(primitiveMarkup).join("")}</${p.tag}>` : `<${p.tag}${attrs}/>`;
6644
+ return _optionalChain([p, 'access', _250 => _250.children, 'optionalAccess', _251 => _251.length]) ? `<${p.tag}${attrs}>${p.children.map(primitiveMarkup).join("")}</${p.tag}>` : `<${p.tag}${attrs}/>`;
6487
6645
  }
6488
6646
  function vectorFilterMarkup(filter, extra = "") {
6489
6647
  return `<filter id="${escapeAttr(filter.id)}" filterUnits="userSpaceOnUse" x="${filter.x}" y="${filter.y}" width="${filter.width}" height="${filter.height}" color-interpolation-filters="sRGB"${extra}>${filter.primitives.map(primitiveMarkup).join("")}</filter>`;
@@ -6501,7 +6659,7 @@ function sanitizeVectorMask(value) {
6501
6659
  return r.invert === true ? { type: r.type, invert: true } : { type: r.type };
6502
6660
  }
6503
6661
  function isVectorMaskGroup(node) {
6504
- return _optionalChain([node, 'optionalAccess', _221 => _221.type]) === "group" && !!node.mask && isVectorMaskType(node.mask.type) && !node.blend && !node.liveBoolean && node.children.length > 0;
6662
+ return _optionalChain([node, 'optionalAccess', _252 => _252.type]) === "group" && !!node.mask && isVectorMaskType(node.mask.type) && !node.blend && !node.liveBoolean && node.children.length > 0;
6505
6663
  }
6506
6664
  function isVectorMaskActive(node) {
6507
6665
  return isVectorMaskGroup(node) && node.children[0].visible !== false;
@@ -6536,7 +6694,7 @@ function vectorMaskRegionShapes(node, type, parent = IDENTITY_MATRIX, self = tru
6536
6694
  if (!self && node.visible === false) return [];
6537
6695
  if (isVectorFrame(node)) node = vectorFrameDrawn(node);
6538
6696
  const m = multiplyMatrices(nodeMatrix(node), parent);
6539
- if (isVectorMaskActive(node) || node.type === "group" && _optionalChain([node, 'access', _222 => _222.effects, 'optionalAccess', _223 => _223.length])) {
6697
+ if (isVectorMaskActive(node) || node.type === "group" && _optionalChain([node, 'access', _253 => _253.effects, 'optionalAccess', _254 => _254.length])) {
6540
6698
  return vectorAppearanceShapes(node).flatMap((s) => regionOfPath(s.path, s.source, type, m));
6541
6699
  }
6542
6700
  const drawn = expandVectorAppearance(node);
@@ -6741,7 +6899,7 @@ function fitRuns(runs, length2, fallback) {
6741
6899
  }
6742
6900
  if (left2 > 0) {
6743
6901
  if (out.length) out[out.length - 1] = { ...out[out.length - 1], length: out[out.length - 1].length + left2 };
6744
- else out.push({ length: left2, style: _nullishCoalesce(_optionalChain([runs, 'access', _224 => _224[runs.length - 1], 'optionalAccess', _225 => _225.style]), () => ( fallback)) });
6902
+ else out.push({ length: left2, style: _nullishCoalesce(_optionalChain([runs, 'access', _255 => _255[runs.length - 1], 'optionalAccess', _256 => _256.style]), () => ( fallback)) });
6745
6903
  }
6746
6904
  return compact(out);
6747
6905
  }
@@ -6751,7 +6909,7 @@ function styleAt(runs, index, fallback) {
6751
6909
  if (index < at2 + r.length) return r.style;
6752
6910
  at2 += r.length;
6753
6911
  }
6754
- return _nullishCoalesce(_optionalChain([runs, 'access', _226 => _226[runs.length - 1], 'optionalAccess', _227 => _227.style]), () => ( fallback));
6912
+ return _nullishCoalesce(_optionalChain([runs, 'access', _257 => _257[runs.length - 1], 'optionalAccess', _258 => _258.style]), () => ( fallback));
6755
6913
  }
6756
6914
  function restyleRange(runs, start, end, patch) {
6757
6915
  const out = [];
@@ -6807,7 +6965,7 @@ function paragraphRanges(text) {
6807
6965
  return out;
6808
6966
  }
6809
6967
  function fitParagraphRuns(runs, text) {
6810
- const fallback = _nullishCoalesce(_optionalChain([runs, 'access', _228 => _228[0], 'optionalAccess', _229 => _229.style]), () => ( {}));
6968
+ const fallback = _nullishCoalesce(_optionalChain([runs, 'access', _259 => _259[0], 'optionalAccess', _260 => _260.style]), () => ( {}));
6811
6969
  const out = compact(paragraphRanges(text).map((p) => ({ length: p.end - p.start, style: styleAt(runs, p.start, fallback) })));
6812
6970
  return out.length ? out : [{ length: 0, style: fallback }];
6813
6971
  }
@@ -6857,7 +7015,7 @@ function textLineRect(l) {
6857
7015
  var layoutCache = /* @__PURE__ */ new WeakMap();
6858
7016
  function layoutText(layer, shaper) {
6859
7017
  let byShaper = layoutCache.get(layer);
6860
- const hit = _optionalChain([byShaper, 'optionalAccess', _230 => _230.get, 'call', _231 => _231(shaper.id)]);
7018
+ const hit = _optionalChain([byShaper, 'optionalAccess', _261 => _261.get, 'call', _262 => _262(shaper.id)]);
6861
7019
  if (hit) return hit;
6862
7020
  const out = computeLayout(layer, shaper);
6863
7021
  if (!byShaper) {
@@ -6921,7 +7079,7 @@ function computeLayout(layer, shaper) {
6921
7079
  const code = seg.charCodeAt(k);
6922
7080
  if (isLow(code) && index > 0 && isHigh(text.charCodeAt(index - 1))) {
6923
7081
  const prev = chars[chars.length - 1];
6924
- if (_optionalChain([prev, 'optionalAccess', _232 => _232.up])) {
7082
+ if (_optionalChain([prev, 'optionalAccess', _263 => _263.up])) {
6925
7083
  chars.push({ index, ch: seg[k], advance: 0, style, up: prev.up, low: true });
6926
7084
  } else chars.push({ index, ch: seg[k], advance, style, low: true });
6927
7085
  continue;
@@ -7249,7 +7407,7 @@ function createCanvasTextShaper(options = {}) {
7249
7407
  return null;
7250
7408
  })));
7251
7409
  const canvas = make(1, 1);
7252
- const ctx = _optionalChain([canvas, 'optionalAccess', _233 => _233.getContext, 'call', _234 => _234("2d")]);
7410
+ const ctx = _optionalChain([canvas, 'optionalAccess', _264 => _264.getContext, 'call', _265 => _265("2d")]);
7253
7411
  if (!ctx || typeof ctx.measureText !== "function") return null;
7254
7412
  const fallback = _nullishCoalesce(options.fallbackFamily, () => ( "sans-serif"));
7255
7413
  const available = /* @__PURE__ */ new Map();
@@ -7322,10 +7480,10 @@ function createOutlineTextShaper(fonts, options = {}) {
7322
7480
  const entries = fonts.map((f) => {
7323
7481
  const e = "face" in f ? f : { face: f };
7324
7482
  const names = e.face.names;
7325
- const family = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(e.family, () => ( _optionalChain([names, 'optionalAccess', _235 => _235.fontFamily, 'optionalAccess', _236 => _236.en]))), () => ( Object.values(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _237 => _237.fontFamily]), () => ( {})))[0])), () => ( "Font"));
7326
- const weight = _nullishCoalesce(_nullishCoalesce(e.weight, () => ( _optionalChain([e, 'access', _238 => _238.face, 'access', _239 => _239.tables, 'optionalAccess', _240 => _240.os2, 'optionalAccess', _241 => _241.usWeightClass]))), () => ( 400));
7327
- const italic = _nullishCoalesce(e.italic, () => ( Boolean((_nullishCoalesce(_optionalChain([e, 'access', _242 => _242.face, 'access', _243 => _243.tables, 'optionalAccess', _244 => _244.os2, 'optionalAccess', _245 => _245.fsSelection]), () => ( 0))) & 1)));
7328
- const postScript = _nullishCoalesce(_optionalChain([names, 'optionalAccess', _246 => _246.postScriptName, 'optionalAccess', _247 => _247.en]), () => ( Object.values(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _248 => _248.postScriptName]), () => ( {})))[0]));
7483
+ const family = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(e.family, () => ( _optionalChain([names, 'optionalAccess', _266 => _266.fontFamily, 'optionalAccess', _267 => _267.en]))), () => ( Object.values(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _268 => _268.fontFamily]), () => ( {})))[0])), () => ( "Font"));
7484
+ const weight = _nullishCoalesce(_nullishCoalesce(e.weight, () => ( _optionalChain([e, 'access', _269 => _269.face, 'access', _270 => _270.tables, 'optionalAccess', _271 => _271.os2, 'optionalAccess', _272 => _272.usWeightClass]))), () => ( 400));
7485
+ const italic = _nullishCoalesce(e.italic, () => ( Boolean((_nullishCoalesce(_optionalChain([e, 'access', _273 => _273.face, 'access', _274 => _274.tables, 'optionalAccess', _275 => _275.os2, 'optionalAccess', _276 => _276.fsSelection]), () => ( 0))) & 1)));
7486
+ const postScript = _nullishCoalesce(_optionalChain([names, 'optionalAccess', _277 => _277.postScriptName, 'optionalAccess', _278 => _278.en]), () => ( Object.values(_nullishCoalesce(_optionalChain([names, 'optionalAccess', _279 => _279.postScriptName]), () => ( {})))[0]));
7329
7487
  return { face: e.face, family, key: family.toLowerCase(), weight, italic, postScript };
7330
7488
  });
7331
7489
  const fallbackKey = (_nullishCoalesce(options.fallback, () => ( entries[0].family))).toLowerCase();
@@ -7372,12 +7530,12 @@ function createOutlineTextShaper(fonts, options = {}) {
7372
7530
  return out;
7373
7531
  },
7374
7532
  outline(text, font, x, y, opts) {
7375
- return toPath(pick(font).entry.face.getPath(text, x, y, font.size, _optionalChain([opts, 'optionalAccess', _249 => _249.vertical]) ? { kerning: true, vertical: true } : { kerning: true }).commands);
7533
+ return toPath(pick(font).entry.face.getPath(text, x, y, font.size, _optionalChain([opts, 'optionalAccess', _280 => _280.vertical]) ? { kerning: true, vertical: true } : { kerning: true }).commands);
7376
7534
  },
7377
7535
  vertical(char, font) {
7378
7536
  const { face } = pick(font).entry;
7379
7537
  const k = font.size / face.unitsPerEm;
7380
- const v2 = _optionalChain([face, 'access', _250 => _250.getVerticalMetrics, 'optionalCall', _251 => _251(char)]);
7538
+ const v2 = _optionalChain([face, 'access', _281 => _281.getVerticalMetrics, 'optionalCall', _282 => _282(char)]);
7381
7539
  if (v2) return { advance: v2.advance * k, originY: v2.originY * k, alternate: v2.alternate };
7382
7540
  return { advance: (face.ascender - face.descender) * k, originY: face.ascender * k, alternate: false };
7383
7541
  },
@@ -7438,7 +7596,7 @@ function vectorTextHasOutlines() {
7438
7596
  return typeof getVectorTextShaper().outline === "function";
7439
7597
  }
7440
7598
  function vectorTextFamilies() {
7441
- return _nullishCoalesce(_optionalChain([getVectorTextShaper, 'call', _252 => _252(), 'access', _253 => _253.families, 'optionalCall', _254 => _254()]), () => ( ["sans-serif", "serif", "monospace"]));
7599
+ return _nullishCoalesce(_optionalChain([getVectorTextShaper, 'call', _283 => _283(), 'access', _284 => _284.families, 'optionalCall', _285 => _285()]), () => ( ["sans-serif", "serif", "monospace"]));
7442
7600
  }
7443
7601
  var DEFAULT_VECTOR_FONT = { fontFamily: "sans-serif", fontWeight: 400, fontSize: 24 };
7444
7602
  var VECTOR_CHARACTER_STYLE_KEYS = ["fontFamily", "fontWeight", "italic", "fontSize", "tracking", "leading", "baselineShift", "underline", "strikethrough", "upright"];
@@ -7614,7 +7772,7 @@ function computeLayout2(node, shaper) {
7614
7772
  const fragments = [];
7615
7773
  const lines = [];
7616
7774
  let overflow = false;
7617
- const fillOf = (f) => _optionalChain([runs, 'access', _255 => _255.find, 'call', _256 => _256((r) => f.start >= r.start && f.start < r.end), 'optionalAccess', _257 => _257.fill]);
7775
+ const fillOf = (f) => _optionalChain([runs, 'access', _286 => _286.find, 'call', _287 => _287((r) => f.start >= r.start && f.start < r.end), 'optionalAccess', _288 => _288.fill]);
7618
7776
  const styleOf = (f) => {
7619
7777
  const { color: _c, opacity: _o, postScriptName: _p, ...style } = f.style;
7620
7778
  return style;
@@ -7653,11 +7811,11 @@ function computeLayout2(node, shaper) {
7653
7811
  } else {
7654
7812
  const line = text.lines[0];
7655
7813
  const measure = measureVectorPath(subpathPath(frame.path), !!frame.flip);
7656
- const align = _nullishCoalesce(_optionalChain([node, 'access', _258 => _258.paragraph, 'optionalAccess', _259 => _259.align]), () => ( "left"));
7814
+ const align = _nullishCoalesce(_optionalChain([node, 'access', _289 => _289.paragraph, 'optionalAccess', _290 => _290.align]), () => ( "left"));
7657
7815
  const start = Math.max(0, _nullishCoalesce(frame.start, () => ( 0)));
7658
7816
  const end = Math.max(0, _nullishCoalesce(frame.end, () => ( 0)));
7659
7817
  const upright = frame.orientation === "upright";
7660
- const baselineOffset = pathBaselineOffset(_nullishCoalesce(frame.baseline, () => ( "baseline")), _nullishCoalesce(_optionalChain([line, 'optionalAccess', _260 => _260.ascent]), () => ( 0)), _nullishCoalesce(_optionalChain([line, 'optionalAccess', _261 => _261.descent]), () => ( 0)));
7818
+ const baselineOffset = pathBaselineOffset(_nullishCoalesce(frame.baseline, () => ( "baseline")), _nullishCoalesce(_optionalChain([line, 'optionalAccess', _291 => _291.ascent]), () => ( 0)), _nullishCoalesce(_optionalChain([line, 'optionalAccess', _292 => _292.descent]), () => ( 0)));
7661
7819
  if (line) {
7662
7820
  const chars = line.chars.filter((c) => {
7663
7821
  const lo = block.text.charCodeAt(c.index);
@@ -7666,7 +7824,7 @@ function computeLayout2(node, shaper) {
7666
7824
  const advanceOf = (c) => {
7667
7825
  const pair = charAt(block.text, c.index).length === 2;
7668
7826
  const low = pair ? line.chars.find((d) => d.index === c.index + 1) : void 0;
7669
- return c.advance + (_nullishCoalesce(_optionalChain([low, 'optionalAccess', _262 => _262.advance]), () => ( 0)));
7827
+ return c.advance + (_nullishCoalesce(_optionalChain([low, 'optionalAccess', _293 => _293.advance]), () => ( 0)));
7670
7828
  };
7671
7829
  const pivots = chars.map((c) => c.x + advanceOf(c) / 2);
7672
7830
  const positions = vectorPathTextPositions(pivots, [line.x, line.x + line.width], align, measure.length, start, end);
@@ -7721,7 +7879,7 @@ function computeLayout2(node, shaper) {
7721
7879
  if (x0 < Infinity) bounds = { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
7722
7880
  else if (frame.kind === "point") {
7723
7881
  const l = text.lines[0];
7724
- bounds = { x: frame.x, y: frame.y - (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _263 => _263.ascent]), () => ( 0))), width: 0, height: (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _264 => _264.ascent]), () => ( 0))) + (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _265 => _265.descent]), () => ( 0))) };
7882
+ bounds = { x: frame.x, y: frame.y - (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _294 => _294.ascent]), () => ( 0))), width: 0, height: (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _295 => _295.ascent]), () => ( 0))) + (_nullishCoalesce(_optionalChain([l, 'optionalAccess', _296 => _296.descent]), () => ( 0))) };
7725
7883
  }
7726
7884
  }
7727
7885
  return { shaper: shaper.id, glyphs, fragments, lines, origin, text, bounds, overflow, missingFonts: text.missingFonts };
@@ -7842,7 +8000,7 @@ function vectorTextCaret(node, index) {
7842
8000
  const t = { x: Math.cos(r), y: Math.sin(r) };
7843
8001
  const n2 = { x: -t.y, y: t.x };
7844
8002
  const o = { x: g2.x + t.x * u, y: g2.y + t.y * u };
7845
- return { top: { x: o.x - n2.x * g2.ascent, y: o.y - n2.y * g2.ascent }, bottom: { x: o.x + n2.x * g2.descent, y: o.y + n2.y * g2.descent }, line: _nullishCoalesce(_optionalChain([layout, 'access', _266 => _266.fragments, 'access', _267 => _267[g2.fragment], 'optionalAccess', _268 => _268.line]), () => ( 0)) };
8003
+ return { top: { x: o.x - n2.x * g2.ascent, y: o.y - n2.y * g2.ascent }, bottom: { x: o.x + n2.x * g2.descent, y: o.y + n2.y * g2.descent }, line: _nullishCoalesce(_optionalChain([layout, 'access', _297 => _297.fragments, 'access', _298 => _298[g2.fragment], 'optionalAccess', _299 => _299.line]), () => ( 0)) };
7846
8004
  };
7847
8005
  if (node.frame.kind !== "path") {
7848
8006
  const c = caretAt(layout.text, index);
@@ -7982,7 +8140,7 @@ function sanitizeVectorTextFrame(value, path = "frame") {
7982
8140
  return { kind: "area", x: num2(f.x, `${path}.x`, -1e7, 1e7), y: num2(f.y, `${path}.y`, -1e7, 1e7), width: num2(f.width, `${path}.width`, 0, 1e7), height: num2(f.height, `${path}.height`, 0, 1e7) };
7983
8141
  if (f.kind === "path") {
7984
8142
  const sp = f.path;
7985
- if (!sp || !Array.isArray(sp.anchors) || sp.anchors.length < 2 || !sp.anchors.every((a) => isNum(_optionalChain([a, 'optionalAccess', _269 => _269.x])) && isNum(_optionalChain([a, 'optionalAccess', _270 => _270.y])))) fail(`${path}.path must be a subpath with at least two anchors.`);
8143
+ if (!sp || !Array.isArray(sp.anchors) || sp.anchors.length < 2 || !sp.anchors.every((a) => isNum(_optionalChain([a, 'optionalAccess', _300 => _300.x])) && isNum(_optionalChain([a, 'optionalAccess', _301 => _301.y])))) fail(`${path}.path must be a subpath with at least two anchors.`);
7986
8144
  const out = { kind: "path", path: { closed: !!sp.closed, anchors: sp.anchors.map((a) => ({ ...a })) } };
7987
8145
  if (f.start !== void 0 && f.start !== 0) out.start = num2(f.start, `${path}.start`, 0, 1e7);
7988
8146
  if (f.end !== void 0 && f.end !== 0) out.end = num2(f.end, `${path}.end`, 0, 1e7);
@@ -8000,7 +8158,7 @@ function sanitizeVectorTextFrame(value, path = "frame") {
8000
8158
  return fail(`${path}.kind must be point, area or path, got ${JSON.stringify(f.kind)}.`);
8001
8159
  }
8002
8160
  function normalizeVectorTextRuns(text, runs) {
8003
- if (!_optionalChain([runs, 'optionalAccess', _271 => _271.length])) return null;
8161
+ if (!_optionalChain([runs, 'optionalAccess', _302 => _302.length])) return null;
8004
8162
  const cleaned = fitVectorTextRuns(
8005
8163
  runs.map((r) => ({ length: r.length, style: stripUndefined(r.style) })),
8006
8164
  text.length
@@ -8040,7 +8198,7 @@ function replaceVectorText(node, start, end, insert) {
8040
8198
  const clean2 = insert.replace(/\r\n?/g, "\n");
8041
8199
  const text = node.text.slice(0, start) + clean2 + node.text.slice(end);
8042
8200
  let runs = null;
8043
- if (_optionalChain([node, 'access', _272 => _272.runs, 'optionalAccess', _273 => _273.length])) {
8201
+ if (_optionalChain([node, 'access', _303 => _303.runs, 'optionalAccess', _304 => _304.length])) {
8044
8202
  const fitted = fitVectorTextRuns(node.runs, node.text.length);
8045
8203
  const style = styleAt(fitted, start > 0 ? start - 1 : start, {});
8046
8204
  runs = normalizeVectorTextRuns(text, spliceRuns(fitted, start, end, clean2.length, style));
@@ -8056,7 +8214,7 @@ function styleVectorText(node, start, end, patch) {
8056
8214
  if (whole) {
8057
8215
  let next2 = { ...node, font: patchVectorCharacterStyle(node.font, fields, "style") };
8058
8216
  const keys = Object.keys(fields).filter((k) => fields[k] !== void 0);
8059
- if (_optionalChain([next2, 'access', _274 => _274.runs, 'optionalAccess', _275 => _275.length]) && (keys.length || fill !== void 0)) {
8217
+ if (_optionalChain([next2, 'access', _305 => _305.runs, 'optionalAccess', _306 => _306.length]) && (keys.length || fill !== void 0)) {
8060
8218
  const runs2 = normalizeVectorTextRuns(
8061
8219
  next2.text,
8062
8220
  next2.runs.map((r) => {
@@ -8101,7 +8259,7 @@ function bakeVectorTextGeometry(node, m) {
8101
8259
  ...s.baselineShift !== void 0 ? { baselineShift: s.baselineShift * k } : {}
8102
8260
  });
8103
8261
  const font = scaleStyle(node.font);
8104
- const runs = _optionalChain([node, 'access', _276 => _276.runs, 'optionalAccess', _277 => _277.map, 'call', _278 => _278((r) => ({ length: r.length, style: scaleStyle(r.style) }))]);
8262
+ const runs = _optionalChain([node, 'access', _307 => _307.runs, 'optionalAccess', _308 => _308.map, 'call', _309 => _309((r) => ({ length: r.length, style: scaleStyle(r.style) }))]);
8105
8263
  const p = node.paragraph;
8106
8264
  const paragraph = p ? {
8107
8265
  ...p,
@@ -8390,7 +8548,7 @@ function vectorInstanceGroup(node, bake) {
8390
8548
  const m = _nullishCoalesce(node.transform, () => ( [1, 0, 0, 1, 0, 0]));
8391
8549
  const { rigid, residual } = decomposeRigid(m);
8392
8550
  const k = Math.sqrt(Math.abs(residual[0] * residual[3] - residual[1] * residual[2]));
8393
- const hidden = new Set(_nullishCoalesce(_optionalChain([node, 'access', _279 => _279.overrides, 'optionalAccess', _280 => _280.hidden]), () => ( [])));
8551
+ const hidden = new Set(_nullishCoalesce(_optionalChain([node, 'access', _310 => _310.overrides, 'optionalAccess', _311 => _311.hidden]), () => ( [])));
8394
8552
  const keep = (list) => list.filter((n) => !hidden.has(n.id)).map((n) => n.type === "group" ? { ...n, children: keep(n.children) } : n);
8395
8553
  let children = prefixVectorIds(keep(_nullishCoalesce(node.art, () => ( []))), node.id);
8396
8554
  if (!isIdentityMatrix(residual)) children = children.map((c) => bake(c, residual));
@@ -8403,8 +8561,8 @@ function vectorInstanceGroup(node, bake) {
8403
8561
  if (node.locked) group.locked = true;
8404
8562
  if (node.opacity !== void 0) group.opacity = node.opacity;
8405
8563
  if (node.blendMode) group.blendMode = node.blendMode;
8406
- if (_optionalChain([node, 'access', _281 => _281.filters, 'optionalAccess', _282 => _282.length])) group.filters = node.filters;
8407
- if (_optionalChain([node, 'access', _283 => _283.effects, 'optionalAccess', _284 => _284.length])) group.effects = node.effects;
8564
+ if (_optionalChain([node, 'access', _312 => _312.filters, 'optionalAccess', _313 => _313.length])) group.filters = node.filters;
8565
+ if (_optionalChain([node, 'access', _314 => _314.effects, 'optionalAccess', _315 => _315.length])) group.effects = node.effects;
8408
8566
  if (node.booleanOperation) group.booleanOperation = node.booleanOperation;
8409
8567
  if (node.blendStep) group.blendStep = true;
8410
8568
  return group;
@@ -8657,8 +8815,8 @@ function vectorLensDrawn(node) {
8657
8815
  if (wire) {
8658
8816
  contents.push(shapePath(shape, id, changed, { fill: null, fills: void 0, stroke: wire, strokes: void 0, strokeWidth: 1, strokeAlign: void 0, strokeDasharray: void 0, strokeWidthProfile: void 0, opacity: Math.min(1, Math.max(0, lens.amount / 100)) }));
8659
8817
  } else if (recolour) {
8660
- const fills = _optionalChain([shape, 'access', _285 => _285.source, 'access', _286 => _286.fills, 'optionalAccess', _287 => _287.map, 'call', _288 => _288((l) => ({ ...l, paint: _nullishCoalesce(mapVectorPaintColors(l.paint, recolour), () => ( null)) }))]);
8661
- const strokes = _optionalChain([shape, 'access', _289 => _289.source, 'access', _290 => _290.strokes, 'optionalAccess', _291 => _291.map, 'call', _292 => _292((l) => ({ ...l, paint: _nullishCoalesce(mapVectorPaintColors(l.paint, recolour), () => ( null)) }))]);
8818
+ const fills = _optionalChain([shape, 'access', _316 => _316.source, 'access', _317 => _317.fills, 'optionalAccess', _318 => _318.map, 'call', _319 => _319((l) => ({ ...l, paint: _nullishCoalesce(mapVectorPaintColors(l.paint, recolour), () => ( null)) }))]);
8819
+ const strokes = _optionalChain([shape, 'access', _320 => _320.source, 'access', _321 => _321.strokes, 'optionalAccess', _322 => _322.map, 'call', _323 => _323((l) => ({ ...l, paint: _nullishCoalesce(mapVectorPaintColors(l.paint, recolour), () => ( null)) }))]);
8662
8820
  contents.push(shapePath(shape, id, changed, { fill: _nullishCoalesce(mapVectorPaintColors(shape.source.fill, recolour), () => ( null)), stroke: _nullishCoalesce(mapVectorPaintColors(shape.source.stroke, recolour), () => ( null)), ...fills ? { fills } : {}, ...strokes ? { strokes } : {} }));
8663
8821
  } else contents.push(shapePath(shape, id, changed));
8664
8822
  }
@@ -8671,7 +8829,7 @@ function vectorLensDrawn(node) {
8671
8829
  const { lens: _l, lensView: _v, transform: _t, opacity: _o, effects: _e, blendMode: _bm, filters: _f, ...style } = node;
8672
8830
  const fillOpacity = lens.type === "transparency" ? 1 - Math.min(100, Math.max(0, lens.amount)) / 100 : 0;
8673
8831
  children.push({ ...style, id: `${node.id}~lens-fill`, stroke: null, strokes: void 0, opacity: fillOpacity });
8674
- const stroked = (_nullishCoalesce(_optionalChain([node, 'access', _293 => _293.strokes, 'optionalAccess', _294 => _294.length]), () => ( 0))) > 0 || node.stroke != null && node.stroke !== "none";
8832
+ const stroked = (_nullishCoalesce(_optionalChain([node, 'access', _324 => _324.strokes, 'optionalAccess', _325 => _325.length]), () => ( 0))) > 0 || node.stroke != null && node.stroke !== "none";
8675
8833
  if (stroked) children.push({ ...style, id: `${node.id}~lens-stroke`, fill: null, fills: void 0 });
8676
8834
  const out = {
8677
8835
  id: node.id,
@@ -8680,7 +8838,7 @@ function vectorLensDrawn(node) {
8680
8838
  ...node.transform ? { transform: node.transform } : {},
8681
8839
  ...node.opacity !== void 0 ? { opacity: node.opacity } : {},
8682
8840
  ...node.blendMode ? { blendMode: node.blendMode } : {},
8683
- ..._optionalChain([node, 'access', _295 => _295.filters, 'optionalAccess', _296 => _296.length]) ? { filters: node.filters } : {},
8841
+ ..._optionalChain([node, 'access', _326 => _326.filters, 'optionalAccess', _327 => _327.length]) ? { filters: node.filters } : {},
8684
8842
  children
8685
8843
  };
8686
8844
  drawnCache2.set(node, out);
@@ -9681,7 +9839,7 @@ function normalizeVectorEffectParams(type, params, base) {
9681
9839
  if (!defaults) return null;
9682
9840
  const out = { ...defaults, ..._nullishCoalesce(base, () => ( {})) };
9683
9841
  for (const spec of VECTOR_EFFECT_PARAM_SPECS[type]) {
9684
- const v2 = _optionalChain([params, 'optionalAccess', _297 => _297[spec.key]]);
9842
+ const v2 = _optionalChain([params, 'optionalAccess', _328 => _328[spec.key]]);
9685
9843
  if (v2 === void 0) continue;
9686
9844
  if (spec.kind === "number" && typeof v2 === "number" && Number.isFinite(v2)) out[spec.key] = Math.min(_nullishCoalesce(spec.max, () => ( Infinity)), Math.max(_nullishCoalesce(spec.min, () => ( -Infinity)), v2));
9687
9845
  else if (spec.kind === "boolean" && typeof v2 === "boolean") out[spec.key] = v2;
@@ -9693,7 +9851,7 @@ function normalizeVectorEffectParams(type, params, base) {
9693
9851
  const o = out;
9694
9852
  o.rows = Math.round(o.rows);
9695
9853
  o.columns = Math.round(o.columns);
9696
- const given = _optionalChain([params, 'optionalAccess', _298 => _298.mesh]);
9854
+ const given = _optionalChain([params, 'optionalAccess', _329 => _329.mesh]);
9697
9855
  let mesh = given !== void 0 ? isValidWarpMesh(given) ? cloneMesh(given) : null : o.mesh;
9698
9856
  if (o.style !== "mesh") mesh = null;
9699
9857
  if (mesh && given !== void 0) {
@@ -9710,10 +9868,10 @@ function createVectorEffect(type, id, params) {
9710
9868
  }
9711
9869
  var isEnabled = (e) => e.enabled !== false && !!VECTOR_EFFECT_DEFAULTS[e.type];
9712
9870
  function activeVectorEffects(node) {
9713
- return _nullishCoalesce(_optionalChain([node, 'access', _299 => _299.effects, 'optionalAccess', _300 => _300.filter, 'call', _301 => _301(isEnabled)]), () => ( []));
9871
+ return _nullishCoalesce(_optionalChain([node, 'access', _330 => _330.effects, 'optionalAccess', _331 => _331.filter, 'call', _332 => _332(isEnabled)]), () => ( []));
9714
9872
  }
9715
9873
  function hasOwnVectorAppearance(node) {
9716
- return node.type === "text" || node.type === "instance" || node.type === "group" && !!node.liveBoolean || isVectorFrame(node) || isVectorSymmetryGroup(node) || isVectorLens(node) || !!_optionalChain([node, 'access', _302 => _302.effects, 'optionalAccess', _303 => _303.some, 'call', _304 => _304(isEnabled)]);
9874
+ return node.type === "text" || node.type === "instance" || node.type === "group" && !!node.liveBoolean || isVectorFrame(node) || isVectorSymmetryGroup(node) || isVectorLens(node) || !!_optionalChain([node, 'access', _333 => _333.effects, 'optionalAccess', _334 => _334.some, 'call', _335 => _335(isEnabled)]);
9717
9875
  }
9718
9876
  var liveCache = /* @__PURE__ */ new WeakMap();
9719
9877
  function hasVectorAppearance(node) {
@@ -9725,18 +9883,18 @@ function hasVectorAppearance(node) {
9725
9883
  return v2;
9726
9884
  }
9727
9885
  function isVectorLiveBoolean(node) {
9728
- return _optionalChain([node, 'optionalAccess', _305 => _305.type]) === "group" && !!node.liveBoolean;
9886
+ return _optionalChain([node, 'optionalAccess', _336 => _336.type]) === "group" && !!node.liveBoolean;
9729
9887
  }
9730
9888
  function vectorOperandOperation(group, child) {
9731
9889
  return _nullishCoalesce(_nullishCoalesce(child.booleanOperation, () => ( group.liveBoolean)), () => ( "union"));
9732
9890
  }
9733
9891
  var PATH_OPS = { union: "union", subtract: "difference", intersect: "intersection", exclude: "xor" };
9734
9892
  var FoldCache = (_class9 = class {
9735
- constructor(cap) {;_class9.prototype.__init60.call(this);
9893
+ constructor(cap) {;_class9.prototype.__init61.call(this);
9736
9894
  this.cap = cap;
9737
9895
  }
9738
9896
 
9739
- __init60() {this.map = /* @__PURE__ */ new Map()}
9897
+ __init61() {this.map = /* @__PURE__ */ new Map()}
9740
9898
  get(key) {
9741
9899
  const hit = this.map.get(key);
9742
9900
  if (hit) {
@@ -9767,9 +9925,9 @@ function vectorLiveBooleanSteps() {
9767
9925
  function clearVectorLiveBooleanCache() {
9768
9926
  foldCache.clear();
9769
9927
  }
9770
- var RollingHash = (_class10 = class _RollingHash {constructor() { _class10.prototype.__init61.call(this);_class10.prototype.__init62.call(this); }
9771
- __init61() {this.a = 2166136261}
9772
- __init62() {this.b = 16777619 ^ 1540483477}
9928
+ var RollingHash = (_class10 = class _RollingHash {constructor() { _class10.prototype.__init62.call(this);_class10.prototype.__init63.call(this); }
9929
+ __init62() {this.a = 2166136261}
9930
+ __init63() {this.b = 16777619 ^ 1540483477}
9773
9931
  static __initStatic() {this.view = new DataView(new ArrayBuffer(8))}
9774
9932
  byte(v2) {
9775
9933
  this.a = Math.imul(this.a ^ v2 & 255, 16777619);
@@ -9842,7 +10000,7 @@ var compareOrder = (a, b) => {
9842
10000
  for (let i = 0; i < n; i++) if (a[i] !== b[i]) return a[i] - b[i];
9843
10001
  return a.length - b.length;
9844
10002
  };
9845
- var add3 = (a, b) => ({ x: a.x + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _306 => _306.x]), () => ( 0))), y: a.y + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _307 => _307.y]), () => ( 0))) });
10003
+ var add3 = (a, b) => ({ x: a.x + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _337 => _337.x]), () => ( 0))), y: a.y + (_nullishCoalesce(_optionalChain([b, 'optionalAccess', _338 => _338.y]), () => ( 0))) });
9846
10004
  var mapPaths = (shapes, fn) => {
9847
10005
  const out = fn(shapes.map((s) => s.path));
9848
10006
  return shapes.map((s, i) => ({ ...s, path: _nullishCoalesce(out[i], () => ( [])) }));
@@ -9870,7 +10028,7 @@ function contourShapes(shapes, c) {
9870
10028
  const power = 2 ** (Math.min(100, Math.max(-100, c.acceleration)) / 50);
9871
10029
  for (let k = 1; k <= n; k++) {
9872
10030
  const [path] = offsetPaths([s.path], (outside ? 1 : -1) * step * k, c.join, c.miterLimit, 1, 0);
9873
- if (!_optionalChain([path, 'optionalAccess', _308 => _308.length])) break;
10031
+ if (!_optionalChain([path, 'optionalAccess', _339 => _339.length])) break;
9874
10032
  const t = (k / n) ** power;
9875
10033
  const source = { ...s.source, fill: _nullishCoalesce(blendPaint(s.source.fill, c.fillColor, t), () => ( null)), stroke: _nullishCoalesce(blendPaint(s.source.stroke, c.strokeColor, t), () => ( null)), fills: void 0, strokes: void 0 };
9876
10034
  out.push({ source, path, opacity: s.opacity, order: [outside ? n - k : k, ...s.order] });
@@ -9945,8 +10103,8 @@ function bevelShapes(shapes, b) {
9945
10103
  out.push({ source, path: f.path, opacity: s.opacity, order: [...s.order, 1, k] });
9946
10104
  });
9947
10105
  const [middle] = offsetPaths([s.path], -b.width, "miter", 4, 1, 0);
9948
- if (_optionalChain([middle, 'optionalAccess', _309 => _309.length])) out.push({ ...s, source: fillOnly, path: middle, order: [...s.order, 2] });
9949
- const hasStroke = _optionalChain([s, 'access', _310 => _310.source, 'access', _311 => _311.strokes, 'optionalAccess', _312 => _312.length]) || s.source.stroke != null && s.source.stroke !== "none";
10106
+ if (_optionalChain([middle, 'optionalAccess', _340 => _340.length])) out.push({ ...s, source: fillOnly, path: middle, order: [...s.order, 2] });
10107
+ const hasStroke = _optionalChain([s, 'access', _341 => _341.source, 'access', _342 => _342.strokes, 'optionalAccess', _343 => _343.length]) || s.source.stroke != null && s.source.stroke !== "none";
9950
10108
  if (hasStroke) out.push({ ...s, source: { ...s.source, fill: null, fills: void 0 }, order: [...s.order, 3] });
9951
10109
  }
9952
10110
  return out;
@@ -10079,10 +10237,10 @@ function vectorEffectInputBounds(node, effectId) {
10079
10237
  return paths ? pathsBounds(paths) : null;
10080
10238
  }
10081
10239
  function vectorNodeEnvelope(node) {
10082
- return _nullishCoalesce(_optionalChain([node, 'optionalAccess', _313 => _313.effects, 'optionalAccess', _314 => _314.find, 'call', _315 => _315((e) => e.type === "envelope" && e.enabled !== false)]), () => ( null));
10240
+ return _nullishCoalesce(_optionalChain([node, 'optionalAccess', _344 => _344.effects, 'optionalAccess', _345 => _345.find, 'call', _346 => _346((e) => e.type === "envelope" && e.enabled !== false)]), () => ( null));
10083
10241
  }
10084
10242
  function vectorEnvelopeFrame(node, effectId) {
10085
- const e = effectId ? _optionalChain([node, 'access', _316 => _316.effects, 'optionalAccess', _317 => _317.find, 'call', _318 => _318((x) => x.id === effectId)]) : vectorNodeEnvelope(node);
10243
+ const e = effectId ? _optionalChain([node, 'access', _347 => _347.effects, 'optionalAccess', _348 => _348.find, 'call', _349 => _349((x) => x.id === effectId)]) : vectorNodeEnvelope(node);
10086
10244
  if (!e || e.type !== "envelope") return null;
10087
10245
  const bounds = vectorEffectInputBounds(node, e.id);
10088
10246
  if (!bounds || !(bounds.width > 0 && bounds.height > 0)) return null;
@@ -10143,7 +10301,7 @@ function placement(node) {
10143
10301
  ...node.blendStep ? { blendStep: true } : {},
10144
10302
  ...node.booleanOperation ? { booleanOperation: node.booleanOperation } : {},
10145
10303
  ...node.blendMode ? { blendMode: node.blendMode } : {},
10146
- ..._optionalChain([node, 'access', _319 => _319.filters, 'optionalAccess', _320 => _320.length]) ? { filters: node.filters } : {}
10304
+ ..._optionalChain([node, 'access', _350 => _350.filters, 'optionalAccess', _351 => _351.length]) ? { filters: node.filters } : {}
10147
10305
  };
10148
10306
  }
10149
10307
  function vectorAppearanceNodes(node) {
@@ -10275,7 +10433,7 @@ function vectorMasterPages(doc) {
10275
10433
  function fillTokens(node, page, pages) {
10276
10434
  const map = (s) => s.replace(/\{page\}/g, String(page)).replace(/\{pages\}/g, String(pages));
10277
10435
  if (!/\{pages?\}/.test(node.text)) return node;
10278
- if (!_optionalChain([node, 'access', _321 => _321.runs, 'optionalAccess', _322 => _322.length])) return { ...node, text: map(node.text) };
10436
+ if (!_optionalChain([node, 'access', _352 => _352.runs, 'optionalAccess', _353 => _353.length])) return { ...node, text: map(node.text) };
10279
10437
  let at2 = 0;
10280
10438
  let text = "";
10281
10439
  const runs = [];
@@ -10298,7 +10456,7 @@ function vectorMasterArt(master, page, number, count) {
10298
10456
  const f = page.frame;
10299
10457
  const key = `${page.id}|${f.x}|${f.y}|${f.width}|${f.height}|${number}|${count}`;
10300
10458
  let byKey = artCache.get(master);
10301
- const hit = _optionalChain([byKey, 'optionalAccess', _323 => _323.get, 'call', _324 => _324(key)]);
10459
+ const hit = _optionalChain([byKey, 'optionalAccess', _354 => _354.get, 'call', _355 => _355(key)]);
10302
10460
  if (hit) return hit;
10303
10461
  const art = master.children.filter((c) => c.visible !== false).map((c) => {
10304
10462
  const box = vectorNodeBounds(c);
@@ -10343,7 +10501,7 @@ function stripVectorMasterArt(doc) {
10343
10501
  // src/vector/connectors.ts
10344
10502
  var SIDES = ["top", "right", "bottom", "left", "center"];
10345
10503
  function isVectorConnector(node) {
10346
- return _optionalChain([node, 'optionalAccess', _325 => _325.type]) === "path" && !!node.connector;
10504
+ return _optionalChain([node, 'optionalAccess', _356 => _356.type]) === "path" && !!node.connector;
10347
10505
  }
10348
10506
  function vectorConnectionSites(nodes, id) {
10349
10507
  const node = findVectorNode(nodes, id);
@@ -10400,7 +10558,7 @@ function facingSite(sites, toward) {
10400
10558
  }
10401
10559
  function storedEnds(node, world) {
10402
10560
  const sp = node.subpaths[0];
10403
- if (!_optionalChain([sp, 'optionalAccess', _326 => _326.anchors, 'access', _327 => _327.length])) return null;
10561
+ if (!_optionalChain([sp, 'optionalAccess', _357 => _357.anchors, 'access', _358 => _358.length])) return null;
10404
10562
  const a = sp.anchors[0];
10405
10563
  const b = sp.anchors[sp.anchors.length - 1];
10406
10564
  return [applyMatrix(world, a), applyMatrix(world, b)];
@@ -10507,8 +10665,8 @@ function routeVectorConnector(nodes, id) {
10507
10665
  }));
10508
10666
  return {
10509
10667
  subpaths: [{ closed: false, anchors: local }],
10510
- startSide: _nullishCoalesce(_optionalChain([s, 'optionalAccess', _328 => _328.side]), () => ( null)),
10511
- endSide: _nullishCoalesce(_optionalChain([e, 'optionalAccess', _329 => _329.side]), () => ( null)),
10668
+ startSide: _nullishCoalesce(_optionalChain([s, 'optionalAccess', _359 => _359.side]), () => ( null)),
10669
+ endSide: _nullishCoalesce(_optionalChain([e, 'optionalAccess', _360 => _360.side]), () => ( null)),
10512
10670
  dropped: { start: !!startGlue && !s, end: !!endGlue && !e }
10513
10671
  };
10514
10672
  }
@@ -10520,7 +10678,7 @@ function sameSubpaths(a, b) {
10520
10678
  const o = b[i];
10521
10679
  return sp.closed === o.closed && sp.anchors.length === o.anchors.length && sp.anchors.every((p, k) => {
10522
10680
  const q = o.anchors[k];
10523
- return samePoint(p, q) && samePoint(p.in, q.in) && samePoint(p.out, q.out) && (_nullishCoalesce(_optionalChain([p, 'access', _330 => _330.corner, 'optionalAccess', _331 => _331.radius]), () => ( 0))) === (_nullishCoalesce(_optionalChain([q, 'access', _332 => _332.corner, 'optionalAccess', _333 => _333.radius]), () => ( 0)));
10681
+ return samePoint(p, q) && samePoint(p.in, q.in) && samePoint(p.out, q.out) && (_nullishCoalesce(_optionalChain([p, 'access', _361 => _361.corner, 'optionalAccess', _362 => _362.radius]), () => ( 0))) === (_nullishCoalesce(_optionalChain([q, 'access', _363 => _363.corner, 'optionalAccess', _364 => _364.radius]), () => ( 0)));
10524
10682
  });
10525
10683
  });
10526
10684
  }
@@ -10799,7 +10957,7 @@ function applyVectorCornersAttribute(subpaths, value) {
10799
10957
  for (const item of value.trim().split(/\s+/)) {
10800
10958
  const m = /^(\d+)\.(\d+):([\d.eE+-]+)(?::([a-z]+))?$/.exec(item);
10801
10959
  if (!m) continue;
10802
- const a = _optionalChain([subpaths, 'access', _334 => _334[+m[1]], 'optionalAccess', _335 => _335.anchors, 'access', _336 => _336[+m[2]]]);
10960
+ const a = _optionalChain([subpaths, 'access', _365 => _365[+m[1]], 'optionalAccess', _366 => _366.anchors, 'access', _367 => _367[+m[2]]]);
10803
10961
  const radius = parseFloat(m[3]);
10804
10962
  if (!a || !(radius > 0)) continue;
10805
10963
  const kind = VECTOR_CORNER_KINDS.includes(m[4]) ? m[4] : void 0;
@@ -10824,7 +10982,7 @@ function vectorPaintToSvg(paint, gradientId, options = {}) {
10824
10982
  const area2 = bounds2 ? { x: bounds2.x - reach2, y: bounds2.y - reach2, width: bounds2.width + 2 * reach2, height: bounds2.height + 2 * reach2 } : null;
10825
10983
  const key2 = `${gradientId}|${_nullishCoalesce(options.role, () => ( "fill"))}|${_nullishCoalesce(options.precision, () => ( 3))}|${area2 ? [area2.x, area2.y, area2.width, area2.height].join(",") : ""}`;
10826
10984
  let byKey2 = paintCache.get(paint);
10827
- const hit = _optionalChain([byKey2, 'optionalAccess', _337 => _337.get, 'call', _338 => _338(key2)]);
10985
+ const hit = _optionalChain([byKey2, 'optionalAccess', _368 => _368.get, 'call', _369 => _369(key2)]);
10828
10986
  if (hit) return { value: `url(#${gradientId})`, defs: hit };
10829
10987
  const defs2 = vectorShadedSvgDefs(paint, gradientId, { bounds: bounds2, area: area2, precision: _nullishCoalesce(options.precision, () => ( 3)) });
10830
10988
  if (!byKey2) paintCache.set(paint, byKey2 = /* @__PURE__ */ new Map());
@@ -10836,7 +10994,7 @@ function vectorPaintToSvg(paint, gradientId, options = {}) {
10836
10994
  const precision = _nullishCoalesce(options.precision, () => ( 3));
10837
10995
  const key = `${gradientId}|${role}|${precision}`;
10838
10996
  const owner = _nullishCoalesce(options.node, () => ( paint));
10839
- const cached = _optionalChain([paintCache, 'access', _339 => _339.get, 'call', _340 => _340(owner), 'optionalAccess', _341 => _341.get, 'call', _342 => _342(key)]);
10997
+ const cached = _optionalChain([paintCache, 'access', _370 => _370.get, 'call', _371 => _371(owner), 'optionalAccess', _372 => _372.get, 'call', _373 => _373(key)]);
10840
10998
  if (cached && (!options.node || (role === "fill" ? options.node.fill : options.node.stroke) === paint)) return { value: `url(#${gradientId})`, defs: cached };
10841
10999
  const node = options.node;
10842
11000
  const bounds = node ? vectorPathLocalBounds(node) : null;
@@ -10890,7 +11048,7 @@ function vectorNodeLocalPaintBounds(node) {
10890
11048
  }
10891
11049
  var filterCache = /* @__PURE__ */ new WeakMap();
10892
11050
  function vectorNodeFilterSvg(node, id) {
10893
- if (!_optionalChain([node, 'access', _343 => _343.filters, 'optionalAccess', _344 => _344.length])) return null;
11051
+ if (!_optionalChain([node, 'access', _374 => _374.filters, 'optionalAccess', _375 => _375.length])) return null;
10894
11052
  const hit = filterCache.get(node);
10895
11053
  if (hit && hit.id === id) return hit.filter;
10896
11054
  const active = activeVectorFilters(node);
@@ -10976,7 +11134,7 @@ function vectorDocumentToSvg(doc, options = {}) {
10976
11134
  if (node.type === "path" && node.lens) out2 += ` data-vector-lens="${escapeAttr2(JSON.stringify(node.lens))}"`;
10977
11135
  const blend = vectorBlendModeCss(node.blendMode);
10978
11136
  if (blend) out2 += ` style="mix-blend-mode:${blend}"`;
10979
- if (_optionalChain([node, 'access', _345 => _345.filters, 'optionalAccess', _346 => _346.length])) {
11137
+ if (_optionalChain([node, 'access', _376 => _376.filters, 'optionalAccess', _377 => _377.length])) {
10980
11138
  const filter = vectorNodeFilterSvg(node, `${prefix}filter-${node.id}`);
10981
11139
  const data = ` data-vector-filters="${escapeAttr2(JSON.stringify(node.filters))}"`;
10982
11140
  if (filter) {
@@ -11023,7 +11181,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11023
11181
  let out2 = ` stroke="${escapeAttr2(strokeValue)}" stroke-width="${num3(width)}"`;
11024
11182
  if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
11025
11183
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
11026
- if (_optionalChain([node, 'access', _347 => _347.strokeDasharray, 'optionalAccess', _348 => _348.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num3).join(" ")}"`;
11184
+ if (_optionalChain([node, 'access', _378 => _378.strokeDasharray, 'optionalAccess', _379 => _379.length])) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num3).join(" ")}"`;
11027
11185
  return out2;
11028
11186
  };
11029
11187
  const liveCorners = (node) => {
@@ -11072,7 +11230,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11072
11230
  };
11073
11231
  const emit2 = (node, depth) => {
11074
11232
  if (node.visible === false && !options.includeHidden) return;
11075
- const wrappers = _nullishCoalesce(_optionalChain([options, 'access', _349 => _349.wrap, 'optionalAccess', _350 => _350[node.id]]), () => ( []));
11233
+ const wrappers = _nullishCoalesce(_optionalChain([options, 'access', _380 => _380.wrap, 'optionalAccess', _381 => _381[node.id]]), () => ( []));
11076
11234
  wrappers.forEach((w2, i) => {
11077
11235
  let attrs = w2.id !== void 0 ? ` id="${escapeAttr2(w2.id)}"` : "";
11078
11236
  if (w2.transform) attrs += ` transform="${escapeAttr2(w2.transform)}"`;
@@ -11093,7 +11251,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11093
11251
  };
11094
11252
  const emitMaskGroup = (node, depth) => {
11095
11253
  const [source, ...contents] = node.children;
11096
- const body = _optionalChain([node, 'access', _351 => _351.effects, 'optionalAccess', _352 => _352.length]) && contents.length ? [{ id: `${node.id}~content`, type: "group", effects: node.effects, children: contents }] : contents;
11254
+ const body = _optionalChain([node, 'access', _382 => _382.effects, 'optionalAccess', _383 => _383.length]) && contents.length ? [{ id: `${node.id}~content`, type: "group", effects: node.effects, children: contents }] : contents;
11097
11255
  const settings = { type: node.mask.type, ...node.mask.invert ? { invert: true } : {} };
11098
11256
  lines.push(`${indent(depth)}<g${common(node)} data-vector-mask="${escapeAttr2(JSON.stringify(settings))}">`);
11099
11257
  const mask = vectorMaskRenderData(node, `${prefix}mask-${node.id}`, `${prefix}mask-filter-${node.id}`, precision);
@@ -11110,7 +11268,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11110
11268
  lines.push(`${indent(depth + 1)}<g data-vector-part="mask-source" display="none">`);
11111
11269
  emitNode(source, depth + 2);
11112
11270
  lines.push(`${indent(depth + 1)}</g>`);
11113
- if (_optionalChain([mask, 'optionalAccess', _353 => _353.clip])) {
11271
+ if (_optionalChain([mask, 'optionalAccess', _384 => _384.clip])) {
11114
11272
  defs.push(`<clipPath id="${escapeAttr2(mask.id)}">${mask.clip.map((c) => `<path d="${c.d}" clip-rule="${c.clipRule}"/>`).join("")}</clipPath>`);
11115
11273
  ref = ` clip-path="url(#${escapeAttr2(mask.id)})"`;
11116
11274
  }
@@ -11122,7 +11280,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11122
11280
  };
11123
11281
  const emitTextElement = (node, depth, attrs) => {
11124
11282
  const geometry = vectorTextGeometryNode(node);
11125
- const fields = { text: node.text, font: node.font, ..._optionalChain([node, 'access', _354 => _354.runs, 'optionalAccess', _355 => _355.length]) ? { runs: node.runs } : {}, ...node.paragraph ? { paragraph: node.paragraph } : {}, frame: node.frame, ...node.orientation ? { orientation: node.orientation } : {}, ..._optionalChain([node, 'access', _356 => _356.effects, 'optionalAccess', _357 => _357.length]) ? { effects: node.effects } : {} };
11283
+ const fields = { text: node.text, font: node.font, ..._optionalChain([node, 'access', _385 => _385.runs, 'optionalAccess', _386 => _386.length]) ? { runs: node.runs } : {}, ...node.paragraph ? { paragraph: node.paragraph } : {}, frame: node.frame, ...node.orientation ? { orientation: node.orientation } : {}, ..._optionalChain([node, 'access', _387 => _387.effects, 'optionalAccess', _388 => _388.length]) ? { effects: node.effects } : {} };
11126
11284
  let data = ` data-vector-text="${escapeAttr2(JSON.stringify(fields))}"`;
11127
11285
  if (hasVectorPaintStacks(node)) data += ` data-vector-fills="${escapeAttr2(JSON.stringify(vectorFills(node)))}" data-vector-strokes="${escapeAttr2(JSON.stringify(vectorStrokes(node)))}"`;
11128
11286
  else {
@@ -11164,12 +11322,12 @@ function vectorDocumentToSvg(doc, options = {}) {
11164
11322
  };
11165
11323
  const emitText = (node, depth) => {
11166
11324
  const outlines = vectorTextPaths(node).outlines;
11167
- const effects = !!_optionalChain([node, 'access', _358 => _358.effects, 'optionalAccess', _359 => _359.some, 'call', _360 => _360((e) => e.enabled !== false)]);
11325
+ const effects = !!_optionalChain([node, 'access', _389 => _389.effects, 'optionalAccess', _390 => _390.some, 'call', _391 => _391((e) => e.enabled !== false)]);
11168
11326
  if (!outlines || !effects && options.text !== "outlines") {
11169
11327
  emitTextElement(node, depth, common(node));
11170
11328
  return;
11171
11329
  }
11172
- lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${escapeAttr2(JSON.stringify({ kind: "text", ..._optionalChain([node, 'access', _361 => _361.effects, 'optionalAccess', _362 => _362.length]) ? { effects: node.effects } : {} }))}">`);
11330
+ lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${escapeAttr2(JSON.stringify({ kind: "text", ..._optionalChain([node, 'access', _392 => _392.effects, 'optionalAccess', _393 => _393.length]) ? { effects: node.effects } : {} }))}">`);
11173
11331
  lines.push(`${indent(depth + 1)}<g data-vector-part="appearance">`);
11174
11332
  for (const shape of vectorAppearanceNodes(node)) emit2(shape, depth + 2);
11175
11333
  lines.push(`${indent(depth + 1)}</g>`);
@@ -11183,7 +11341,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11183
11341
  const symbolRef = (symbolId) => {
11184
11342
  const hit = symbolIds.get(symbolId);
11185
11343
  if (hit) return hit;
11186
- const sym2 = _optionalChain([doc, 'access', _363 => _363.symbols, 'optionalAccess', _364 => _364.find, 'call', _365 => _365((x) => x.id === symbolId)]);
11344
+ const sym2 = _optionalChain([doc, 'access', _394 => _394.symbols, 'optionalAccess', _395 => _395.find, 'call', _396 => _396((x) => x.id === symbolId)]);
11187
11345
  if (!sym2) return null;
11188
11346
  const id = `${prefix}symbol-${symbolId}`;
11189
11347
  symbolIds.set(symbolId, id);
@@ -11193,20 +11351,20 @@ function vectorDocumentToSvg(doc, options = {}) {
11193
11351
  };
11194
11352
  const emitInstance = (node, depth) => {
11195
11353
  const data = { symbolId: node.symbolId, ...node.scaleStrokes === false ? { scaleStrokes: false } : {}, ...node.overrides ? { overrides: node.overrides } : {} };
11196
- const exact2 = !node.overrides && node.scaleStrokes !== false && !_optionalChain([node, 'access', _366 => _366.effects, 'optionalAccess', _367 => _367.length]) && !_optionalChain([node, 'access', _368 => _368.filters, 'optionalAccess', _369 => _369.length]);
11354
+ const exact2 = !node.overrides && node.scaleStrokes !== false && !_optionalChain([node, 'access', _397 => _397.effects, 'optionalAccess', _398 => _398.length]) && !_optionalChain([node, 'access', _399 => _399.filters, 'optionalAccess', _400 => _400.length]);
11197
11355
  const ref = symbolRef(node.symbolId);
11198
11356
  if (exact2 && ref) {
11199
11357
  lines.push(`${indent(depth)}<use${common(node)} href="#${escapeAttr2(ref)}" data-vector-instance="${escapeAttr2(JSON.stringify(data))}"/>`);
11200
11358
  return;
11201
11359
  }
11202
- const full = { ...data, ...node.transform ? { transform: node.transform } : {}, ..._optionalChain([node, 'access', _370 => _370.effects, 'optionalAccess', _371 => _371.length]) ? { effects: node.effects } : {} };
11360
+ const full = { ...data, ...node.transform ? { transform: node.transform } : {}, ..._optionalChain([node, 'access', _401 => _401.effects, 'optionalAccess', _402 => _402.length]) ? { effects: node.effects } : {} };
11203
11361
  lines.push(`${indent(depth)}<g data-vector-instance="${escapeAttr2(JSON.stringify(full))}">`);
11204
11362
  emitNode(vectorInstanceDrawn(node), depth + 1);
11205
11363
  lines.push(`${indent(depth)}</g>`);
11206
11364
  };
11207
11365
  const emitFrame = (node, depth) => {
11208
11366
  const f = node.frame;
11209
- const data = { ...f, ..._optionalChain([node, 'access', _372 => _372.effects, 'optionalAccess', _373 => _373.length]) ? { effects: node.effects } : {} };
11367
+ const data = { ...f, ..._optionalChain([node, 'access', _403 => _403.effects, 'optionalAccess', _404 => _404.length]) ? { effects: node.effects } : {} };
11210
11368
  lines.push(`${indent(depth)}<g${common(node)} data-vector-frame="${escapeAttr2(JSON.stringify(data))}">`);
11211
11369
  const rect = vectorFrameRectPath(f);
11212
11370
  if (f.fill !== void 0 && f.fill !== null && f.fill !== "none") {
@@ -11221,7 +11379,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11221
11379
  ref = ` clip-path="url(#${escapeAttr2(id)})"`;
11222
11380
  }
11223
11381
  lines.push(`${indent(depth + 1)}<g data-vector-part="frame-contents"${ref}>`);
11224
- if (_optionalChain([node, 'access', _374 => _374.masterArt, 'optionalAccess', _375 => _375.length])) {
11382
+ if (_optionalChain([node, 'access', _405 => _405.masterArt, 'optionalAccess', _406 => _406.length])) {
11225
11383
  lines.push(`${indent(depth + 2)}<g data-vector-part="frame-master">`);
11226
11384
  for (const child of node.masterArt) emit2(child, depth + 3);
11227
11385
  lines.push(`${indent(depth + 2)}</g>`);
@@ -11250,7 +11408,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11250
11408
  if (hasOwnVectorAppearance(node)) {
11251
11409
  const live2 = {
11252
11410
  kind: node.type,
11253
- ..._optionalChain([node, 'access', _376 => _376.effects, 'optionalAccess', _377 => _377.length]) ? { effects: node.effects } : {},
11411
+ ..._optionalChain([node, 'access', _407 => _407.effects, 'optionalAccess', _408 => _408.length]) ? { effects: node.effects } : {},
11254
11412
  ...node.type === "group" && node.liveBoolean ? { liveBoolean: node.liveBoolean } : {},
11255
11413
  ...node.type === "group" && node.symmetry ? { symmetry: node.symmetry } : {}
11256
11414
  };
@@ -11301,7 +11459,7 @@ function vectorDocumentToSvg(doc, options = {}) {
11301
11459
  data += ` data-vector-width-profile="${widthProfileToAttribute(profile)}"`;
11302
11460
  if (node.strokeLinecap && node.strokeLinecap !== "butt") data += ` data-vector-stroke-linecap="${node.strokeLinecap}"`;
11303
11461
  if (node.strokeLinejoin && node.strokeLinejoin !== "miter") data += ` data-vector-stroke-linejoin="${node.strokeLinejoin}"`;
11304
- if (_optionalChain([node, 'access', _378 => _378.strokeDasharray, 'optionalAccess', _379 => _379.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num3).join(" ")}"`;
11462
+ if (_optionalChain([node, 'access', _409 => _409.strokeDasharray, 'optionalAccess', _410 => _410.length])) data += ` data-vector-stroke-dasharray="${node.strokeDasharray.map(num3).join(" ")}"`;
11305
11463
  }
11306
11464
  lines.push(`${indent(depth)}<g${common(node)}${data}>`);
11307
11465
  lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
@@ -11482,7 +11640,7 @@ function readStyle(el, parent, cssRules) {
11482
11640
  const { mixBlendMode: _m, filter: _f, ...inherited } = parent;
11483
11641
  const out = { ...inherited };
11484
11642
  for (const [attr, key] of Object.entries(STYLE_KEYS)) if (el.attrs[attr] !== void 0) out[key] = el.attrs[attr].trim();
11485
- if (_optionalChain([cssRules, 'optionalAccess', _380 => _380.length])) {
11643
+ if (_optionalChain([cssRules, 'optionalAccess', _411 => _411.length])) {
11486
11644
  for (const rule of cssRules) {
11487
11645
  if (matchesSelector(el, rule.selector)) {
11488
11646
  for (const [prop, val] of Object.entries(rule.properties)) {
@@ -11538,7 +11696,7 @@ function attrOrStyle(el, name) {
11538
11696
  return el.attrs[name];
11539
11697
  }
11540
11698
  function urlId(value) {
11541
- return _nullishCoalesce(_optionalChain([/^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/, 'access', _381 => _381.exec, 'call', _382 => _382((_nullishCoalesce(value, () => ( ""))).trim()), 'optionalAccess', _383 => _383[1]]), () => ( null));
11699
+ return _nullishCoalesce(_optionalChain([/^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/, 'access', _412 => _412.exec, 'call', _413 => _413((_nullishCoalesce(value, () => ( ""))).trim()), 'optionalAccess', _414 => _414[1]]), () => ( null));
11542
11700
  }
11543
11701
  function clipRulesAsFillRules(el) {
11544
11702
  const attrs = { ...el.attrs };
@@ -11603,9 +11761,9 @@ function resolveGradient(id, raw) {
11603
11761
  for (let el = first; el && !chain.includes(el) && chain.length < 32; ) {
11604
11762
  chain.push(el);
11605
11763
  const href = _nullishCoalesce(el.attrs.href, () => ( el.attrs["xlink:href"]));
11606
- el = _optionalChain([href, 'optionalAccess', _384 => _384.startsWith, 'call', _385 => _385("#")]) ? raw.get(href.slice(1)) : void 0;
11764
+ el = _optionalChain([href, 'optionalAccess', _415 => _415.startsWith, 'call', _416 => _416("#")]) ? raw.get(href.slice(1)) : void 0;
11607
11765
  }
11608
- const attr = (name) => _optionalChain([chain, 'access', _386 => _386.find, 'call', _387 => _387((el) => el.attrs[name] !== void 0), 'optionalAccess', _388 => _388.attrs, 'access', _389 => _389[name]]);
11766
+ const attr = (name) => _optionalChain([chain, 'access', _417 => _417.find, 'call', _418 => _418((el) => el.attrs[name] !== void 0), 'optionalAccess', _419 => _419.attrs, 'access', _420 => _420[name]]);
11609
11767
  const stops = _nullishCoalesce(chain.map(readStops).find((s) => s.length), () => ( []));
11610
11768
  if (!stops.length) return null;
11611
11769
  const user = attr("gradientUnits") === "userSpaceOnUse";
@@ -11777,7 +11935,7 @@ function parseVectorSvg(svg, options = {}) {
11777
11935
  const stackedPath = (g, _style, m, meta) => {
11778
11936
  const fillEl = g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === "fill");
11779
11937
  const subpaths = fillEl ? shapeOf(fillEl) : null;
11780
- if (!_optionalChain([subpaths, 'optionalAccess', _390 => _390.length])) return null;
11938
+ if (!_optionalChain([subpaths, 'optionalAccess', _421 => _421.length])) return null;
11781
11939
  const parse = (v2) => {
11782
11940
  try {
11783
11941
  return v2 ? JSON.parse(v2) : [];
@@ -11796,7 +11954,7 @@ function parseVectorSvg(svg, options = {}) {
11796
11954
  const key = (n) => JSON.stringify([n.subpaths, _nullishCoalesce(n.transform, () => ( null)), _nullishCoalesce(n.opacity, () => ( 1)), n.visible !== false, _nullishCoalesce(n.filters, () => ( null)), _nullishCoalesce(n.blendMode, () => ( "normal")), _nullishCoalesce(n.fillRule, () => ( "nonzero")), _nullishCoalesce(n.booleanOperation, () => ( null))]);
11797
11955
  for (const n of nodes2) {
11798
11956
  const prev = out[out.length - 1];
11799
- if (_optionalChain([prev, 'optionalAccess', _391 => _391.type]) === "path" && n.type === "path" && key(prev) === key(n)) {
11957
+ if (_optionalChain([prev, 'optionalAccess', _422 => _422.type]) === "path" && n.type === "path" && key(prev) === key(n)) {
11800
11958
  const fills = vectorFills(n);
11801
11959
  const strokesBefore = vectorStrokes(prev);
11802
11960
  if (!(fills.length && strokesBefore.length)) {
@@ -11814,7 +11972,7 @@ function parseVectorSvg(svg, options = {}) {
11814
11972
  const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
11815
11973
  const fillEl = part("fill");
11816
11974
  const subpaths = fillEl ? shapeOf(fillEl) : null;
11817
- if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _392 => _392.length])) return null;
11975
+ if (!fillEl || !_optionalChain([subpaths, 'optionalAccess', _423 => _423.length])) return null;
11818
11976
  const a = g.attrs;
11819
11977
  const fs = readStyle(fillEl, style, styleRules);
11820
11978
  const strokeEl = part("stroke");
@@ -11851,7 +12009,7 @@ function parseVectorSvg(svg, options = {}) {
11851
12009
  ...profile.length ? { strokeWidthProfile: profile } : {},
11852
12010
  ...keptCap ? { strokeLinecap: keptCap } : {},
11853
12011
  ...keptJoin ? { strokeLinejoin: keptJoin } : {},
11854
- ..._optionalChain([keptDash, 'optionalAccess', _393 => _393.length]) ? { strokeDasharray: keptDash } : {}
12012
+ ..._optionalChain([keptDash, 'optionalAccess', _424 => _424.length]) ? { strokeDasharray: keptDash } : {}
11855
12013
  };
11856
12014
  return placed(node, m);
11857
12015
  };
@@ -11916,8 +12074,8 @@ function parseVectorSvg(svg, options = {}) {
11916
12074
  } else {
11917
12075
  const fill = json2(g.attrs["data-vector-fill"]);
11918
12076
  const stroke = json2(g.attrs["data-vector-stroke"]);
11919
- node.fill = fill == null ? null : _nullishCoalesce(_optionalChain([sanitizeVectorFills, 'call', _394 => _394([{ paint: fill }]), 'access', _395 => _395[0], 'optionalAccess', _396 => _396.paint]), () => ( null));
11920
- node.stroke = stroke == null ? null : _nullishCoalesce(_optionalChain([sanitizeVectorFills, 'call', _397 => _397([{ paint: stroke }]), 'access', _398 => _398[0], 'optionalAccess', _399 => _399.paint]), () => ( null));
12077
+ node.fill = fill == null ? null : _nullishCoalesce(_optionalChain([sanitizeVectorFills, 'call', _425 => _425([{ paint: fill }]), 'access', _426 => _426[0], 'optionalAccess', _427 => _427.paint]), () => ( null));
12078
+ node.stroke = stroke == null ? null : _nullishCoalesce(_optionalChain([sanitizeVectorFills, 'call', _428 => _428([{ paint: stroke }]), 'access', _429 => _429[0], 'optionalAccess', _430 => _430.paint]), () => ( null));
11921
12079
  const settings = json2(g.attrs["data-vector-stroke-settings"]);
11922
12080
  if (settings && typeof settings === "object") {
11923
12081
  const strokes = sanitizeVectorStrokes([{ paint: _nullishCoalesce(node.stroke, () => ( "#000")), ...settings }]);
@@ -11953,8 +12111,8 @@ function parseVectorSvg(svg, options = {}) {
11953
12111
  const anchor = attrOrStyle(el, "text-anchor");
11954
12112
  const first0 = (v2) => _nullishCoalesce(numberList(v2)[0], () => ( 0));
11955
12113
  const tspan = el.children.find((c) => c.name === "tspan");
11956
- const x = el.attrs.x !== void 0 ? first0(el.attrs.x) : first0(_optionalChain([tspan, 'optionalAccess', _400 => _400.attrs, 'access', _401 => _401.x]));
11957
- const y = el.attrs.y !== void 0 ? first0(el.attrs.y) : first0(_optionalChain([tspan, 'optionalAccess', _402 => _402.attrs, 'access', _403 => _403.y]));
12114
+ const x = el.attrs.x !== void 0 ? first0(el.attrs.x) : first0(_optionalChain([tspan, 'optionalAccess', _431 => _431.attrs, 'access', _432 => _432.x]));
12115
+ const y = el.attrs.y !== void 0 ? first0(el.attrs.y) : first0(_optionalChain([tspan, 'optionalAccess', _433 => _433.attrs, 'access', _434 => _434.y]));
11958
12116
  const fillValue = _nullishCoalesce(attrOrStyle(el, "fill"), () => ( style.fill));
11959
12117
  let node = {
11960
12118
  id: idFor(el),
@@ -11985,12 +12143,12 @@ function parseVectorSvg(svg, options = {}) {
11985
12143
  if (symbolOfElement.has(el)) return symbolOfElement.get(el);
11986
12144
  symbolOfElement.set(el, null);
11987
12145
  const own = json2(el.attrs["data-vector-symbol"]);
11988
- let id = typeof _optionalChain([own, 'optionalAccess', _404 => _404.id]) === "string" && own.id ? own.id : _nullishCoalesce(el.attrs.id, () => ( createId()));
12146
+ let id = typeof _optionalChain([own, 'optionalAccess', _435 => _435.id]) === "string" && own.id ? own.id : _nullishCoalesce(el.attrs.id, () => ( createId()));
11989
12147
  while (usedSymbolIds.has(id)) id = `${id}-${usedSymbolIds.size}`;
11990
12148
  usedSymbolIds.add(id);
11991
12149
  const style = readStyle(el, rootStyle, styleRules);
11992
12150
  const nodes2 = el.name === "symbol" ? visit2(el, style, IDENTITY_MATRIX) : visitOne({ ...el, attrs: { ...el.attrs, transform: "" } }, rootStyle, parseSvgTransform(el.attrs.transform));
11993
- symbols.push({ id, name: typeof _optionalChain([own, 'optionalAccess', _405 => _405.name]) === "string" && own.name ? own.name : _nullishCoalesce(el.attrs.id, () => ( "Symbol")), nodes: nodes2 });
12151
+ symbols.push({ id, name: typeof _optionalChain([own, 'optionalAccess', _436 => _436.name]) === "string" && own.name ? own.name : _nullishCoalesce(el.attrs.id, () => ( "Symbol")), nodes: nodes2 });
11994
12152
  symbolOfElement.set(el, id);
11995
12153
  return id;
11996
12154
  };
@@ -12002,13 +12160,13 @@ function parseVectorSvg(svg, options = {}) {
12002
12160
  if (!symbolId) return null;
12003
12161
  const own = json2(el.attrs["data-vector-instance"]);
12004
12162
  const place3 = multiplyMatrices(translateMatrix(length(el.attrs.x), length(el.attrs.y)), m);
12005
- const node = { id: idFor(el), type: "instance", ...meta, symbolId, ..._optionalChain([own, 'optionalAccess', _406 => _406.scaleStrokes]) === false ? { scaleStrokes: false } : {}, ..._optionalChain([own, 'optionalAccess', _407 => _407.overrides]) ? { overrides: own.overrides } : {} };
12163
+ const node = { id: idFor(el), type: "instance", ...meta, symbolId, ..._optionalChain([own, 'optionalAccess', _437 => _437.scaleStrokes]) === false ? { scaleStrokes: false } : {}, ..._optionalChain([own, 'optionalAccess', _438 => _438.overrides]) ? { overrides: own.overrides } : {} };
12006
12164
  return isIdentityMatrix(place3) ? node : { ...node, transform: place3 };
12007
12165
  };
12008
12166
  const ownInstance = (g, m, meta) => {
12009
12167
  const raw = json2(g.attrs["data-vector-instance"]);
12010
12168
  if (!raw || typeof raw.symbolId !== "string") return null;
12011
- const sym2 = [...byId.values()].find((e) => e.name === "symbol" && _optionalChain([json2, 'call', _408 => _408(e.attrs["data-vector-symbol"]), 'optionalAccess', _409 => _409.id]) === raw.symbolId);
12169
+ const sym2 = [...byId.values()].find((e) => e.name === "symbol" && _optionalChain([json2, 'call', _439 => _439(e.attrs["data-vector-symbol"]), 'optionalAccess', _440 => _440.id]) === raw.symbolId);
12012
12170
  const symbolId = sym2 ? symbolFor(sym2) : raw.symbolId;
12013
12171
  if (!symbolId) return null;
12014
12172
  const t = Array.isArray(raw.transform) && raw.transform.length === 6 && raw.transform.every(Number.isFinite) ? raw.transform : IDENTITY_MATRIX;
@@ -12016,7 +12174,7 @@ function parseVectorSvg(svg, options = {}) {
12016
12174
  const drawn = g.children.find((c) => c.name === "g");
12017
12175
  const effects = sanitizeVectorEffects(raw.effects);
12018
12176
  const node = {
12019
- id: _nullishCoalesce(_optionalChain([drawn, 'optionalAccess', _410 => _410.attrs, 'access', _411 => _411.id]), () => ( idFor(g))),
12177
+ id: _nullishCoalesce(_optionalChain([drawn, 'optionalAccess', _441 => _441.attrs, 'access', _442 => _442.id]), () => ( idFor(g))),
12020
12178
  type: "instance",
12021
12179
  ...meta,
12022
12180
  symbolId,
@@ -12073,12 +12231,12 @@ function parseVectorSvg(svg, options = {}) {
12073
12231
  const masked = (el, nodes2, m) => {
12074
12232
  let out = nodes2;
12075
12233
  const clipEl = rawMasks.get(_nullishCoalesce(urlId(attrOrStyle(el, "clip-path")), () => ( "")));
12076
- if (_optionalChain([clipEl, 'optionalAccess', _412 => _412.name]) === "clipPath") {
12234
+ if (_optionalChain([clipEl, 'optionalAccess', _443 => _443.name]) === "clipPath") {
12077
12235
  const source = maskNode(clipEl, m, out, clipEl.attrs.clipPathUnits);
12078
12236
  if (source) out = [{ id: idFor({ name: "g", attrs: {}, children: [] }), type: "group", name: "Clip Group", mask: { type: "clip" }, children: [source, ...out] }];
12079
12237
  }
12080
12238
  const maskEl = rawMasks.get(_nullishCoalesce(urlId(attrOrStyle(el, "mask")), () => ( "")));
12081
- if (_optionalChain([maskEl, 'optionalAccess', _413 => _413.name]) === "mask") {
12239
+ if (_optionalChain([maskEl, 'optionalAccess', _444 => _444.name]) === "mask") {
12082
12240
  const source = maskNode(maskEl, m, out, maskEl.attrs.maskContentUnits);
12083
12241
  const type = attrOrStyle(maskEl, "mask-type") === "alpha" ? "alpha" : "luminance";
12084
12242
  if (source) out = [{ id: idFor({ name: "g", attrs: {}, children: [] }), type: "group", name: "Opacity Mask", mask: { type }, children: [source, ...out] }];
@@ -12100,19 +12258,19 @@ function parseVectorSvg(svg, options = {}) {
12100
12258
  let sourceEl = part("mask-source");
12101
12259
  if (!sourceEl) {
12102
12260
  const el = rawMasks.get(_nullishCoalesce(urlId(maskedEl.attrs.mask), () => ( "")));
12103
- const invert2 = _optionalChain([el, 'optionalAccess', _414 => _414.children, 'access', _415 => _415.find, 'call', _416 => _416((c) => c.name === "g" && c.attrs["data-vector-part"] === "mask-invert")]);
12261
+ const invert2 = _optionalChain([el, 'optionalAccess', _445 => _445.children, 'access', _446 => _446.find, 'call', _447 => _447((c) => c.name === "g" && c.attrs["data-vector-part"] === "mask-invert")]);
12104
12262
  sourceEl = _nullishCoalesce(invert2, () => ( el));
12105
12263
  }
12106
12264
  const source = sourceEl ? visit2(sourceEl, style, m)[0] : void 0;
12107
12265
  let contents = visit2(maskedEl, style, m);
12108
12266
  let effects;
12109
12267
  const wrapper = contents.length === 1 && contents[0].type === "group" && contents[0].id === `${id}~content` ? contents[0] : null;
12110
- if (_optionalChain([wrapper, 'optionalAccess', _417 => _417.type]) === "group") {
12268
+ if (_optionalChain([wrapper, 'optionalAccess', _448 => _448.type]) === "group") {
12111
12269
  effects = _nullishCoalesce(wrapper.effects, () => ( void 0));
12112
12270
  contents = wrapper.children;
12113
12271
  }
12114
12272
  if (!source) return contents.length ? { id, type: "group", ...meta, children: contents } : null;
12115
- return { id, type: "group", ...meta, mask, ..._optionalChain([effects, 'optionalAccess', _418 => _418.length]) ? { effects } : {}, children: [source, ...contents] };
12273
+ return { id, type: "group", ...meta, mask, ..._optionalChain([effects, 'optionalAccess', _449 => _449.length]) ? { effects } : {}, children: [source, ...contents] };
12116
12274
  };
12117
12275
  const frameGroup = (g, style, m, meta) => {
12118
12276
  const raw = parseJson(g.attrs["data-vector-frame"]);
@@ -12124,7 +12282,7 @@ function parseVectorSvg(svg, options = {}) {
12124
12282
  const { rigid, residual } = decomposeRigid(m);
12125
12283
  const r = _chunkGF2RBSDMcjs.bezierPathBounds.call(void 0, _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, subpathsToBezier(vectorFrameRectPath(frame)), residual));
12126
12284
  const back = invertMatrix(rigid);
12127
- const effects = sanitizeVectorEffects(_optionalChain([raw, 'optionalAccess', _419 => _419.effects]));
12285
+ const effects = sanitizeVectorEffects(_optionalChain([raw, 'optionalAccess', _450 => _450.effects]));
12128
12286
  return {
12129
12287
  id,
12130
12288
  type: "group",
@@ -12596,13 +12754,13 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX, opt
12596
12754
  }
12597
12755
  if (isVectorMaskGroup(node)) {
12598
12756
  const m = multiplyMatrices(nodeMatrix(node), parent);
12599
- const entered = !!_optionalChain([options, 'access', _420 => _420.entered, 'optionalAccess', _421 => _421.has, 'call', _422 => _422(node.id)]);
12757
+ const entered = !!_optionalChain([options, 'access', _451 => _451.entered, 'optionalAccess', _452 => _452.has, 'call', _453 => _453(node.id)]);
12600
12758
  if (!entered && isVectorMaskActive(node) && !vectorMaskContains(node, applyMatrix(invertMatrix(m), p), tolerance)) return false;
12601
12759
  const shown = !entered && hasOwnVectorAppearance(node) ? expandVectorAppearance(node).children : node.children;
12602
12760
  for (let i = shown.length - 1; i >= 1; i--) if (hitTestVectorNode(shown[i], p, tolerance, m, options)) return true;
12603
12761
  return entered && hitTestVectorMaskSource(node, p, tolerance, m, options);
12604
12762
  }
12605
- if (!(node.type === "group" && (!hasOwnVectorAppearance(node) || _optionalChain([options, 'access', _423 => _423.entered, 'optionalAccess', _424 => _424.has, 'call', _425 => _425(node.id)])))) node = expandVectorAppearance(node);
12763
+ if (!(node.type === "group" && (!hasOwnVectorAppearance(node) || _optionalChain([options, 'access', _454 => _454.entered, 'optionalAccess', _455 => _455.has, 'call', _456 => _456(node.id)])))) node = expandVectorAppearance(node);
12606
12764
  if (node.type === "group") {
12607
12765
  const m = multiplyMatrices(nodeMatrix(node), parent);
12608
12766
  return node.children.some((c) => hitTestVectorNode(c, p, tolerance, m, options));
@@ -12614,7 +12772,7 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX, opt
12614
12772
  function hitTestVectorMaskSource(group, p, tolerance, m, options) {
12615
12773
  const source = group.children[0];
12616
12774
  if (source.visible === false) return false;
12617
- if (_optionalChain([group, 'access', _426 => _426.mask, 'optionalAccess', _427 => _427.type]) !== "clip") return hitTestVectorNode(source, p, tolerance, m, options);
12775
+ if (_optionalChain([group, 'access', _457 => _457.mask, 'optionalAccess', _458 => _458.type]) !== "clip") return hitTestVectorNode(source, p, tolerance, m, options);
12618
12776
  const paths = collectPathNodes(source).filter((n) => n.visible !== false);
12619
12777
  const pt2 = [p.x, p.y];
12620
12778
  return paths.some((n) => {
@@ -12663,24 +12821,24 @@ function mapAnchor(a, m) {
12663
12821
  }
12664
12822
  function bakeIntoGeometry(node, m) {
12665
12823
  if (isIdentityMatrix(m)) return node;
12666
- if (_optionalChain([node, 'access', _428 => _428.effects, 'optionalAccess', _429 => _429.length])) node = { ...node, effects: transformVectorEffects(node.effects, m, node) };
12824
+ if (_optionalChain([node, 'access', _459 => _459.effects, 'optionalAccess', _460 => _460.length])) node = { ...node, effects: transformVectorEffects(node.effects, m, node) };
12667
12825
  if (isVectorFrame(node)) return bakeFrame(node, m);
12668
12826
  if (node.type === "group") {
12669
12827
  const group = node;
12670
12828
  const children = group.children.map((c) => transformVectorNode(c, m));
12671
12829
  const sym2 = group.symmetry ? { symmetry: transformVectorSymmetry(group.symmetry, m) } : {};
12672
- const spine = _optionalChain([group, 'access', _430 => _430.blend, 'optionalAccess', _431 => _431.spine]);
12830
+ const spine = _optionalChain([group, 'access', _461 => _461.blend, 'optionalAccess', _462 => _462.spine]);
12673
12831
  if (!spine) return { ...group, ...sym2, children };
12674
12832
  const moved = { closed: spine.closed, anchors: spine.anchors.map((a) => mapAnchor(a, m)) };
12675
12833
  return { ...group, children, blend: { ...group.blend, spine: moved } };
12676
12834
  }
12677
12835
  const path = node.type === "text" ? bakeVectorTextGeometry(node, m) : node;
12678
12836
  const flips = m[0] * m[3] - m[1] * m[2] < 0;
12679
- const mirrored = flips && _optionalChain([path, 'access', _432 => _432.strokeWidthProfile, 'optionalAccess', _433 => _433.length]);
12837
+ const mirrored = flips && _optionalChain([path, 'access', _463 => _463.strokeWidthProfile, 'optionalAccess', _464 => _464.length]);
12680
12838
  const layer = (l) => ({
12681
12839
  ...l,
12682
12840
  ...isVectorGradient(l.paint) || isVectorShadedPaint(l.paint) ? { paint: transformVectorPaint(l.paint, m) } : {},
12683
- ...flips && _optionalChain([l, 'access', _434 => _434.strokeWidthProfile, 'optionalAccess', _435 => _435.length]) ? { strokeWidthProfile: mirrorWidthProfile(l.strokeWidthProfile) } : {}
12841
+ ...flips && _optionalChain([l, 'access', _465 => _465.strokeWidthProfile, 'optionalAccess', _466 => _466.length]) ? { strokeWidthProfile: mirrorWidthProfile(l.strokeWidthProfile) } : {}
12684
12842
  });
12685
12843
  return {
12686
12844
  ...path,
@@ -12915,7 +13073,7 @@ function roundSubpaths(subpaths, precision = 3) {
12915
13073
 
12916
13074
  // src/vector/symmetry.ts
12917
13075
  function isVectorSymmetryGroup(node) {
12918
- return _optionalChain([node, 'optionalAccess', _436 => _436.type]) === "group" && !!node.symmetry && !node.blend && !node.liveBoolean && !node.mask && !node.frame;
13076
+ return _optionalChain([node, 'optionalAccess', _467 => _467.type]) === "group" && !!node.symmetry && !node.blend && !node.liveBoolean && !node.mask && !node.frame;
12919
13077
  }
12920
13078
  var rad = (deg) => deg * Math.PI / 180;
12921
13079
  var exact = (v2) => Math.abs(v2) < 1e-12 ? 0 : v2;