@pixerate/editor 0.243.0 → 0.244.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 (62) hide show
  1. package/dist/animation-editor/index.cjs +59 -59
  2. package/dist/animation-editor/index.js +3 -3
  3. package/dist/{brushstrokeRender-274HGNZR.js → brushstrokeRender-4542T5HP.js} +2 -2
  4. package/dist/{brushstrokeRender-C7RJZPMC.cjs → brushstrokeRender-QA5WVIDT.cjs} +5 -5
  5. package/dist/canvas/index.cjs +8 -8
  6. package/dist/canvas/index.js +1 -1
  7. package/dist/{chunk-6L3WWIDW.js → chunk-4EQY4TZJ.js} +1 -1
  8. package/dist/{chunk-5FZS7J7C.cjs → chunk-4T47Z4J3.cjs} +18 -2
  9. package/dist/{chunk-4ZHXLFXS.js → chunk-5RFENYO5.js} +1 -1
  10. package/dist/{chunk-SRXWDOUI.js → chunk-7YQNKSQ7.js} +1 -1
  11. package/dist/{chunk-OONFIFEU.cjs → chunk-BDIH4DYR.cjs} +23 -23
  12. package/dist/{chunk-KK2FWMA2.cjs → chunk-HZ547SGQ.cjs} +1 -1
  13. package/dist/{chunk-3WOZEBXZ.cjs → chunk-IZL5V5RK.cjs} +2 -2
  14. package/dist/{chunk-IXI5KATU.js → chunk-L5PB7EG3.js} +1 -1
  15. package/dist/{chunk-R2FVAKFH.cjs → chunk-M6JORA5Z.cjs} +86 -86
  16. package/dist/{chunk-H4Z72Z4Z.js → chunk-OSTKS3YN.js} +1 -1
  17. package/dist/{chunk-HLBTRSQJ.js → chunk-P3NIPIKS.js} +263 -63
  18. package/dist/{chunk-UV7OOZJQ.cjs → chunk-SD23XMVJ.cjs} +35 -35
  19. package/dist/{chunk-HQZHOPNE.js → chunk-TBJEMELS.js} +18 -2
  20. package/dist/{chunk-XFYLA3ZO.cjs → chunk-VMROIWLL.cjs} +290 -90
  21. package/dist/image-editor/index.cjs +785 -777
  22. package/dist/image-editor/index.js +13 -5
  23. package/dist/kernel-wasm-4KVONDAU.js +9 -0
  24. package/dist/kernel-wasm-TTYRBGAK.cjs +9 -0
  25. package/dist/paint/index.cjs +10 -2
  26. package/dist/paint/index.js +9 -1
  27. package/dist/paint/wet/film.d.cts +19 -1
  28. package/dist/paint/wet/film.d.ts +19 -1
  29. package/dist/paint/wet/gpu-kernels.d.cts +2 -2
  30. package/dist/paint/wet/gpu-kernels.d.ts +2 -2
  31. package/dist/paint/wet/kernel-wasm.d.cts +5 -5
  32. package/dist/paint/wet/kernel-wasm.d.ts +5 -5
  33. package/dist/paint/wet/kernel.d.cts +1 -1
  34. package/dist/paint/wet/kernel.d.ts +1 -1
  35. package/dist/paint/wet/medium.d.cts +3 -1
  36. package/dist/paint/wet/medium.d.ts +3 -1
  37. package/dist/paint/wet/model.d.cts +19 -4
  38. package/dist/paint/wet/model.d.ts +19 -4
  39. package/dist/paint/wet/world.d.cts +34 -8
  40. package/dist/paint/wet/world.d.ts +34 -8
  41. package/dist/paint-editor/backlight.d.cts +77 -0
  42. package/dist/paint-editor/backlight.d.ts +77 -0
  43. package/dist/paint-editor/controller.d.cts +11 -0
  44. package/dist/paint-editor/controller.d.ts +11 -0
  45. package/dist/paint-editor/index.cjs +685 -397
  46. package/dist/paint-editor/index.d.cts +1 -0
  47. package/dist/paint-editor/index.d.ts +1 -0
  48. package/dist/paint-editor/index.js +308 -20
  49. package/dist/paint-editor/paper.d.cts +7 -0
  50. package/dist/paint-editor/paper.d.ts +7 -0
  51. package/dist/paint-editor/wet.d.cts +9 -0
  52. package/dist/paint-editor/wet.d.ts +9 -0
  53. package/dist/vector/index.cjs +962 -962
  54. package/dist/vector/index.js +4 -4
  55. package/package.json +1 -1
  56. package/skills/pixerate-paint-editor/SKILL.md +3 -3
  57. package/skills/pixerate-paint-editor/references/light-paint.md +24 -7
  58. package/skills/pixerate-paint-watercolour/SKILL.md +10 -1
  59. package/skills/pixerate-paint-watercolour/evals/glowing-wash.json +22 -0
  60. package/skills/pixerate-paint-watercolour/evals/stained-glass.json +16 -0
  61. package/dist/kernel-wasm-6FPOLVUZ.cjs +0 -9
  62. package/dist/kernel-wasm-WIMMJUF2.js +0 -9
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14;
2
2
 
3
3
  var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
4
4
 
@@ -7,7 +7,7 @@ var _chunkXNZFVYC2cjs = require('../chunk-XNZFVYC2.cjs');
7
7
 
8
8
 
9
9
 
10
- var _chunkR2FVAKFHcjs = require('../chunk-R2FVAKFH.cjs');
10
+ var _chunkM6JORA5Zcjs = require('../chunk-M6JORA5Z.cjs');
11
11
  require('../chunk-A2IS7EHE.cjs');
12
12
  require('../chunk-SS53NNZO.cjs');
13
13
 
@@ -44,7 +44,7 @@ require('../chunk-K6PXS6DO.cjs');
44
44
 
45
45
 
46
46
 
47
- var _chunkXFYLA3ZOcjs = require('../chunk-XFYLA3ZO.cjs');
47
+ var _chunkVMROIWLLcjs = require('../chunk-VMROIWLL.cjs');
48
48
  require('../chunk-BROJYMWU.cjs');
49
49
 
50
50
 
@@ -55,7 +55,7 @@ var _chunkJLWLX52Lcjs = require('../chunk-JLWLX52L.cjs');
55
55
 
56
56
 
57
57
  var _chunkK7ENM55Pcjs = require('../chunk-K7ENM55P.cjs');
58
- require('../chunk-3WOZEBXZ.cjs');
58
+ require('../chunk-IZL5V5RK.cjs');
59
59
 
60
60
 
61
61
 
@@ -133,7 +133,7 @@ require('../chunk-3WOZEBXZ.cjs');
133
133
 
134
134
 
135
135
 
136
- var _chunk5FZS7J7Ccjs = require('../chunk-5FZS7J7C.cjs');
136
+ var _chunk4T47Z4J3cjs = require('../chunk-4T47Z4J3.cjs');
137
137
  require('../chunk-CVFAAZXE.cjs');
138
138
  require('../chunk-GF2RBSDM.cjs');
139
139
  require('../chunk-NM3G4VQT.cjs');
@@ -295,7 +295,7 @@ function normalizeCanvas(raw) {
295
295
  function createPaintDocument(options = {}) {
296
296
  const canvas = normalizeCanvas({ width: _nullishCoalesce(options.width, () => ( 2048)), height: _nullishCoalesce(options.height, () => ( 1536)), dpi: options.dpi });
297
297
  const layer = createPaintLayer("Layer 1");
298
- return { canvas, paper: _chunk5FZS7J7Ccjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
298
+ return { canvas, paper: _chunk4T47Z4J3cjs.normalizePaper.call(void 0, _nullishCoalesce(options.paper, () => ( {}))), layers: [layer], activeLayerId: layer.id, strokes: [] };
299
299
  }
300
300
 
301
301
  // src/paint-editor/dab-stroke.ts
@@ -349,13 +349,13 @@ var PaintDabStroke = (_class = class {
349
349
  constructor(brush, options) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);
350
350
  this.brush = brush;
351
351
  this.options = options;
352
- this.smoother = new (0, _chunk5FZS7J7Ccjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
353
- this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunk5FZS7J7Ccjs.IDENTITY_COPY];
352
+ this.smoother = new (0, _chunk4T47Z4J3cjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
353
+ this.copies = _optionalChain([options, 'access', _2 => _2.copies, 'optionalAccess', _3 => _3.length]) ? options.copies : [_chunk4T47Z4J3cjs.IDENTITY_COPY];
354
354
  const exchanging = brush.engine === "mixer" || brush.engine === "dab";
355
355
  const rates = brush.engine === "mixer" ? _chunkPQ3H2AANcjs.mixerRates.call(void 0, brush.mixer) : _chunkPQ3H2AANcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, 1, brush.behavior.mixing);
356
356
  this.mixing = brush.engine === "mixer" ? brush.mixer.mixing : brush.behavior.mixing;
357
357
  this.states = this.copies.map((c, i) => ({
358
- walker: new (0, _chunk5FZS7J7Ccjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
358
+ walker: new (0, _chunk4T47Z4J3cjs.PenDabWalker)(brush, (_nullishCoalesce(options.seed, () => ( 0))) + i * 7919 | 0, c.linear),
359
359
  exchange: exchanging ? new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, options.load) : null,
360
360
  smudge: brush.engine === "smudge" ? new (0, _chunkPQ3H2AANcjs.SmudgeTip)(brush.smudge, brush.tip.size * (1 + brush.dynamics.tiltSize * 1.5)) : null
361
361
  }));
@@ -468,7 +468,7 @@ var PaintDabStroke = (_class = class {
468
468
  let flow = 1;
469
469
  if (this.options.effect) {
470
470
  const rgb = [0, 0, 0];
471
- flow = _chunk5FZS7J7Ccjs.sampleEffectAt.call(void 0, this.options.effect, d.x, d.y, rgb, d);
471
+ flow = _chunk4T47Z4J3cjs.sampleEffectAt.call(void 0, this.options.effect, d.x, d.y, rgb, d);
472
472
  ex.setReservoirColor(rgb[0], rgb[1], rgb[2]);
473
473
  } else if (this.sampler && !this.gradient) {
474
474
  const g = this.sampler.dab(d, this.sample);
@@ -636,10 +636,10 @@ function lightTile(color, height, heightAround, material, light) {
636
636
  const nh = Math.max(0, nx * hx + ny * hy + nz * hz);
637
637
  const spec = Math.max(0, Math.pow(nh, shininess) - Math.pow(hz, shininess)) * (0.25 + 0.75 * gloss) * light.relief;
638
638
  for (let c = 0; c < 3; c++) {
639
- const a = _chunkXFYLA3ZOcjs.SRGB_TO_LINEAR[color[i + c]];
639
+ const a = _chunkVMROIWLLcjs.SRGB_TO_LINEAR[color[i + c]];
640
640
  const tint = metal * a + (1 - metal);
641
641
  const v = a * shade * (1 - 0.35 * metal) + spec * tint * (1 + metal);
642
- out[i + c] = _chunkXFYLA3ZOcjs.linearToSrgb8.call(void 0, v);
642
+ out[i + c] = _chunkVMROIWLLcjs.linearToSrgb8.call(void 0, v);
643
643
  }
644
644
  }
645
645
  }
@@ -699,12 +699,12 @@ var ThickStrokeDriver = (_class3 = class {
699
699
  constructor(init) {;_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);
700
700
  this.init = init;
701
701
  const b = init.brush;
702
- this.smoother = new (0, _chunk5FZS7J7Ccjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
703
- const copies = init.copies.length ? init.copies : [_chunk5FZS7J7Ccjs.IDENTITY_COPY];
702
+ this.smoother = new (0, _chunk4T47Z4J3cjs.PenSmoother)(b.tip.smoothing, b.pressureSmoothing);
703
+ const copies = init.copies.length ? init.copies : [_chunk4T47Z4J3cjs.IDENTITY_COPY];
704
704
  this.copies = copies;
705
705
  const rates = _chunkPQ3H2AANcjs.exchangeRates.call(void 0, b.behavior.pickup, b.behavior.mix, 1, b.behavior.mixing);
706
706
  this.states = copies.map((c, i) => ({
707
- walker: new (0, _chunk5FZS7J7Ccjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
707
+ walker: new (0, _chunk4T47Z4J3cjs.PenDabWalker)(b, init.seed + i * 7919 | 0, c.linear),
708
708
  exchange: new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, init.load),
709
709
  smudge: b.impasto.tool === "knife" ? new (0, _chunkPQ3H2AANcjs.SmudgeTip)({ strength: 0.85, length: 0.6 + 0.38 * b.impasto.drag, mixing: b.behavior.mixing }, b.tip.size * 1.2) : null,
710
710
  carried: null,
@@ -850,7 +850,7 @@ var ThickStrokeDriver = (_class3 = class {
850
850
  let flow = 1;
851
851
  const effect = this.init.effect;
852
852
  if (effect) {
853
- _chunk5FZS7J7Ccjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
853
+ _chunk4T47Z4J3cjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
854
854
  ex.setReservoirColor(this.centre[0], this.centre[1], this.centre[2]);
855
855
  } else if (this.sampler) {
856
856
  const g = this.sampler.dab(d, this.sample);
@@ -867,7 +867,7 @@ var ThickStrokeDriver = (_class3 = class {
867
867
  let field = null;
868
868
  if (effect) {
869
869
  field = new Float32Array(n * 3);
870
- _chunk5FZS7J7Ccjs.effectDabField.call(void 0, effect, rect, cov, this.centre, this.paint, field, 0, d);
870
+ _chunk4T47Z4J3cjs.effectDabField.call(void 0, effect, rect, cov, this.centre, this.paint, field, 0, d);
871
871
  }
872
872
  this.medium.deposit(rect, cov, dep, this.paint, ex.paintPigment, field);
873
873
  }
@@ -1044,7 +1044,7 @@ function shadowToLight(shadow) {
1044
1044
  return new (0, _chunk474IQG74cjs.TiledSurface)(1, tiles, 0);
1045
1045
  }
1046
1046
  function lightTwinBrush(brush) {
1047
- return _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0,
1047
+ return _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0,
1048
1048
  {
1049
1049
  tip: { ...brush.tip, blend: "normal", pressureOpacity: brush.tip.pressureOpacity || brush.light.pressure },
1050
1050
  behavior: { ...brush.behavior, mixing: "rgb" },
@@ -1274,7 +1274,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1274
1274
  this.layerId = init.layerId;
1275
1275
  this.base = init.surface;
1276
1276
  this.live = new Map(this.base.tiles);
1277
- this.copies = init.copies.length ? init.copies : [_chunk5FZS7J7Ccjs.IDENTITY_COPY];
1277
+ this.copies = init.copies.length ? init.copies : [_chunk4T47Z4J3cjs.IDENTITY_COPY];
1278
1278
  const brush = init.brush;
1279
1279
  if (init.wet) this.wetDriver = init.wet.driver;
1280
1280
  if (init.light && !init.wet && !init.sticker) this.lightTwin = this.makeLightTwin(init.light.surface);
@@ -1291,11 +1291,11 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1291
1291
  };
1292
1292
  if (this.wetDriver) {
1293
1293
  } else if (init.sticker) {
1294
- this.stickerSpray = new (0, _chunk5FZS7J7Ccjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)), effect });
1294
+ this.stickerSpray = new (0, _chunk4T47Z4J3cjs.StickerSpray)({ brush, target: this.tileTarget(), color: init.colorHex, seed: init.seed, copies: this.copies, nextId: init.sticker.nextId, paint: _nullishCoalesce(init.paint, () => ( null)), effect });
1295
1295
  } else if (init.thick) {
1296
1296
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
1297
1297
  this.thickDriver = new ThickStrokeDriver({ brush, target: this.tileTarget(), channels: init.thick.channels, color: rgb(init.color), load: init.mixerLoad, seed: init.seed, copies: this.copies, paint: _nullishCoalesce(init.paint, () => ( null)), effect });
1298
- } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunk5FZS7J7Ccjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
1298
+ } else if (brush.engine === "mixer" || brush.engine === "blender" || brush.engine === "smudge" || _chunk4T47Z4J3cjs.usesPaintExchange.call(void 0, brush, Boolean(init.paint))) {
1299
1299
  const rgb = (c) => [c[0] / 255, c[1] / 255, c[2] / 255];
1300
1300
  this.wet = new PaintDabStroke(brush, {
1301
1301
  target: this.tileTarget(),
@@ -1311,7 +1311,7 @@ var PaintStrokeSession = (_class5 = class _PaintStrokeSession {
1311
1311
  });
1312
1312
  } else {
1313
1313
  const opts = { grain: init.grain, paperDepth: init.paperDepth, seed: init.seed, copies: this.copies, paint: _nullishCoalesce(init.paint, () => ( null)), effect };
1314
- this.dry = brush.engine === "particle" ? new (0, _chunk5FZS7J7Ccjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunk5FZS7J7Ccjs.BristleStroke)(brush, opts) : new (0, _chunk5FZS7J7Ccjs.DryStroke)(brush, opts);
1314
+ this.dry = brush.engine === "particle" ? new (0, _chunk4T47Z4J3cjs.ParticleStroke)(brush, opts) : brush.engine === "bristle" ? new (0, _chunk4T47Z4J3cjs.BristleStroke)(brush, opts) : new (0, _chunk4T47Z4J3cjs.DryStroke)(brush, opts);
1315
1315
  }
1316
1316
  }
1317
1317
 
@@ -1532,7 +1532,7 @@ function brushLoadForStroke(brush, current, color) {
1532
1532
  if (brush.engine === "mixer") return mixerLoadForStroke(brush, current, color);
1533
1533
  if (brush.engine === "impasto") return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1534
1534
  if (brush.engine === "wet") return brush.wet.tool === "paint" ? { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null } : _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD;
1535
- if (_chunk5FZS7J7Ccjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1535
+ if (_chunk4T47Z4J3cjs.usesPaintExchange.call(void 0, brush)) return { reservoir: [color[0], color[1], color[2]], amount: 1, pickup: brush.behavior.dirty ? current.pickup : null };
1536
1536
  return _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD;
1537
1537
  }
1538
1538
 
@@ -1800,7 +1800,7 @@ function normalizeBrushStroke(raw) {
1800
1800
  const out = {
1801
1801
  id: r.id,
1802
1802
  layerId: r.layerId,
1803
- brush: _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1803
+ brush: _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, _nullishCoalesce(r.brush, () => ( {}))),
1804
1804
  color: typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : "#000000",
1805
1805
  points,
1806
1806
  seed: finite2(r.seed) ? r.seed | 0 : 0
@@ -1819,7 +1819,7 @@ function normalizeBrushStroke(raw) {
1819
1819
  }
1820
1820
  if (st.length) out.stencils = st;
1821
1821
  }
1822
- const effect = _chunk5FZS7J7Ccjs.readPaintEffectPaint.call(void 0, r.paint);
1822
+ const effect = _chunk4T47Z4J3cjs.readPaintEffectPaint.call(void 0, r.paint);
1823
1823
  const paint = effect ? null : _chunkPQ3H2AANcjs.readPaintSource.call(void 0, r.paint);
1824
1824
  if (effect) out.paint = effect;
1825
1825
  else if (paint && paint.type === "gradient") out.paint = paint;
@@ -1859,7 +1859,7 @@ function varyStroke(stroke, m, v) {
1859
1859
  if (ps !== 1) q.pressure = Math.min(1, Math.max(0, (_nullishCoalesce(p.pressure, () => ( 1))) * ps));
1860
1860
  return q;
1861
1861
  });
1862
- const brush = s !== 1 ? _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1862
+ const brush = s !== 1 ? _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...stroke.brush, tip: { ...stroke.brush.tip, size: stroke.brush.tip.size * s } }) : stroke.brush;
1863
1863
  const out = { ...stroke, brush, points };
1864
1864
  if (_optionalChain([stroke, 'access', _87 => _87.paint, 'optionalAccess', _88 => _88.type]) === "gradient" && s !== 1) out.paint = _chunkPQ3H2AANcjs.scalePaintGradient.call(void 0, stroke.paint, s);
1865
1865
  if (_optionalChain([stroke, 'access', _89 => _89.paint, 'optionalAccess', _90 => _90.type]) === "effect" && stroke.paint.map && s !== 1) out.paint = { ...stroke.paint, map: { ...stroke.paint.map, length: Math.min(4096, Math.max(16, Math.round(stroke.paint.map.length * s))) } };
@@ -1904,7 +1904,7 @@ function paperTile(paper, r, light) {
1904
1904
  const key = `${paperKey(paper, light)}|${r.x},${r.y},${r.width},${r.height}`;
1905
1905
  let t = tileCache.get(key);
1906
1906
  if (!t) {
1907
- t = _chunk5FZS7J7Ccjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1907
+ t = _chunk4T47Z4J3cjs.renderPaper.call(void 0, paper, r, paperGrain(paper), light);
1908
1908
  if (tileCache.size > 512) tileCache.delete(tileCache.keys().next().value);
1909
1909
  tileCache.set(key, t);
1910
1910
  }
@@ -2009,11 +2009,11 @@ function header(state, options) {
2009
2009
  return out;
2010
2010
  }
2011
2011
  function serializePaintDocument(state, options = {}) {
2012
- const { layers, assets } = _chunkR2FVAKFHcjs.serializeLayers.call(void 0, state.layers);
2012
+ const { layers, assets } = _chunkM6JORA5Zcjs.serializeLayers.call(void 0, state.layers);
2013
2013
  return { ...header(state, options), layers, assets };
2014
2014
  }
2015
2015
  async function serializePaintDocumentExternal(state, store, options = {}) {
2016
- const { layers, assets } = await _chunkR2FVAKFHcjs.serializeLayersExternal.call(void 0, state.layers, store);
2016
+ const { layers, assets } = await _chunkM6JORA5Zcjs.serializeLayersExternal.call(void 0, state.layers, store);
2017
2017
  return { ...header(state, options), layers, assets };
2018
2018
  }
2019
2019
  function paintLayersOnly(layers, problems) {
@@ -2048,9 +2048,9 @@ function deserializePaintDocument(raw) {
2048
2048
  }
2049
2049
  const problems = [];
2050
2050
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
2051
- const paper = _chunk5FZS7J7Ccjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
2051
+ const paper = _chunk4T47Z4J3cjs.normalizePaper.call(void 0, _nullishCoalesce(r.paper, () => ( {})));
2052
2052
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
2053
- const layers = paintLayersOnly(_chunkR2FVAKFHcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
2053
+ const layers = paintLayersOnly(_chunkM6JORA5Zcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
2054
2054
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
2055
2055
  const activeLayerId = wanted && _chunkHB4ICNNAcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers), 'access', _104 => _104.filter, 'call', _105 => _105((l) => l.type === "pixel"), 'access', _106 => _106.pop, 'call', _107 => _107(), 'optionalAccess', _108 => _108.id]), () => ( null));
2056
2056
  const wetEvents = Array.isArray(r.wetEvents) ? r.wetEvents.filter((e) => e && typeof e === "object" && Number.isInteger(e.clock) && typeof e.kind === "string") : [];
@@ -2066,7 +2066,7 @@ async function deserializePaintDocumentAsync(raw, store) {
2066
2066
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
2067
2067
  const r = raw;
2068
2068
  const problems = [];
2069
- const assets = await _chunkR2FVAKFHcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
2069
+ const assets = await _chunkM6JORA5Zcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
2070
2070
  const loaded = deserializePaintDocument({ ...r, assets });
2071
2071
  return { ...loaded, problems: [...problems, ...loaded.problems] };
2072
2072
  }
@@ -2143,13 +2143,13 @@ function viewPenToDocument(view, p) {
2143
2143
 
2144
2144
  // src/paint-editor/input.ts
2145
2145
  function samplePressure(e) {
2146
- return _chunkXFYLA3ZOcjs.pointerPressure.call(void 0, e);
2146
+ return _chunkVMROIWLLcjs.pointerPressure.call(void 0, e);
2147
2147
  }
2148
2148
  function pointerToPenPoint(e, x, y, view) {
2149
2149
  const p = { x, y, pressure: samplePressure(e) };
2150
2150
  if (typeof e.timeStamp === "number" && Number.isFinite(e.timeStamp)) p.t = e.timeStamp;
2151
2151
  if (e.pointerType !== "pen") return p;
2152
- const o = _chunk5FZS7J7Ccjs.penOrientation.call(void 0, {
2152
+ const o = _chunk4T47Z4J3cjs.penOrientation.call(void 0, {
2153
2153
  x,
2154
2154
  y,
2155
2155
  altitude: typeof e.altitudeAngle === "number" ? e.altitudeAngle : void 0,
@@ -2213,7 +2213,8 @@ function downloadBytes(bytes, fileName, mimeType) {
2213
2213
 
2214
2214
  // src/paint-editor/wet.ts
2215
2215
  var STROKE_WATER = 0.9;
2216
- var STROKE_MASS = _chunkXFYLA3ZOcjs.PIGMENT_UNIT * 2.5;
2216
+ var STROKE_MASS = _chunkVMROIWLLcjs.PIGMENT_UNIT * 2.5;
2217
+ var STROKE_LIGHT = 1.5;
2217
2218
  var COVERAGE_STEPS = 4096;
2218
2219
  function union2(a, b) {
2219
2220
  if (!a) return { ...b };
@@ -2228,7 +2229,7 @@ function wetPaperInput(paper) {
2228
2229
  absorption: paper.absorption,
2229
2230
  permeability: paper.permeability,
2230
2231
  roughness: flat ? 0 : paper.roughness,
2231
- color: _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, paper.color),
2232
+ color: _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, paper.color),
2232
2233
  heightAt: flat ? () => 0.5 : (x, y) => grain.at(x, y)
2233
2234
  };
2234
2235
  }
@@ -2236,20 +2237,22 @@ var WetStrokeDriver = (_class6 = class {
2236
2237
  constructor(init) {;_class6.prototype.__init40.call(this);_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);
2237
2238
  this.init = init;
2238
2239
  const brush = init.brush;
2239
- this.smoother = new (0, _chunk5FZS7J7Ccjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
2240
- const copies = init.copies.length ? init.copies : [_chunk5FZS7J7Ccjs.IDENTITY_COPY];
2240
+ this.smoother = new (0, _chunk4T47Z4J3cjs.PenSmoother)(brush.tip.smoothing, brush.pressureSmoothing);
2241
+ const copies = init.copies.length ? init.copies : [_chunk4T47Z4J3cjs.IDENTITY_COPY];
2241
2242
  const wet = brush.wet;
2242
2243
  const spacing = Math.max(0.02, brush.tip.spacing);
2243
2244
  const perDab = Math.min(1, spacing * 1.2);
2244
2245
  const thin = wet.thinner;
2245
- this.medium = new (0, _chunkXFYLA3ZOcjs.WetMedium)(init.world, init.laneId, {
2246
+ this.medium = new (0, _chunkVMROIWLLcjs.WetMedium)(init.world, init.laneId, {
2246
2247
  water: STROKE_WATER * Math.min(1, wet.water * (1 + thin)) * perDab,
2247
2248
  mass: STROKE_MASS * wet.pigment * (1 - 0.6 * thin) * perDab,
2248
- body: wet.body * (1 - thin)
2249
+ body: wet.body * (1 - thin),
2250
+ light: 0
2249
2251
  });
2252
+ this.lightBase = wet.tool === "paint" ? STROKE_LIGHT * brush.light.amount * (1 - 0.6 * thin) * perDab : 0;
2250
2253
  const rates = _chunkPQ3H2AANcjs.exchangeRates.call(void 0, brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
2251
2254
  this.states = copies.map((c, i) => ({
2252
- walker: new (0, _chunk5FZS7J7Ccjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
2255
+ walker: new (0, _chunk4T47Z4J3cjs.PenDabWalker)(brush, init.seed + i * 7919 | 0, c.linear),
2253
2256
  exchange: wet.tool === "paint" ? new (0, _chunkPQ3H2AANcjs.PaintExchange)(rates, init.load) : null,
2254
2257
  last: null
2255
2258
  }));
@@ -2277,6 +2280,7 @@ var WetStrokeDriver = (_class6 = class {
2277
2280
  __init51() {this.centre = [0, 0, 0]}
2278
2281
 
2279
2282
 
2283
+
2280
2284
  __init52() {this.sample = { rgb: [0, 0, 0], alpha: 1 }}
2281
2285
 
2282
2286
  /** What copy 0's brush carries after the dabs so far. */
@@ -2374,10 +2378,11 @@ var WetStrokeDriver = (_class6 = class {
2374
2378
  switch (wet.tool) {
2375
2379
  case "paint": {
2376
2380
  const ex = st.exchange;
2381
+ this.medium.options.light = this.lightBase * (brush.light.pressure ? d.pressure : 1);
2377
2382
  let flow = 1;
2378
2383
  const effect = this.init.effect;
2379
2384
  if (effect) {
2380
- _chunk5FZS7J7Ccjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
2385
+ _chunk4T47Z4J3cjs.sampleEffectAt.call(void 0, effect, d.x, d.y, this.centre, d);
2381
2386
  ex.setReservoirColor(this.centre[0], this.centre[1], this.centre[2]);
2382
2387
  } else if (this.sampler) {
2383
2388
  const g = this.sampler.dab(d, this.sample);
@@ -2389,7 +2394,7 @@ var WetStrokeDriver = (_class6 = class {
2389
2394
  if (total > 0 && flow > 0 && effect) {
2390
2395
  const ec = cov.slice();
2391
2396
  const field = new Float32Array(ec.length * 3);
2392
- _chunk5FZS7J7Ccjs.effectDabField.call(void 0, effect, rect, ec, this.centre, this.paint, field, COVERAGE_STEPS, d);
2397
+ _chunk4T47Z4J3cjs.effectDabField.call(void 0, effect, rect, ec, this.centre, this.paint, field, COVERAGE_STEPS, d);
2393
2398
  this.medium.deposit(rect, ec, Math.min(1, total) * k, this.paint, null, field);
2394
2399
  } else if (total > 0 && flow > 0) this.medium.deposit(rect, cov, Math.min(1, total) * k * flow, this.paint, null);
2395
2400
  else world.paint(laneId, rect, cov, this.medium.options.water * k, null);
@@ -2444,7 +2449,7 @@ var PaintWetLayers = (_class7 = class {
2444
2449
 
2445
2450
 
2446
2451
  __init53() {this.world = null}
2447
- __init54() {this.tilt = { ..._chunkXFYLA3ZOcjs.FLAT }}
2452
+ __init54() {this.tilt = { ..._chunkVMROIWLLcjs.FLAT }}
2448
2453
  __init55() {this.settings = /* @__PURE__ */ new Map()}
2449
2454
  __init56() {this.paused = false}
2450
2455
  /** Wet strokes dry as soon as they end (one undo step with the stroke). */
@@ -2468,8 +2473,8 @@ var PaintWetLayers = (_class7 = class {
2468
2473
  /** Starts the GPU engine for the world (once; it may turn out unavailable). */
2469
2474
  startGpu() {
2470
2475
  if (this.gpuMode === "off" || this.gpu || this.gpuStarting || this.gpuSupport) return;
2471
- const provider = this.options.gpuProvider === void 0 ? _chunkXFYLA3ZOcjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
2472
- this.gpuStarting = _chunkXFYLA3ZOcjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
2476
+ const provider = this.options.gpuProvider === void 0 ? _chunkVMROIWLLcjs.findWebGpu.call(void 0, ) : this.options.gpuProvider;
2477
+ this.gpuStarting = _chunkVMROIWLLcjs.createWetGpuEngine.call(void 0, provider).then(({ engine, support }) => {
2473
2478
  this.gpuSupport = support;
2474
2479
  if (!engine) return;
2475
2480
  if (this.gpuMode === "off" || !this.world) {
@@ -2528,7 +2533,7 @@ var PaintWetLayers = (_class7 = class {
2528
2533
  return this.world;
2529
2534
  }
2530
2535
  makeWorld(width, height, paper) {
2531
- const world = new (0, _chunkXFYLA3ZOcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
2536
+ const world = new (0, _chunkVMROIWLLcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: this.options.kernel, threads: this.options.threads });
2532
2537
  world.setTilt(this.tilt);
2533
2538
  world.gpuMinTiles = this.gpuMinTiles;
2534
2539
  if (this.gpu) world.attachGpu(this.gpu);
@@ -2540,7 +2545,7 @@ var PaintWetLayers = (_class7 = class {
2540
2545
  * sides: the shift has to be whole wet tiles (256 px), and no wet stroke may be live.
2541
2546
  */
2542
2547
  canExtend(left, top) {
2543
- return left % _chunkXFYLA3ZOcjs.WET_TILE === 0 && top % _chunkXFYLA3ZOcjs.WET_TILE === 0 && !this.driver;
2548
+ return left % _chunkVMROIWLLcjs.WET_TILE === 0 && top % _chunkVMROIWLLcjs.WET_TILE === 0 && !this.driver;
2544
2549
  }
2545
2550
  /**
2546
2551
  * Keeps the wet paint while the canvas grows to `width`×`height` by `left` / `top` on those
@@ -2558,11 +2563,12 @@ var PaintWetLayers = (_class7 = class {
2558
2563
  this.lastTick = null;
2559
2564
  this.stepsOwed = 0;
2560
2565
  if (!old || !snap) return;
2561
- const moved = _chunkXFYLA3ZOcjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left, top, (l) => {
2566
+ const moved = _chunkVMROIWLLcjs.moveWetSnapshot.call(void 0, snap, old, { width, height }, left, top, (l) => {
2562
2567
  const flow = _optionalChain([this, 'access', _132 => _132.settings, 'access', _133 => _133.get, 'call', _134 => _134(l.id), 'optionalAccess', _135 => _135.flow]);
2563
2568
  return {
2564
2569
  base: _chunk474IQG74cjs.translateSurface.call(void 0, l.base, left, top),
2565
- flow: l.flow && flow && flow.kind !== "none" ? _chunkXFYLA3ZOcjs.flowField.call(void 0, flow, width, height) : l.flow
2570
+ ...l.light ? { light: _chunk474IQG74cjs.translateSurface.call(void 0, l.light, left, top) } : {},
2571
+ flow: l.flow && flow && flow.kind !== "none" ? _chunkVMROIWLLcjs.flowField.call(void 0, flow, width, height) : l.flow
2566
2572
  };
2567
2573
  });
2568
2574
  this.world = this.makeWorld(width, height, paper);
@@ -2590,7 +2596,7 @@ var PaintWetLayers = (_class7 = class {
2590
2596
  settingsOf(layerId, medium = "watercolor") {
2591
2597
  let s = this.settings.get(layerId);
2592
2598
  if (!s) {
2593
- s = { params: _chunkXFYLA3ZOcjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkXFYLA3ZOcjs.DEFAULT_WET_PARAMS), flow: { ..._chunkXFYLA3ZOcjs.DEFAULT_FLOW } };
2599
+ s = { params: _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, WET_MEDIUM_PARAMS[medium], _chunkVMROIWLLcjs.DEFAULT_WET_PARAMS), flow: { ..._chunkVMROIWLLcjs.DEFAULT_FLOW } };
2594
2600
  this.settings.set(layerId, s);
2595
2601
  }
2596
2602
  return s;
@@ -2601,29 +2607,29 @@ var PaintWetLayers = (_class7 = class {
2601
2607
  if (!w.hasLane(layerId)) {
2602
2608
  const base = _nullishCoalesce(this.host.layerSurface(layerId), () => ( new (0, _chunk474IQG74cjs.TiledSurface)(4, /* @__PURE__ */ new Map(), 0)));
2603
2609
  const s = this.settingsOf(layerId, medium);
2604
- w.ensureLane(layerId, { params: s.params, base });
2610
+ w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId) });
2605
2611
  const { width, height } = this.host.canvas();
2606
- if (s.flow.kind !== "none") w.setFlow(layerId, _chunkXFYLA3ZOcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2612
+ if (s.flow.kind !== "none") w.setFlow(layerId, _chunkVMROIWLLcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2607
2613
  }
2608
2614
  return w;
2609
2615
  }
2610
2616
  setParams(layerId, update) {
2611
2617
  const s = this.settingsOf(layerId);
2612
- s.params = _chunkXFYLA3ZOcjs.normalizeWetParams.call(void 0, update, s.params);
2618
+ s.params = _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, update, s.params);
2613
2619
  if (_optionalChain([this, 'access', _141 => _141.world, 'optionalAccess', _142 => _142.hasLane, 'call', _143 => _143(layerId)])) this.world.setParams(layerId, s.params);
2614
2620
  return { ...s.params };
2615
2621
  }
2616
2622
  setFlow(layerId, update) {
2617
2623
  const s = this.settingsOf(layerId);
2618
- s.flow = _chunkXFYLA3ZOcjs.normalizeFlow.call(void 0, update, s.flow);
2624
+ s.flow = _chunkVMROIWLLcjs.normalizeFlow.call(void 0, update, s.flow);
2619
2625
  if (_optionalChain([this, 'access', _144 => _144.world, 'optionalAccess', _145 => _145.hasLane, 'call', _146 => _146(layerId)])) {
2620
2626
  const { width, height } = this.host.canvas();
2621
- this.world.setFlow(layerId, _chunkXFYLA3ZOcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2627
+ this.world.setFlow(layerId, _chunkVMROIWLLcjs.flowField.call(void 0, s.flow, width, height), s.flow.strength);
2622
2628
  }
2623
2629
  return { ...s.flow };
2624
2630
  }
2625
2631
  setTilt(update) {
2626
- this.tilt = _chunkXFYLA3ZOcjs.normalizeTilt.call(void 0, update, this.tilt);
2632
+ this.tilt = _chunkVMROIWLLcjs.normalizeTilt.call(void 0, update, this.tilt);
2627
2633
  _optionalChain([this, 'access', _147 => _147.world, 'optionalAccess', _148 => _148.setTilt, 'call', _149 => _149(this.tilt)]);
2628
2634
  return { ...this.tilt };
2629
2635
  }
@@ -2659,6 +2665,7 @@ var PaintWetLayers = (_class7 = class {
2659
2665
  if (this.host.layerSurface(id) !== d.surface) surfaces.set(id, d.surface);
2660
2666
  rects.push(...d.changed);
2661
2667
  }
2668
+ this.syncLights();
2662
2669
  if (surfaces.size) this.host.updateSurfaces(surfaces, rects);
2663
2670
  return rects;
2664
2671
  }
@@ -2674,9 +2681,21 @@ var PaintWetLayers = (_class7 = class {
2674
2681
  if (this.host.layerSurface(id) !== d.surface) surfaces.set(id, d.surface);
2675
2682
  rects.push(...d.changed);
2676
2683
  }
2684
+ this.syncLights();
2677
2685
  if (surfaces.size) this.host.updateSurfaces(surfaces, rects);
2678
2686
  return rects;
2679
2687
  }
2688
+ /** Shows each wet layer's live light paint (the light under it with the wet light shaded in). */
2689
+ syncLights() {
2690
+ const w = this.world;
2691
+ if (!w) return;
2692
+ const lights = /* @__PURE__ */ new Map();
2693
+ for (const id of w.laneIds()) {
2694
+ const l = w.lightDisplay(id);
2695
+ if (l && this.host.layerLight(id) !== l) lights.set(id, l);
2696
+ }
2697
+ if (lights.size) this.host.updateLights(lights);
2698
+ }
2680
2699
  /** Drops the wet layers whose paint has all dried (they become ordinary pixel layers). */
2681
2700
  retireDry() {
2682
2701
  const w = this.world;
@@ -2684,7 +2703,9 @@ var PaintWetLayers = (_class7 = class {
2684
2703
  for (const id of w.laneIds()) {
2685
2704
  if (w.isActive(id) || _optionalChain([this, 'access', _162 => _162.driver, 'optionalAccess', _163 => _163.init, 'access', _164 => _164.laneId]) === id) continue;
2686
2705
  const base = w.getBase(id);
2706
+ const light = w.isLit(id) ? w.getLight(id) : null;
2687
2707
  w.removeLane(id);
2708
+ if (light && this.host.layerLight(id) !== light) this.host.updateLights(/* @__PURE__ */ new Map([[id, light]]));
2688
2709
  this.host.updateSurfaces(/* @__PURE__ */ new Map([[id, base]]), []);
2689
2710
  }
2690
2711
  }
@@ -2803,10 +2824,16 @@ var PaintWetLayers = (_class7 = class {
2803
2824
  this.retireDry();
2804
2825
  return out;
2805
2826
  }
2827
+ /** The layer's light paint with all its wet paint dried (`null` without a wet layer or light), without changing anything. */
2828
+ bakedLight(layerId) {
2829
+ const w = this.world;
2830
+ if (!_optionalChain([w, 'optionalAccess', _167 => _167.hasLane, 'call', _168 => _168(layerId)]) || !w.isLit(layerId)) return null;
2831
+ return w.bakedLight(layerId);
2832
+ }
2806
2833
  /** The layer's pixels with all its wet paint dried (deterministic), without changing anything. */
2807
2834
  bakedSurface(layerId) {
2808
2835
  const w = this.world;
2809
- if (!_optionalChain([w, 'optionalAccess', _167 => _167.hasLane, 'call', _168 => _168(layerId)])) return null;
2836
+ if (!_optionalChain([w, 'optionalAccess', _169 => _169.hasLane, 'call', _170 => _170(layerId)])) return null;
2810
2837
  return w.bakedSurface(layerId);
2811
2838
  }
2812
2839
  /** A snapshot of the world for undo (`null` when there is none). */
@@ -2827,13 +2854,13 @@ var PaintWetLayers = (_class7 = class {
2827
2854
  this.syncDisplays();
2828
2855
  }
2829
2856
  dropWorld() {
2830
- _optionalChain([this, 'access', _169 => _169.world, 'optionalAccess', _170 => _170.destroy, 'call', _171 => _171()]);
2857
+ _optionalChain([this, 'access', _171 => _171.world, 'optionalAccess', _172 => _172.destroy, 'call', _173 => _173()]);
2831
2858
  this.world = null;
2832
2859
  this.driver = null;
2833
2860
  }
2834
2861
  /** Forgets everything wet (a new canvas, a resize, opening a document). */
2835
2862
  reset() {
2836
- _optionalChain([this, 'access', _172 => _172.world, 'optionalAccess', _173 => _173.destroy, 'call', _174 => _174()]);
2863
+ _optionalChain([this, 'access', _174 => _174.world, 'optionalAccess', _175 => _175.destroy, 'call', _176 => _176()]);
2837
2864
  this.world = null;
2838
2865
  this.driver = null;
2839
2866
  this.settings.clear();
@@ -2863,32 +2890,32 @@ var PaintWetLayers = (_class7 = class {
2863
2890
  return out;
2864
2891
  }
2865
2892
  destroy() {
2866
- _optionalChain([this, 'access', _175 => _175.world, 'optionalAccess', _176 => _176.destroy, 'call', _177 => _177()]);
2893
+ _optionalChain([this, 'access', _177 => _177.world, 'optionalAccess', _178 => _178.destroy, 'call', _179 => _179()]);
2867
2894
  this.world = null;
2868
- _optionalChain([this, 'access', _178 => _178.gpu, 'optionalAccess', _179 => _179.destroy, 'call', _180 => _180()]);
2895
+ _optionalChain([this, 'access', _180 => _180.gpu, 'optionalAccess', _181 => _181.destroy, 'call', _182 => _182()]);
2869
2896
  this.gpu = null;
2870
2897
  }
2871
2898
  }, _class7);
2872
2899
  function wetPigmentOf(hex, body) {
2873
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, hex);
2874
- return Array.from(_chunkXFYLA3ZOcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
2900
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, hex);
2901
+ return Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], body));
2875
2902
  }
2876
2903
 
2877
2904
  // src/paint-editor/thumbnails.ts
2878
2905
  var thumbWorld = null;
2879
2906
  function paintWetTestStroke(brush, paper, color, width, height) {
2880
2907
  if (!thumbWorld || thumbWorld.width !== width || thumbWorld.height !== height) {
2881
- _optionalChain([thumbWorld, 'optionalAccess', _181 => _181.destroy, 'call', _182 => _182()]);
2882
- thumbWorld = new (0, _chunkXFYLA3ZOcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: "typescript", threads: 0 });
2908
+ _optionalChain([thumbWorld, 'optionalAccess', _183 => _183.destroy, 'call', _184 => _184()]);
2909
+ thumbWorld = new (0, _chunkVMROIWLLcjs.WetWorld)(width, height, wetPaperInput(paper), { kernel: "typescript", threads: 0 });
2883
2910
  } else thumbWorld.setPaper(wetPaperInput(paper));
2884
2911
  const w = thumbWorld;
2885
2912
  if (w.hasLane("thumb")) w.removeLane("thumb");
2886
2913
  w.ensureLane("thumb");
2887
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, color);
2914
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, color);
2888
2915
  if (brush.wet.tool !== "paint" && brush.wet.tool !== "water") {
2889
2916
  const half = Math.ceil(height / 2);
2890
- w.paint("thumb", { x: 0, y: 0, width, height: half }, null, 0.4, Array.from(_chunkXFYLA3ZOcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], 0), (v) => v * 0.05));
2891
- w.paint("thumb", { x: 0, y: half, width, height: height - half }, null, 0.4, Array.from(_chunkXFYLA3ZOcjs.pigmentOf.call(void 0, [232 / 255, 196 / 255, 64 / 255], 0), (v) => v * 0.05));
2917
+ w.paint("thumb", { x: 0, y: 0, width, height: half }, null, 0.4, Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [r / 255, g / 255, b / 255], 0), (v) => v * 0.05));
2918
+ w.paint("thumb", { x: 0, y: half, width, height: height - half }, null, 0.4, Array.from(_chunkVMROIWLLcjs.pigmentOf.call(void 0, [232 / 255, 196 / 255, 64 / 255], 0), (v) => v * 0.05));
2892
2919
  }
2893
2920
  const driver = new WetStrokeDriver({
2894
2921
  world: w,
@@ -2898,9 +2925,9 @@ function paintWetTestStroke(brush, paper, color, width, height) {
2898
2925
  load: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2899
2926
  grain: paperGrain(paper),
2900
2927
  paperDepth: paper.depth,
2901
- paperColor: _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, paper.color),
2928
+ paperColor: _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, paper.color),
2902
2929
  seed: 7,
2903
- copies: [_chunk5FZS7J7Ccjs.IDENTITY_COPY]
2930
+ copies: [_chunk4T47Z4J3cjs.IDENTITY_COPY]
2904
2931
  });
2905
2932
  driver.push(thumbnailStroke(width, height));
2906
2933
  driver.finish();
@@ -2920,7 +2947,7 @@ function thumbnailStroke(width, height) {
2920
2947
  return pts;
2921
2948
  }
2922
2949
  function paintTestStroke(surface, brush, paper, color, width, height) {
2923
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, color);
2950
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, color);
2924
2951
  let result = surface;
2925
2952
  let thick = null;
2926
2953
  let light = null;
@@ -2941,13 +2968,13 @@ function paintTestStroke(surface, brush, paper, color, width, height) {
2941
2968
  lockTransparency: false,
2942
2969
  brush,
2943
2970
  color: [r, g, b, 255],
2944
- background: [..._chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, paper.color), 255],
2971
+ background: [..._chunk4T47Z4J3cjs.hexToRgb8.call(void 0, paper.color), 255],
2945
2972
  grain: paperGrain(paper),
2946
2973
  paperDepth: paper.depth,
2947
2974
  seed: 7,
2948
2975
  colorHex: color,
2949
2976
  affineCopies: [],
2950
- copies: [_chunk5FZS7J7Ccjs.IDENTITY_COPY],
2977
+ copies: [_chunk4T47Z4J3cjs.IDENTITY_COPY],
2951
2978
  mixerLoad: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255]),
2952
2979
  thick: brush.engine === "impasto" ? { channels: emptyThickChannels() } : void 0,
2953
2980
  sticker: brush.engine === "sticker" ? { nextId: 1 } : void 0,
@@ -2963,8 +2990,8 @@ function renderBrushThumbnail(brush, options) {
2963
2990
  const width = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.width, () => ( 160)))));
2964
2991
  const height = Math.max(16, Math.min(512, Math.round(_nullishCoalesce(options.height, () => ( 48)))));
2965
2992
  const maxSize = height * 0.42;
2966
- const b = brush.tip.size > maxSize ? _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
2967
- const rgba = [..._chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, options.color), 255];
2993
+ const b = brush.tip.size > maxSize ? _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: maxSize } }, brush) : brush;
2994
+ const rgba = [..._chunk4T47Z4J3cjs.hexToRgb8.call(void 0, options.color), 255];
2968
2995
  let surface = _chunk474IQG74cjs.emptySurface.call(void 0, 4);
2969
2996
  if (b.engine === "eraser") {
2970
2997
  surface = _chunk474IQG74cjs.fillRect.call(void 0, surface, { x: 0, y: 0, width, height }, rgba);
@@ -3223,11 +3250,11 @@ function readSwatch(raw) {
3223
3250
  if (!raw || typeof raw !== "object") return null;
3224
3251
  const r = raw;
3225
3252
  const g = _chunkPQ3H2AANcjs.readPaintSource.call(void 0, r.paint);
3226
- const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _183 => _183.type]) === "gradient" ? _chunkPQ3H2AANcjs.paintSourceColor.call(void 0, g) : null;
3253
+ const color = typeof r.color === "string" && /^#[0-9a-f]{6}$/i.test(r.color) ? r.color.toLowerCase() : _optionalChain([g, 'optionalAccess', _185 => _185.type]) === "gradient" ? _chunkPQ3H2AANcjs.paintSourceColor.call(void 0, g) : null;
3227
3254
  if (!color) return null;
3228
3255
  const out = { color };
3229
3256
  if (typeof r.name === "string" && r.name.trim()) out.name = r.name.trim().slice(0, 80);
3230
- if (_optionalChain([g, 'optionalAccess', _184 => _184.type]) === "gradient") out.paint = g;
3257
+ if (_optionalChain([g, 'optionalAccess', _186 => _186.type]) === "gradient") out.paint = g;
3231
3258
  return out;
3232
3259
  }
3233
3260
  var DEFAULT_SWATCHES = [
@@ -3246,7 +3273,7 @@ var DEFAULT_SWATCHES = [
3246
3273
  // src/paint-editor/mixing-pad.ts
3247
3274
  var MIXING_PAD_WIDTH = 360;
3248
3275
  var MIXING_PAD_HEIGHT = 220;
3249
- var PAD_PAINT = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, {
3276
+ var PAD_PAINT = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, {
3250
3277
  id: "pad-paint",
3251
3278
  name: "Pad paint",
3252
3279
  category: "mixer",
@@ -3254,7 +3281,7 @@ var PAD_PAINT = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, {
3254
3281
  tip: { size: 28, hardness: 0.75, spacing: 0.1, opacity: 1, flow: 0.7, pressureSize: false, pressureOpacity: false },
3255
3282
  mixer: { wet: 0.45, load: 1, mix: 0.4, loadEachStroke: true, cleanEachStroke: true, mixing: "pigment" }
3256
3283
  });
3257
- var PAD_KNIFE = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, {
3284
+ var PAD_KNIFE = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, {
3258
3285
  id: "pad-knife",
3259
3286
  name: "Palette knife",
3260
3287
  category: "smudge",
@@ -3264,7 +3291,7 @@ var PAD_KNIFE = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, {
3264
3291
  // A knife drags streaks of paint and folds them into each other, mixing them as pigment.
3265
3292
  smudge: { strength: 0.6, length: 0.8, mixing: "pigment" }
3266
3293
  });
3267
- var PAD_BLOB = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, {
3294
+ var PAD_BLOB = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, {
3268
3295
  id: "pad-blob",
3269
3296
  name: "Pad blob",
3270
3297
  category: "custom",
@@ -3286,12 +3313,12 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3286
3313
  }
3287
3314
  }
3288
3315
  let brush = options.tool === "knife" ? PAD_KNIFE : PAD_PAINT;
3289
- if (options.size !== void 0) brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
3316
+ if (options.size !== void 0) brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...brush.tip, size: options.size } }, brush);
3290
3317
  return this.run(brush, points, options.color);
3291
3318
  }
3292
3319
  /** Paints `points` with `brush` in `color` on the pad. */
3293
3320
  run(brush, points, color) {
3294
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, color);
3321
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, color);
3295
3322
  let result = null;
3296
3323
  const session = new PaintStrokeSession(
3297
3324
  { update: () => {
@@ -3309,7 +3336,7 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3309
3336
  seed: 1,
3310
3337
  colorHex: color,
3311
3338
  affineCopies: [],
3312
- copies: [_chunk5FZS7J7Ccjs.IDENTITY_COPY],
3339
+ copies: [_chunk4T47Z4J3cjs.IDENTITY_COPY],
3313
3340
  mixerLoad: brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, [r / 255, g / 255, b / 255])
3314
3341
  }
3315
3342
  );
@@ -3385,10 +3412,10 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3385
3412
  const off = used.length === 1 ? 0 : 0.45 * R;
3386
3413
  const x = Math.min(cx + R - r, Math.max(cx - R + r, cx + Math.cos(a) * off));
3387
3414
  const y = Math.min(cy + R - r, Math.max(cy - R + r, cy + Math.sin(a) * off));
3388
- const blob = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
3415
+ const blob = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: Math.max(2, 2 * r) } }, PAD_BLOB);
3389
3416
  this.run(blob, [{ x, y }], p.color.toLowerCase());
3390
3417
  });
3391
- const knife = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
3418
+ const knife = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_KNIFE.tip, size: Math.max(12, R * 0.5) } }, PAD_KNIFE);
3392
3419
  for (let k = 0; k < passes; k++) {
3393
3420
  const stir = [];
3394
3421
  const turns = 1.6;
@@ -3400,10 +3427,10 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3400
3427
  this.run(knife, stir, "#000000");
3401
3428
  }
3402
3429
  const mixed = _chunkOLNIPTB3cjs.mixPigments.call(void 0,
3403
- paints.map((p) => _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
3430
+ paints.map((p) => _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, p.color).map((v) => v / 255)),
3404
3431
  paints.map((p) => p.parts)
3405
3432
  );
3406
- const core = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
3433
+ const core = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...PAD_BLOB.tip, size: R * 1.1, hardness: 0.55 } }, PAD_BLOB);
3407
3434
  const hex = "#" + mixed.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
3408
3435
  this.run(core, [{ x: cx, y: cy }], hex);
3409
3436
  return { color: this.pick(cx, cy, 2), bounds };
@@ -3414,7 +3441,7 @@ var MixingPad = (_class9 = class {constructor() { _class9.prototype.__init71.cal
3414
3441
  }
3415
3442
  /** Replaces the pad with a PNG (data URL or base64) of the pad's size, as `toPng` writes. */
3416
3443
  fromPng(png) {
3417
- const bytes = png.startsWith("data:") ? _optionalChain([_chunkOLNIPTB3cjs.parseDataUrl.call(void 0, png), 'optionalAccess', _185 => _185.bytes]) : _chunkOLNIPTB3cjs.base64ToBytes.call(void 0, png);
3444
+ const bytes = png.startsWith("data:") ? _optionalChain([_chunkOLNIPTB3cjs.parseDataUrl.call(void 0, png), 'optionalAccess', _187 => _187.bytes]) : _chunkOLNIPTB3cjs.base64ToBytes.call(void 0, png);
3418
3445
  if (!bytes || !_chunkOLNIPTB3cjs.isPng.call(void 0, bytes)) throw new Error("The pad image is not a PNG data URL or base64 PNG.");
3419
3446
  const img = _chunkOLNIPTB3cjs.decodePng.call(void 0, bytes);
3420
3447
  if (img.width !== this.width || img.height !== this.height) throw new Error(`The pad image is ${img.width}\xD7${img.height}; a mixing pad is ${this.width}\xD7${this.height}.`);
@@ -3477,6 +3504,212 @@ function liveStrokeBounds(stroke) {
3477
3504
  return { x: Math.floor(x0 - pad), y: Math.floor(y0 - pad), width: Math.ceil(x1 - x0 + 2 * pad), height: Math.ceil(y1 - y0 + 2 * pad) };
3478
3505
  }
3479
3506
 
3507
+ // src/paint-editor/backlight.ts
3508
+ var DEFAULT_BACKLIGHT_COLOR = "#fff1d6";
3509
+ var BACKLIGHT_SPILL = { radius: 24, strength: 1.5 };
3510
+ var BLOCK_HEIGHT = 96;
3511
+ var VALLEY_GAIN = 0.35;
3512
+ function backlightOf(paper) {
3513
+ return _nullishCoalesce(paper.backlight, () => ( 0));
3514
+ }
3515
+ var LIN = new Float64Array(256);
3516
+ for (let i = 0; i < 256; i++) LIN[i] = _chunk7AHBW2CQcjs.srgbToLinear.call(void 0, i / 255);
3517
+ function needAlpha(e, p) {
3518
+ if (e < p) return 1 - e / p;
3519
+ if (e > p) return (e - p) / (255 - p);
3520
+ return 0;
3521
+ }
3522
+ function tilesUnder(surface, rect, offset, out) {
3523
+ if (!surface) {
3524
+ out.push(null);
3525
+ return;
3526
+ }
3527
+ const x0 = Math.floor((rect.x - offset.x) / _chunk474IQG74cjs.TILE);
3528
+ const y0 = Math.floor((rect.y - offset.y) / _chunk474IQG74cjs.TILE);
3529
+ const x1 = Math.floor((rect.x - offset.x + rect.width - 1) / _chunk474IQG74cjs.TILE);
3530
+ const y1 = Math.floor((rect.y - offset.y + rect.height - 1) / _chunk474IQG74cjs.TILE);
3531
+ for (let ty = y0; ty <= y1; ty++) for (let tx = x0; tx <= x1; tx++) out.push(_nullishCoalesce(surface.tiles.get(_chunk474IQG74cjs.tileKey.call(void 0, tx, ty)), () => ( null)));
3532
+ }
3533
+ var sameRefs = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
3534
+ var BacklightCache = (_class10 = class {constructor() { _class10.prototype.__init75.call(this);_class10.prototype.__init76.call(this);_class10.prototype.__init77.call(this);_class10.prototype.__init78.call(this); }
3535
+ __init75() {this.tiles = /* @__PURE__ */ new Map()}
3536
+ __init76() {this.key = ""}
3537
+ __init77() {this.spillOf = null}
3538
+ __init78() {this.out = null}
3539
+ /**
3540
+ * The backlight layer's pixels for `layers` (bottom first) on `paper` over a `width` × `height`
3541
+ * canvas, or `null` when the paper has no backlight. `spillFrom` is the committed painting (the
3542
+ * spill is drawn from it, so a stroke in progress does not redo the blur every frame).
3543
+ */
3544
+ surface(paper, grain, width, height, layers, spillFrom) {
3545
+ const amount = backlightOf(paper);
3546
+ if (!(amount > 0)) return null;
3547
+ const key = JSON.stringify([amount, _nullishCoalesce(paper.backlightColor, () => ( DEFAULT_BACKLIGHT_COLOR)), paper.color, paper.depth, grain.flat, width, height, layers.length, layers.map((l) => [l.opacity, l.offset.x, l.offset.y, l.surface.channels])]);
3548
+ if (key !== this.key) {
3549
+ this.tiles.clear();
3550
+ this.key = key;
3551
+ }
3552
+ const light = /* @__PURE__ */ new Map();
3553
+ const color = /* @__PURE__ */ new Map();
3554
+ const painted = /* @__PURE__ */ new Map();
3555
+ const tilesX = Math.ceil(width / _chunk474IQG74cjs.TILE);
3556
+ const tilesY = Math.ceil(height / _chunk474IQG74cjs.TILE);
3557
+ const refs = [];
3558
+ for (let ty = 0; ty < tilesY; ty++) {
3559
+ for (let tx = 0; tx < tilesX; tx++) {
3560
+ const rect = { x: tx * _chunk474IQG74cjs.TILE, y: ty * _chunk474IQG74cjs.TILE, width: Math.min(_chunk474IQG74cjs.TILE, width - tx * _chunk474IQG74cjs.TILE), height: Math.min(_chunk474IQG74cjs.TILE, height - ty * _chunk474IQG74cjs.TILE) };
3561
+ refs.length = 0;
3562
+ for (const l of layers) {
3563
+ tilesUnder(l.surface, rect, l.offset, refs);
3564
+ tilesUnder(_optionalChain([l, 'access', _188 => _188.thick, 'optionalAccess', _189 => _189.height]), rect, l.offset, refs);
3565
+ tilesUnder(_optionalChain([l, 'access', _190 => _190.thick, 'optionalAccess', _191 => _191.material]), rect, l.offset, refs);
3566
+ }
3567
+ const k = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
3568
+ let r = this.tiles.get(k);
3569
+ if (!r || !sameRefs(r.refs, refs)) {
3570
+ r = { refs: [...refs], ...computeTile(paper, grain, amount, rect, layers) };
3571
+ this.tiles.set(k, r);
3572
+ }
3573
+ if (r.light) light.set(k, r.light);
3574
+ if (r.color) color.set(k, r.color);
3575
+ if (r.painted) painted.set(k, r.painted);
3576
+ }
3577
+ }
3578
+ return { light: new (0, _chunk474IQG74cjs.TiledSurface)(4, light, 0), color: new (0, _chunk474IQG74cjs.TiledSurface)(4, color, 0), painted: new (0, _chunk474IQG74cjs.TiledSurface)(1, painted, 0) };
3579
+ }
3580
+ /**
3581
+ * The full Backlight layer: the light through the paint (`current`) plus the spill of the light
3582
+ * through the committed paint (`committed`), both Linear Dodge. Cached on their tiles.
3583
+ */
3584
+ layer(current, committed, amount) {
3585
+ let spill = null;
3586
+ if (committed) {
3587
+ const s = this.spillOf;
3588
+ if (s && s.color.id === committed.color.id && s.painted.id === committed.painted.id) spill = s.out;
3589
+ else {
3590
+ spill = computeSpill(committed.color, committed.painted, { radius: BACKLIGHT_SPILL.radius, strength: BACKLIGHT_SPILL.strength * amount });
3591
+ this.spillOf = { color: committed.color, painted: committed.painted, out: spill };
3592
+ }
3593
+ }
3594
+ if (!spill) return current.light;
3595
+ const parts = [...current.light.tiles.values(), ...spill.tiles.values()];
3596
+ if (this.out && sameRefs(this.out.parts, parts)) return this.out.surface;
3597
+ const keys = /* @__PURE__ */ new Set([...current.light.tiles.keys(), ...spill.tiles.keys()]);
3598
+ const tiles = /* @__PURE__ */ new Map();
3599
+ for (const key of keys) {
3600
+ const a = current.light.tiles.get(key);
3601
+ const b = spill.tiles.get(key);
3602
+ const t = !a ? b : !b ? a : addTiles(a, b);
3603
+ if (t) tiles.set(key, t);
3604
+ }
3605
+ const surface = new (0, _chunk474IQG74cjs.TiledSurface)(4, tiles, 0);
3606
+ this.out = { parts, surface };
3607
+ return surface;
3608
+ }
3609
+ }, _class10);
3610
+ var full4 = (t) => {
3611
+ if (t.data.length === _chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4) return t.data;
3612
+ const out = new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4);
3613
+ const u = _nullishCoalesce(t.uniform, () => ( 0));
3614
+ const bytes = [u >>> 24 & 255, u >>> 16 & 255, u >>> 8 & 255, u & 255];
3615
+ for (let i = 0; i < out.length; i += 4) out.set(bytes, i);
3616
+ return out;
3617
+ };
3618
+ function addTiles(a, b) {
3619
+ const x = full4(a);
3620
+ const y = full4(b);
3621
+ const out = new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4);
3622
+ for (let i = 0; i < out.length; i += 4) {
3623
+ const ay = y[i + 3] / 255;
3624
+ const r = x[i] + y[i] * ay;
3625
+ const g = x[i + 1] + y[i + 1] * ay;
3626
+ const bl = x[i + 2] + y[i + 2] * ay;
3627
+ if (r < 0.5 && g < 0.5 && bl < 0.5) continue;
3628
+ out[i] = Math.round(r);
3629
+ out[i + 1] = Math.round(g);
3630
+ out[i + 2] = Math.round(bl);
3631
+ out[i + 3] = 255;
3632
+ }
3633
+ return _chunk474IQG74cjs.finishTile.call(void 0, out, 4, 0);
3634
+ }
3635
+ function computeTile(paper, grain, amount, rect, layers) {
3636
+ const n = rect.width * rect.height;
3637
+ const [p0, p1, p2] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, paper.color);
3638
+ const pb = [p0, p1, p2];
3639
+ const pl = [Math.max(1e-4, LIN[p0]), Math.max(1e-4, LIN[p1]), Math.max(1e-4, LIN[p2])];
3640
+ const [c0, c1, c2] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, _nullishCoalesce(paper.backlightColor, () => ( DEFAULT_BACKLIGHT_COLOR)));
3641
+ const t0 = new Float32Array(n).fill(amount * LIN[c0]);
3642
+ const t1 = new Float32Array(n).fill(amount * LIN[c1]);
3643
+ const t2 = new Float32Array(n).fill(amount * LIN[c2]);
3644
+ const depth = grain.flat ? 0 : paper.depth;
3645
+ if (depth > 0) {
3646
+ for (let y = 0, i = 0; y < rect.height; y++)
3647
+ for (let x = 0; x < rect.width; x++, i++) {
3648
+ const g = 1 + VALLEY_GAIN * depth * (0.5 - grain.at(rect.x + x + 0.5, rect.y + y + 0.5));
3649
+ t0[i] *= g;
3650
+ t1[i] *= g;
3651
+ t2[i] *= g;
3652
+ }
3653
+ }
3654
+ const clear = new Float32Array(n).fill(1);
3655
+ for (const l of layers) {
3656
+ const lr = { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height };
3657
+ if (!l.surface.tiles.size) continue;
3658
+ const px = _chunk474IQG74cjs.readRegion.call(void 0, l.surface, lr);
3659
+ const h = _optionalChain([l, 'access', _192 => _192.thick, 'optionalAccess', _193 => _193.height, 'access', _194 => _194.tiles, 'access', _195 => _195.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.height, lr) : null;
3660
+ const m = h && _optionalChain([l, 'access', _196 => _196.thick, 'optionalAccess', _197 => _197.material, 'access', _198 => _198.tiles, 'access', _199 => _199.size]) ? _chunk474IQG74cjs.readRegion.call(void 0, l.thick.material, lr) : null;
3661
+ const op = l.opacity;
3662
+ for (let i = 0; i < n; i++) {
3663
+ const a8 = px[i * 4 + 3];
3664
+ if (!a8 && !(h && h[i])) continue;
3665
+ const a = a8 / 255;
3666
+ let aMin = 0;
3667
+ const tr = [1, 1, 1];
3668
+ for (let c = 0; c < 3; c++) {
3669
+ const e = a * px[i * 4 + c] + (1 - a) * pb[c];
3670
+ aMin = Math.max(aMin, needAlpha(e, pb[c]));
3671
+ tr[c] = Math.min(1, LIN[Math.round(e)] / pl[c]);
3672
+ }
3673
+ const hide = aMin < 1 && a > aMin ? (a - aMin) / (1 - aMin) : 0;
3674
+ let k = 1 - hide;
3675
+ if (h && h[i]) {
3676
+ const ma = m ? m[i * 4 + 3] : 0;
3677
+ const clarity = ma ? (255 - ma) / 254 : 0;
3678
+ k *= 1 - Math.min(1, h[i] / BLOCK_HEIGHT) * (1 - clarity);
3679
+ }
3680
+ t0[i] *= 1 - op + op * tr[0] * k;
3681
+ t1[i] *= 1 - op + op * tr[1] * k;
3682
+ t2[i] *= 1 - op + op * tr[2] * k;
3683
+ clear[i] *= 1 - op * Math.max(a, h && h[i] ? 1 : 0);
3684
+ }
3685
+ }
3686
+ const light = new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4);
3687
+ const color = new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4);
3688
+ const painted = new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE);
3689
+ for (let y = 0, i = 0; y < rect.height; y++) {
3690
+ for (let x = 0; x < rect.width; x++, i++) {
3691
+ const o = (y * _chunk474IQG74cjs.TILE + x) * 4;
3692
+ const add = [Math.min(1, t0[i]), Math.min(1, t1[i]), Math.min(1, t2[i])];
3693
+ const mx = Math.max(add[0], add[1], add[2]);
3694
+ if (mx > 0.5 / 255) {
3695
+ light[o] = Math.round(add[0] * 255);
3696
+ light[o + 1] = Math.round(add[1] * 255);
3697
+ light[o + 2] = Math.round(add[2] * 255);
3698
+ light[o + 3] = 255;
3699
+ }
3700
+ const pv = Math.round((1 - clear[i]) * 255);
3701
+ if (pv && mx > 0.5 / 255) {
3702
+ painted[y * _chunk474IQG74cjs.TILE + x] = pv;
3703
+ color[o] = Math.round(_chunk7AHBW2CQcjs.linearToSrgb.call(void 0, add[0]) * 255);
3704
+ color[o + 1] = Math.round(_chunk7AHBW2CQcjs.linearToSrgb.call(void 0, add[1]) * 255);
3705
+ color[o + 2] = Math.round(_chunk7AHBW2CQcjs.linearToSrgb.call(void 0, add[2]) * 255);
3706
+ color[o + 3] = 255;
3707
+ }
3708
+ }
3709
+ }
3710
+ return { light: _chunk474IQG74cjs.finishTile.call(void 0, light, 4, 0), color: _chunk474IQG74cjs.finishTile.call(void 0, color, 4, 0), painted: _chunk474IQG74cjs.finishTile.call(void 0, painted, 1, 0) };
3711
+ }
3712
+
3480
3713
  // src/paint-editor/replay.ts
3481
3714
  function replayItems(doc) {
3482
3715
  const items = [];
@@ -3499,7 +3732,7 @@ async function replayPainting(source, target, options = {}) {
3499
3732
  const maxStrokes = _nullishCoalesce(options.strokes, () => ( source.strokes.length));
3500
3733
  const chunk = Math.max(1, _nullishCoalesce(options.wetChunk, () => ( 0))) || Infinity;
3501
3734
  let strokes = 0;
3502
- await target.prepareEffectPaints(source.strokes.slice(0, maxStrokes).flatMap((st) => _optionalChain([st, 'access', _186 => _186.paint, 'optionalAccess', _187 => _187.type]) === "effect" ? [st.paint] : []));
3735
+ await target.prepareEffectPaints(source.strokes.slice(0, maxStrokes).flatMap((st) => _optionalChain([st, 'access', _200 => _200.paint, 'optionalAccess', _201 => _201.type]) === "effect" ? [st.paint] : []));
3503
3736
  const advanceTo = async (clock) => {
3504
3737
  const now = target.getState().wet.clock;
3505
3738
  let left = clock - now;
@@ -3507,7 +3740,7 @@ async function replayPainting(source, target, options = {}) {
3507
3740
  const n = Math.min(left, chunk);
3508
3741
  await target.advanceWet({ steps: n });
3509
3742
  left -= n;
3510
- if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _188 => _188.onWetSteps, 'optionalCall', _189 => _189(target.getState().wet.clock)]);
3743
+ if (Number.isFinite(chunk)) await _optionalChain([options, 'access', _202 => _202.onWetSteps, 'optionalCall', _203 => _203(target.getState().wet.clock)]);
3511
3744
  }
3512
3745
  };
3513
3746
  const sr = (r) => ({ x: r.x * s, y: r.y * s, width: r.width * s, height: r.height * s });
@@ -3520,14 +3753,14 @@ async function replayPainting(source, target, options = {}) {
3520
3753
  else if (e.kind === "clear") target.clearLayer(e.layerId);
3521
3754
  else if (e.kind === "live-strokes") {
3522
3755
  const d = e.data;
3523
- if (_optionalChain([d, 'optionalAccess', _190 => _190.rasterized])) target.replaceLiveStrokes(e.layerId, null);
3756
+ if (_optionalChain([d, 'optionalAccess', _204 => _204.rasterized])) target.replaceLiveStrokes(e.layerId, null);
3524
3757
  else {
3525
- const list = (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _191 => _191.strokes]), () => ( []))).map((st2) => s === 1 ? st2 : { ...varyStroke(st2, scaleM, { scale: s }), ...st2.stencils ? { stencils: st2.stencils.map((x) => scaleStencil(x, s)) } : {} });
3526
- await target.prepareEffectPaints(list.flatMap((st2) => _optionalChain([st2, 'access', _192 => _192.paint, 'optionalAccess', _193 => _193.type]) === "effect" ? [st2.paint] : []));
3758
+ const list = (_nullishCoalesce(_optionalChain([d, 'optionalAccess', _205 => _205.strokes]), () => ( []))).map((st2) => s === 1 ? st2 : { ...varyStroke(st2, scaleM, { scale: s }), ...st2.stencils ? { stencils: st2.stencils.map((x) => scaleStencil(x, s)) } : {} });
3759
+ await target.prepareEffectPaints(list.flatMap((st2) => _optionalChain([st2, 'access', _206 => _206.paint, 'optionalAccess', _207 => _207.type]) === "effect" ? [st2.paint] : []));
3527
3760
  target.replaceLiveStrokes(e.layerId, list);
3528
3761
  }
3529
3762
  } else if (e.kind === "stickers") {
3530
- const list = (_nullishCoalesce(_optionalChain([e, 'access', _194 => _194.data, 'optionalAccess', _195 => _195.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3763
+ const list = (_nullishCoalesce(_optionalChain([e, 'access', _208 => _208.data, 'optionalAccess', _209 => _209.stickers]), () => ( []))).map((x) => s === 1 ? x : { ...x, x: x.x * s, y: x.y * s, size: x.size * s });
3531
3764
  target.replaceStickers(e.layerId, list);
3532
3765
  } else target.flattenRelief(e.layerId);
3533
3766
  continue;
@@ -3540,8 +3773,8 @@ async function replayPainting(source, target, options = {}) {
3540
3773
  switch (e.kind) {
3541
3774
  case "dry": {
3542
3775
  const rect = e.data;
3543
- const ids = _optionalChain([e, 'access', _196 => _196.layerId, 'optionalAccess', _197 => _197.split, 'call', _198 => _198(","), 'access', _199 => _199.filter, 'call', _200 => _200(Boolean)]);
3544
- if (_optionalChain([ids, 'optionalAccess', _201 => _201.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3776
+ const ids = _optionalChain([e, 'access', _210 => _210.layerId, 'optionalAccess', _211 => _211.split, 'call', _212 => _212(","), 'access', _213 => _213.filter, 'call', _214 => _214(Boolean)]);
3777
+ if (_optionalChain([ids, 'optionalAccess', _215 => _215.length])) for (const id of ids) target.dryPaint({ layerId: id, rect: rect ? sr(rect) : void 0 });
3545
3778
  else target.dryPaint({ rect: rect ? sr(rect) : void 0 });
3546
3779
  break;
3547
3780
  }
@@ -3572,7 +3805,7 @@ async function replayPainting(source, target, options = {}) {
3572
3805
  strokes++;
3573
3806
  if (!target.getLayer(st.layerId)) continue;
3574
3807
  const init = { layerId: st.layerId, color: st.color, brush: st.brush, seed: st.seed, copies: _nullishCoalesce(st.copies, () => ( [])), ...st.load ? { load: st.load } : {}, ...st.paint ? { paint: st.paint } : {}, snapToPerspective: false, stencils: false, maskStencils: (_nullishCoalesce(st.stencils, () => ( []))).map((x) => s === 1 ? x : scaleStencil(x, s)) };
3575
- if (st.brush.engine === "wet" && _optionalChain([st, 'access', _202 => _202.steps, 'optionalAccess', _203 => _203.length]) === st.points.length) {
3808
+ if (st.brush.engine === "wet" && _optionalChain([st, 'access', _216 => _216.steps, 'optionalAccess', _217 => _217.length]) === st.points.length) {
3576
3809
  await target.wetIdle();
3577
3810
  await advanceTo(st.steps[0]);
3578
3811
  const session = target.beginStroke({ ...init, start: st.points[0] });
@@ -3592,7 +3825,7 @@ async function replayPainting(source, target, options = {}) {
3592
3825
  await target.wetIdle();
3593
3826
  target.paintStroke({ ...init, points: st.points });
3594
3827
  }
3595
- await _optionalChain([options, 'access', _204 => _204.onStroke, 'optionalCall', _205 => _205(strokes)]);
3828
+ await _optionalChain([options, 'access', _218 => _218.onStroke, 'optionalCall', _219 => _219(strokes)]);
3596
3829
  }
3597
3830
  void IDENTITY_AFFINE;
3598
3831
  }
@@ -3637,7 +3870,7 @@ async function buildTimeLapse(source, target, options = {}) {
3637
3870
  wetChunk: wetEvery > 0 ? wetEvery : 0,
3638
3871
  onStroke: (i) => {
3639
3872
  if (i % perFrame === 0 || i === total) shoot(i);
3640
- _optionalChain([options, 'access', _206 => _206.onProgress, 'optionalCall', _207 => _207(total ? i / total : 1)]);
3873
+ _optionalChain([options, 'access', _220 => _220.onProgress, 'optionalCall', _221 => _221(total ? i / total : 1)]);
3641
3874
  },
3642
3875
  onWetSteps: wetEvery > 0 ? () => shoot(-1) : void 0
3643
3876
  });
@@ -3724,10 +3957,10 @@ function mixPixels(before, after, amount) {
3724
3957
  }
3725
3958
  return out;
3726
3959
  }
3727
- var PaintEffectsRenderer = (_class10 = class {constructor() { _class10.prototype.__init75.call(this);_class10.prototype.__init76.call(this);_class10.prototype.__init77.call(this); }
3728
- __init75() {this.pool = new (0, _chunkPY4GWSE2cjs.EffectRendererPool)({ maxRenderers: 3 })}
3729
- __init76() {this.descriptions = /* @__PURE__ */ new Map()}
3730
- __init77() {this.provider = null}
3960
+ var PaintEffectsRenderer = (_class11 = class {constructor() { _class11.prototype.__init79.call(this);_class11.prototype.__init80.call(this);_class11.prototype.__init81.call(this); }
3961
+ __init79() {this.pool = new (0, _chunkPY4GWSE2cjs.EffectRendererPool)({ maxRenderers: 3 })}
3962
+ __init80() {this.descriptions = /* @__PURE__ */ new Map()}
3963
+ __init81() {this.provider = null}
3731
3964
  /** Forgets cached descriptions and renderers when the provider changes. */
3732
3965
  follow(provider) {
3733
3966
  if (provider === this.provider) return;
@@ -3757,7 +3990,7 @@ var PaintEffectsRenderer = (_class10 = class {constructor() { _class10.prototype
3757
3990
  this.pool.clear();
3758
3991
  this.descriptions.clear();
3759
3992
  }
3760
- }, _class10);
3993
+ }, _class11);
3761
3994
  var sourceOut = (s) => ({
3762
3995
  effect: s.effect,
3763
3996
  ...s.provider ? { provider: s.provider } : {},
@@ -3812,7 +4045,7 @@ function parseColor(value, what = "color") {
3812
4045
  return value.trim().toLowerCase();
3813
4046
  }
3814
4047
  function rgbaOf(hex) {
3815
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, hex);
4048
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, hex);
3816
4049
  return [r, g, b, 255];
3817
4050
  }
3818
4051
  function rgbToHex(r, g, b) {
@@ -3825,90 +4058,93 @@ function unionRect(a, b) {
3825
4058
  const y = Math.min(a.y, b.y);
3826
4059
  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 };
3827
4060
  }
3828
- var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _208 => _208.type]) === "pixel";
3829
- var PaintEditorController = (_class11 = class _PaintEditorController {
4061
+ var isPixelLayer = (l) => _optionalChain([l, 'optionalAccess', _222 => _222.type]) === "pixel";
4062
+ var PaintEditorController = (_class12 = class _PaintEditorController {
3830
4063
 
3831
- __init78() {this.extensions = {}}
3832
- __init79() {this.undoStack = []}
3833
- __init80() {this.redoStack = []}
4064
+ __init82() {this.extensions = {}}
4065
+ __init83() {this.undoStack = []}
4066
+ __init84() {this.redoStack = []}
3834
4067
 
3835
4068
 
3836
4069
 
3837
4070
  /** The library list in the state (the same array until the user brushes change, so thumbnails are not redrawn). */
3838
- __init81() {this.library = null}
4071
+ __init85() {this.library = null}
3839
4072
 
3840
- __init82() {this.secondaryColor = "#ffffff"}
4073
+ __init86() {this.secondaryColor = "#ffffff"}
3841
4074
  /** Gradient paint chosen with `setPaint` (`null`: the paint colour). */
3842
- __init83() {this.gradient = null}
4075
+ __init87() {this.gradient = null}
3843
4076
  /** Effect paint chosen with `setEffectPaint` (rendered), and one still rendering. */
3844
- __init84() {this.effectPaint = null}
3845
- __init85() {this.effectPaintPending = null}
4077
+ __init88() {this.effectPaint = null}
4078
+ __init89() {this.effectPaintPending = null}
3846
4079
  /** Changes whenever the paint is chosen, so an effect paint that finishes rendering late does not take over. */
3847
- __init86() {this.paintEpoch = 0}
4080
+ __init90() {this.paintEpoch = 0}
3848
4081
  /** Rendered effect paints by `effectPaintKey` (most recently used last). */
3849
- __init87() {this.effectPaintPixels = /* @__PURE__ */ new Map()}
3850
- __init88() {this.mixerLoad = _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD}
3851
- __init89() {this.view = { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } }}
4082
+ __init91() {this.effectPaintPixels = /* @__PURE__ */ new Map()}
4083
+ __init92() {this.mixerLoad = _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD}
4084
+ __init93() {this.view = { ...DEFAULT_VIEW, pan: { ...DEFAULT_VIEW.pan } }}
3852
4085
 
3853
- __init90() {this.selectedStroke = null}
3854
- __init91() {this.selectedSticker = null}
4086
+ __init94() {this.selectedStroke = null}
4087
+ __init95() {this.selectedSticker = null}
3855
4088
  /** A sticker drag in progress (`previewSticker`): the document before it, so the drop undoes in one step, and the one it showed last. */
3856
- __init92() {this.stickerPreview = null}
4089
+ __init96() {this.stickerPreview = null}
3857
4090
 
3858
- __init93() {this.listeners = /* @__PURE__ */ new Set()}
3859
- __init94() {this.version = 0}
3860
- __init95() {this.cached = null}
3861
- __init96() {this.session = null}
3862
- __init97() {this.live = null}
3863
- __init98() {this.liveLayers = null}
3864
- __init99() {this.dirty = "all"}
3865
- __init100() {this.seedCounter = 1}
3866
- __init101() {this.strokeCounter = 1}
4091
+ __init97() {this.listeners = /* @__PURE__ */ new Set()}
4092
+ __init98() {this.version = 0}
4093
+ __init99() {this.cached = null}
4094
+ __init100() {this.session = null}
4095
+ __init101() {this.live = null}
4096
+ __init102() {this.liveLayers = null}
4097
+ __init103() {this.dirty = "all"}
4098
+ __init104() {this.seedCounter = 1}
4099
+ __init105() {this.strokeCounter = 1}
3867
4100
  /** Light paint: each layer's spill settings (saved with the document, not undo steps; missing = the defaults). */
3868
- __init102() {this.lightSpills = {}}
3869
- __init103() {this.lightCaches = /* @__PURE__ */ new Map()}
4101
+ __init106() {this.lightSpills = {}}
4102
+ __init107() {this.lightCaches = /* @__PURE__ */ new Map()}
4103
+ /** Backlit paper: the light through the paint as drawn (live strokes too), and as committed (its spill). */
4104
+ __init108() {this.backlightView = new BacklightCache()}
4105
+ __init109() {this.backlightCommitted = new BacklightCache()}
3870
4106
  /** Live effect paint: playing and the frame rate cap (editor state), and the time the view shows. */
3871
- __init104() {this.effectPlaybackState = { playing: true, fps: 30 }}
3872
- __init105() {this.effectTime = 0}
4107
+ __init110() {this.effectPlaybackState = { playing: true, fps: 30 }}
4108
+ __init111() {this.effectTime = 0}
3873
4109
  /** While a frame is drawn: the time live effect strokes are drawn at (else their own time). */
3874
- __init106() {this.liveEffectAt = null}
4110
+ __init112() {this.liveEffectAt = null}
3875
4111
  /** The view's stroke layers at `effectTime`, each with the document surface it was drawn from (stale once that changes). */
3876
- __init107() {this.animatedLayers = /* @__PURE__ */ new Map()}
4112
+ __init113() {this.animatedLayers = /* @__PURE__ */ new Map()}
3877
4113
  /** `renderAnimationFrame` / `withEffectTime`: layer surfaces at another time, for one render. */
3878
- __init108() {this.frameOverride = null}
4114
+ __init114() {this.frameOverride = null}
3879
4115
  /** The area each stroke painted (document pixels; `null`: nothing), learnt as it is painted or drawn, so a stroke layer edit redraws only where it changes (see `drawLiveStrokes`). */
3880
- __init109() {this.paintedBounds = /* @__PURE__ */ new WeakMap()}
4116
+ __init115() {this.paintedBounds = /* @__PURE__ */ new WeakMap()}
3881
4117
 
3882
- __init110() {this.swatches = DEFAULT_SWATCHES.map((s) => ({ ...s }))}
3883
- __init111() {this.pad = new MixingPad()}
3884
- __init112() {this.savedPads = []}
3885
- __init113() {this.nextPadId = 1}
3886
- __init114() {this.tracingVersion = 1}
3887
- __init115() {this.tracingCache = null}
3888
- __init116() {this.imagePixels = /* @__PURE__ */ new Map()}
3889
- __init117() {this.nextReferenceId = 1}
3890
- __init118() {this.viewCompositor = createPaintCompositor()}
3891
- __init119() {this.exportCompositor = createPaintCompositor()}
4118
+ __init116() {this.swatches = DEFAULT_SWATCHES.map((s) => ({ ...s }))}
4119
+ __init117() {this.pad = new MixingPad()}
4120
+ __init118() {this.savedPads = []}
4121
+ __init119() {this.nextPadId = 1}
4122
+ __init120() {this.tracingVersion = 1}
4123
+ __init121() {this.tracingCache = null}
4124
+ __init122() {this.imagePixels = /* @__PURE__ */ new Map()}
4125
+ __init123() {this.nextReferenceId = 1}
4126
+ __init124() {this.viewCompositor = createPaintCompositor()}
4127
+ __init125() {this.exportCompositor = createPaintCompositor()}
3892
4128
  /** Wet media: the simulation, its settings and time. */
3893
4129
 
3894
4130
 
3895
4131
  /** Where the light comes from for thick paint (saved with the document, not undo steps). */
3896
- __init120() {this.lighting = { ...DEFAULT_LIGHTING }}
3897
- __init121() {this.litCaches = /* @__PURE__ */ new Map()}
4132
+ __init126() {this.lighting = { ...DEFAULT_LIGHTING }}
4133
+ __init127() {this.litCaches = /* @__PURE__ */ new Map()}
3898
4134
  /** The live impasto stroke's channels. */
3899
- __init122() {this.liveThick = null}
4135
+ __init128() {this.liveThick = null}
3900
4136
  /** Set while an operation that changes wet paint runs: the simulation before it (for undo). */
3901
- __init123() {this.wetOp = null}
4137
+ __init129() {this.wetOp = null}
3902
4138
  /** The effects provider slot (see `setEffectsProvider`). */
3903
- __init124() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
3904
- __init125() {this.effectsRenderer = new PaintEffectsRenderer()}
3905
- __init126() {this.paperEffectNodeCache = null}
3906
- constructor(options = {}) {;_class11.prototype.__init78.call(this);_class11.prototype.__init79.call(this);_class11.prototype.__init80.call(this);_class11.prototype.__init81.call(this);_class11.prototype.__init82.call(this);_class11.prototype.__init83.call(this);_class11.prototype.__init84.call(this);_class11.prototype.__init85.call(this);_class11.prototype.__init86.call(this);_class11.prototype.__init87.call(this);_class11.prototype.__init88.call(this);_class11.prototype.__init89.call(this);_class11.prototype.__init90.call(this);_class11.prototype.__init91.call(this);_class11.prototype.__init92.call(this);_class11.prototype.__init93.call(this);_class11.prototype.__init94.call(this);_class11.prototype.__init95.call(this);_class11.prototype.__init96.call(this);_class11.prototype.__init97.call(this);_class11.prototype.__init98.call(this);_class11.prototype.__init99.call(this);_class11.prototype.__init100.call(this);_class11.prototype.__init101.call(this);_class11.prototype.__init102.call(this);_class11.prototype.__init103.call(this);_class11.prototype.__init104.call(this);_class11.prototype.__init105.call(this);_class11.prototype.__init106.call(this);_class11.prototype.__init107.call(this);_class11.prototype.__init108.call(this);_class11.prototype.__init109.call(this);_class11.prototype.__init110.call(this);_class11.prototype.__init111.call(this);_class11.prototype.__init112.call(this);_class11.prototype.__init113.call(this);_class11.prototype.__init114.call(this);_class11.prototype.__init115.call(this);_class11.prototype.__init116.call(this);_class11.prototype.__init117.call(this);_class11.prototype.__init118.call(this);_class11.prototype.__init119.call(this);_class11.prototype.__init120.call(this);_class11.prototype.__init121.call(this);_class11.prototype.__init122.call(this);_class11.prototype.__init123.call(this);_class11.prototype.__init124.call(this);_class11.prototype.__init125.call(this);_class11.prototype.__init126.call(this);_class11.prototype.__init127.call(this);_class11.prototype.__init128.call(this);_class11.prototype.__init129.call(this);_class11.prototype.__init130.call(this);
4139
+ __init130() {this.effects = new (0, _chunkGHCSC2WPcjs.EffectsSlot)()}
4140
+ __init131() {this.effectsRenderer = new PaintEffectsRenderer()}
4141
+ __init132() {this.paperEffectNodeCache = null}
4142
+ constructor(options = {}) {;_class12.prototype.__init82.call(this);_class12.prototype.__init83.call(this);_class12.prototype.__init84.call(this);_class12.prototype.__init85.call(this);_class12.prototype.__init86.call(this);_class12.prototype.__init87.call(this);_class12.prototype.__init88.call(this);_class12.prototype.__init89.call(this);_class12.prototype.__init90.call(this);_class12.prototype.__init91.call(this);_class12.prototype.__init92.call(this);_class12.prototype.__init93.call(this);_class12.prototype.__init94.call(this);_class12.prototype.__init95.call(this);_class12.prototype.__init96.call(this);_class12.prototype.__init97.call(this);_class12.prototype.__init98.call(this);_class12.prototype.__init99.call(this);_class12.prototype.__init100.call(this);_class12.prototype.__init101.call(this);_class12.prototype.__init102.call(this);_class12.prototype.__init103.call(this);_class12.prototype.__init104.call(this);_class12.prototype.__init105.call(this);_class12.prototype.__init106.call(this);_class12.prototype.__init107.call(this);_class12.prototype.__init108.call(this);_class12.prototype.__init109.call(this);_class12.prototype.__init110.call(this);_class12.prototype.__init111.call(this);_class12.prototype.__init112.call(this);_class12.prototype.__init113.call(this);_class12.prototype.__init114.call(this);_class12.prototype.__init115.call(this);_class12.prototype.__init116.call(this);_class12.prototype.__init117.call(this);_class12.prototype.__init118.call(this);_class12.prototype.__init119.call(this);_class12.prototype.__init120.call(this);_class12.prototype.__init121.call(this);_class12.prototype.__init122.call(this);_class12.prototype.__init123.call(this);_class12.prototype.__init124.call(this);_class12.prototype.__init125.call(this);_class12.prototype.__init126.call(this);_class12.prototype.__init127.call(this);_class12.prototype.__init128.call(this);_class12.prototype.__init129.call(this);_class12.prototype.__init130.call(this);_class12.prototype.__init131.call(this);_class12.prototype.__init132.call(this);_class12.prototype.__init133.call(this);_class12.prototype.__init134.call(this);_class12.prototype.__init135.call(this);_class12.prototype.__init136.call(this);
3907
4143
  this.historyLimit = Math.max(1, _nullishCoalesce(options.historyLimit, () => ( 200)));
3908
4144
  this.doc = createPaintDocument({ width: options.width, height: options.height, dpi: options.dpi, paper: this.resolvePaper(options.paper) });
3909
- this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
3910
- const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunk5FZS7J7Ccjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunk5FZS7J7Ccjs.DEFAULT_BRUSH_ID)));
3911
- this.brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, start);
4145
+ this.userBrushes = (_nullishCoalesce(options.brushes, () => ( []))).map((b) => _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...b, builtin: false }));
4146
+ const start = _nullishCoalesce(this.findBrush(_nullishCoalesce(options.brushId, () => ( _chunk4T47Z4J3cjs.DEFAULT_BRUSH_ID))), () => ( this.findBrush(_chunk4T47Z4J3cjs.DEFAULT_BRUSH_ID)));
4147
+ this.brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, start);
3912
4148
  this.color = options.color ? parseColor(options.color) : "#1f2937";
3913
4149
  this.hand = options.hand === "left" ? "left" : "right";
3914
4150
  this.encodeImage = options.encodeImage;
@@ -3919,7 +4155,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
3919
4155
  canvas: () => this.doc.canvas,
3920
4156
  paper: () => this.doc.paper,
3921
4157
  layerSurface: (id) => {
3922
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _209 => _209.layer]);
4158
+ const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _223 => _223.layer]);
3923
4159
  return isPixelLayer(l) ? l.surface : null;
3924
4160
  },
3925
4161
  updateSurfaces: (surfaces, rects) => {
@@ -3928,12 +4164,18 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
3928
4164
  this.doc = { ...this.doc, layers };
3929
4165
  this.emit(rects.length ? rects : "all");
3930
4166
  },
4167
+ layerLight: (id) => _nullishCoalesce(_optionalChain([this, 'access', _224 => _224.doc, 'access', _225 => _225.light, 'optionalAccess', _226 => _226[id]]), () => ( null)),
4168
+ updateLights: (lights) => {
4169
+ let light = this.doc.light;
4170
+ for (const [id, surface] of lights) if (_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) light = withLayerLight(light, id, surface);
4171
+ this.doc = { ...this.doc, ...light ? { light } : {} };
4172
+ },
3931
4173
  changed: () => {
3932
4174
  }
3933
4175
  },
3934
4176
  options.wet
3935
4177
  );
3936
- this.wet.onDriverDone = () => _optionalChain([this, 'access', _210 => _210.session, 'optionalAccess', _211 => _211.completeWetEnd, 'call', _212 => _212()]);
4178
+ this.wet.onDriverDone = () => _optionalChain([this, 'access', _227 => _227.session, 'optionalAccess', _228 => _228.completeWetEnd, 'call', _229 => _229()]);
3937
4179
  }
3938
4180
  // --- State and events ----------------------------------------------------------
3939
4181
  subscribe(listener) {
@@ -3955,7 +4197,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
3955
4197
  this.cached = {
3956
4198
  document: this.doc,
3957
4199
  brush: this.brush,
3958
- brushes: this.library ??= [..._chunk5FZS7J7Ccjs.BUILTIN_BRUSHES, ...this.userBrushes],
4200
+ brushes: this.library ??= [..._chunk4T47Z4J3cjs.BUILTIN_BRUSHES, ...this.userBrushes],
3959
4201
  color: this.color,
3960
4202
  secondaryColor: this.secondaryColor,
3961
4203
  paint: _nullishCoalesce(this.gradient, () => ( { type: "color", color: this.color })),
@@ -3969,8 +4211,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
3969
4211
  selectedSticker: this.selectedSticker,
3970
4212
  canUndo: this.undoStack.length > 0 && !this.session,
3971
4213
  canRedo: this.redoStack.length > 0 && !this.session,
3972
- undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _213 => _213.label]), () => ( null)),
3973
- redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _214 => _214.label]), () => ( null)),
4214
+ undoLabel: _nullishCoalesce(_optionalChain([last, 'optionalAccess', _230 => _230.label]), () => ( null)),
4215
+ redoLabel: _nullishCoalesce(_optionalChain([next, 'optionalAccess', _231 => _231.label]), () => ( null)),
3974
4216
  guides: this.guides,
3975
4217
  swatches: this.swatches,
3976
4218
  mixingPadVersion: this.pad.version,
@@ -3983,10 +4225,10 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
3983
4225
  overlay: this.wet.overlay,
3984
4226
  instantDry: this.wet.instantDry,
3985
4227
  speed: this.wet.speed,
3986
- clock: _nullishCoalesce(_optionalChain([this, 'access', _215 => _215.wet, 'access', _216 => _216.world, 'optionalAccess', _217 => _217.clock]), () => ( 0)),
4228
+ clock: _nullishCoalesce(_optionalChain([this, 'access', _232 => _232.wet, 'access', _233 => _233.world, 'optionalAccess', _234 => _234.clock]), () => ( 0)),
3987
4229
  tilt: { ...this.wet.tilt },
3988
4230
  gpu: this.wet.gpuMode,
3989
- gpuActive: Boolean(_optionalChain([this, 'access', _218 => _218.wet, 'access', _219 => _219.world, 'optionalAccess', _220 => _220.gpuActive]))
4231
+ gpuActive: Boolean(_optionalChain([this, 'access', _235 => _235.wet, 'access', _236 => _236.world, 'optionalAccess', _237 => _237.gpuActive]))
3990
4232
  },
3991
4233
  version: this.version
3992
4234
  };
@@ -4005,7 +4247,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4005
4247
  return d;
4006
4248
  }
4007
4249
  // --- History -------------------------------------------------------------------
4008
- __init127() {this.docRevision = 0}
4250
+ __init133() {this.docRevision = 0}
4009
4251
  /**
4010
4252
  * Bumped on every change to the painting (a committed or amended step, undo, redo, opening a
4011
4253
  * document), not on wet-paint frames or view changes. `createPaintEditorDocument` uses it.
@@ -4088,9 +4330,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4088
4330
  return wetIds;
4089
4331
  }
4090
4332
  /** Records a wet event (for replays) in the document being built. */
4091
- __init128() {this.pendingWetEvents = []}
4333
+ __init134() {this.pendingWetEvents = []}
4092
4334
  logWet(e) {
4093
- this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _221 => _221.wet, 'access', _222 => _222.world, 'optionalAccess', _223 => _223.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
4335
+ this.pendingWetEvents.push({ clock: _nullishCoalesce(_optionalChain([this, 'access', _238 => _238.wet, 'access', _239 => _239.world, 'optionalAccess', _240 => _240.clock]), () => ( 0)), at: this.doc.strokes.length, ...e });
4094
4336
  }
4095
4337
  /** The document with a paint event appended (for replays). */
4096
4338
  withPaintEvent(doc, e) {
@@ -4151,7 +4393,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4151
4393
  // --- Canvas and paper ----------------------------------------------------------
4152
4394
  resolvePaper(paper) {
4153
4395
  if (typeof paper === "string") {
4154
- const p = _chunk5FZS7J7Ccjs.paperPreset.call(void 0, paper);
4396
+ const p = _chunk4T47Z4J3cjs.paperPreset.call(void 0, paper);
4155
4397
  if (!p) throw new PaintEditorError(`Unknown paper "${paper}". Call list_papers for the ids.`);
4156
4398
  return p;
4157
4399
  }
@@ -4234,7 +4476,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4234
4476
  }
4235
4477
  let next = { ...shiftDocument(this.withWetEvents(this.doc), left, top), canvas: { ...was, width, height } };
4236
4478
  for (const id of keptWet) {
4237
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _224 => _224.layer]);
4479
+ const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, next.layers, id), 'optionalAccess', _241 => _241.layer]);
4238
4480
  if (isPixelLayer(l)) next = { ...next, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, next.layers, id, () => ({ ...l, surface: _chunk474IQG74cjs.translateSurface.call(void 0, l.surface, l.offset.x, l.offset.y), offset: { x: 0, y: 0 } })) };
4239
4481
  }
4240
4482
  if (this.wet.world) {
@@ -4262,23 +4504,23 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4262
4504
  this.requireIdle("changing the paper");
4263
4505
  let base = this.doc.paper;
4264
4506
  if (update.preset !== void 0 && update.preset !== this.doc.paper.preset) {
4265
- const p = _chunk5FZS7J7Ccjs.paperPreset.call(void 0, update.preset);
4507
+ const p = _chunk4T47Z4J3cjs.paperPreset.call(void 0, update.preset);
4266
4508
  if (!p) throw new PaintEditorError(`Unknown paper "${update.preset}". Call list_papers for the ids.`);
4267
4509
  base = p;
4268
4510
  }
4269
4511
  const { preset: _p, ...rest } = update;
4270
4512
  if (rest.color !== void 0) parseColor(rest.color, "paper color");
4271
- const paper = _chunk5FZS7J7Ccjs.normalizePaper.call(void 0, { ...rest, preset: base.preset, offset: _nullishCoalesce(rest.offset, () => ( this.doc.paper.offset)) }, base);
4513
+ const paper = _chunk4T47Z4J3cjs.normalizePaper.call(void 0, { ...rest, preset: base.preset, offset: _nullishCoalesce(rest.offset, () => ( this.doc.paper.offset)) }, base);
4272
4514
  const changedKeys = Object.keys(rest).filter((k) => k !== "name");
4273
4515
  if (changedKeys.length && update.preset === void 0) paper.preset = base.preset;
4274
4516
  if (this.wet.world) this.beginWetOp();
4275
4517
  this.commit("Paper", { ...this.doc, paper });
4276
4518
  this.wet.paperChanged();
4277
- return _chunk5FZS7J7Ccjs.clonePaper.call(void 0, paper);
4519
+ return _chunk4T47Z4J3cjs.clonePaper.call(void 0, paper);
4278
4520
  }
4279
4521
  // --- Layers --------------------------------------------------------------------
4280
4522
  getLayer(id) {
4281
- return _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _225 => _225.layer]);
4523
+ return _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _242 => _242.layer]);
4282
4524
  }
4283
4525
  /** The active pixel layer (or `undefined`). */
4284
4526
  getActiveLayer() {
@@ -4297,7 +4539,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4297
4539
  walk(this.doc.layers, null, 0);
4298
4540
  return out;
4299
4541
  }
4300
- describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _226 => _226.parent, 'optionalAccess', _227 => _227.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _228 => _228.path, 'access', _229 => _229.length]), () => ( 0))) {
4542
+ describeLayer(l, parentId = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _243 => _243.parent, 'optionalAccess', _244 => _244.id]), () => ( null)), depth = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, l.id), 'optionalAccess', _245 => _245.path, 'access', _246 => _246.length]), () => ( 0))) {
4301
4543
  let bounds = null;
4302
4544
  if (l.type === "pixel") {
4303
4545
  const b = _chunk474IQG74cjs.contentBounds.call(void 0, l.surface);
@@ -4314,7 +4556,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4314
4556
  locks: { ..._nullishCoalesce(l.locks, () => ( {})) },
4315
4557
  active: l.id === this.doc.activeLayerId,
4316
4558
  bounds,
4317
- ..._optionalChain([this, 'access', _230 => _230.doc, 'access', _231 => _231.liveStrokes, 'optionalAccess', _232 => _232[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
4559
+ ..._optionalChain([this, 'access', _247 => _247.doc, 'access', _248 => _248.liveStrokes, 'optionalAccess', _249 => _249[l.id]]) ? { liveStrokes: this.doc.liveStrokes[l.id].length } : {},
4318
4560
  parentId,
4319
4561
  depth
4320
4562
  };
@@ -4346,7 +4588,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4346
4588
  this.requireIdle("adding a layer");
4347
4589
  const count = _chunkHB4ICNNAcjs.flattenLayers.call(void 0, this.doc.layers).length;
4348
4590
  const type = _nullishCoalesce(options.type, () => ( "pixel"));
4349
- const name = _optionalChain([options, 'access', _233 => _233.name, 'optionalAccess', _234 => _234.trim, 'call', _235 => _235()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
4591
+ const name = _optionalChain([options, 'access', _250 => _250.name, 'optionalAccess', _251 => _251.trim, 'call', _252 => _252()]) || (type === "group" ? `Group ${count + 1}` : type === "strokes" ? `Strokes ${count + 1}` : `Layer ${count + 1}`);
4350
4592
  const layer = type === "group" ? { type: "group", id: newPaintLayerId(), name, visible: true, opacity: 1, blend: "pass-through", children: [] } : createPaintLayer(name);
4351
4593
  let parentId = null;
4352
4594
  let index;
@@ -4358,7 +4600,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4358
4600
  } else if (above) {
4359
4601
  const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, above);
4360
4602
  if (!loc) throw new PaintEditorError(`Unknown layer "${above}". Call list_layers for the ids.`);
4361
- parentId = _nullishCoalesce(_optionalChain([loc, 'access', _236 => _236.parent, 'optionalAccess', _237 => _237.id]), () => ( null));
4603
+ parentId = _nullishCoalesce(_optionalChain([loc, 'access', _253 => _253.parent, 'optionalAccess', _254 => _254.id]), () => ( null));
4362
4604
  index = loc.index + 1;
4363
4605
  }
4364
4606
  const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, layer, parentId, index);
@@ -4399,7 +4641,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4399
4641
  }
4400
4642
  const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, id, () => null);
4401
4643
  let active = this.doc.activeLayerId;
4402
- if (active && !_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers), 'access', _238 => _238.filter, 'call', _239 => _239((x) => x.type === "pixel"), 'access', _240 => _240.pop, 'call', _241 => _241(), 'optionalAccess', _242 => _242.id]), () => ( null));
4644
+ if (active && !_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, active)) active = _nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.flattenLayers.call(void 0, layers), 'access', _255 => _255.filter, 'call', _256 => _256((x) => x.type === "pixel"), 'access', _257 => _257.pop, 'call', _258 => _258(), 'optionalAccess', _259 => _259.id]), () => ( null));
4403
4645
  this.commit("Remove layer", { ...this.doc, layers, activeLayerId: active, ...this.thickWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.stickersWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.liveStrokesWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)), ...this.lightWithout(_chunkHB4ICNNAcjs.flattenLayers.call(void 0, [l]).map((x) => x.id)) });
4404
4646
  return { removed: id, activeLayerId: active };
4405
4647
  }
@@ -4425,7 +4667,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4425
4667
  return l.type === "group" ? { ...l, id: id2, children: l.children.map(copy) } : { ...l, id: id2 };
4426
4668
  };
4427
4669
  const dup = { ...copy(loc.layer), name: `${loc.layer.name} copy` };
4428
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _243 => _243.parent, 'optionalAccess', _244 => _244.id]), () => ( null)), loc.index + 1);
4670
+ const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, dup, _nullishCoalesce(_optionalChain([loc, 'access', _260 => _260.parent, 'optionalAccess', _261 => _261.id]), () => ( null)), loc.index + 1);
4429
4671
  this.commit("Duplicate layer", this.withWetEvents({ ...this.doc, layers, activeLayerId: dup.id, ...this.doc.thick ? { thick } : {}, ...this.doc.stickers ? { stickers } : {}, ...this.doc.liveStrokes ? { liveStrokes } : {}, ...this.doc.light ? { light } : {} }));
4430
4672
  return this.describeLayer(dup);
4431
4673
  }
@@ -4434,7 +4676,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4434
4676
  this.requireIdle("moving a layer");
4435
4677
  const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4436
4678
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
4437
- const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _245 => _245.parent, 'optionalAccess', _246 => _246.id]), () => ( null)) : parentId;
4679
+ const target = parentId === void 0 ? _nullishCoalesce(_optionalChain([loc, 'access', _262 => _262.parent, 'optionalAccess', _263 => _263.id]), () => ( null)) : parentId;
4438
4680
  if (target) {
4439
4681
  const g = this.requireLayer(target);
4440
4682
  if (g.type !== "group") throw new PaintEditorError(`Layer "${g.name}" is not a group; pass a group id as parentId.`);
@@ -4453,7 +4695,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4453
4695
  const pre = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4454
4696
  if (pre) {
4455
4697
  const sib = pre.parent ? pre.parent.children : this.doc.layers;
4456
- this.dryLayersFirst([id, _optionalChain([sib, 'access', _247 => _247[pre.index - 1], 'optionalAccess', _248 => _248.id])].filter((x) => Boolean(x)));
4698
+ this.dryLayersFirst([id, _optionalChain([sib, 'access', _264 => _264[pre.index - 1], 'optionalAccess', _265 => _265.id])].filter((x) => Boolean(x)));
4457
4699
  }
4458
4700
  const loc = _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id);
4459
4701
  if (!loc) throw new PaintEditorError(`Unknown layer "${id}". Call list_layers for the ids.`);
@@ -4473,7 +4715,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4473
4715
  const merged = { ...below, surface, offset: { x: 0, y: 0 } };
4474
4716
  const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, upper.id, () => null), below.id, () => merged);
4475
4717
  const toDoc = (t, l) => t ? _chunk474IQG74cjs.translateSurface.call(void 0, t, l.offset.x, l.offset.y) : void 0;
4476
- const mergedLight = _optionalChain([this, 'access', _249 => _249.doc, 'access', _250 => _250.light, 'optionalAccess', _251 => _251[upper.id]]) || _optionalChain([this, 'access', _252 => _252.doc, 'access', _253 => _253.light, 'optionalAccess', _254 => _254[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _255 => _255.doc, 'access', _256 => _256.light, 'optionalAccess', _257 => _257[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _258 => _258.doc, 'access', _259 => _259.light, 'optionalAccess', _260 => _260[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
4718
+ const mergedLight = _optionalChain([this, 'access', _266 => _266.doc, 'access', _267 => _267.light, 'optionalAccess', _268 => _268[upper.id]]) || _optionalChain([this, 'access', _269 => _269.doc, 'access', _270 => _270.light, 'optionalAccess', _271 => _271[below.id]]) ? mergeLight(toDoc(_optionalChain([this, 'access', _272 => _272.doc, 'access', _273 => _273.light, 'optionalAccess', _274 => _274[below.id]]), below), upper.visible ? toDoc(_optionalChain([this, 'access', _275 => _275.doc, 'access', _276 => _276.light, 'optionalAccess', _277 => _277[upper.id]]), upper) : void 0, _chunk474IQG74cjs.translateSurface.call(void 0, upper.surface, upper.offset.x, upper.offset.y)) : void 0;
4477
4719
  const lightAfter = _nullishCoalesce(this.lightWithout([upper.id, below.id]).light, () => ( (this.doc.light ? { ...this.doc.light } : void 0)));
4478
4720
  const light = mergedLight ? { ..._nullishCoalesce(lightAfter, () => ( {})), [below.id]: mergedLight } : lightAfter;
4479
4721
  this.commit("Merge down", this.withWetEvents({ ...this.doc, layers, activeLayerId: below.id, ...this.thickWithout([upper.id]), ...this.stickersWithout([upper.id, below.id]), ...this.liveStrokesWithout([upper.id, below.id]), ...light ? { light } : {} }));
@@ -4488,7 +4730,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4488
4730
  this.wet.world.removeLane(l.id);
4489
4731
  }
4490
4732
  const bounds = this.describeLayer(l).bounds;
4491
- this.commit("Clear layer", this.withPaintEvent({ ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4) })), ...this.thickWithout([l.id]), ...this.stickersWithout([l.id]), ..._optionalChain([this, 'access', _261 => _261.doc, 'access', _262 => _262.liveStrokes, 'optionalAccess', _263 => _263[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
4733
+ this.commit("Clear layer", this.withPaintEvent({ ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface: _chunk474IQG74cjs.emptySurface.call(void 0, 4) })), ...this.thickWithout([l.id]), ...this.stickersWithout([l.id]), ..._optionalChain([this, 'access', _278 => _278.doc, 'access', _279 => _279.liveStrokes, 'optionalAccess', _280 => _280[l.id]]) ? { liveStrokes: { ...this.doc.liveStrokes, [l.id]: [] } } : {}, ...this.lightWithout([l.id]) }, { kind: "clear", layerId: l.id }));
4492
4734
  return { layerId: l.id, bounds };
4493
4735
  }
4494
4736
  /**
@@ -4498,8 +4740,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4498
4740
  fillLayer(options = {}) {
4499
4741
  this.requireIdle("filling");
4500
4742
  const fillTarget = this.paintTarget(options.layerId, "fill");
4501
- if (_optionalChain([this, 'access', _264 => _264.doc, 'access', _265 => _265.stickers, 'optionalAccess', _266 => _266[fillTarget.id], 'optionalAccess', _267 => _267.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
4502
- if (_optionalChain([this, 'access', _268 => _268.doc, 'access', _269 => _269.liveStrokes, 'optionalAccess', _270 => _270[fillTarget.id]])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a stroke layer (its pixels are drawn from its strokes); fill another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
4743
+ if (_optionalChain([this, 'access', _281 => _281.doc, 'access', _282 => _282.stickers, 'optionalAccess', _283 => _283[fillTarget.id], 'optionalAccess', _284 => _284.length])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a sticker layer; fill another layer (add_layer).`);
4744
+ if (_optionalChain([this, 'access', _285 => _285.doc, 'access', _286 => _286.liveStrokes, 'optionalAccess', _287 => _287[fillTarget.id]])) throw new PaintEditorError(`Layer "${fillTarget.name}" is a stroke layer (its pixels are drawn from its strokes); fill another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
4503
4745
  this.dryLayersFirst([_nullishCoalesce(_nullishCoalesce(options.layerId, () => ( this.doc.activeLayerId)), () => ( ""))]);
4504
4746
  const l = this.paintTarget(options.layerId, "fill");
4505
4747
  const color = options.color === void 0 ? this.color : parseColor(options.color);
@@ -4532,7 +4774,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4532
4774
  offset: l.offset
4533
4775
  };
4534
4776
  const surface = this.applyCoverage(l, coverage, rect, apply);
4535
- const lit = _optionalChain([this, 'access', _271 => _271.doc, 'access', _272 => _272.light, 'optionalAccess', _273 => _273[l.id]]);
4777
+ const lit = _optionalChain([this, 'access', _288 => _288.doc, 'access', _289 => _289.light, 'optionalAccess', _290 => _290[l.id]]);
4536
4778
  const light = lit ? withLayerLight(this.doc.light, l.id, scaleLight(lit, 1 - opacity)) : void 0;
4537
4779
  this.commit("Fill layer", this.withPaintEvent(this.withWetEvents({ ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), ...light ? { light } : {} }), { kind: "fill", layerId: l.id, data: { color, opacity, grain: grainAmount, pressure, blend } }));
4538
4780
  return { layerId: l.id, bounds: rect };
@@ -4542,7 +4784,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4542
4784
  const tiles = new Map(base.tiles);
4543
4785
  for (const { tx, ty } of _chunk474IQG74cjs.tilesInRect.call(void 0, { x: rect.x - l.offset.x, y: rect.y - l.offset.y, width: rect.width, height: rect.height })) {
4544
4786
  const key = _chunk474IQG74cjs.tileKey.call(void 0, tx, ty);
4545
- const src = _nullishCoalesce(_optionalChain([base, 'access', _274 => _274.tiles, 'access', _275 => _275.get, 'call', _276 => _276(key), 'optionalAccess', _277 => _277.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
4787
+ const src = _nullishCoalesce(_optionalChain([base, 'access', _291 => _291.tiles, 'access', _292 => _292.get, 'call', _293 => _293(key), 'optionalAccess', _294 => _294.data]), () => ( new Uint8ClampedArray(_chunk474IQG74cjs.TILE * _chunk474IQG74cjs.TILE * 4)));
4546
4788
  const tile = _chunk474IQG74cjs.finishTile.call(void 0, _chunkPQ3H2AANcjs.applyStrokeToTile.call(void 0, coverage, src, 4, tx, ty, apply), 4, 0);
4547
4789
  if (tile) tiles.set(key, tile);
4548
4790
  else tiles.delete(key);
@@ -4575,7 +4817,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4575
4817
  }
4576
4818
  /** The effect a layer is drawn from, or `undefined` for other layers. */
4577
4819
  getEffectLayer(layerId) {
4578
- return _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _278 => _278.doc, 'access', _279 => _279.effectLayers, 'optionalAccess', _280 => _280[layerId]]) : void 0;
4820
+ return _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId) ? _optionalChain([this, 'access', _295 => _295.doc, 'access', _296 => _296.effectLayers, 'optionalAccess', _297 => _297[layerId]]) : void 0;
4579
4821
  }
4580
4822
  /** The effect paper (without its pixels), or `null`. */
4581
4823
  getPaperEffect() {
@@ -4612,8 +4854,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4612
4854
  /** A pixel layer that takes effect pixels: unlocked, visible, no sticker layer, no wet paint. */
4613
4855
  effectTarget(layerId, what) {
4614
4856
  const l = this.paintTarget(layerId, what);
4615
- if (_optionalChain([this, 'access', _281 => _281.doc, 'access', _282 => _282.stickers, 'optionalAccess', _283 => _283[l.id], 'optionalAccess', _284 => _284.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
4616
- if (_optionalChain([this, 'access', _285 => _285.doc, 'access', _286 => _286.liveStrokes, 'optionalAccess', _287 => _287[l.id]])) throw new PaintEditorError(`Layer "${l.name}" is a stroke layer (its pixels are drawn from its strokes); ${what} another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
4857
+ if (_optionalChain([this, 'access', _298 => _298.doc, 'access', _299 => _299.stickers, 'optionalAccess', _300 => _300[l.id], 'optionalAccess', _301 => _301.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; ${what} another layer (add_layer).`);
4858
+ if (_optionalChain([this, 'access', _302 => _302.doc, 'access', _303 => _303.liveStrokes, 'optionalAccess', _304 => _304[l.id]])) throw new PaintEditorError(`Layer "${l.name}" is a stroke layer (its pixels are drawn from its strokes); ${what} another layer (add_layer), or rasterize it first (rasterize_stroke_layer).`);
4617
4859
  if (this.wet.wetLayerIds().includes(l.id)) throw new PaintEditorError(`Layer "${l.name}" holds wet paint; effects go on dried paint, so dry it first (dry_paint) and try again.`);
4618
4860
  return l;
4619
4861
  }
@@ -4652,8 +4894,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4652
4894
  const was = this.doc.paperEffect;
4653
4895
  const paperEffect = {
4654
4896
  ...this.sourceOf(d, values, options.time),
4655
- opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _288 => _288.opacity]))), () => ( 1)),
4656
- blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _289 => _289.blend]))), () => ( "multiply")),
4897
+ opacity: _nullishCoalesce(_nullishCoalesce(options.opacity, () => ( _optionalChain([was, 'optionalAccess', _305 => _305.opacity]))), () => ( 1)),
4898
+ blend: _nullishCoalesce(_nullishCoalesce(options.blend, () => ( _optionalChain([was, 'optionalAccess', _306 => _306.blend]))), () => ( "multiply")),
4657
4899
  image: { width: pixels.width, height: pixels.height, data: new Uint8ClampedArray(pixels.data) },
4658
4900
  version: nextPaperEffectVersion()
4659
4901
  };
@@ -4706,8 +4948,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4706
4948
  const above = _nullishCoalesce(options.aboveId, () => ( this.doc.activeLayerId));
4707
4949
  const loc = above ? _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, above) : null;
4708
4950
  if (options.aboveId !== void 0 && !loc) throw new PaintEditorError(`Layer "${options.aboveId}" was removed while the effect rendered.`);
4709
- const layer = { ...createPaintLayer(_optionalChain([options, 'access', _290 => _290.name, 'optionalAccess', _291 => _291.trim, 'call', _292 => _292()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
4710
- const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _293 => _293.parent, 'optionalAccess', _294 => _294.id]), () => ( null)), loc ? loc.index + 1 : void 0);
4951
+ const layer = { ...createPaintLayer(_optionalChain([options, 'access', _307 => _307.name, 'optionalAccess', _308 => _308.trim, 'call', _309 => _309()]) || d.name), surface: _chunk474IQG74cjs.surfaceFromPixels.call(void 0, pixels, 4), opacity: _nullishCoalesce(options.opacity, () => ( 1)), blend: _nullishCoalesce(options.blend, () => ( "normal")) };
4952
+ const layers = _chunkHB4ICNNAcjs.insertLayer.call(void 0, this.doc.layers, layer, _nullishCoalesce(_optionalChain([loc, 'optionalAccess', _310 => _310.parent, 'optionalAccess', _311 => _311.id]), () => ( null)), loc ? loc.index + 1 : void 0);
4711
4953
  const source = this.sourceOf(d, values, options.time);
4712
4954
  this.commit("Add effect layer", { ...this.doc, layers, activeLayerId: layer.id, effectLayers: { ..._nullishCoalesce(this.doc.effectLayers, () => ( {})), [layer.id]: source } });
4713
4955
  return { layer: this.describeLayer(layer), source };
@@ -4785,7 +5027,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4785
5027
  this.checkTime(source.time);
4786
5028
  let map;
4787
5029
  try {
4788
- map = _chunk5FZS7J7Ccjs.readEffectStrokeMap.call(void 0, source.map);
5030
+ map = _chunk4T47Z4J3cjs.readEffectStrokeMap.call(void 0, source.map);
4789
5031
  } catch (e) {
4790
5032
  throw new PaintEditorError(e.message);
4791
5033
  }
@@ -4816,9 +5058,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4816
5058
  }
4817
5059
  /** The rendered pixels of an effect paint at the current canvas size, or `null` when it has not been rendered. */
4818
5060
  effectPaintImage(p) {
4819
- const key = _chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, p);
5061
+ const key = _chunk4T47Z4J3cjs.effectPaintKey.call(void 0, p);
4820
5062
  const img = this.effectPaintPixels.get(key);
4821
- const size = _chunk5FZS7J7Ccjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5063
+ const size = _chunk4T47Z4J3cjs.effectPaintSize.call(void 0, p, this.doc.canvas);
4822
5064
  if (!img || img.width !== size.width || img.height !== size.height) return null;
4823
5065
  this.effectPaintPixels.delete(key);
4824
5066
  this.effectPaintPixels.set(key, img);
@@ -4832,7 +5074,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4832
5074
  const what = `the effect "${p.effect}"${p.provider ? ` from provider "${p.provider}"` : ""}`;
4833
5075
  if (!provider) throw new PaintEditorError(`Effect paint needs ${what}, but no effects provider is registered; register it (setEffectsProvider) and try again.`);
4834
5076
  if (p.provider && provider.id !== p.provider) throw new PaintEditorError(`Effect paint needs ${what}, but the registered provider is "${provider.id}"; register "${p.provider}" (setEffectsProvider) and try again.`);
4835
- const { width, height } = _chunk5FZS7J7Ccjs.effectPaintSize.call(void 0, p, this.doc.canvas);
5077
+ const { width, height } = _chunk4T47Z4J3cjs.effectPaintSize.call(void 0, p, this.doc.canvas);
4836
5078
  let pixels;
4837
5079
  try {
4838
5080
  pixels = await this.effectsRenderer.render(provider, p.effect, { width, height }, { time: p.time, values: p.values });
@@ -4840,7 +5082,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4840
5082
  throw new PaintEditorError(`Effect paint could not render ${what}: ${e instanceof Error ? e.message : String(e)}`);
4841
5083
  }
4842
5084
  const img = { width, height, data: new Uint8ClampedArray(pixels.data), ...p.map ? { map: p.map } : {} };
4843
- this.effectPaintPixels.set(_chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, p), img);
5085
+ this.effectPaintPixels.set(_chunk4T47Z4J3cjs.effectPaintKey.call(void 0, p), img);
4844
5086
  while (this.effectPaintPixels.size > _PaintEditorController.EFFECT_PAINT_CACHE) this.effectPaintPixels.delete(this.effectPaintPixels.keys().next().value);
4845
5087
  return img;
4846
5088
  }
@@ -4851,7 +5093,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4851
5093
  async prepareEffectPaints(paints) {
4852
5094
  const seen = /* @__PURE__ */ new Set();
4853
5095
  for (const p of paints) {
4854
- const key = _chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, p);
5096
+ const key = _chunk4T47Z4J3cjs.effectPaintKey.call(void 0, p);
4855
5097
  if (seen.has(key)) continue;
4856
5098
  seen.add(key);
4857
5099
  await this.renderEffectPaint(p);
@@ -4860,7 +5102,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4860
5102
  /** Renders the effect paints of recorded strokes (default all of them) before a replay. */
4861
5103
  async prepareStrokeEffects(strokeIds) {
4862
5104
  const ids = strokeIds ? new Set(strokeIds) : null;
4863
- const paints = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _295 => _295.paint, 'optionalAccess', _296 => _296.type]) === "effect").map((s) => s.paint);
5105
+ const paints = this.doc.strokes.filter((s) => (!ids || ids.has(s.id)) && _optionalChain([s, 'access', _312 => _312.paint, 'optionalAccess', _313 => _313.type]) === "effect").map((s) => s.paint);
4864
5106
  await this.prepareEffectPaints(paints);
4865
5107
  }
4866
5108
  /** A small preview of the effect paint (a PNG data URL `size` px wide), or `null` without a rendered one. */
@@ -4889,11 +5131,11 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4889
5131
  * its pixels are not rendered.
4890
5132
  */
4891
5133
  strokeEffect(init, brush) {
4892
- if (!_chunk5FZS7J7Ccjs.brushTakesPaint.call(void 0, brush)) return null;
5134
+ if (!_chunk4T47Z4J3cjs.brushTakesPaint.call(void 0, brush)) return null;
4893
5135
  let source = null;
4894
5136
  if (init.paint !== void 0) {
4895
- if (!_chunk5FZS7J7Ccjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
4896
- source = _chunk5FZS7J7Ccjs.readPaintEffectPaint.call(void 0, init.paint);
5137
+ if (!_chunk4T47Z4J3cjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5138
+ source = _chunk4T47Z4J3cjs.readPaintEffectPaint.call(void 0, init.paint);
4897
5139
  if (!source) throw new PaintEditorError("The stroke's effect paint needs an effect id and values (getEffectPaint returns one).");
4898
5140
  } else if (init.color === void 0 && !brush.paint) {
4899
5141
  if (this.effectPaintPending) throw new PaintEditorError(`The effect paint "${this.effectPaintPending.effect}" is still rendering; wait for set_effect_paint to finish, then paint.`);
@@ -4923,14 +5165,14 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4923
5165
  const before = _chunk474IQG74cjs.readRegion.call(void 0, l.surface, rect);
4924
5166
  const inputs = { source: { width: rect.width, height: rect.height, data: before } };
4925
5167
  const heightInput = d.inputs.find((i) => i.kind === "image" && /^(height|depth|relief)$/i.test(i.name));
4926
- const relief = _optionalChain([this, 'access', _297 => _297.doc, 'access', _298 => _298.thick, 'optionalAccess', _299 => _299[l.id]]);
5168
+ const relief = _optionalChain([this, 'access', _314 => _314.doc, 'access', _315 => _315.thick, 'optionalAccess', _316 => _316[l.id]]);
4927
5169
  if (heightInput && relief) {
4928
5170
  const h = _chunk474IQG74cjs.readRegion.call(void 0, relief.height, rect);
4929
5171
  const rgba = new Uint8ClampedArray(rect.width * rect.height * 4);
4930
5172
  for (let i = 0; i < h.length; i++) rgba.set([h[i], h[i], h[i], 255], i * 4);
4931
5173
  inputs[heightInput.name] = { width: rect.width, height: rect.height, data: rgba };
4932
5174
  }
4933
- const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _300 => _300.inputs, 'access', _301 => _301.find, 'call', _302 => _302((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _303 => _303.name])), 'optionalAccess', _304 => _304.name]), () => ( "source"));
5175
+ const sourceInput = _nullishCoalesce(_optionalChain([d, 'access', _317 => _317.inputs, 'access', _318 => _318.find, 'call', _319 => _319((i) => i.kind === "image" && i.name !== _optionalChain([heightInput, 'optionalAccess', _320 => _320.name])), 'optionalAccess', _321 => _321.name]), () => ( "source"));
4934
5176
  if (sourceInput !== "source") {
4935
5177
  inputs[sourceInput] = inputs.source;
4936
5178
  delete inputs.source;
@@ -4943,12 +5185,12 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4943
5185
  }
4944
5186
  // --- Brushes -------------------------------------------------------------------
4945
5187
  findBrush(id) {
4946
- return _nullishCoalesce(_chunk5FZS7J7Ccjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
5188
+ return _nullishCoalesce(_chunk4T47Z4J3cjs.BUILTIN_BRUSHES.find((b) => b.id === id), () => ( this.userBrushes.find((b) => b.id === id)));
4947
5189
  }
4948
5190
  /** A library brush by id (`undefined` when unknown). */
4949
5191
  getBrush(id) {
4950
5192
  const b = this.findBrush(id);
4951
- return b ? _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, b, b) : void 0;
5193
+ return b ? _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, b, b) : void 0;
4952
5194
  }
4953
5195
  requireBrush(id) {
4954
5196
  const b = this.findBrush(id);
@@ -4963,7 +5205,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4963
5205
  const { id, ...changes } = update;
4964
5206
  const base = id !== void 0 ? this.requireBrush(id) : this.brush;
4965
5207
  if (changes.paint !== void 0 && changes.paint !== null) this.readStrokePaint(changes.paint);
4966
- const next = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
5208
+ const next = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...changes, id: base.id }, base);
4967
5209
  if (base.builtin && !Object.keys(changes).length) next.builtin = true;
4968
5210
  else delete next.builtin;
4969
5211
  this.brush = next;
@@ -4972,10 +5214,10 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4972
5214
  }
4973
5215
  /** Saves the active brush (or `brush`) into the user library under `id` / `name`. */
4974
5216
  saveBrush(options) {
4975
- if (!_chunk5FZS7J7Ccjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
4976
- if (_chunk5FZS7J7Ccjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
4977
- const source = options.brush ? _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
4978
- const saved = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
5217
+ if (!_chunk4T47Z4J3cjs.BRUSH_ID.test(options.id)) throw new PaintEditorError(`Brush id "${options.id}" is invalid; use lowercase letters, digits and dashes (e.g. "my-pencil").`);
5218
+ if (_chunk4T47Z4J3cjs.BUILTIN_BRUSHES.some((b) => b.id === options.id)) throw new PaintEditorError(`"${options.id}" is a built-in brush; save under another id.`);
5219
+ const source = options.brush ? _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, options.brush, this.brush) : this.brush;
5220
+ const saved = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...source, id: options.id, name: _nullishCoalesce(options.name, () => ( source.name)) });
4979
5221
  delete saved.builtin;
4980
5222
  const i = this.userBrushes.findIndex((b) => b.id === options.id);
4981
5223
  if (i >= 0) this.userBrushes[i] = saved;
@@ -4985,7 +5227,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4985
5227
  return saved;
4986
5228
  }
4987
5229
  removeBrush(id) {
4988
- if (_chunk5FZS7J7Ccjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
5230
+ if (_chunk4T47Z4J3cjs.BUILTIN_BRUSHES.some((b) => b.id === id)) throw new PaintEditorError(`"${id}" is a built-in brush and cannot be removed.`);
4989
5231
  const i = this.userBrushes.findIndex((b) => b.id === id);
4990
5232
  if (i < 0) throw new PaintEditorError(`Unknown brush "${id}". Call list_brushes for the ids.`);
4991
5233
  this.userBrushes.splice(i, 1);
@@ -4994,12 +5236,12 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
4994
5236
  }
4995
5237
  /** The user's saved brushes. */
4996
5238
  getUserBrushes() {
4997
- return this.userBrushes.map((b) => _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, b, b));
5239
+ return this.userBrushes.map((b) => _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, b, b));
4998
5240
  }
4999
5241
  /** A brush library file of the given brushes (default: the user's brushes). */
5000
5242
  exportBrushes(ids) {
5001
5243
  const list = ids ? ids.map((id) => this.requireBrush(id)) : this.userBrushes;
5002
- return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunk5FZS7J7Ccjs.brushToJSON) };
5244
+ return { format: "pixerate-brushes", version: 1, brushes: list.map(_chunk4T47Z4J3cjs.brushToJSON) };
5003
5245
  }
5004
5246
  /**
5005
5247
  * Adds the brushes of a library file to the user library. A brush whose id is taken is skipped
@@ -5009,14 +5251,14 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5009
5251
  const problems = [];
5010
5252
  let list;
5011
5253
  try {
5012
- list = _chunk5FZS7J7Ccjs.parseBrushLibrary.call(void 0, file, problems);
5254
+ list = _chunk4T47Z4J3cjs.parseBrushLibrary.call(void 0, file, problems);
5013
5255
  } catch (e) {
5014
5256
  throw new PaintEditorError(e.message);
5015
5257
  }
5016
5258
  const added = [];
5017
5259
  const skipped = [];
5018
5260
  for (const b of list) {
5019
- if (_chunk5FZS7J7Ccjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
5261
+ if (_chunk4T47Z4J3cjs.BUILTIN_BRUSHES.some((x) => x.id === b.id)) {
5020
5262
  skipped.push(b.id);
5021
5263
  problems.push(`"${b.id}" is a built-in brush id; rename it to import it.`);
5022
5264
  continue;
@@ -5081,10 +5323,10 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5081
5323
  * brush's gradient, else the editor's gradient paint. Erasers, blenders and smudges take none.
5082
5324
  */
5083
5325
  strokeGradient(init, brush, color) {
5084
- if (!_chunk5FZS7J7Ccjs.brushTakesPaint.call(void 0, brush)) return null;
5326
+ if (!_chunk4T47Z4J3cjs.brushTakesPaint.call(void 0, brush)) return null;
5085
5327
  let g = null;
5086
5328
  if (init.paint !== void 0) {
5087
- if (_chunk5FZS7J7Ccjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5329
+ if (_chunk4T47Z4J3cjs.isPaintEffectPaint.call(void 0, init.paint)) return null;
5088
5330
  const p = this.readStrokePaint(init.paint);
5089
5331
  g = p.type === "gradient" ? p : null;
5090
5332
  } else g = _nullishCoalesce(brush.paint, () => ( (init.color === void 0 ? this.gradient : null)));
@@ -5128,7 +5370,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5128
5370
  // --- Mixer Brush ---------------------------------------------------------------
5129
5371
  /** Fills the Mixer Brush reservoir with a colour (default the editor colour). */
5130
5372
  loadMixerBrush(color) {
5131
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
5373
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, color === void 0 ? this.color : parseColor(color));
5132
5374
  this.mixerLoad = _chunkPQ3H2AANcjs.loadMixer.call(void 0, this.mixerLoad, [r / 255, g / 255, b / 255]);
5133
5375
  this.emit([]);
5134
5376
  return this.mixerLoad;
@@ -5158,7 +5400,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5158
5400
  // --- Strokes -------------------------------------------------------------------
5159
5401
  strokeBrush(init) {
5160
5402
  let brush = init.brushId !== void 0 ? this.requireBrush(init.brushId) : this.brush;
5161
- if (init.brush) brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
5403
+ if (init.brush) brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...init.brush, id: brush.id }, brush);
5162
5404
  return brush;
5163
5405
  }
5164
5406
  /**
@@ -5174,7 +5416,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5174
5416
  return symmetryCopies(this.guides.symmetry);
5175
5417
  }
5176
5418
  sessionFor(doc, init, host) {
5177
- if (init.paint !== void 0 && !_chunk5FZS7J7Ccjs.isPaintEffectPaint.call(void 0, init.paint)) {
5419
+ if (init.paint !== void 0 && !_chunk4T47Z4J3cjs.isPaintEffectPaint.call(void 0, init.paint)) {
5178
5420
  const p = this.readStrokePaint(init.paint);
5179
5421
  if (p.type === "color") init = { ...init, color: p.color, paint: void 0 };
5180
5422
  else init = { ...init, paint: p };
@@ -5193,28 +5435,27 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5193
5435
  const brush = this.strokeBrush(init);
5194
5436
  const effect = this.strokeEffect(init, brush);
5195
5437
  if (brush.light.amount > 0) {
5196
- if (brush.engine === "wet") throw new PaintEditorError(`The ${brush.name} brush paints wet media, which doesn't take light yet (glowing watercolour is planned in #494); paint light with a dab or impasto light brush (list_brushes category light), or set light.amount to 0 (set_brush).`);
5197
5438
  if (brush.engine === "sticker") throw new PaintEditorError(`The ${brush.name} brush sprays stickers, which don't take light yet; paint light with a dab or particle light brush (list_brushes category light), or set light.amount to 0 (set_brush).`);
5198
5439
  }
5199
- if (_optionalChain([doc, 'access', _305 => _305.liveStrokes, 'optionalAccess', _306 => _306[layer.id]])) {
5440
+ if (_optionalChain([doc, 'access', _322 => _322.liveStrokes, 'optionalAccess', _323 => _323[layer.id]])) {
5200
5441
  const why = liveStrokeRefusal(brush);
5201
5442
  if (why) throw new PaintEditorError(`Layer "${layer.name}" is a stroke layer. ${why}`);
5202
5443
  }
5203
- if (_optionalChain([doc, 'access', _307 => _307.liveStrokes, 'optionalAccess', _308 => _308[layer.id]]) && _optionalChain([effect, 'optionalAccess', _309 => _309.source, 'access', _310 => _310.live])) {
5204
- const key = _chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, effect.source);
5444
+ if (_optionalChain([doc, 'access', _324 => _324.liveStrokes, 'optionalAccess', _325 => _325[layer.id]]) && _optionalChain([effect, 'optionalAccess', _326 => _326.source, 'access', _327 => _327.live])) {
5445
+ const key = _chunk4T47Z4J3cjs.effectPaintKey.call(void 0, effect.source);
5205
5446
  const { sources } = this.liveEffects(doc);
5206
- if (!sources.some((p) => _chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
5447
+ if (!sources.some((p) => _chunk4T47Z4J3cjs.effectPaintKey.call(void 0, p) === key) && sources.length >= MAX_LIVE_EFFECT_SOURCES) {
5207
5448
  throw new PaintEditorError(`The painting already plays ${MAX_LIVE_EFFECT_SOURCES} live effects, the most it can; paint with one of them, or set_effect_paint with live false to bake this one.`);
5208
5449
  }
5209
5450
  }
5210
- const stickerLayer = Boolean(_optionalChain([doc, 'access', _311 => _311.stickers, 'optionalAccess', _312 => _312[layer.id], 'optionalAccess', _313 => _313.length]));
5451
+ const stickerLayer = Boolean(_optionalChain([doc, 'access', _328 => _328.stickers, 'optionalAccess', _329 => _329[layer.id], 'optionalAccess', _330 => _330.length]));
5211
5452
  if (brush.engine === "sticker") {
5212
5453
  if (!stickerLayer && _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; spray stickers onto an empty layer (add_layer) so they stay editable.`);
5213
5454
  } else if (stickerLayer) {
5214
5455
  throw new PaintEditorError(`Layer "${layer.name}" is a sticker layer (its pixels are drawn from its stickers); paint on another layer (add_layer).`);
5215
5456
  }
5216
5457
  let wet;
5217
- if (_chunk5FZS7J7Ccjs.isWetBrush.call(void 0, brush)) {
5458
+ if (_chunk4T47Z4J3cjs.isWetBrush.call(void 0, brush)) {
5218
5459
  this.requireWetIdle("painting");
5219
5460
  if (layer.offset.x || layer.offset.y) {
5220
5461
  const moved = { ...layer, surface: _chunk474IQG74cjs.translateSurface.call(void 0, layer.surface, layer.offset.x, layer.offset.y), offset: { x: 0, y: 0 } };
@@ -5222,14 +5463,14 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5222
5463
  if (doc !== this.doc) doc = { ...doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, doc.layers, layer.id, () => moved) };
5223
5464
  layer = moved;
5224
5465
  }
5225
- if (!this.wet.wetLayerIds().includes(layer.id) && this.wet.wetLayerIds().length >= _chunkXFYLA3ZOcjs.MAX_WET_LANES) {
5226
- throw new PaintEditorError(`At most ${_chunkXFYLA3ZOcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
5466
+ if (!this.wet.wetLayerIds().includes(layer.id) && this.wet.wetLayerIds().length >= _chunkVMROIWLLcjs.MAX_WET_LANES) {
5467
+ throw new PaintEditorError(`At most ${_chunkVMROIWLLcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
5227
5468
  }
5228
5469
  this.beginWetOp();
5229
5470
  const world = this.wet.ensureLane(layer.id, brush.wet.medium);
5230
5471
  const id = layer.id;
5231
5472
  const wetColor = init.color === void 0 ? this.color : parseColor(init.color);
5232
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, wetColor);
5473
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, wetColor);
5233
5474
  const wetGradient = this.strokeGradient(init, brush, wetColor);
5234
5475
  const load = _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [r / 255, g / 255, b / 255])));
5235
5476
  const seedW = _nullishCoalesce(init.seed, () => ( _chunkPQ3H2AANcjs.mix32.call(void 0, this.seedCounter * 2654435761 >>> 0) & 2147483647));
@@ -5242,12 +5483,12 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5242
5483
  load,
5243
5484
  grain: paperGrain(doc.paper),
5244
5485
  paperDepth: doc.paper.depth,
5245
- paperColor: _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, doc.paper.color),
5486
+ paperColor: _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, doc.paper.color),
5246
5487
  seed: seedW,
5247
5488
  copies: [IDENTITY_AFFINE, ...copiesW].map(affineCopy),
5248
5489
  mask: init.maskStencils ? this.stencilSelection(init.maskStencils) : init.stencils !== false ? this.stencilSelection() : null,
5249
5490
  paint: effect ? null : wetGradient,
5250
- effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _314 => _314.pixels]), () => ( null))
5491
+ effect: _nullishCoalesce(_optionalChain([effect, 'optionalAccess', _331 => _331.pixels]), () => ( null))
5251
5492
  });
5252
5493
  init = { ...init, seed: seedW, load };
5253
5494
  wet = { driver, surface: () => world.display(id).surface };
@@ -5258,7 +5499,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5258
5499
  }
5259
5500
  let color = init.color === void 0 ? this.color : parseColor(init.color);
5260
5501
  const tracing = this.guides.tracing;
5261
- if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _315 => _315.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
5502
+ if (init.color === void 0 && init.start && _optionalChain([tracing, 'optionalAccess', _332 => _332.visible]) && tracing.sampleColors) color = _nullishCoalesce(this.sampleTracingColor(init.start.x, init.start.y), () => ( color));
5262
5503
  const perspective = this.guides.perspective;
5263
5504
  const snapper = init.snapToPerspective && perspective.enabled && perspective.snap ? new PerspectiveSnapper(perspective) : null;
5264
5505
  const useStencils = init.stencils !== false;
@@ -5291,9 +5532,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5291
5532
  mixerLoad: _nullishCoalesce(init.load, () => ( brushLoadForStroke(brush, this.mixerLoad, [rgba[0] / 255, rgba[1] / 255, rgba[2] / 255]))),
5292
5533
  secondary: rgbaOf(this.secondaryColor),
5293
5534
  wet,
5294
- thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _316 => _316.thick, 'optionalAccess', _317 => _317[layer.id]]), () => ( emptyThickChannels())) } : void 0,
5535
+ thick: brush.engine === "impasto" ? { channels: _nullishCoalesce(_optionalChain([doc, 'access', _333 => _333.thick, 'optionalAccess', _334 => _334[layer.id]]), () => ( emptyThickChannels())) } : void 0,
5295
5536
  // Light paint: a twin of the stroke paints the light channel (laying, dimming, moving light).
5296
- light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _318 => _318.light, 'optionalAccess', _319 => _319[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _320 => _320.light, 'optionalAccess', _321 => _321[layer.id]]), () => ( emptyLight())) } : null,
5537
+ light: !wet && brush.engine !== "sticker" && (brush.light.amount > 0 || _optionalChain([doc, 'access', _335 => _335.light, 'optionalAccess', _336 => _336[layer.id]])) ? { surface: _nullishCoalesce(_optionalChain([doc, 'access', _337 => _337.light, 'optionalAccess', _338 => _338[layer.id]]), () => ( emptyLight())) } : null,
5297
5538
  sticker: brush.engine === "sticker" ? { nextId: this.nextStickerNumber(doc) } : void 0,
5298
5539
  paint: effect ? null : this.strokeGradient(init, brush, color),
5299
5540
  effect
@@ -5307,7 +5548,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5307
5548
  const stroke = {
5308
5549
  id: `s${this.strokeCounter++}`,
5309
5550
  layerId: session.layerId,
5310
- brush: _chunk5FZS7J7Ccjs.brushToJSON.call(void 0, init.brush),
5551
+ brush: _chunk4T47Z4J3cjs.brushToJSON.call(void 0, init.brush),
5311
5552
  color: init.colorHex,
5312
5553
  points: session.points.map((p) => ({ ...p })),
5313
5554
  seed: init.seed
@@ -5332,12 +5573,12 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5332
5573
  const before = this.doc;
5333
5574
  const host = {
5334
5575
  update: (layerId, surface, rects) => {
5335
- if (_optionalChain([this, 'access', _322 => _322.session, 'optionalAccess', _323 => _323.init, 'access', _324 => _324.wet])) {
5576
+ if (_optionalChain([this, 'access', _339 => _339.session, 'optionalAccess', _340 => _340.init, 'access', _341 => _341.wet])) {
5336
5577
  this.wet.syncDisplays();
5337
5578
  return;
5338
5579
  }
5339
5580
  this.live = { layerId, surface };
5340
- const ch = _optionalChain([this, 'access', _325 => _325.session, 'optionalAccess', _326 => _326.thickChannels, 'call', _327 => _327()]);
5581
+ const ch = _optionalChain([this, 'access', _342 => _342.session, 'optionalAccess', _343 => _343.thickChannels, 'call', _344 => _344()]);
5341
5582
  this.liveThick = ch ? { layerId, channels: ch } : null;
5342
5583
  this.emit(rects);
5343
5584
  },
@@ -5349,7 +5590,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5349
5590
  const wetStroke = Boolean(s.init.wet);
5350
5591
  if (wetStroke) this.wet.driver = null;
5351
5592
  const brush = s.init.brush;
5352
- if (!cancelled && _optionalChain([s, 'access', _328 => _328.result, 'optionalAccess', _329 => _329.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
5593
+ if (!cancelled && _optionalChain([s, 'access', _345 => _345.result, 'optionalAccess', _346 => _346.mixerLoad])) this.keepLoad(brush, s.result.mixerLoad);
5353
5594
  if (cancelled || !surface) {
5354
5595
  if (this.wetOp) {
5355
5596
  const snap = this.wetOp.before;
@@ -5364,7 +5605,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5364
5605
  }
5365
5606
  const stroke = this.record(s);
5366
5607
  s.result.strokeId = stroke.id;
5367
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _330 => _330.result, 'optionalAccess', _331 => _331.bounds]), () => ( null)));
5608
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _347 => _347.result, 'optionalAccess', _348 => _348.bounds]), () => ( null)));
5368
5609
  if (wetStroke && this.wet.instantDry) {
5369
5610
  this.wet.dry(s.layerId);
5370
5611
  this.logWet({ kind: "dry", layerId: s.layerId, at: this.doc.strokes.length + 1 });
@@ -5375,8 +5616,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5375
5616
  const ch = s.thickChannels();
5376
5617
  const thick = ch ? { ..._nullishCoalesce(this.doc.thick, () => ( {})), [l.id]: ch } : this.doc.thick;
5377
5618
  const sprayed = s.stickers();
5378
- const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _332 => _332.doc, 'access', _333 => _333.stickers, 'optionalAccess', _334 => _334[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
5379
- const light = withLayerLight(this.doc.light, l.id, s.lightChannel());
5619
+ const stickers = sprayed ? { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([this, 'access', _349 => _349.doc, 'access', _350 => _350.stickers, 'optionalAccess', _351 => _351[l.id]]), () => ( [])), ...sprayed] } : this.doc.stickers;
5620
+ const wetLight = wetStroke && _optionalChain([this, 'access', _352 => _352.wet, 'access', _353 => _353.world, 'optionalAccess', _354 => _354.hasLane, 'call', _355 => _355(l.id)]) ? this.wet.world.lightDisplay(l.id) : null;
5621
+ const light = withLayerLight(this.doc.light, l.id, _nullishCoalesce(s.lightChannel(), () => ( wetLight)));
5380
5622
  this.commit(`${brush.name} stroke`, this.withWetEvents(withLiveStroke({ ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, l.id, () => ({ ...l, surface })), strokes: [...this.doc.strokes, stroke], ...thick ? { thick } : {}, ...stickers ? { stickers } : {}, ...light ? { light } : {} }, stroke)), wetStroke ? before : this.doc);
5381
5623
  }
5382
5624
  };
@@ -5405,18 +5647,19 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5405
5647
  if (cancelled || !surface) return;
5406
5648
  const stroke = this.record(s);
5407
5649
  s.result.strokeId = stroke.id;
5408
- this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _335 => _335.result, 'optionalAccess', _336 => _336.bounds]), () => ( null)));
5650
+ this.paintedBounds.set(stroke, _nullishCoalesce(_optionalChain([s, 'access', _356 => _356.result, 'optionalAccess', _357 => _357.bounds]), () => ( null)));
5409
5651
  const l = _chunkHB4ICNNAcjs.findLayer.call(void 0, out.layers, s.layerId).layer;
5410
5652
  const offset = s.init.wet ? { x: 0, y: 0 } : l.offset;
5411
5653
  const ch = s.thickChannels();
5412
5654
  const sprayed = s.stickers();
5655
+ const lit = _nullishCoalesce(s.lightChannel(), () => ( (s.init.wet && _optionalChain([this, 'access', _358 => _358.wet, 'access', _359 => _359.world, 'optionalAccess', _360 => _360.hasLane, 'call', _361 => _361(l.id)]) ? this.wet.world.lightDisplay(l.id) : null)));
5413
5656
  out = withLiveStroke({
5414
5657
  ...out,
5415
5658
  layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, out.layers, l.id, () => ({ ...l, surface, offset })),
5416
5659
  strokes: [...out.strokes, stroke],
5417
5660
  ...ch ? { thick: { ..._nullishCoalesce(out.thick, () => ( {})), [l.id]: ch } } : {},
5418
- ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _337 => _337.stickers, 'optionalAccess', _338 => _338[l.id]]), () => ( [])), ...sprayed] } } : {},
5419
- ...s.lightChannel() ? { light: withLayerLight(out.light, l.id, s.lightChannel()) } : {}
5661
+ ...sprayed ? { stickers: { ..._nullishCoalesce(out.stickers, () => ( {})), [l.id]: [..._nullishCoalesce(_optionalChain([out, 'access', _362 => _362.stickers, 'optionalAccess', _363 => _363[l.id]]), () => ( [])), ...sprayed] } } : {},
5662
+ ...lit ? { light: withLayerLight(out.light, l.id, lit) } : {}
5420
5663
  }, stroke);
5421
5664
  }
5422
5665
  };
@@ -5474,7 +5717,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5474
5717
  */
5475
5718
  replayStrokes(options) {
5476
5719
  this.requireIdle("replaying");
5477
- if (!_optionalChain([options, 'access', _339 => _339.strokeIds, 'optionalAccess', _340 => _340.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
5720
+ if (!_optionalChain([options, 'access', _364 => _364.strokeIds, 'optionalAccess', _365 => _365.length])) throw new PaintEditorError("strokeIds is empty; pass ids from list_strokes.");
5478
5721
  const strokes = options.strokeIds.map((id) => {
5479
5722
  const s = this.doc.strokes.find((x) => x.id === id);
5480
5723
  if (!s) throw new PaintEditorError(`Unknown stroke "${id}". Call list_strokes for the ids.`);
@@ -5488,7 +5731,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5488
5731
  if (options.layerId !== void 0) this.paintTarget(options.layerId, "replay onto");
5489
5732
  if (options.color === void 0) {
5490
5733
  for (const s of strokes) {
5491
- if (_optionalChain([s, 'access', _341 => _341.paint, 'optionalAccess', _342 => _342.type]) === "effect" && !this.effectPaintImage(s.paint)) {
5734
+ if (_optionalChain([s, 'access', _366 => _366.paint, 'optionalAccess', _367 => _367.type]) === "effect" && !this.effectPaintImage(s.paint)) {
5492
5735
  throw new PaintEditorError(`Stroke "${s.id}" paints with the effect "${s.paint.effect}"${s.paint.provider ? ` from provider "${s.paint.provider}"` : ""}, which is not rendered in this editor; render it first (prepareStrokeEffects; the replay_strokes tool does this) or recolour the replay with color.`);
5493
5736
  }
5494
5737
  }
@@ -5511,13 +5754,13 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5511
5754
  let brush = v.brush;
5512
5755
  if (options.brushId !== void 0) {
5513
5756
  const b = this.requireBrush(options.brushId);
5514
- brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
5757
+ brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: b.tip.size * (v.brush.tip.size / s.brush.tip.size) } }, b);
5515
5758
  }
5516
5759
  const layerId = _nullishCoalesce(options.layerId, () => ( s.layerId));
5517
5760
  if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, layerId)) throw new PaintEditorError(`Stroke "${s.id}" was painted on layer "${layerId}", which no longer exists; pass layerId to replay it elsewhere.`);
5518
5761
  let load = s.load;
5519
5762
  if (load && options.color !== void 0 && load.reservoir) {
5520
- const [r, g, b] = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, options.color);
5763
+ const [r, g, b] = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, options.color);
5521
5764
  load = { ...load, reservoir: [r / 255, g / 255, b / 255] };
5522
5765
  }
5523
5766
  const paint = v.paint && options.color === void 0 ? { paint: v.paint } : {};
@@ -5546,7 +5789,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5546
5789
  /** A layer's light paint: whether it has any, where (document pixels), its brightest value 0..255, and its spill. */
5547
5790
  lightOf(layerId) {
5548
5791
  const l = this.wetLayer(layerId, "read the light of");
5549
- const info = lightInfo(_optionalChain([this, 'access', _343 => _343.doc, 'access', _344 => _344.light, 'optionalAccess', _345 => _345[l.id]]));
5792
+ const info = lightInfo(_optionalChain([this, 'access', _368 => _368.doc, 'access', _369 => _369.light, 'optionalAccess', _370 => _370[l.id]]));
5550
5793
  const bounds = info.bounds ? { ...info.bounds, x: info.bounds.x + l.offset.x, y: info.bounds.y + l.offset.y } : null;
5551
5794
  return { layerId: l.id, hasLight: info.peak > 0, bounds, peak: info.peak, spill: { ...this.lightSpillOf(l.id) } };
5552
5795
  }
@@ -5565,6 +5808,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5565
5808
  clearLight(layerId) {
5566
5809
  this.requireIdle("clearing light");
5567
5810
  const l = this.paintTarget(layerId, "clear the light of");
5811
+ if (this.wet.bakedLight(l.id)) this.dryLayersFirst([l.id]);
5568
5812
  const t = this.lightWithout([l.id]);
5569
5813
  if (!t.light) return { layerId: l.id, cleared: false };
5570
5814
  this.commit("Clear light", { ...this.doc, light: t.light });
@@ -5596,7 +5840,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5596
5840
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
5597
5841
  if (!id) return null;
5598
5842
  this.requireLayer(id);
5599
- const ch = _optionalChain([this, 'access', _346 => _346.doc, 'access', _347 => _347.thick, 'optionalAccess', _348 => _348[id]]);
5843
+ const ch = _optionalChain([this, 'access', _371 => _371.doc, 'access', _372 => _372.thick, 'optionalAccess', _373 => _373[id]]);
5600
5844
  if (!ch) return null;
5601
5845
  const r = reliefInfo(ch);
5602
5846
  return { layerId: id, bounds: r.bounds, maxHeight: r.maxHeight };
@@ -5704,7 +5948,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5704
5948
  wetState() {
5705
5949
  const st = this.getState().wet;
5706
5950
  const backend = this.wet.backend();
5707
- return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _349 => _349.message]), () => ( _chunkXFYLA3ZOcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
5951
+ return { ...st, layers: this.wet.wetLayerIds().map((id) => this.wet.info(id)), backend, message: _nullishCoalesce(_optionalChain([backend, 'optionalAccess', _374 => _374.message]), () => ( _chunkVMROIWLLcjs.wetSupport.call(void 0, ).message)), engine: this.wet.engineInfo() };
5708
5952
  }
5709
5953
  /**
5710
5954
  * Engine B, the WebGPU accelerator for large wet areas: whether it may run, its state (`off`,
@@ -5777,7 +6021,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5777
6021
  const amount = _nullishCoalesce(options.amount, () => ( 1));
5778
6022
  if (!(amount > 0 && amount <= 1)) throw new PaintEditorError(`amount ${amount} is out of range; use above 0 up to 1.`);
5779
6023
  const rect = _nullishCoalesce(this.checkRect(options.rect), () => ( { x: 0, y: 0, width: this.doc.canvas.width, height: this.doc.canvas.height }));
5780
- if (!this.wet.wetLayerIds().includes(l.id) && this.wet.wetLayerIds().length >= _chunkXFYLA3ZOcjs.MAX_WET_LANES) throw new PaintEditorError(`At most ${_chunkXFYLA3ZOcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
6024
+ if (!this.wet.wetLayerIds().includes(l.id) && this.wet.wetLayerIds().length >= _chunkVMROIWLLcjs.MAX_WET_LANES) throw new PaintEditorError(`At most ${_chunkVMROIWLLcjs.MAX_WET_LANES} layers can hold wet paint at once; dry one first (dry_paint).`);
5781
6025
  const before = this.doc;
5782
6026
  this.beginWetOp();
5783
6027
  const world = this.wet.ensureLane(l.id);
@@ -5789,7 +6033,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5789
6033
  }
5790
6034
  /** Records a settings change as a wet event (not an undo step). */
5791
6035
  recordWetSetting(e) {
5792
- this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _350 => _350.wet, 'access', _351 => _351.world, 'optionalAccess', _352 => _352.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
6036
+ this.doc = { ...this.doc, wetEvents: [..._nullishCoalesce(this.doc.wetEvents, () => ( [])), { clock: _nullishCoalesce(_optionalChain([this, 'access', _375 => _375.wet, 'access', _376 => _376.world, 'optionalAccess', _377 => _377.clock]), () => ( 0)), at: this.doc.strokes.length, ...e }] };
5793
6037
  }
5794
6038
  /** Changes a layer's wet settings (viscosity, evaporation, granulation…). Editor settings saved with the document, not an undo step. */
5795
6039
  setWetParams(layerId, update) {
@@ -5858,7 +6102,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5858
6102
  if (override) return Array.from(override).reduce((ls, [id, surface]) => _chunkHB4ICNNAcjs.mapLayer.call(void 0, ls, id, (l) => ({ ...l, surface })), this.doc.layers);
5859
6103
  const live = this.live;
5860
6104
  if (!live) return this.animatedView();
5861
- if (_optionalChain([this, 'access', _353 => _353.liveLayers, 'optionalAccess', _354 => _354.key]) === live.surface) return this.liveLayers.layers;
6105
+ if (_optionalChain([this, 'access', _378 => _378.liveLayers, 'optionalAccess', _379 => _379.key]) === live.surface) return this.liveLayers.layers;
5862
6106
  const layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, live.layerId, (l) => ({ ...l, surface: live.surface }));
5863
6107
  this.liveLayers = { key: live.surface, layers };
5864
6108
  return layers;
@@ -5881,7 +6125,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5881
6125
  tracingNode(t) {
5882
6126
  const { width, height } = this.doc.canvas;
5883
6127
  const key = this.tracingVersion * 100003 + width * 7 + height;
5884
- if (_optionalChain([this, 'access', _355 => _355.tracingCache, 'optionalAccess', _356 => _356.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
6128
+ if (_optionalChain([this, 'access', _380 => _380.tracingCache, 'optionalAccess', _381 => _381.key]) === key && this.tracingCache.node.opacity === t.opacity) return this.tracingCache.node;
5885
6129
  const src = _nullishCoalesce(this.imagePixels.get(t.src), () => ( this.decodeImage(t.src)));
5886
6130
  const image = resampleInto(src, t.rect, width, height);
5887
6131
  const node = { type: "image", id: TRACING_NODE_ID, name: "Tracing", visible: true, opacity: t.opacity, blend: "normal", image, version: key + Math.round(t.opacity * 1e3) / 1e4 };
@@ -5908,8 +6152,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5908
6152
  let out = layers;
5909
6153
  const ids = /* @__PURE__ */ new Set([...Object.keys(_nullishCoalesce(thick, () => ( {}))), ...live ? [live.layerId] : []]);
5910
6154
  for (const id of ids) {
5911
- const ch = _optionalChain([live, 'optionalAccess', _357 => _357.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _358 => _358[id]]);
5912
- const l = ch && _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _359 => _359.layer]);
6155
+ const ch = _optionalChain([live, 'optionalAccess', _382 => _382.layerId]) === id ? live.channels : _optionalChain([thick, 'optionalAccess', _383 => _383[id]]);
6156
+ const l = ch && _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _384 => _384.layer]);
5913
6157
  if (!ch || !isPixelLayer(l)) continue;
5914
6158
  let cache = this.litCaches.get(id);
5915
6159
  if (!cache) this.litCaches.set(id, cache = new LitCache());
@@ -5929,23 +6173,54 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5929
6173
  if (!ids.size) return layers;
5930
6174
  let out = layers;
5931
6175
  for (const id of ids) {
5932
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _360 => _360.layer]);
6176
+ const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, out, id), 'optionalAccess', _385 => _385.layer]);
5933
6177
  if (!isPixelLayer(l)) continue;
5934
6178
  let cache = this.lightCaches.get(id);
5935
6179
  if (!cache) this.lightCaches.set(id, cache = new LightCache());
5936
- const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _361 => _361.liveThick, 'optionalAccess', _362 => _362.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _363 => _363.doc, 'access', _364 => _364.thick, 'optionalAccess', _365 => _365[id]]));
6180
+ const glowed = cache.glow(l.surface, light[id], _optionalChain([this, 'access', _386 => _386.liveThick, 'optionalAccess', _387 => _387.layerId]) === id ? this.liveThick.channels : _optionalChain([this, 'access', _388 => _388.doc, 'access', _389 => _389.thick, 'optionalAccess', _390 => _390[id]]));
5937
6181
  if (glowed !== l.surface) out = _chunkHB4ICNNAcjs.mapLayer.call(void 0, out, id, () => ({ ...l, surface: glowed }));
5938
- const committed = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _366 => _366.layer]);
6182
+ const committed = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _391 => _391.layer]);
5939
6183
  const spill = light[id] && isPixelLayer(committed) ? cache.spill(committed.surface, light[id], this.lightSpillOf(id)) : null;
5940
6184
  if (spill) out = insertAfter(out, id, { type: "pixel", id: `${id}${SPILL_SUFFIX}`, name: `${l.name} light`, visible: l.visible, opacity: l.opacity, blend: "linear-dodge", surface: spill, offset: { ...l.offset } });
5941
6185
  }
5942
6186
  return out;
5943
6187
  }
6188
+ /** Visible pixel layers bottom first, as the backlight reads them (group opacities multiplied in). */
6189
+ backlitLayers(layers, committed, opacity = 1, out = []) {
6190
+ for (const l of layers) {
6191
+ if (!l.visible) continue;
6192
+ if (l.type === "group") this.backlitLayers(l.children, committed, opacity * l.opacity, out);
6193
+ else if (isPixelLayer(l)) {
6194
+ const thick = !committed && _optionalChain([this, 'access', _392 => _392.liveThick, 'optionalAccess', _393 => _393.layerId]) === l.id ? this.liveThick.channels : _optionalChain([this, 'access', _394 => _394.doc, 'access', _395 => _395.thick, 'optionalAccess', _396 => _396[l.id]]);
6195
+ out.push({ surface: l.surface, offset: l.offset, opacity: opacity * l.opacity, ...thick ? { thick } : {} });
6196
+ }
6197
+ }
6198
+ return out;
6199
+ }
6200
+ /**
6201
+ * Backlit paper: the light that makes it through `base` (the layers as drawn), with the spill of
6202
+ * the light through the committed painting, as a Linear Dodge (Add) layer for the top of the
6203
+ * stack; `null` when the paper has no backlight.
6204
+ */
6205
+ backlightLayer(base) {
6206
+ const paper = this.doc.paper;
6207
+ const amount = backlightOf(paper);
6208
+ if (!(amount > 0)) return null;
6209
+ const { width, height } = this.doc.canvas;
6210
+ const grain = paperGrain(paper);
6211
+ const current = this.backlightView.surface(paper, grain, width, height, this.backlitLayers(base, false), null);
6212
+ const committed = base === this.doc.layers ? current : this.backlightCommitted.surface(paper, grain, width, height, this.backlitLayers(this.doc.layers, true), null);
6213
+ const surface = this.backlightView.layer(current, committed, amount);
6214
+ return { type: "pixel", id: BACKLIGHT_LAYER_ID, name: "Backlight", visible: true, opacity: 1, blend: "linear-dodge", surface, offset: { x: 0, y: 0 } };
6215
+ }
5944
6216
  renderLayers(options, view = false) {
5945
- let layers = this.lightLayers(this.litLayers((_nullishCoalesce(options.wet, () => ( "display"))) === "dried" ? this.driedLayers() : this.currentLayers()));
6217
+ const base = (_nullishCoalesce(options.wet, () => ( "display"))) === "dried" ? this.driedLayers() : this.currentLayers();
6218
+ let layers = this.lightLayers(this.litLayers(base));
6219
+ const backlight = options.paper !== false && !options.layerIds ? this.backlightLayer(base) : null;
6220
+ if (backlight) layers = [...layers, backlight];
5946
6221
  if (options.layerIds) {
5947
6222
  const picked = [];
5948
- for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _367 => _367.layer]), () => ( this.requireLayer(id))));
6223
+ for (const id of options.layerIds) picked.push(_nullishCoalesce(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _397 => _397.layer]), () => ( this.requireLayer(id))));
5949
6224
  layers = picked.map((l) => ({ ...l, visible: true }));
5950
6225
  }
5951
6226
  const under = options.paper === false ? [] : [paperNode(this.doc.paper, this.lighting)];
@@ -5961,7 +6236,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5961
6236
  */
5962
6237
  compositeTiles(rect, onTile, options = {}) {
5963
6238
  const dirty = options.dirty === "all" ? void 0 : options.dirty;
5964
- this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _368 => _368.live, 'optionalAccess', _369 => _369.layerId]), () => ( this.doc.activeLayerId)) });
6239
+ this.viewCompositor.compositeTiles(this.renderLayers({ paper: options.paper }, true), rect, this.sources(), onTile, { dirty, checkpointLayerId: _nullishCoalesce(_optionalChain([this, 'access', _398 => _398.live, 'optionalAccess', _399 => _399.layerId]), () => ( this.doc.activeLayerId)) });
5965
6240
  }
5966
6241
  /** The canvas as canvas-sized RGBA (paper included by default). */
5967
6242
  compositePixels(options = {}) {
@@ -5998,7 +6273,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
5998
6273
  this.wet.reset();
5999
6274
  if (!raw || typeof raw !== "object") return;
6000
6275
  const r = raw;
6001
- this.wet.setTilt(_chunkXFYLA3ZOcjs.normalizeTilt.call(void 0, _nullishCoalesce(r.tilt, () => ( {}))));
6276
+ this.wet.setTilt(_chunkVMROIWLLcjs.normalizeTilt.call(void 0, _nullishCoalesce(r.tilt, () => ( {}))));
6002
6277
  if (r.layers && typeof r.layers === "object") {
6003
6278
  for (const [id, v] of Object.entries(r.layers)) {
6004
6279
  if (!v || typeof v !== "object") {
@@ -6006,7 +6281,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6006
6281
  continue;
6007
6282
  }
6008
6283
  const x = v;
6009
- this.wet.settings.set(id, { params: _chunkXFYLA3ZOcjs.normalizeWetParams.call(void 0, _nullishCoalesce(x.params, () => ( {}))), flow: _chunkXFYLA3ZOcjs.normalizeFlow.call(void 0, _nullishCoalesce(x.flow, () => ( {}))) });
6284
+ this.wet.settings.set(id, { params: _chunkVMROIWLLcjs.normalizeWetParams.call(void 0, _nullishCoalesce(x.params, () => ( {}))), flow: _chunkVMROIWLLcjs.normalizeFlow.call(void 0, _nullishCoalesce(x.flow, () => ( {}))) });
6010
6285
  }
6011
6286
  }
6012
6287
  }
@@ -6032,7 +6307,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6032
6307
  const light = {};
6033
6308
  for (const [id, t] of Object.entries(_nullishCoalesce(this.doc.light, () => ( {})))) {
6034
6309
  if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)) continue;
6035
- const saved = lightToJSON(t);
6310
+ const saved = lightToJSON(_nullishCoalesce(this.wet.bakedLight(id), () => ( t)));
6036
6311
  if (saved) light[id] = saved;
6037
6312
  }
6038
6313
  if (Object.keys(light).length) ext.light = light;
@@ -6040,7 +6315,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6040
6315
  const spills = Object.fromEntries(Object.entries(this.lightSpills).filter(([id]) => _chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id)));
6041
6316
  if (Object.keys(spills).length) ext.lightSpill = spills;
6042
6317
  else delete ext.lightSpill;
6043
- const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _370 => _370.layer])));
6318
+ const effectLayers = effectLayersToJSON(_nullishCoalesce(this.doc.effectLayers, () => ( {})), (id) => isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, id), 'optionalAccess', _400 => _400.layer])));
6044
6319
  if (effectLayers) ext.effectLayers = effectLayers;
6045
6320
  else delete ext.effectLayers;
6046
6321
  if (this.doc.paperEffect) ext.paperEffect = paperEffectToJSON(this.doc.paperEffect);
@@ -6057,7 +6332,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6057
6332
  const stickers = {};
6058
6333
  for (const [id, list] of Object.entries(ext.stickers)) {
6059
6334
  if (!_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id) || !Array.isArray(list)) continue;
6060
- const ok = list.filter((x) => x && typeof x.id === "string" && _chunk5FZS7J7Ccjs.STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
6335
+ const ok = list.filter((x) => x && typeof x.id === "string" && _chunk4T47Z4J3cjs.STAMP_KINDS.includes(x.stamp) && Number.isFinite(x.x) && Number.isFinite(x.y) && x.size > 0);
6061
6336
  if (ok.length !== list.length) problems.push(`Some stickers of layer "${id}" could not be read; they were dropped.`);
6062
6337
  stickers[id] = ok.map((x) => ({ ...x }));
6063
6338
  }
@@ -6066,7 +6341,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6066
6341
  if (ext.liveStrokes && typeof ext.liveStrokes === "object") {
6067
6342
  const liveStrokes = {};
6068
6343
  for (const [id, list] of Object.entries(ext.liveStrokes)) {
6069
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _371 => _371.layer])) || !Array.isArray(list)) continue;
6344
+ if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _401 => _401.layer])) || !Array.isArray(list)) continue;
6070
6345
  const ok = list.map(normalizeBrushStroke).filter((x) => x !== null).map((x) => ({ ...x, layerId: id }));
6071
6346
  if (ok.length !== list.length) problems.push(`Some strokes of stroke layer "${id}" could not be read; they were dropped (the layer's pixels are kept until a stroke is edited).`);
6072
6347
  liveStrokes[id] = ok;
@@ -6076,7 +6351,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6076
6351
  if (ext.effectLayers && typeof ext.effectLayers === "object") {
6077
6352
  const effectLayers = {};
6078
6353
  for (const [id, v] of Object.entries(ext.effectLayers)) {
6079
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _372 => _372.layer]))) continue;
6354
+ if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _402 => _402.layer]))) continue;
6080
6355
  const source = readPaintEffectSource(v);
6081
6356
  if (source) effectLayers[id] = source;
6082
6357
  else problems.push(`The effect of layer "${id}" could not be read; it loads as a plain layer.`);
@@ -6104,7 +6379,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6104
6379
  if (ext.light && typeof ext.light === "object") {
6105
6380
  const light = {};
6106
6381
  for (const [id, v] of Object.entries(ext.light)) {
6107
- if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _373 => _373.layer]))) continue;
6382
+ if (!isPixelLayer(_optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, state.layers, id), 'optionalAccess', _403 => _403.layer]))) continue;
6108
6383
  try {
6109
6384
  light[id] = lightFromJSON(v);
6110
6385
  } catch (e) {
@@ -6140,7 +6415,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6140
6415
  this.readGuides(loaded.guides, loaded.state, loaded.problems);
6141
6416
  if (Array.isArray(loaded.swatches)) this.swatches = loaded.swatches.map(readSwatch).filter((x) => x !== null);
6142
6417
  for (const s of loaded.state.strokes) {
6143
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _374 => _374.exec, 'call', _375 => _375(s.id), 'optionalAccess', _376 => _376[1]]), () => ( 0)));
6418
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _404 => _404.exec, 'call', _405 => _405(s.id), 'optionalAccess', _406 => _406[1]]), () => ( 0)));
6144
6419
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
6145
6420
  }
6146
6421
  this.undoStack = [];
@@ -6148,7 +6423,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6148
6423
  this.doc = this.readThick(loaded.state, loaded.extensions, loaded.problems);
6149
6424
  for (const list of Object.values(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
6150
6425
  for (const s of list) {
6151
- const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _377 => _377.exec, 'call', _378 => _378(s.id), 'optionalAccess', _379 => _379[1]]), () => ( 0)));
6426
+ const n = Number(_nullishCoalesce(_optionalChain([/^s(\d+)$/, 'access', _407 => _407.exec, 'call', _408 => _408(s.id), 'optionalAccess', _409 => _409[1]]), () => ( 0)));
6152
6427
  if (n >= this.strokeCounter) this.strokeCounter = n + 1;
6153
6428
  }
6154
6429
  }
@@ -6218,7 +6493,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6218
6493
  * pixels), and the composite as the merged image.
6219
6494
  */
6220
6495
  exportPsd() {
6221
- const dried = this.lightLayers(this.litLayers(this.driedLayers(this.doc.layers)));
6496
+ const driedBase = this.driedLayers(this.doc.layers);
6497
+ const backlight = this.backlightLayer(driedBase);
6498
+ const dried = [...this.lightLayers(this.litLayers(driedBase)), ...backlight ? [backlight] : []];
6222
6499
  const { width, height, dpi } = this.doc.canvas;
6223
6500
  const paperPixels = this.compositePixels({ layerIds: [], paper: true });
6224
6501
  const paperLayer = {
@@ -6241,14 +6518,17 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6241
6518
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
6242
6519
  });
6243
6520
  const layers = toStandard(dried);
6244
- const result = _chunkR2FVAKFHcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
6521
+ const result = _chunkM6JORA5Zcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
6245
6522
  for (const [mode, names] of changed) {
6246
- const label = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _380 => _380.find, 'call', _381 => _381((m) => m.id === mode), 'optionalAccess', _382 => _382.label]), () => ( mode));
6247
- const std = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _383 => _383.find, 'call', _384 => _384((m) => m.id === _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _385 => _385.label]), () => ( _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)));
6523
+ const label = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _410 => _410.find, 'call', _411 => _411((m) => m.id === mode), 'optionalAccess', _412 => _412.label]), () => ( mode));
6524
+ const std = _nullishCoalesce(_optionalChain([_chunkOLNIPTB3cjs.BLEND_MODES, 'access', _413 => _413.find, 'call', _414 => _414((m) => m.id === _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _415 => _415.label]), () => ( _chunkOLNIPTB3cjs.standardBlendMode.call(void 0, mode)));
6248
6525
  const list = names.map((n) => `"${n}"`).join(", ");
6249
6526
  const one = names.length === 1;
6250
6527
  result.warnings.push(`${label} blending has no PSD equivalent; ${list} ${one ? "was" : "were"} written as ${std}, the nearest Photoshop mode, so ${one ? "it looks" : "they look"} different in Photoshop (the merged image is exact).`);
6251
6528
  }
6529
+ if (backlight) {
6530
+ result.warnings.push('Backlit paper is written as pixels: the light that comes through the paint is a "Backlight" Linear Dodge (Add) layer at the top. Opening the PSD again gives a plain pixel layer, not a backlight.');
6531
+ }
6252
6532
  if (Object.values(_nullishCoalesce(this.doc.light, () => ( {}))).some((l) => l.tiles.size)) {
6253
6533
  result.warnings.push('Light paint is written as pixels: each layer with its glow, and its spill as a "\u2039layer\u203A light" Linear Dodge (Add) layer above it. Opening the PSD again gives plain pixel layers, not editable light.');
6254
6534
  }
@@ -6363,7 +6643,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6363
6643
  const { src, pixels } = this.importImage(options, "The reference image");
6364
6644
  const ref2 = {
6365
6645
  id: `ref${this.nextReferenceId++}`,
6366
- name: _optionalChain([options, 'access', _386 => _386.name, 'optionalAccess', _387 => _387.trim, 'call', _388 => _388()]) || `Reference ${this.guides.references.length + 1}`,
6646
+ name: _optionalChain([options, 'access', _416 => _416.name, 'optionalAccess', _417 => _417.trim, 'call', _418 => _418()]) || `Reference ${this.guides.references.length + 1}`,
6367
6647
  src,
6368
6648
  width: pixels.width,
6369
6649
  height: pixels.height,
@@ -6442,7 +6722,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6442
6722
  try {
6443
6723
  const px = this.decodeImage(ref2.src, `Reference "${ref2.name}"`);
6444
6724
  guides.references.push({ id: ref2.id, name: String(_nullishCoalesce(ref2.name, () => ( ref2.id))), src: ref2.src, width: px.width, height: px.height, x: Number(ref2.x) || 0, y: Number(ref2.y) || 0, displayWidth: Number(ref2.displayWidth) || 240, visible: ref2.visible !== false });
6445
- const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _389 => _389.exec, 'call', _390 => _390(ref2.id), 'optionalAccess', _391 => _391[1]]), () => ( 0)));
6725
+ const n = Number(_nullishCoalesce(_optionalChain([/^ref(\d+)$/, 'access', _419 => _419.exec, 'call', _420 => _420(ref2.id), 'optionalAccess', _421 => _421[1]]), () => ( 0)));
6446
6726
  if (n >= this.nextReferenceId) this.nextReferenceId = n + 1;
6447
6727
  } catch (e) {
6448
6728
  problems.push(e.message);
@@ -6453,7 +6733,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6453
6733
  guides.stencils = [];
6454
6734
  r.stencils.forEach((raw2, i) => {
6455
6735
  try {
6456
- const id = typeof _optionalChain([raw2, 'optionalAccess', _392 => _392.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
6736
+ const id = typeof _optionalChain([raw2, 'optionalAccess', _422 => _422.id]) === "string" && /^stencil\d+$/.test(raw2.id) ? raw2.id : `stencil${this.nextStencilId}`;
6457
6737
  guides.stencils.push(normalizeStencil(raw2, id));
6458
6738
  const n = Number(id.slice(7));
6459
6739
  if (n >= this.nextStencilId) this.nextStencilId = n + 1;
@@ -6476,12 +6756,12 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6476
6756
  /** The next free sticker number (ids `st<n>` are unique across the document). */
6477
6757
  nextStickerNumber(doc = this.doc) {
6478
6758
  let n = 0;
6479
- for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _393 => _393.exec, 'call', _394 => _394(st.id), 'optionalAccess', _395 => _395[1]]), () => ( 0))));
6759
+ for (const list of Object.values(_nullishCoalesce(doc.stickers, () => ( {})))) for (const st of list) n = Math.max(n, Number(_nullishCoalesce(_optionalChain([/^st(\d+)$/, 'access', _423 => _423.exec, 'call', _424 => _424(st.id), 'optionalAccess', _425 => _425[1]]), () => ( 0))));
6480
6760
  return n + 1;
6481
6761
  }
6482
6762
  stickerLayer(layerId) {
6483
6763
  const l = this.wetLayer(layerId, "edit the stickers of");
6484
- const stickers = _optionalChain([this, 'access', _396 => _396.doc, 'access', _397 => _397.stickers, 'optionalAccess', _398 => _398[l.id]]);
6764
+ const stickers = _optionalChain([this, 'access', _426 => _426.doc, 'access', _427 => _427.stickers, 'optionalAccess', _428 => _428[l.id]]);
6485
6765
  if (!stickers) throw new PaintEditorError(`Layer "${l.name}" has no stickers; spray some with a sticker brush (list_brushes category sticker).`);
6486
6766
  return { layer: l, stickers };
6487
6767
  }
@@ -6490,7 +6770,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6490
6770
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
6491
6771
  if (!id) return [];
6492
6772
  this.requireLayer(id);
6493
- return (_nullishCoalesce(_optionalChain([this, 'access', _399 => _399.doc, 'access', _400 => _400.stickers, 'optionalAccess', _401 => _401[id]]), () => ( []))).map((s) => ({ ...s }));
6773
+ return (_nullishCoalesce(_optionalChain([this, 'access', _429 => _429.doc, 'access', _430 => _430.stickers, 'optionalAccess', _431 => _431[id]]), () => ( []))).map((s) => ({ ...s }));
6494
6774
  }
6495
6775
  /**
6496
6776
  * Replaces a layer's stickers and redraws its pixels from them (one undo step). With `dirty`,
@@ -6506,15 +6786,15 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6506
6786
  }
6507
6787
  redrawStickers(layer, stickers, dirty) {
6508
6788
  const partial = dirty && !layer.offset.x && !layer.offset.y;
6509
- return partial ? _chunk5FZS7J7Ccjs.stickerSurface.call(void 0, stickers, layer.surface, dirty) : _chunk5FZS7J7Ccjs.stickerSurface.call(void 0, stickers);
6789
+ return partial ? _chunk4T47Z4J3cjs.stickerSurface.call(void 0, stickers, layer.surface, dirty) : _chunk4T47Z4J3cjs.stickerSurface.call(void 0, stickers);
6510
6790
  }
6511
6791
  /** The document from before the sticker preview on screen, or `null` when none is (anything else changed the document since). */
6512
6792
  previewBase() {
6513
- return _optionalChain([this, 'access', _402 => _402.stickerPreview, 'optionalAccess', _403 => _403.shown]) === this.doc ? this.stickerPreview.base : null;
6793
+ return _optionalChain([this, 'access', _432 => _432.stickerPreview, 'optionalAccess', _433 => _433.shown]) === this.doc ? this.stickerPreview.base : null;
6514
6794
  }
6515
6795
  readStickerUpdate(update) {
6516
6796
  try {
6517
- return _chunk5FZS7J7Ccjs.normalizeStickerUpdate.call(void 0, update);
6797
+ return _chunk4T47Z4J3cjs.normalizeStickerUpdate.call(void 0, update);
6518
6798
  } catch (e) {
6519
6799
  throw new PaintEditorError(e.message);
6520
6800
  }
@@ -6525,7 +6805,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6525
6805
  const id = _nullishCoalesce(layerId, () => ( this.doc.activeLayerId));
6526
6806
  if (!id) return null;
6527
6807
  this.requireLayer(id);
6528
- const hit = _chunk5FZS7J7Ccjs.stickerAt.call(void 0, _nullishCoalesce(_optionalChain([this, 'access', _404 => _404.doc, 'access', _405 => _405.stickers, 'optionalAccess', _406 => _406[id]]), () => ( [])), x, y);
6808
+ const hit = _chunk4T47Z4J3cjs.stickerAt.call(void 0, _nullishCoalesce(_optionalChain([this, 'access', _434 => _434.doc, 'access', _435 => _435.stickers, 'optionalAccess', _436 => _436[id]]), () => ( [])), x, y);
6529
6809
  return hit ? { ...hit } : null;
6530
6810
  }
6531
6811
  /** Picks a sticker for the panel and canvas (`null` for none). Editor state, not an undo step. */
@@ -6546,7 +6826,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6546
6826
  if (i < 0) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6547
6827
  const next = { ...stickers[i], ...this.readStickerUpdate(update) };
6548
6828
  const list = stickers.map((s, j) => j === i ? next : s);
6549
- const dirty = [_chunk5FZS7J7Ccjs.stickerRect.call(void 0, stickers[i]), _chunk5FZS7J7Ccjs.stickerRect.call(void 0, next)];
6829
+ const dirty = [_chunk4T47Z4J3cjs.stickerRect.call(void 0, stickers[i]), _chunk4T47Z4J3cjs.stickerRect.call(void 0, next)];
6550
6830
  const base = _nullishCoalesce(this.previewBase(), () => ( this.doc));
6551
6831
  const surface = this.redrawStickers(layer, list, dirty);
6552
6832
  this.doc = { ...this.doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, this.doc.layers, layer.id, () => ({ ...layer, surface, offset: { x: 0, y: 0 } })), stickers: { ..._nullishCoalesce(this.doc.stickers, () => ( {})), [layer.id]: list } };
@@ -6569,7 +6849,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6569
6849
  if (i < 0) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6570
6850
  const u = this.readStickerUpdate(update);
6571
6851
  const next = { ...stickers[i], ...u };
6572
- this.commitStickers("Edit sticker", layer, stickers.map((s, j) => j === i ? next : s), [_chunk5FZS7J7Ccjs.stickerRect.call(void 0, stickers[i]), _chunk5FZS7J7Ccjs.stickerRect.call(void 0, next)]);
6852
+ this.commitStickers("Edit sticker", layer, stickers.map((s, j) => j === i ? next : s), [_chunk4T47Z4J3cjs.stickerRect.call(void 0, stickers[i]), _chunk4T47Z4J3cjs.stickerRect.call(void 0, next)]);
6573
6853
  return { ...next };
6574
6854
  }
6575
6855
  /**
@@ -6581,8 +6861,8 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6581
6861
  const layer = this.wetLayer(layerId, "add stickers to");
6582
6862
  if (!input.length) throw new PaintEditorError("Pass at least one sticker (stamp, x, y).");
6583
6863
  if (input.length > MAX_ADD_STICKERS) throw new PaintEditorError(`At most ${MAX_ADD_STICKERS} stickers per call; split them over several calls.`);
6584
- const existing = _optionalChain([this, 'access', _407 => _407.doc, 'access', _408 => _408.stickers, 'optionalAccess', _409 => _409[layer.id]]);
6585
- if (!_optionalChain([existing, 'optionalAccess', _410 => _410.length])) {
6864
+ const existing = _optionalChain([this, 'access', _437 => _437.doc, 'access', _438 => _438.stickers, 'optionalAccess', _439 => _439[layer.id]]);
6865
+ if (!_optionalChain([existing, 'optionalAccess', _440 => _440.length])) {
6586
6866
  if (this.wet.wetLayerIds().includes(layer.id) || _chunk474IQG74cjs.contentBounds.call(void 0, layer.surface)) throw new PaintEditorError(`Layer "${layer.name}" already has paint; add stickers to an empty layer (add_layer) or a sticker layer so they stay editable.`);
6587
6867
  }
6588
6868
  let n = this.nextStickerNumber();
@@ -6598,7 +6878,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6598
6878
  const id = n++;
6599
6879
  return { id: `st${id}`, size: 48, rotation: 0, color: this.color, opacity: 1, seed: _nullishCoalesce(raw.seed, () => ( _chunkPQ3H2AANcjs.mix32.call(void 0, id * 2654435761 >>> 0) & 2147483647)), ...u };
6600
6880
  });
6601
- this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _411 => _411.length]) ? added.map(_chunk5FZS7J7Ccjs.stickerRect) : void 0);
6881
+ this.commitStickers("Add stickers", layer, [..._nullishCoalesce(existing, () => ( [])), ...added], _optionalChain([existing, 'optionalAccess', _441 => _441.length]) ? added.map(_chunk4T47Z4J3cjs.stickerRect) : void 0);
6602
6882
  return added.map((s) => ({ ...s }));
6603
6883
  }
6604
6884
  /** Brings stickers to the top (`front`) or bottom of their layer (one undo step). */
@@ -6608,7 +6888,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6608
6888
  const picked = stickers.filter((s) => ids.includes(s.id));
6609
6889
  const rest = stickers.filter((s) => !ids.includes(s.id));
6610
6890
  const next = to === "front" ? [...rest, ...picked] : [...picked, ...rest];
6611
- this.commitStickers("Arrange stickers", layer, next, picked.map(_chunk5FZS7J7Ccjs.stickerRect));
6891
+ this.commitStickers("Arrange stickers", layer, next, picked.map(_chunk4T47Z4J3cjs.stickerRect));
6612
6892
  return next.map((s) => s.id);
6613
6893
  }
6614
6894
  /** Deletes stickers (`ids`, or all of them on the layer) (one undo step). Returns the ids removed. */
@@ -6618,7 +6898,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6618
6898
  for (const id of ids) if (!stickers.some((s) => s.id === id)) throw new PaintEditorError(`Layer "${layer.name}" has no sticker "${id}". Call list_stickers for the ids.`);
6619
6899
  }
6620
6900
  const removed = ids ? [...ids] : stickers.map((s) => s.id);
6621
- this.commitStickers("Remove stickers", layer, stickers.filter((s) => !removed.includes(s.id)), ids ? stickers.filter((s) => removed.includes(s.id)).map(_chunk5FZS7J7Ccjs.stickerRect) : void 0);
6901
+ this.commitStickers("Remove stickers", layer, stickers.filter((s) => !removed.includes(s.id)), ids ? stickers.filter((s) => removed.includes(s.id)).map(_chunk4T47Z4J3cjs.stickerRect) : void 0);
6622
6902
  return removed;
6623
6903
  }
6624
6904
  /** Sets a layer's stickers (replays). */
@@ -6637,20 +6917,20 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6637
6917
  }
6638
6918
  liveStrokeLayer(layerId, what) {
6639
6919
  const l = this.wetLayer(layerId, what);
6640
- const strokes = _optionalChain([this, 'access', _412 => _412.doc, 'access', _413 => _413.liveStrokes, 'optionalAccess', _414 => _414[l.id]]);
6920
+ const strokes = _optionalChain([this, 'access', _442 => _442.doc, 'access', _443 => _443.liveStrokes, 'optionalAccess', _444 => _444[l.id]]);
6641
6921
  if (!strokes) throw new PaintEditorError(`Layer "${l.name}" is not a stroke layer; add one with add_layer {type: "strokes"} (or convert_to_stroke_layer on an empty layer), then paint on it.`);
6642
6922
  return { layer: l, strokes };
6643
6923
  }
6644
6924
  /** Whether a layer is a live stroke layer. */
6645
6925
  isLiveStrokeLayer(layerId) {
6646
- return Boolean(_optionalChain([this, 'access', _415 => _415.doc, 'access', _416 => _416.liveStrokes, 'optionalAccess', _417 => _417[layerId]]));
6926
+ return Boolean(_optionalChain([this, 'access', _445 => _445.doc, 'access', _446 => _446.liveStrokes, 'optionalAccess', _447 => _447[layerId]]));
6647
6927
  }
6648
6928
  /** Makes an empty pixel layer a live stroke layer (one undo step). */
6649
6929
  convertToLiveStrokes(layerId) {
6650
6930
  this.requireIdle("converting a layer");
6651
6931
  const l = this.paintTarget(layerId, "convert");
6652
- if (_optionalChain([this, 'access', _418 => _418.doc, 'access', _419 => _419.liveStrokes, 'optionalAccess', _420 => _420[l.id]])) return this.describeLayer(l);
6653
- if (_optionalChain([this, 'access', _421 => _421.doc, 'access', _422 => _422.stickers, 'optionalAccess', _423 => _423[l.id], 'optionalAccess', _424 => _424.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
6932
+ if (_optionalChain([this, 'access', _448 => _448.doc, 'access', _449 => _449.liveStrokes, 'optionalAccess', _450 => _450[l.id]])) return this.describeLayer(l);
6933
+ if (_optionalChain([this, 'access', _451 => _451.doc, 'access', _452 => _452.stickers, 'optionalAccess', _453 => _453[l.id], 'optionalAccess', _454 => _454.length])) throw new PaintEditorError(`Layer "${l.name}" is a sticker layer; add a stroke layer instead (add_layer {type: "strokes"}).`);
6654
6934
  if (_chunk474IQG74cjs.contentBounds.call(void 0, l.surface) || this.wet.wetLayerIds().includes(l.id)) throw new PaintEditorError(`Layer "${l.name}" already has paint, which isn't kept as strokes; convert an empty layer or add a stroke layer (add_layer {type: "strokes"}).`);
6655
6935
  this.commit("Convert to stroke layer", { ...this.doc, liveStrokes: { ..._nullishCoalesce(this.doc.liveStrokes, () => ( {})), [l.id]: [] } });
6656
6936
  return this.describeLayer(this.getLayer(l.id));
@@ -6663,7 +6943,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6663
6943
  findLiveStroke(id) {
6664
6944
  for (const [layerId, strokes] of Object.entries(_nullishCoalesce(this.doc.liveStrokes, () => ( {})))) {
6665
6945
  const index = strokes.findIndex((x) => x.id === id);
6666
- const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _425 => _425.layer]);
6946
+ const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.doc.layers, layerId), 'optionalAccess', _455 => _455.layer]);
6667
6947
  if (index >= 0 && isPixelLayer(layer)) return { layer, strokes, index };
6668
6948
  }
6669
6949
  const baked = this.doc.strokes.some((x) => x.id === id);
@@ -6683,15 +6963,15 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6683
6963
  let brush = was.brush;
6684
6964
  if (update.brushId !== void 0) {
6685
6965
  const b = this.requireBrush(update.brushId);
6686
- brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
6966
+ brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { tip: { ...b.tip, size: was.brush.tip.size } }, b);
6687
6967
  }
6688
6968
  if (update.brush !== void 0) {
6689
6969
  if (!update.brush || typeof update.brush !== "object") throw new PaintEditorError("brush must be an object of brush settings (as set_brush takes).");
6690
- brush = _chunk5FZS7J7Ccjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
6970
+ brush = _chunk4T47Z4J3cjs.normalizePaintBrush.call(void 0, { ...update.brush, id: brush.id }, brush);
6691
6971
  }
6692
6972
  const why = liveStrokeRefusal(brush);
6693
6973
  if (why) throw new PaintEditorError(why);
6694
- const next = { ...was, brush: _chunk5FZS7J7Ccjs.brushToJSON.call(void 0, brush) };
6974
+ const next = { ...was, brush: _chunk4T47Z4J3cjs.brushToJSON.call(void 0, brush) };
6695
6975
  if (update.seed !== void 0) {
6696
6976
  if (!Number.isInteger(update.seed) || update.seed < 0) throw new PaintEditorError(`seed ${update.seed} must be a whole number of 0 or more.`);
6697
6977
  next.seed = update.seed;
@@ -6702,7 +6982,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6702
6982
  }
6703
6983
  if (update.paint !== void 0) {
6704
6984
  if (update.paint === null) delete next.paint;
6705
- else if (_chunk5FZS7J7Ccjs.isPaintEffectPaint.call(void 0, update.paint)) {
6985
+ else if (_chunk4T47Z4J3cjs.isPaintEffectPaint.call(void 0, update.paint)) {
6706
6986
  if (!this.effectPaintImage(update.paint)) throw new PaintEditorError(`The effect "${update.paint.effect}" is not rendered yet; render it first (prepareEffectPaints; the update_stroke tool does this).`);
6707
6987
  next.paint = JSON.parse(JSON.stringify(update.paint));
6708
6988
  } else {
@@ -6713,7 +6993,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6713
6993
  } else next.paint = JSON.parse(JSON.stringify(p));
6714
6994
  }
6715
6995
  }
6716
- const rgb = _chunk5FZS7J7Ccjs.hexToRgb8.call(void 0, next.color).map((v) => v / 255);
6996
+ const rgb = _chunk4T47Z4J3cjs.hexToRgb8.call(void 0, next.color).map((v) => v / 255);
6717
6997
  const load = brushLoadForStroke(brush, _chunkPQ3H2AANcjs.EMPTY_MIXER_LOAD, rgb);
6718
6998
  if (load.reservoir || load.pickup) next.load = load;
6719
6999
  else delete next.load;
@@ -6758,9 +7038,9 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6758
7038
  const layers = /* @__PURE__ */ new Map();
6759
7039
  for (const f of found) layers.set(f.layer.id, f.layer);
6760
7040
  for (const [layerId, layer] of layers) {
6761
- const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _426 => _426.liveStrokes, 'optionalAccess', _427 => _427[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
7041
+ const gone = (_nullishCoalesce(_optionalChain([doc, 'access', _456 => _456.liveStrokes, 'optionalAccess', _457 => _457[layerId]]), () => ( []))).filter((x) => ids.includes(x.id));
6762
7042
  for (const x of gone) bounds = unionRect(bounds, this.strokeArea(x));
6763
- doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _428 => _428.liveStrokes, 'optionalAccess', _429 => _429[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
7043
+ doc = this.withLiveStrokes(doc, layer, (_nullishCoalesce(_optionalChain([doc, 'access', _458 => _458.liveStrokes, 'optionalAccess', _459 => _459[layerId]]), () => ( []))).filter((x) => !ids.includes(x.id)), this.strokeAreas(gone));
6764
7044
  }
6765
7045
  this.commit(ids.length === 1 ? "Remove stroke" : "Remove strokes", doc);
6766
7046
  return { removed: [...ids], bounds };
@@ -6828,7 +7108,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6828
7108
  }
6829
7109
  withLiveStrokes(doc, layer, list, dirty) {
6830
7110
  if (_chunkHB4ICNNAcjs.isLayerLocked.call(void 0, layer, "pixels")) throw new PaintEditorError(`Layer "${layer.name}" has its pixels locked; unlock it (update_layer locks) first.`);
6831
- const current = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _430 => _430.layer]);
7111
+ const current = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, layer.id), 'optionalAccess', _460 => _460.layer]);
6832
7112
  const surface = this.drawLiveStrokes(_nullishCoalesce(current, () => ( layer)), list, dirty);
6833
7113
  const next = { ...doc, layers: _chunkHB4ICNNAcjs.mapLayer.call(void 0, doc.layers, layer.id, (l) => ({ ...l, surface, offset: { x: 0, y: 0 } })), liveStrokes: { ..._nullishCoalesce(doc.liveStrokes, () => ( {})), [layer.id]: [...list] } };
6834
7114
  return this.withPaintEvent(next, { kind: "live-strokes", layerId: layer.id, data: { strokes: list.map((x) => JSON.parse(JSON.stringify(x))) } });
@@ -6906,7 +7186,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6906
7186
  if (!this.animatedLayers.size) return this.doc.layers;
6907
7187
  let layers = this.doc.layers;
6908
7188
  for (const [id, a] of this.animatedLayers) {
6909
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _431 => _431.layer]);
7189
+ const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, layers, id), 'optionalAccess', _461 => _461.layer]);
6910
7190
  if (isPixelLayer(l) && l.surface === a.base) layers = _chunkHB4ICNNAcjs.mapLayer.call(void 0, layers, id, () => ({ ...l, surface: a.surface }));
6911
7191
  }
6912
7192
  return layers;
@@ -6916,11 +7196,11 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
6916
7196
  const layers = [];
6917
7197
  const sources = /* @__PURE__ */ new Map();
6918
7198
  for (const [id, strokes] of Object.entries(_nullishCoalesce(doc.liveStrokes, () => ( {})))) {
6919
- const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _432 => _432.layer]);
7199
+ const layer = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, doc.layers, id), 'optionalAccess', _462 => _462.layer]);
6920
7200
  const live = strokes.filter(isLiveEffect);
6921
7201
  if (!isPixelLayer(layer) || !live.length) continue;
6922
7202
  layers.push({ layer, strokes });
6923
- for (const st of live) sources.set(_chunk5FZS7J7Ccjs.effectPaintKey.call(void 0, st.paint), st.paint);
7203
+ for (const st of live) sources.set(_chunk4T47Z4J3cjs.effectPaintKey.call(void 0, st.paint), st.paint);
6924
7204
  }
6925
7205
  return { layers, sources: [...sources.values()] };
6926
7206
  }
@@ -7041,13 +7321,13 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
7041
7321
  return this.withEffectTime(time, () => this.compositePixels(options));
7042
7322
  }
7043
7323
  // --- Stencils --------------------------------------------------------------------
7044
- __init129() {this.stencilCache = null}
7045
- __init130() {this.nextStencilId = 1}
7324
+ __init135() {this.stencilCache = null}
7325
+ __init136() {this.nextStencilId = 1}
7046
7326
  /** The mask stencils' coverage over the canvas (cached), or `null` when none masks. */
7047
7327
  stencilSelection(stencils = this.guides.stencils) {
7048
7328
  const { width, height } = this.doc.canvas;
7049
7329
  const size = `${width}x${height}`;
7050
- if (_optionalChain([this, 'access', _433 => _433.stencilCache, 'optionalAccess', _434 => _434.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
7330
+ if (_optionalChain([this, 'access', _463 => _463.stencilCache, 'optionalAccess', _464 => _464.key]) === stencils && this.stencilCache.size === size) return this.stencilCache.mask;
7051
7331
  const mask = stencilMask(stencils, width, height);
7052
7332
  this.stencilCache = { key: stencils, size, mask };
7053
7333
  return mask;
@@ -7109,7 +7389,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
7109
7389
  makeSwatch(color, name) {
7110
7390
  const p = typeof color === "string" ? { type: "color", color: parseColor(color) } : this.readStrokePaint(color);
7111
7391
  const out = { color: _chunkPQ3H2AANcjs.paintSourceColor.call(void 0, p, { paint: this.color, secondary: this.secondaryColor }) };
7112
- if (_optionalChain([name, 'optionalAccess', _435 => _435.trim, 'call', _436 => _436()])) out.name = name.trim();
7392
+ if (_optionalChain([name, 'optionalAccess', _465 => _465.trim, 'call', _466 => _466()])) out.name = name.trim();
7113
7393
  if (p.type === "gradient") out.paint = p;
7114
7394
  return out;
7115
7395
  }
@@ -7161,7 +7441,7 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
7161
7441
  * mix becomes the paint colour. Returns the mixed colour and the pile's bounds.
7162
7442
  */
7163
7443
  mixOnPad(paints, options = {}) {
7164
- const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _437 => _437.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _438 => _438.parts]) }));
7444
+ const parsed = (_nullishCoalesce(paints, () => ( []))).map((p, i) => ({ color: parseColor(_optionalChain([p, 'optionalAccess', _467 => _467.color]), `paints[${i}].color`), parts: _optionalChain([p, 'optionalAccess', _468 => _468.parts]) }));
7165
7445
  let r;
7166
7446
  try {
7167
7447
  r = this.pad.mix(parsed, options);
@@ -7250,10 +7530,10 @@ var PaintEditorController = (_class11 = class _PaintEditorController {
7250
7530
  }
7251
7531
  /** A layer's tile surface (live while stroking), for thumbnails. */
7252
7532
  layerSurface(id) {
7253
- const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _439 => _439.layer]);
7533
+ const l = _optionalChain([_chunkHB4ICNNAcjs.findLayer.call(void 0, this.currentLayers(), id), 'optionalAccess', _469 => _469.layer]);
7254
7534
  return isPixelLayer(l) ? l.surface : null;
7255
7535
  }
7256
- }, _class11.__initStatic(), _class11);
7536
+ }, _class12.__initStatic(), _class12);
7257
7537
  var MAX_IMAGE_SIDE = 8192;
7258
7538
  var movePoint = (p, dx, dy) => ({ x: p.x + dx, y: p.y + dy });
7259
7539
  var moveRect = (r, dx, dy) => ({ ...r, x: r.x + dx, y: r.y + dy });
@@ -7265,13 +7545,14 @@ function withLayerLight(light, layerId, next) {
7265
7545
  else delete out[layerId];
7266
7546
  return out;
7267
7547
  }
7548
+ var BACKLIGHT_LAYER_ID = "__backlight";
7268
7549
  function insertAfter(layers, id, node) {
7269
7550
  const i = layers.findIndex((l) => l.id === id);
7270
7551
  if (i >= 0) return [...layers.slice(0, i + 1), node, ...layers.slice(i + 1)];
7271
7552
  return layers.map((l) => l.type === "group" ? { ...l, children: insertAfter(l.children, id, node) } : l);
7272
7553
  }
7273
7554
  function isLiveEffect(s) {
7274
- return _optionalChain([s, 'access', _440 => _440.paint, 'optionalAccess', _441 => _441.type]) === "effect" && s.paint.live === true;
7555
+ return _optionalChain([s, 'access', _470 => _470.paint, 'optionalAccess', _471 => _471.type]) === "effect" && s.paint.live === true;
7275
7556
  }
7276
7557
  function framePaint(p, t) {
7277
7558
  return { ...p, time: p.time + t };
@@ -7296,7 +7577,7 @@ function clipRect(r, width, height) {
7296
7577
  return x1 > x0 && y1 > y0 ? { x: x0, y: y0, width: x1 - x0, height: y1 - y0 } : null;
7297
7578
  }
7298
7579
  function withLiveStroke(doc, stroke) {
7299
- const list = _optionalChain([doc, 'access', _442 => _442.liveStrokes, 'optionalAccess', _443 => _443[stroke.layerId]]);
7580
+ const list = _optionalChain([doc, 'access', _472 => _472.liveStrokes, 'optionalAccess', _473 => _473[stroke.layerId]]);
7300
7581
  return list ? { ...doc, liveStrokes: { ...doc.liveStrokes, [stroke.layerId]: [...list, stroke] } } : doc;
7301
7582
  }
7302
7583
  function shiftDocument(doc, dx, dy) {
@@ -7323,9 +7604,9 @@ function shiftDocument(doc, dx, dy) {
7323
7604
  if (doc.liveStrokes) out.liveStrokes = Object.fromEntries(Object.entries(doc.liveStrokes).map(([id, list]) => [id, list.map(moveStroke)]));
7324
7605
  if (doc.paintEvents) {
7325
7606
  out.paintEvents = doc.paintEvents.map((e) => {
7326
- const list = e.kind === "stickers" ? _optionalChain([e, 'access', _444 => _444.data, 'optionalAccess', _445 => _445.stickers]) : void 0;
7607
+ const list = e.kind === "stickers" ? _optionalChain([e, 'access', _474 => _474.data, 'optionalAccess', _475 => _475.stickers]) : void 0;
7327
7608
  if (list) return { ...e, data: { ...e.data, stickers: moveStickers(list) } };
7328
- const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _446 => _446.data, 'optionalAccess', _447 => _447.strokes]) : void 0;
7609
+ const strokes = e.kind === "live-strokes" ? _optionalChain([e, 'access', _476 => _476.data, 'optionalAccess', _477 => _477.strokes]) : void 0;
7329
7610
  return strokes ? { ...e, data: { ...e.data, strokes: strokes.map(moveStroke) } } : e;
7330
7611
  });
7331
7612
  }
@@ -7407,8 +7688,8 @@ function strokeSchedule(points) {
7407
7688
  return total > 0 ? acc.map((d) => d / total) : points.map(() => 1);
7408
7689
  }
7409
7690
  function strokeDuration(points, max = 1800) {
7410
- const t0 = _optionalChain([points, 'access', _448 => _448[0], 'optionalAccess', _449 => _449.t]);
7411
- const t1 = _optionalChain([points, 'access', _450 => _450[points.length - 1], 'optionalAccess', _451 => _451.t]);
7691
+ const t0 = _optionalChain([points, 'access', _478 => _478[0], 'optionalAccess', _479 => _479.t]);
7692
+ const t1 = _optionalChain([points, 'access', _480 => _480[points.length - 1], 'optionalAccess', _481 => _481.t]);
7412
7693
  let ms;
7413
7694
  if (points.every((p) => Number.isFinite(p.t)) && t1 > t0) ms = t1 - t0;
7414
7695
  else {
@@ -7462,7 +7743,7 @@ var PaintDirector = class {
7462
7743
  }
7463
7744
  where(id) {
7464
7745
  const a = this.presence.get(id);
7465
- return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _452 => _452.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _453 => _453.y]), () => ( 0)) };
7746
+ return { x: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _482 => _482.x]), () => ( 0)), y: _nullishCoalesce(_optionalChain([a, 'optionalAccess', _483 => _483.y]), () => ( 0)) };
7466
7747
  }
7467
7748
  /** Glides to `to`; an actor that just appeared starts there instead of the corner. */
7468
7749
  async glide(id, to, ms = 380) {
@@ -7509,8 +7790,8 @@ var PaintDirector = class {
7509
7790
  }
7510
7791
  case "replay": {
7511
7792
  await this.say(id, command.note, 500);
7512
- const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _454 => _454.replay, 'access', _455 => _455.strokeIds, 'optionalAccess', _456 => _456.includes, 'call', _457 => _457(s.id)]));
7513
- const first = _optionalChain([source, 'access', _458 => _458[0], 'optionalAccess', _459 => _459.points, 'access', _460 => _460[0]]);
7793
+ const source = c.getStrokes().filter((s) => _optionalChain([command, 'access', _484 => _484.replay, 'access', _485 => _485.strokeIds, 'optionalAccess', _486 => _486.includes, 'call', _487 => _487(s.id)]));
7794
+ const first = _optionalChain([source, 'access', _488 => _488[0], 'optionalAccess', _489 => _489.points, 'access', _490 => _490[0]]);
7514
7795
  if (first) await this.glide(id, first);
7515
7796
  const result = c.replayStrokes(command.replay);
7516
7797
  if (result.bounds) await this.glide(id, centre(result.bounds), 520);
@@ -7691,7 +7972,7 @@ function createPaintStickerTools(c) {
7691
7972
  items: {
7692
7973
  type: "object",
7693
7974
  properties: {
7694
- stamp: { type: "string", enum: [..._chunk5FZS7J7Ccjs.STAMP_KINDS], description: "The stamp." },
7975
+ stamp: { type: "string", enum: [..._chunk4T47Z4J3cjs.STAMP_KINDS], description: "The stamp." },
7695
7976
  x: { type: "number", description: "Centre x in document pixels." },
7696
7977
  y: { type: "number", description: "Centre y in document pixels." },
7697
7978
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels (default 48)." },
@@ -7721,7 +8002,7 @@ function createPaintStickerTools(c) {
7721
8002
  properties: {
7722
8003
  layerId: LAYER_ID,
7723
8004
  id: { type: "string", description: "Sticker id from list_stickers." },
7724
- stamp: { type: "string", enum: [..._chunk5FZS7J7Ccjs.STAMP_KINDS], description: "Another stamp." },
8005
+ stamp: { type: "string", enum: [..._chunk4T47Z4J3cjs.STAMP_KINDS], description: "Another stamp." },
7725
8006
  x: { type: "number", description: "Centre x in document pixels." },
7726
8007
  y: { type: "number", description: "Centre y in document pixels." },
7727
8008
  size: { type: "number", minimum: 2, maximum: 2048, description: "Diameter in pixels." },
@@ -8259,7 +8540,7 @@ function createPaintWetTools(c) {
8259
8540
  {
8260
8541
  name: "advance_wet_paint",
8261
8542
  title: "Let the wet paint flow",
8262
- description: "Lets time pass for wet paint: the water spreads, runs downhill on a tilted canvas, granulates, blooms and evaporates, and pigment settles. Give steps (simulation steps; at the default 120 per second, 120 steps is one second) or seconds (default 1). Not an undo step, as time passing never is. Returns the steps run, the clock, stillWet and each wet layer\u2019s state. Paint dries by itself after a few thousand steps; dry_paint dries it at once.",
8543
+ description: "Lets time pass for wet paint: the water spreads, runs downhill on a tilted canvas, granulates, blooms and evaporates, and pigment settles. Give steps (simulation steps; at the default 120 per second, 120 steps is one second) or seconds (default 1). Not an undo step, as time passing never is. Returns the steps run, the clock, stillWet and each wet layer\u2019s state. Paint dries by itself after a few thousand steps; dry_paint dries it at once. Wet light paint (wet brushes with light.amount) flows with the pigment and settles where it dries into the layer\u2019s light (get_light).",
8263
8544
  inputSchema: {
8264
8545
  type: "object",
8265
8546
  properties: {
@@ -8321,7 +8602,7 @@ function createPaintWetTools(c) {
8321
8602
  type: "object",
8322
8603
  properties: {
8323
8604
  layerId: LAYER_ID2,
8324
- kind: { type: "string", enum: [..._chunkXFYLA3ZOcjs.WET_FLOW_KINDS], description: "none, linear, swirl, radial or turbulent." },
8605
+ kind: { type: "string", enum: [..._chunkVMROIWLLcjs.WET_FLOW_KINDS], description: "none, linear, swirl, radial or turbulent." },
8325
8606
  strength: UNIT("How hard it pushes, 0..1 (1 is about a 25\xB0 tilt; default 0.5)."),
8326
8607
  angle: { type: "number", minimum: -360, maximum: 360, description: "linear: direction in degrees clockwise from canvas down (default 0)." },
8327
8608
  center: {
@@ -8632,7 +8913,7 @@ var BEHAVIOR = {
8632
8913
  type: "object",
8633
8914
  description: "Multi-coloured brush (the older form of paint, the brush's own gradient: tip is across-tip, dab is distance in dabs or random). Read back from paint when it has a multi-colour equivalent. Missing fields keep their current values.",
8634
8915
  properties: {
8635
- mode: { type: "string", enum: [..._chunk5FZS7J7Ccjs.MULTI_COLOR_MODES], description: "off; tip: the colours lie side by side across the tip (stripes along the stroke, like a brush loaded with several paints); dab: the colour changes along the stroke." },
8916
+ mode: { type: "string", enum: [..._chunk4T47Z4J3cjs.MULTI_COLOR_MODES], description: "off; tip: the colours lie side by side across the tip (stripes along the stroke, like a brush loaded with several paints); dab: the colour changes along the stroke." },
8636
8917
  colors: { type: "array", maxItems: 8, items: { ...COLOR3 }, description: "2..8 colours #rrggbb; fewer than 2 uses the paint colour and the secondary colour." },
8637
8918
  order: { type: "string", enum: ["sequence", "random"], description: "dab mode: sequence runs through the colours in order, blending between them; random picks one per run of dabs (seeded)." },
8638
8919
  length: { type: "integer", minimum: 1, maximum: 500, description: "dab mode: dabs per colour (default 12)." },
@@ -8673,10 +8954,10 @@ var WET_BRUSH = {
8673
8954
  properties: {
8674
8955
  tool: {
8675
8956
  type: "string",
8676
- enum: [..._chunk5FZS7J7Ccjs.WET_TOOLS],
8957
+ enum: [..._chunk4T47Z4J3cjs.WET_TOOLS],
8677
8958
  description: "paint: water and pigment (picks up and mixes wet paint by behavior.pickup / mix); water: clear water (with rewet it lifts dried paint); dry: a hair dryer, takes water; blow: pushes the water along the stroke; blend: evens out wet pigment; smudge: drags wet paint; blot: a tissue, takes wet paint up (erase wet)."
8678
8959
  },
8679
- medium: { type: "string", enum: [..._chunk5FZS7J7Ccjs.WET_MEDIA], description: "The medium: watercolor, gouache or oil. A layer takes the medium's wet settings the first time it holds wet paint (oil: thick, barely flows, stays wet long and blends into the wet paint it meets)." },
8960
+ medium: { type: "string", enum: [..._chunk4T47Z4J3cjs.WET_MEDIA], description: "The medium: watercolor, gouache or oil. A layer takes the medium's wet settings the first time it holds wet paint (oil: thick, barely flows, stays wet long and blends into the wet paint it meets)." },
8680
8961
  load: { type: "number", minimum: 0, maximum: 1, description: "Paint loading: 1 never runs out; lower, the brush runs dry along a long stroke (each stroke reloads)." },
8681
8962
  thinner: { type: "number", minimum: 0, maximum: 1, description: "Thinner (water or solvent): more transparent, runnier paint." },
8682
8963
  water: { type: "number", minimum: 0, maximum: 1, description: "Wetness: water laid per stroke, 0.2 a damp brush .. 1 a dripping one." },
@@ -8693,7 +8974,7 @@ var IMPASTO_BRUSH = {
8693
8974
  properties: {
8694
8975
  tool: {
8695
8976
  type: "string",
8696
- enum: [..._chunk5FZS7J7Ccjs.IMPASTO_TOOLS],
8977
+ enum: [..._chunk4T47Z4J3cjs.IMPASTO_TOOLS],
8697
8978
  description: "brush: thick paint with bristle ridges along the stroke; tube: blobs squeezed from the tube; knife: a palette knife that scrapes the relief flat and smears the paint; roller: a flat stippled band; gloop: a thick, glossy, rounded bead."
8698
8979
  },
8699
8980
  thickness: { type: "number", minimum: 0, maximum: 1, description: "How far the paint stands up." },
@@ -8709,7 +8990,7 @@ var IMPASTO_BRUSH = {
8709
8990
  };
8710
8991
  var LIGHT_BRUSH = {
8711
8992
  type: "object",
8712
- description: "Light paint: the light the brush lays with its colour, glowing in the paint's own colour and spilling onto its surroundings (set_light_spill). Dab, particle, bristle, Mixer Brush and impasto brushes take it; wet and sticker brushes refuse light above 0. Missing fields keep their current values.",
8993
+ description: "Light paint: the light the brush lays with its colour, glowing in the paint's own colour and spilling onto its surroundings (set_light_spill). Dab, particle, bristle, Mixer Brush, impasto and wet paint brushes take it (wet light flows, pools, granulates and blooms with the pigment until the paint dries, then is ordinary light paint); wet tools other than paint lay none, and sticker brushes refuse light above 0. Missing fields keep their current values.",
8713
8994
  properties: {
8714
8995
  amount: { type: "number", minimum: 0, maximum: 1, description: "Light each dab lays, scaled by its coverage and flow (0 none, default; 1 full)." },
8715
8996
  pressure: { type: "boolean", description: "Pressure scales the light (default false)." }
@@ -8720,8 +9001,8 @@ var PARTICLE_BRUSH = {
8720
9001
  type: "object",
8721
9002
  description: "Particle engine settings (procedural brushes). Missing fields keep their current values.",
8722
9003
  properties: {
8723
- kind: { type: "string", enum: [..._chunk5FZS7J7Ccjs.PARTICLE_KINDS], description: "string: strands of masses on springs dragged behind the pen (hair, fur, wet string); spring: particles on springs to the pen, overshooting and wobbling; orbit: particles circling the pen (curls); flow: particles thrown off the pen into a swirling flow until they fade." },
8724
- render: { type: "string", enum: [..._chunk5FZS7J7Ccjs.PARTICLE_RENDERS], description: "dot: a mark at each step; line: each particle draws a continuous line; sequence: beads spaced along each path." },
9004
+ kind: { type: "string", enum: [..._chunk4T47Z4J3cjs.PARTICLE_KINDS], description: "string: strands of masses on springs dragged behind the pen (hair, fur, wet string); spring: particles on springs to the pen, overshooting and wobbling; orbit: particles circling the pen (curls); flow: particles thrown off the pen into a swirling flow until they fade." },
9005
+ render: { type: "string", enum: [..._chunk4T47Z4J3cjs.PARTICLE_RENDERS], description: "dot: a mark at each step; line: each particle draws a continuous line; sequence: beads spaced along each path." },
8725
9006
  count: { type: "integer", minimum: 1, maximum: 64, description: "Particles (flow: how many are thrown per tip of travel)." },
8726
9007
  size: { type: "number", minimum: 0, maximum: 1, description: "Mark size as a fraction of the tip size." },
8727
9008
  spread: { type: "number", minimum: 0, maximum: 1, description: "How far apart the particles start, as a fraction of the tip size." },
@@ -8751,7 +9032,7 @@ var STICKER_BRUSH = {
8751
9032
  type: "object",
8752
9033
  description: "Sticker engine settings: stamps sprayed along the stroke as editable stickers. Missing fields keep their current values.",
8753
9034
  properties: {
8754
- stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [..._chunk5FZS7J7Ccjs.STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
9035
+ stamps: { type: "array", minItems: 1, maxItems: 9, items: { type: "string", enum: [..._chunk4T47Z4J3cjs.STAMP_KINDS], description: "A stamp." }, description: "The stamps to spray (one picked at random per sticker)." },
8755
9036
  density: { type: "number", minimum: 0, maximum: 1, description: "How closely stickers follow each other: about density \xD7 4 stickers per tip diameter of travel (0.25 \u2248 one per diameter, 1 \u2248 four). Default 0.4." },
8756
9037
  sizeJitter: { type: "number", minimum: 0, maximum: 1, description: "Random size change." },
8757
9038
  rotationJitter: { type: "number", minimum: 0, maximum: 1, description: "Random turn as a fraction of \xB1180\xB0." },
@@ -8762,16 +9043,16 @@ var STICKER_BRUSH = {
8762
9043
  };
8763
9044
  var BRUSH_FIELDS = {
8764
9045
  name: { type: "string", minLength: 1, maxLength: 80, description: "Display name." },
8765
- category: { type: "string", enum: [..._chunk5FZS7J7Ccjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
9046
+ category: { type: "string", enum: [..._chunk4T47Z4J3cjs.PAINT_BRUSH_CATEGORIES], description: "Library category." },
8766
9047
  engine: {
8767
9048
  type: "string",
8768
- enum: [..._chunk5FZS7J7Ccjs.PAINT_BRUSH_ENGINES],
9049
+ enum: [..._chunk4T47Z4J3cjs.PAINT_BRUSH_ENGINES],
8769
9050
  description: "dab: paints dabs (with behavior.pickup or gradient paint it paints dab by dab, lifting and mixing paint); eraser: removes paint; mixer: the Mixer Brush (a reservoir plus picked-up paint); blender: mixes the colours under and near the tip; smudge: drags paint along the stroke; wet: watercolour, gouache, oil and the wet tools on a simulated wet layer (see wet); impasto: thick paint with relief (see impasto); particle: procedural particle brushes (see particle); bristle: a tuft of bristles that bend and splay (see bristle); sticker: sprays editable sticker stamps (see sticker)."
8770
9051
  },
8771
9052
  tip: TIP,
8772
9053
  grain: { type: "number", minimum: 0, maximum: 1, description: "Paper grain response: 0 ignores the grain, 1 catches only its peaks at light pressure (pencil, pastel, charcoal). Multiplied by the paper depth." },
8773
9054
  pressureSmoothing: { type: "number", minimum: 0, maximum: 0.95, description: "Pressure smoothing, separate from the tip position smoothing." },
8774
- rotation: { type: "string", enum: [..._chunk5FZS7J7Ccjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
9055
+ rotation: { type: "string", enum: [..._chunk4T47Z4J3cjs.BRUSH_ROTATIONS], description: "What turns the tip: fixed (tip.angle), stroke (follows the direction of travel) or barrel (the pen barrel rotation, twist)." },
8775
9056
  dynamics: DYNAMICS,
8776
9057
  mixer: MIXER,
8777
9058
  loadsColor: { type: "boolean", description: "Mixer engine: load the colour each stroke (false for a mixer that only moves paint)." },
@@ -8823,7 +9104,7 @@ function brushSummary(b) {
8823
9104
  size: b.tip.size,
8824
9105
  grain: b.grain,
8825
9106
  rotation: b.rotation,
8826
- wetCapable: _chunk5FZS7J7Ccjs.isWetCapable.call(void 0, b),
9107
+ wetCapable: _chunk4T47Z4J3cjs.isWetCapable.call(void 0, b),
8827
9108
  pickup: b.behavior.pickup,
8828
9109
  dirty: b.behavior.dirty,
8829
9110
  multicolor: b.behavior.multicolor.mode,
@@ -8932,15 +9213,15 @@ function createPaintEditorToolProvider(controller, options = {}) {
8932
9213
  inputSchema: EMPTY3,
8933
9214
  annotations: { title: "List papers", ...READ6 },
8934
9215
  handler: () => ({
8935
- papers: _chunk5FZS7J7Ccjs.PAPER_LIBRARY.map((p) => ({ id: p.preset, name: p.name, family: p.family, pattern: p.pattern, color: p.color, depth: p.depth, absorption: p.absorption, permeability: p.permeability, roughness: p.roughness })),
8936
- families: [..._chunk5FZS7J7Ccjs.PAPER_FAMILIES],
9216
+ papers: _chunk4T47Z4J3cjs.PAPER_LIBRARY.map((p) => ({ id: p.preset, name: p.name, family: p.family, pattern: p.pattern, color: p.color, depth: p.depth, absorption: p.absorption, permeability: p.permeability, roughness: p.roughness })),
9217
+ families: [..._chunk4T47Z4J3cjs.PAPER_FAMILIES],
8937
9218
  patterns: [..._chunkPQ3H2AANcjs.GRAIN_PATTERNS]
8938
9219
  })
8939
9220
  });
8940
9221
  add({
8941
9222
  name: "get_paper",
8942
9223
  title: "Get the paper",
8943
- description: "Reads every setting of the current paper (preset, pattern, seed, colour, scale, tiling, depth, shading, dry and wet tuning, absorption, permeability, roughness).",
9224
+ description: "Reads every setting of the current paper (preset, pattern, seed, colour, scale, tiling, depth, shading, dry and wet tuning, absorption, permeability, roughness, and metallic, backlight and backlightColor when set).",
8944
9225
  inputSchema: EMPTY3,
8945
9226
  annotations: { title: "Get the paper", ...READ6 },
8946
9227
  handler: () => JSON.parse(JSON.stringify(c.document.paper))
@@ -8956,7 +9237,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
8956
9237
  add({
8957
9238
  name: "set_paper",
8958
9239
  title: "Set the paper",
8959
- description: "Changes the paper under the whole painting: a preset from list_papers and / or its settings. Grain depth decides how much grain-responsive brushes (pencil, pastel, charcoal) skip the valleys; changing it re-renders the paper but not strokes already painted. One undo step. Returns the paper.",
9240
+ description: "Changes the paper under the whole painting: a preset from list_papers and / or its settings. Grain depth decides how much grain-responsive brushes (pencil, pastel, charcoal) skip the valleys; changing it re-renders the paper but not strokes already painted. backlight lights the paper from behind (the stained-glass preset has it on). One undo step. Returns the paper.",
8960
9241
  inputSchema: {
8961
9242
  type: "object",
8962
9243
  properties: {
@@ -8974,6 +9255,8 @@ function createPaintEditorToolProvider(controller, options = {}) {
8974
9255
  permeability: { type: "number", minimum: 0, maximum: 1, description: "Wet media: how freely water flows over the fibres (low: more ragged, slower spreading)." },
8975
9256
  roughness: { type: "number", minimum: 0, maximum: 1, description: "Wet media: how much the grain pins wet edges and catches granulating pigment." },
8976
9257
  metallic: { type: "number", minimum: 0, maximum: 1, description: "Metallic paper (gold or silver leaf, pearlescent card): the grain catches the light (see set_lighting). 0 by default." },
9258
+ backlight: { type: "number", minimum: 0, maximum: 1, description: "Backlit paper (a lightbox, stained glass): light from behind the paper, 0 (none, the default) .. 1. Transparent glazes (watercolour, airbrush, thin marker) glow in their own colour; opaque paint (gouache, oil, solid ink) and thick paint block it; the light through paint spills softly around it. Nothing is repainted." },
9259
+ backlightColor: { ...COLOR3, description: "The backlight\u2019s colour #rrggbb (default #fff1d6, warm white)." },
8977
9260
  name: { type: "string", minLength: 1, description: "Display name." }
8978
9261
  },
8979
9262
  additionalProperties: false
@@ -9148,12 +9431,12 @@ function createPaintEditorToolProvider(controller, options = {}) {
9148
9431
  add({
9149
9432
  name: "list_brushes",
9150
9433
  title: "List brushes",
9151
- description: "Lists the brush library: built-in dry media (pencils, pastels, charcoal, airbrush, marker, ink, erasers), paint brushes (dirty round, multi-colour flat, palette dabber), blending tools (blender, smudge, pigment smudge, Mixer Brush), light paint (category light: glow gel, neon marker, light airbrush, spark trail; light is the amount they lay) and saved user brushes, with id, name, category, engine, size, grain response, rotation mode, whether it can pick up paint (wetCapable), its pick-up ratio, dirty and multi-colour mode, plus the active brush id.",
9434
+ description: "Lists the brush library: built-in dry media (pencils, pastels, charcoal, airbrush, marker, ink, erasers), paint brushes (dirty round, multi-colour flat, palette dabber), blending tools (blender, smudge, pigment smudge, Mixer Brush), light paint (category light: glow gel, neon marker, light airbrush, spark trail, glow wash; light is the amount they lay) and saved user brushes, with id, name, category, engine, size, grain response, rotation mode, whether it can pick up paint (wetCapable), its pick-up ratio, dirty and multi-colour mode, plus the active brush id.",
9152
9435
  inputSchema: EMPTY3,
9153
9436
  annotations: { title: "List brushes", ...READ6 },
9154
9437
  handler: () => {
9155
9438
  const s = c.getState();
9156
- return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _461 => _461.getBrush, 'call', _462 => _462(s.brush.id), 'optionalAccess', _463 => _463.builtin])), brushes: s.brushes.map(brushSummary) };
9439
+ return { activeBrushId: s.brush.id, activeEdited: !s.brush.builtin && Boolean(_optionalChain([c, 'access', _491 => _491.getBrush, 'call', _492 => _492(s.brush.id), 'optionalAccess', _493 => _493.builtin])), brushes: s.brushes.map(brushSummary) };
9157
9440
  }
9158
9441
  });
9159
9442
  add({
@@ -9164,10 +9447,10 @@ function createPaintEditorToolProvider(controller, options = {}) {
9164
9447
  annotations: { title: "Get a brush", ...READ6 },
9165
9448
  handler: ({ id }) => {
9166
9449
  const st = c.getState();
9167
- if (id === void 0) return { ..._chunk5FZS7J7Ccjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
9450
+ if (id === void 0) return { ..._chunk4T47Z4J3cjs.brushToJSON.call(void 0, st.brush), strokePaint: _nullishCoalesce(st.brush.paint, () => ( st.paint)) };
9168
9451
  const b = c.getBrush(id);
9169
9452
  if (!b) throw new Error(`Unknown brush "${id}". Call list_brushes for the ids.`);
9170
- return { ..._chunk5FZS7J7Ccjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
9453
+ return { ..._chunk4T47Z4J3cjs.brushToJSON.call(void 0, b), builtin: Boolean(b.builtin), strokePaint: _nullishCoalesce(b.paint, () => ( st.paint)) };
9171
9454
  }
9172
9455
  });
9173
9456
  add({
@@ -9176,7 +9459,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9176
9459
  description: "Chooses the active brush (id) and / or changes its settings; strokes without a brush use it. Editor state, not an undo step. Changes stay on the active brush until save_brush stores them. Returns the active brush.",
9177
9460
  inputSchema: { type: "object", properties: { id: { type: "string", description: "Brush id from list_brushes to start from." }, ...BRUSH_FIELDS }, additionalProperties: false },
9178
9461
  annotations: { title: "Set the brush", ...SET4 },
9179
- handler: (a) => _chunk5FZS7J7Ccjs.brushToJSON.call(void 0, c.setBrush(a))
9462
+ handler: (a) => _chunk4T47Z4J3cjs.brushToJSON.call(void 0, c.setBrush(a))
9180
9463
  });
9181
9464
  add({
9182
9465
  name: "save_brush",
@@ -9192,7 +9475,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9192
9475
  additionalProperties: false
9193
9476
  },
9194
9477
  annotations: { title: "Save a brush", ...SET4 },
9195
- handler: ({ id, name }) => _chunk5FZS7J7Ccjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
9478
+ handler: ({ id, name }) => _chunk4T47Z4J3cjs.brushToJSON.call(void 0, c.saveBrush({ id, name }))
9196
9479
  });
9197
9480
  add({
9198
9481
  name: "remove_brush",
@@ -9332,7 +9615,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9332
9615
  add({
9333
9616
  name: "paint_stroke",
9334
9617
  title: "Paint a brush stroke",
9335
- description: "Paints one stroke through points (document pixels, with optional pressure, time, tilt and barrel rotation) on a pixel layer with a library brush or the active one, optionally changed for this stroke. Grain-responsive brushes follow the paper; the mixer engine (mixer-brush) picks up and mixes paint already on the layer, the blender mixes nearby colours, the smudge drags paint, and dab brushes with behavior.pickup lift and carry paint, and wet brushes (engine wet: watercolour, gouache, add water, dry, blow, wet blend, wet smudge, blot) paint on the layer\u2019s wet layer, where the paint keeps moving until it dries (the result says wet: true while it is; see advance_wet_paint and dry_paint; a dry brush on wet paint dries it first; wet oil brushes blend into the wet oil they meet), impasto brushes (engine impasto: impasto brush, paint tube, palette knife, roller, gloop pen, metallic paint) lay thick paint whose relief is lit by set_lighting, particle and bristle brushes draw procedural marks, and sticker brushes spray editable stickers onto an empty or sticker layer (list_stickers). Guide stencils make strokes that start near them follow them; mask stencils keep paint inside them. The symmetry guide adds its mirror copies; with a tracing image that samples colours, a stroke without color takes the image colour at its first point. With an agent cursor (a director), the stroke is painted live along the points at the pace of their times. One undo step. Returns the layer id, changed bounds, dab count, the recorded strokeId (for replay_strokes), for wet brushes wet (paint still wet) and, for brushes that pick up paint, mixerLoad: what the brush carries after the stroke.",
9618
+ description: "Paints one stroke through points (document pixels, with optional pressure, time, tilt and barrel rotation) on a pixel layer with a library brush or the active one, optionally changed for this stroke. Grain-responsive brushes follow the paper; the mixer engine (mixer-brush) picks up and mixes paint already on the layer, the blender mixes nearby colours, the smudge drags paint, and dab brushes with behavior.pickup lift and carry paint, and wet brushes (engine wet: watercolour, gouache, add water, dry, blow, wet blend, wet smudge, blot) paint on the layer\u2019s wet layer, where the paint keeps moving until it dries (the result says wet: true while it is; see advance_wet_paint and dry_paint; a dry brush on wet paint dries it first; wet oil brushes blend into the wet oil they meet; with light.amount, as glow-wash has, their light flows with the paint), impasto brushes (engine impasto: impasto brush, paint tube, palette knife, roller, gloop pen, metallic paint) lay thick paint whose relief is lit by set_lighting, particle and bristle brushes draw procedural marks, and sticker brushes spray editable stickers onto an empty or sticker layer (list_stickers). Guide stencils make strokes that start near them follow them; mask stencils keep paint inside them. The symmetry guide adds its mirror copies; with a tracing image that samples colours, a stroke without color takes the image colour at its first point. With an agent cursor (a director), the stroke is painted live along the points at the pace of their times. One undo step. Returns the layer id, changed bounds, dab count, the recorded strokeId (for replay_strokes), for wet brushes wet (paint still wet) and, for brushes that pick up paint, mixerLoad: what the brush carries after the stroke.",
9336
9619
  inputSchema: {
9337
9620
  type: "object",
9338
9621
  properties: {
@@ -9383,7 +9666,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9383
9666
  if (ids) {
9384
9667
  for (const id of ids) if (!all.some((s) => s.id === id)) throw new Error(`Unknown stroke "${id}". Call list_strokes without ids for the ids.`);
9385
9668
  }
9386
- return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _464 => _464.document, 'access', _465 => _465.liveStrokes, 'optionalAccess', _466 => _466[s.layerId], 'optionalAccess', _467 => _467.includes, 'call', _468 => _468(s)]) === true)) };
9669
+ return { total: all.length, strokes: picked.map((s) => strokeSummary(s, Boolean(ids), live ? true : liveIds.has(s.id) && _optionalChain([c, 'access', _494 => _494.document, 'access', _495 => _495.liveStrokes, 'optionalAccess', _496 => _496[s.layerId], 'optionalAccess', _497 => _497.includes, 'call', _498 => _498(s)]) === true)) };
9387
9670
  }
9388
9671
  });
9389
9672
  add({
@@ -9659,7 +9942,7 @@ function createPaintEditorToolProvider(controller, options = {}) {
9659
9942
  tools.push(...createPaintThickTools(c));
9660
9943
  tools.push(...createPaintReplayTools(c));
9661
9944
  tools.push(...createPaintStickerTools(c));
9662
- tools.push(..._chunkXFYLA3ZOcjs.createPigmentTools.call(void 0, ));
9945
+ tools.push(..._chunkVMROIWLLcjs.createPigmentTools.call(void 0, ));
9663
9946
  const exclude = new Set(_nullishCoalesce(options.exclude, () => ( [])));
9664
9947
  const description = "Natural-media painting: paper and grain, dry and wet brushes, the brush library, strokes as data, pigment mixing, stencils, guides, layers and export.";
9665
9948
  return withPaintPlayback({
@@ -9673,16 +9956,16 @@ function createPaintEditorToolProvider(controller, options = {}) {
9673
9956
  }
9674
9957
  function hostTool({ coordinates, ...tool }, { origin, onChange }) {
9675
9958
  if (!origin && !onChange) return tool;
9676
- const write = !_optionalChain([tool, 'access', _469 => _469.annotations, 'optionalAccess', _470 => _470.readOnlyHint]);
9959
+ const write = !_optionalChain([tool, 'access', _499 => _499.annotations, 'optionalAccess', _500 => _500.readOnlyHint]);
9677
9960
  const done = (result) => {
9678
- if (write) _optionalChain([onChange, 'optionalCall', _471 => _471({ tool: tool.name })]);
9679
- return origin && _optionalChain([coordinates, 'optionalAccess', _472 => _472.out]) ? fromDocument(result, coordinates.out, origin) : result;
9961
+ if (write) _optionalChain([onChange, 'optionalCall', _501 => _501({ tool: tool.name })]);
9962
+ return origin && _optionalChain([coordinates, 'optionalAccess', _502 => _502.out]) ? fromDocument(result, coordinates.out, origin) : result;
9680
9963
  };
9681
9964
  return {
9682
9965
  ...tool,
9683
9966
  ...origin ? { description: hostedText(_nullishCoalesce(tool.description, () => ( ""))), inputSchema: hostedSchema(tool.inputSchema) } : {},
9684
9967
  handler: (args, context) => {
9685
- const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _473 => _473.in]) ? toDocument(args, coordinates.in, origin) : args, context);
9968
+ const r = tool.handler(origin && _optionalChain([coordinates, 'optionalAccess', _503 => _503.in]) ? toDocument(args, coordinates.in, origin) : args, context);
9686
9969
  return r instanceof Promise ? r.then(done) : done(r);
9687
9970
  }
9688
9971
  };
@@ -9699,7 +9982,7 @@ function strokeSummary(s, withPoints, live) {
9699
9982
  color: s.color,
9700
9983
  points: withPoints ? s.points : s.points.length,
9701
9984
  seed: s.seed,
9702
- copies: _nullishCoalesce(_optionalChain([s, 'access', _474 => _474.copies, 'optionalAccess', _475 => _475.length]), () => ( 0)),
9985
+ copies: _nullishCoalesce(_optionalChain([s, 'access', _504 => _504.copies, 'optionalAccess', _505 => _505.length]), () => ( 0)),
9703
9986
  live,
9704
9987
  bounds: { x: Math.floor(Math.min(...xs) - pad), y: Math.floor(Math.min(...ys) - pad), width: Math.ceil(Math.max(...xs) - Math.min(...xs) + 2 * pad), height: Math.ceil(Math.max(...ys) - Math.min(...ys) + 2 * pad) }
9705
9988
  };
@@ -9714,21 +9997,21 @@ var PAINT_TOOLS = [
9714
9997
  { id: "pan", label: "Pan", key: "h" },
9715
9998
  { id: "rotate", label: "Rotate view", key: "r" }
9716
9999
  ];
9717
- var PaintGesture = (_class12 = class {
9718
- constructor(controller, box) {;_class12.prototype.__init131.call(this);_class12.prototype.__init132.call(this);_class12.prototype.__init133.call(this);_class12.prototype.__init134.call(this);_class12.prototype.__init135.call(this);_class12.prototype.__init136.call(this);
10000
+ var PaintGesture = (_class13 = class {
10001
+ constructor(controller, box) {;_class13.prototype.__init137.call(this);_class13.prototype.__init138.call(this);_class13.prototype.__init139.call(this);_class13.prototype.__init140.call(this);_class13.prototype.__init141.call(this);_class13.prototype.__init142.call(this);
9719
10002
  this.controller = controller;
9720
10003
  this.box = box;
9721
10004
  }
9722
10005
 
9723
10006
 
9724
- __init131() {this.tool = "brush"}
10007
+ __init137() {this.tool = "brush"}
9725
10008
  /** The last refusal (a hidden or locked layer), for the editor to show. */
9726
- __init132() {this.error = null}
10009
+ __init138() {this.error = null}
9727
10010
  /** The predicted tail of the current stroke in document pixels (draw it as a thin preview). */
9728
- __init133() {this.predicted = []}
9729
- __init134() {this.mode = null}
9730
- __init135() {this.penAt = null}
9731
- __init136() {this.penDown = false}
10011
+ __init139() {this.predicted = []}
10012
+ __init140() {this.mode = null}
10013
+ __init141() {this.penAt = null}
10014
+ __init142() {this.penDown = false}
9732
10015
  doc(e) {
9733
10016
  const b = this.box();
9734
10017
  const s = this.controller.getState();
@@ -9784,13 +10067,13 @@ var PaintGesture = (_class12 = class {
9784
10067
  const p = this.doc(e);
9785
10068
  const s = this.controller.getState();
9786
10069
  const layerId = s.document.activeLayerId;
9787
- if (!layerId || !_optionalChain([s, 'access', _476 => _476.document, 'access', _477 => _477.liveStrokes, 'optionalAccess', _478 => _478[layerId]])) {
10070
+ if (!layerId || !_optionalChain([s, 'access', _506 => _506.document, 'access', _507 => _507.liveStrokes, 'optionalAccess', _508 => _508[layerId]])) {
9788
10071
  this.error = "Pick a stroke layer in the Layers panel (or add one) to select its strokes.";
9789
10072
  return false;
9790
10073
  }
9791
10074
  try {
9792
10075
  const hit = this.controller.liveStrokeAt(layerId, p.x, p.y);
9793
- this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _479 => _479.id]), () => ( null)));
10076
+ this.controller.selectStroke(_nullishCoalesce(_optionalChain([hit, 'optionalAccess', _509 => _509.id]), () => ( null)));
9794
10077
  if (!hit) return false;
9795
10078
  this.mode = { kind: "move-stroke", pointerId: e.pointerId, id: hit.id, from: p, to: p };
9796
10079
  return true;
@@ -9802,7 +10085,7 @@ var PaintGesture = (_class12 = class {
9802
10085
  /** While a stroke is dragged: how far it has moved (document pixels), to draw its outline there. */
9803
10086
  get strokeDrag() {
9804
10087
  const m = this.mode;
9805
- return _optionalChain([m, 'optionalAccess', _480 => _480.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
10088
+ return _optionalChain([m, 'optionalAccess', _510 => _510.kind]) === "move-stroke" ? { id: m.id, dx: m.to.x - m.from.x, dy: m.to.y - m.from.y } : null;
9806
10089
  }
9807
10090
  /**
9808
10091
  * The Stickers tool: pressing a sticker picks it and dragging moves it (one undo step at the
@@ -9876,7 +10159,7 @@ var PaintGesture = (_class12 = class {
9876
10159
  if (!m || m.pointerId !== e.pointerId) return;
9877
10160
  this.mode = null;
9878
10161
  this.predicted = [];
9879
- if (m.kind === "stroke") _optionalChain([this, 'access', _481 => _481.controller, 'access', _482 => _482.activeStroke, 'optionalAccess', _483 => _483.end, 'call', _484 => _484()]);
10162
+ if (m.kind === "stroke") _optionalChain([this, 'access', _511 => _511.controller, 'access', _512 => _512.activeStroke, 'optionalAccess', _513 => _513.end, 'call', _514 => _514()]);
9880
10163
  if (m.kind === "move-stroke") {
9881
10164
  const dx = Math.round((this.doc(e).x - m.from.x) * 100) / 100;
9882
10165
  const dy = Math.round((this.doc(e).y - m.from.y) * 100) / 100;
@@ -9900,8 +10183,8 @@ var PaintGesture = (_class12 = class {
9900
10183
  cancel() {
9901
10184
  this.penDown = false;
9902
10185
  this.predicted = [];
9903
- if (_optionalChain([this, 'access', _485 => _485.mode, 'optionalAccess', _486 => _486.kind]) === "stroke") _optionalChain([this, 'access', _487 => _487.controller, 'access', _488 => _488.activeStroke, 'optionalAccess', _489 => _489.cancel, 'call', _490 => _490()]);
9904
- if (_optionalChain([this, 'access', _491 => _491.mode, 'optionalAccess', _492 => _492.kind]) === "sticker") this.controller.cancelStickerPreview();
10186
+ if (_optionalChain([this, 'access', _515 => _515.mode, 'optionalAccess', _516 => _516.kind]) === "stroke") _optionalChain([this, 'access', _517 => _517.controller, 'access', _518 => _518.activeStroke, 'optionalAccess', _519 => _519.cancel, 'call', _520 => _520()]);
10187
+ if (_optionalChain([this, 'access', _521 => _521.mode, 'optionalAccess', _522 => _522.kind]) === "sticker") this.controller.cancelStickerPreview();
9905
10188
  this.mode = null;
9906
10189
  }
9907
10190
  get active() {
@@ -9921,7 +10204,7 @@ var PaintGesture = (_class12 = class {
9921
10204
  const py = e.clientY - b.top - b.height / 2;
9922
10205
  this.controller.setView({ zoom, pan: { x: px - (px - s.view.pan.x) * k, y: py - (py - s.view.pan.y) * k } });
9923
10206
  }
9924
- }, _class12);
10207
+ }, _class13);
9925
10208
  var round2 = (v) => Math.round(v * 100) / 100;
9926
10209
  function handlePaintShortcut(controller, gesture, e) {
9927
10210
  const mod = e.ctrlKey || e.metaKey;
@@ -9962,14 +10245,14 @@ function handlePaintShortcut(controller, gesture, e) {
9962
10245
  }
9963
10246
  return false;
9964
10247
  }
9965
- var PaintCanvasPresenter = (_class13 = class {
9966
- constructor(controller) {;_class13.prototype.__init137.call(this);_class13.prototype.__init138.call(this);_class13.prototype.__init139.call(this);
10248
+ var PaintCanvasPresenter = (_class14 = class {
10249
+ constructor(controller) {;_class14.prototype.__init143.call(this);_class14.prototype.__init144.call(this);_class14.prototype.__init145.call(this);
9967
10250
  this.controller = controller;
9968
10251
  }
9969
10252
 
9970
- __init137() {this.uploaded = /* @__PURE__ */ new Map()}
9971
- __init138() {this.scratch = null}
9972
- __init139() {this.size = ""}
10253
+ __init143() {this.uploaded = /* @__PURE__ */ new Map()}
10254
+ __init144() {this.scratch = null}
10255
+ __init145() {this.size = ""}
9973
10256
  /** Draws what changed into `ctx` (a canvas the size of the document); returns the tiles drawn. */
9974
10257
  render(ctx) {
9975
10258
  const { width, height } = this.controller.document.canvas;
@@ -9995,13 +10278,13 @@ var PaintCanvasPresenter = (_class13 = class {
9995
10278
  }, { dirty });
9996
10279
  return drawn;
9997
10280
  }
9998
- }, _class13);
10281
+ }, _class14);
9999
10282
  function guideOverlay(controller, drag) {
10000
10283
  const s = controller.getState();
10001
10284
  const size = s.document.canvas;
10002
10285
  const out = [];
10003
10286
  const layerId = s.document.activeLayerId;
10004
- const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _493 => _493.document, 'access', _494 => _494.liveStrokes, 'optionalAccess', _495 => _495[layerId], 'optionalAccess', _496 => _496.some, 'call', _497 => _497((x) => x.id === s.selectedStroke)]) : false;
10287
+ const strokePicked = layerId && s.selectedStroke ? _optionalChain([s, 'access', _523 => _523.document, 'access', _524 => _524.liveStrokes, 'optionalAccess', _525 => _525[layerId], 'optionalAccess', _526 => _526.some, 'call', _527 => _527((x) => x.id === s.selectedStroke)]) : false;
10005
10288
  const area = strokePicked ? controller.liveStrokeArea(s.selectedStroke) : null;
10006
10289
  if (area) {
10007
10290
  const dx = drag && drag.id === s.selectedStroke ? drag.dx : 0;
@@ -10014,7 +10297,7 @@ function guideOverlay(controller, drag) {
10014
10297
  ];
10015
10298
  for (let i = 0; i < 4; i++) out.push({ from: box[i], to: box[(i + 1) % 4], kind: "stroke" });
10016
10299
  }
10017
- const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _498 => _498.document, 'access', _499 => _499.stickers, 'optionalAccess', _500 => _500[layerId], 'optionalAccess', _501 => _501.find, 'call', _502 => _502((x) => x.id === s.selectedSticker)]) : void 0;
10300
+ const picked = layerId && s.selectedSticker ? _optionalChain([s, 'access', _528 => _528.document, 'access', _529 => _529.stickers, 'optionalAccess', _530 => _530[layerId], 'optionalAccess', _531 => _531.find, 'call', _532 => _532((x) => x.id === s.selectedSticker)]) : void 0;
10018
10301
  if (picked) {
10019
10302
  const r = picked.size / 2 + 2;
10020
10303
  const a = picked.rotation * Math.PI / 180;
@@ -10054,11 +10337,12 @@ var PAPER_SLIDERS = [
10054
10337
  { path: "absorption", label: "Absorption", min: 0, max: 1, step: 0.01 },
10055
10338
  { path: "permeability", label: "Permeability", min: 0, max: 1, step: 0.01 },
10056
10339
  { path: "roughness", label: "Roughness", min: 0, max: 1, step: 0.01 },
10057
- { path: "metallic", label: "Metallic", min: 0, max: 1, step: 0.01 }
10340
+ { path: "metallic", label: "Metallic", min: 0, max: 1, step: 0.01 },
10341
+ { path: "backlight", label: "Backlight", min: 0, max: 1, step: 0.01 }
10058
10342
  ];
10059
10343
  function readPath(obj, path) {
10060
10344
  let v = obj;
10061
- for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _503 => _503[k]]);
10345
+ for (const k of path.split(".")) v = _optionalChain([v, 'optionalAccess', _533 => _533[k]]);
10062
10346
  return typeof v === "number" ? v : 0;
10063
10347
  }
10064
10348
  function patchPath(obj, path, value) {
@@ -10110,7 +10394,8 @@ var PICKUP_SLIDERS = [
10110
10394
  ];
10111
10395
  function brushEngineControls(brush) {
10112
10396
  const c = engineControls(brush);
10113
- if (!c || !["dab", "mixer", "particle", "bristle", "impasto"].includes(brush.engine)) return c;
10397
+ const wetPaint = brush.engine === "wet" && _optionalChain([brush, 'access', _534 => _534.wet, 'optionalAccess', _535 => _535.tool]) === "paint";
10398
+ if (!c || !(wetPaint || ["dab", "mixer", "particle", "bristle", "impasto"].includes(brush.engine))) return c;
10114
10399
  const extra = brush.engine === "impasto" ? [{ path: "impasto.rim", label: "Rim", min: 0, max: 1, step: 0.01 }, { path: "impasto.clarity", label: "Clarity", min: 0, max: 1, step: 0.01 }] : [];
10115
10400
  return { ...c, sliders: [...c.sliders, LIGHT_SLIDER, ...extra], light: true };
10116
10401
  }
@@ -10187,7 +10472,7 @@ function engineControls(brush) {
10187
10472
  impastoTool: true
10188
10473
  };
10189
10474
  case "wet": {
10190
- const tool = _nullishCoalesce(_optionalChain([brush, 'access', _504 => _504.wet, 'optionalAccess', _505 => _505.tool]), () => ( "paint"));
10475
+ const tool = _nullishCoalesce(_optionalChain([brush, 'access', _536 => _536.wet, 'optionalAccess', _537 => _537.tool]), () => ( "paint"));
10191
10476
  const sliders = tool === "paint" ? [
10192
10477
  { path: "wet.water", label: "Water", min: 0, max: 1, step: 0.01 },
10193
10478
  { path: "wet.pigment", label: "Pigment", min: 0, max: 1, step: 0.01 },
@@ -10320,7 +10605,7 @@ function startWetClock(controller, frame, cancel) {
10320
10605
  id = raf(loop);
10321
10606
  return () => {
10322
10607
  stopped = true;
10323
- _optionalChain([caf, 'optionalCall', _506 => _506(id)]);
10608
+ _optionalChain([caf, 'optionalCall', _538 => _538(id)]);
10324
10609
  };
10325
10610
  }
10326
10611
  function drawWaterOverlay(controller, ctx) {
@@ -10968,4 +11253,7 @@ function createPaintEditorDocument(controller, options = {}) {
10968
11253
 
10969
11254
 
10970
11255
 
10971
- exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkOLNIPTB3cjs.BLEND_MODES; exports.BRUSH_ID = _chunk5FZS7J7Ccjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunk5FZS7J7Ccjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunk5FZS7J7Ccjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunk5FZS7J7Ccjs.BristleStroke; exports.DEFAULT_BEHAVIOR = _chunk5FZS7J7Ccjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunk5FZS7J7Ccjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunk5FZS7J7Ccjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunk5FZS7J7Ccjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkXFYLA3ZOcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunk5FZS7J7Ccjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunk5FZS7J7Ccjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunk5FZS7J7Ccjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunk5FZS7J7Ccjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunk5FZS7J7Ccjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunk5FZS7J7Ccjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunk5FZS7J7Ccjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkXFYLA3ZOcjs.DEFAULT_WET_PARAMS; exports.DryStroke = _chunk5FZS7J7Ccjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunk5FZS7J7Ccjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunk5FZS7J7Ccjs.EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkPQ3H2AANcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkPQ3H2AANcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunk7PT4RJL5cjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunk5FZS7J7Ccjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunk5FZS7J7Ccjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkPQ3H2AANcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunk5FZS7J7Ccjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunkOLNIPTB3cjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunk5FZS7J7Ccjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunk5FZS7J7Ccjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkPQ3H2AANcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkPQ3H2AANcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunk5FZS7J7Ccjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunk5FZS7J7Ccjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunk5FZS7J7Ccjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunk5FZS7J7Ccjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkPQ3H2AANcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkPQ3H2AANcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkPQ3H2AANcjs.PaperGrain; exports.ParticleStroke = _chunk5FZS7J7Ccjs.ParticleStroke; exports.PenDabWalker = _chunk5FZS7J7Ccjs.PenDabWalker; exports.PenSmoother = _chunk5FZS7J7Ccjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunk5FZS7J7Ccjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerSpray = _chunk5FZS7J7Ccjs.StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunkPQ3H2AANcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkXFYLA3ZOcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunk5FZS7J7Ccjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkXFYLA3ZOcjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunk5FZS7J7Ccjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkPQ3H2AANcjs.addPaintGradientStop; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunk5FZS7J7Ccjs.brushTakesPaint; exports.brushToJSON = _chunk5FZS7J7Ccjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunk5FZS7J7Ccjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintLayer = createPaintLayer; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = _chunk5FZS7J7Ccjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = _chunk5FZS7J7Ccjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunk5FZS7J7Ccjs.effectPaintKey; exports.effectPaintSize = _chunk5FZS7J7Ccjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkPQ3H2AANcjs.grainCatch; exports.grainHeights = _chunkPQ3H2AANcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunkPQ3H2AANcjs.hash2; exports.hexToPaintRgb = _chunkPQ3H2AANcjs.hexToPaintRgb; exports.hexToRgb8 = _chunk5FZS7J7Ccjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunk7PT4RJL5cjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkOLNIPTB3cjs.isBlendMode; exports.isGradientPaint = _chunkPQ3H2AANcjs.isGradientPaint; exports.isPaintEffectPaint = _chunk5FZS7J7Ccjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunkOLNIPTB3cjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunk5FZS7J7Ccjs.isWetBrush; exports.isWetCapable = _chunk5FZS7J7Ccjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunkPQ3H2AANcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunk5FZS7J7Ccjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunk5FZS7J7Ccjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunk5FZS7J7Ccjs.normalizeBehavior; exports.normalizeBristle = _chunk5FZS7J7Ccjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunk5FZS7J7Ccjs.normalizeDynamics; exports.normalizeFlow = _chunkXFYLA3ZOcjs.normalizeFlow; exports.normalizeHexColor = _chunkPQ3H2AANcjs.normalizeHexColor; exports.normalizeImpasto = _chunk5FZS7J7Ccjs.normalizeImpasto; exports.normalizeLight = _chunk5FZS7J7Ccjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunk5FZS7J7Ccjs.normalizeMultiColor; exports.normalizePaintBrush = _chunk5FZS7J7Ccjs.normalizePaintBrush; exports.normalizePaper = _chunk5FZS7J7Ccjs.normalizePaper; exports.normalizeParticle = _chunk5FZS7J7Ccjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunk5FZS7J7Ccjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunk5FZS7J7Ccjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunk5FZS7J7Ccjs.normalizeWetBrush; exports.normalizeWetParams = _chunkXFYLA3ZOcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkPQ3H2AANcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkPQ3H2AANcjs.paintSourceColor; exports.paintSourceCss = _chunkPQ3H2AANcjs.paintSourceCss; exports.paintToMultiColor = _chunk5FZS7J7Ccjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunk5FZS7J7Ccjs.paperPreset; exports.parseBrushLibrary = _chunk5FZS7J7Ccjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkPQ3H2AANcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunk5FZS7J7Ccjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunkPQ3H2AANcjs.rand01; exports.randSigned = _chunkPQ3H2AANcjs.randSigned; exports.readEffectStrokeMap = _chunk5FZS7J7Ccjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunk5FZS7J7Ccjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkPQ3H2AANcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkPQ3H2AANcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunk5FZS7J7Ccjs.renderPaper; exports.renderStickers = _chunk5FZS7J7Ccjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkPQ3H2AANcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkPQ3H2AANcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleEffectAt = _chunk5FZS7J7Ccjs.sampleEffectAt; exports.sampleEffectField = _chunk5FZS7J7Ccjs.sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkPQ3H2AANcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunkPQ3H2AANcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkPQ3H2AANcjs.solidPaint; exports.stampCoverage = _chunk5FZS7J7Ccjs.stampCoverage; exports.standardBlendMode = _chunkOLNIPTB3cjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = _chunk5FZS7J7Ccjs.stickerAt; exports.stickerRect = _chunk5FZS7J7Ccjs.stickerRect; exports.stickerSurface = _chunk5FZS7J7Ccjs.stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunk5FZS7J7Ccjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunk5FZS7J7Ccjs.toStrokePoint; exports.toggleStamp = toggleStamp; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkPQ3H2AANcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunk5FZS7J7Ccjs.usesPaintExchange; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = wetPaperInput; exports.wetPigmentOf = wetPigmentOf; exports.wetSupport = _chunkXFYLA3ZOcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunk7PT4RJL5cjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;
11256
+
11257
+
11258
+
11259
+ exports.BACKLIGHT_SPILL = BACKLIGHT_SPILL; exports.BLEND_MENU_GROUPS = BLEND_MENU_GROUPS; exports.BLEND_MODES = _chunkOLNIPTB3cjs.BLEND_MODES; exports.BRUSH_ID = _chunk4T47Z4J3cjs.BRUSH_ID; exports.BRUSH_ROTATIONS = _chunk4T47Z4J3cjs.BRUSH_ROTATIONS; exports.BRUSH_SLIDERS = BRUSH_SLIDERS; exports.BUILTIN_BRUSHES = _chunk4T47Z4J3cjs.BUILTIN_BRUSHES; exports.BristleStroke = _chunk4T47Z4J3cjs.BristleStroke; exports.DEFAULT_BACKLIGHT_COLOR = DEFAULT_BACKLIGHT_COLOR; exports.DEFAULT_BEHAVIOR = _chunk4T47Z4J3cjs.DEFAULT_BEHAVIOR; exports.DEFAULT_BRISTLE = _chunk4T47Z4J3cjs.DEFAULT_BRISTLE; exports.DEFAULT_BRUSH_ID = _chunk4T47Z4J3cjs.DEFAULT_BRUSH_ID; exports.DEFAULT_DPI = DEFAULT_DPI; exports.DEFAULT_DYNAMICS = _chunk4T47Z4J3cjs.DEFAULT_DYNAMICS; exports.DEFAULT_FLOW = _chunkVMROIWLLcjs.DEFAULT_FLOW; exports.DEFAULT_IMPASTO = _chunk4T47Z4J3cjs.DEFAULT_IMPASTO; exports.DEFAULT_LIGHT = _chunk4T47Z4J3cjs.DEFAULT_LIGHT; exports.DEFAULT_LIGHTING = DEFAULT_LIGHTING; exports.DEFAULT_MULTI_COLOR = _chunk4T47Z4J3cjs.DEFAULT_MULTI_COLOR; exports.DEFAULT_PAINT_GRADIENT = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT; exports.DEFAULT_PAINT_GRADIENT_MAPPING = _chunkPQ3H2AANcjs.DEFAULT_PAINT_GRADIENT_MAPPING; exports.DEFAULT_PAPER = _chunk4T47Z4J3cjs.DEFAULT_PAPER; exports.DEFAULT_PARTICLE = _chunk4T47Z4J3cjs.DEFAULT_PARTICLE; exports.DEFAULT_STICKER = _chunk4T47Z4J3cjs.DEFAULT_STICKER; exports.DEFAULT_SWATCHES = DEFAULT_SWATCHES; exports.DEFAULT_VIEW = DEFAULT_VIEW; exports.DEFAULT_WET_BRUSH = _chunk4T47Z4J3cjs.DEFAULT_WET_BRUSH; exports.DEFAULT_WET_PARAMS = _chunkVMROIWLLcjs.DEFAULT_WET_PARAMS; exports.DryStroke = _chunk4T47Z4J3cjs.DryStroke; exports.EFFECT_MAP_REPEATS = _chunk4T47Z4J3cjs.EFFECT_MAP_REPEATS; exports.EFFECT_STRIP_HEIGHT = _chunk4T47Z4J3cjs.EFFECT_STRIP_HEIGHT; exports.GPU_LEAD = GPU_LEAD; exports.GRAIN_PATTERNS = _chunkPQ3H2AANcjs.GRAIN_PATTERNS; exports.GRAIN_TILE = _chunkPQ3H2AANcjs.GRAIN_TILE; exports.HARMONY_KINDS = _chunk7PT4RJL5cjs.HARMONY_KINDS; exports.IDENTITY_AFFINE = IDENTITY_AFFINE; exports.IDENTITY_COPY = _chunk4T47Z4J3cjs.IDENTITY_COPY; exports.IMPASTO_TOOLS = _chunk4T47Z4J3cjs.IMPASTO_TOOLS; exports.IMPASTO_TOOL_LABELS = IMPASTO_TOOL_LABELS; exports.LIGHT_SLIDERS = LIGHT_SLIDERS; exports.LIVE_STROKE_ENGINES = LIVE_STROKE_ENGINES; exports.LitCache = LitCache; exports.MAX_BRUSH_SIZE = _chunkPQ3H2AANcjs.MAX_BRUSH_SIZE; exports.MAX_CANVAS_SIDE = MAX_CANVAS_SIDE; exports.MAX_COORDINATE = MAX_COORDINATE; exports.MAX_IMAGE_SIDE = MAX_IMAGE_SIDE; exports.MAX_LIVE_EFFECT_SOURCES = MAX_LIVE_EFFECT_SOURCES; exports.MAX_ZOOM = MAX_ZOOM; exports.MIN_CANVAS_SIDE = MIN_CANVAS_SIDE; exports.MIN_ZOOM = MIN_ZOOM; exports.MIXING_PAD_HEIGHT = MIXING_PAD_HEIGHT; exports.MIXING_PAD_WIDTH = MIXING_PAD_WIDTH; exports.MULTI_COLOR_MODES = _chunk4T47Z4J3cjs.MULTI_COLOR_MODES; exports.MixingPad = MixingPad; exports.PAD_SAMPLE_SIZES = PAD_SAMPLE_SIZES; exports.PAINTERLY_BLEND_MODES = _chunkOLNIPTB3cjs.PAINTERLY_BLEND_MODES; exports.PAINT_BRUSH_CATEGORIES = _chunk4T47Z4J3cjs.PAINT_BRUSH_CATEGORIES; exports.PAINT_BRUSH_ENGINES = _chunk4T47Z4J3cjs.PAINT_BRUSH_ENGINES; exports.PAINT_COLOR_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_COLOR_JSON_SCHEMA; exports.PAINT_EFFECT_PLACES = PAINT_EFFECT_PLACES; exports.PAINT_FORMAT = PAINT_FORMAT; exports.PAINT_GRADIENT_FULL_SPEED = _chunkPQ3H2AANcjs.PAINT_GRADIENT_FULL_SPEED; exports.PAINT_GRADIENT_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_GRADIENT_JSON_SCHEMA; exports.PAINT_GRADIENT_KIT = _chunkPQ3H2AANcjs.PAINT_GRADIENT_KIT; exports.PAINT_GRADIENT_MAPPINGS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPINGS; exports.PAINT_GRADIENT_MAPPING_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_MAPPING_LABELS; exports.PAINT_GRADIENT_PRESETS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_PRESETS; exports.PAINT_GRADIENT_REPEATS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEATS; exports.PAINT_GRADIENT_REPEAT_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_REPEAT_LABELS; exports.PAINT_GRADIENT_SPACES = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACES; exports.PAINT_GRADIENT_SPACE_LABELS = _chunkPQ3H2AANcjs.PAINT_GRADIENT_SPACE_LABELS; exports.PAINT_SCHEMA_VERSION = PAINT_SCHEMA_VERSION; exports.PAINT_SOURCE_JSON_SCHEMA = _chunkPQ3H2AANcjs.PAINT_SOURCE_JSON_SCHEMA; exports.PAINT_TARGET = PAINT_TARGET; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PAPER_EFFECT_BLENDS = PAPER_EFFECT_BLENDS; exports.PAPER_EFFECT_NODE_ID = PAPER_EFFECT_NODE_ID; exports.PAPER_FAMILIES = _chunk4T47Z4J3cjs.PAPER_FAMILIES; exports.PAPER_LIBRARY = _chunk4T47Z4J3cjs.PAPER_LIBRARY; exports.PAPER_NODE_ID = PAPER_NODE_ID; exports.PAPER_SLIDERS = PAPER_SLIDERS; exports.PAPER_TARGET = PAPER_TARGET; exports.PARTICLE_KINDS = _chunk4T47Z4J3cjs.PARTICLE_KINDS; exports.PARTICLE_KIND_LABELS = PARTICLE_KIND_LABELS; exports.PARTICLE_RENDERS = _chunk4T47Z4J3cjs.PARTICLE_RENDERS; exports.PARTICLE_RENDER_LABELS = PARTICLE_RENDER_LABELS; exports.PaintCanvasPresenter = PaintCanvasPresenter; exports.PaintDabStroke = PaintDabStroke; exports.PaintDirector = PaintDirector; exports.PaintDocumentError = PaintDocumentError; exports.PaintEditorController = PaintEditorController; exports.PaintEditorError = PaintEditorError; exports.PaintEffectsRenderer = PaintEffectsRenderer; exports.PaintGesture = PaintGesture; exports.PaintGradientSampler = _chunkPQ3H2AANcjs.PaintGradientSampler; exports.PaintPresence = PaintPresence; exports.PaintSourceError = _chunkPQ3H2AANcjs.PaintSourceError; exports.PaintStrokeSession = PaintStrokeSession; exports.PaintWetLayers = PaintWetLayers; exports.PaperGrain = _chunkPQ3H2AANcjs.PaperGrain; exports.ParticleStroke = _chunk4T47Z4J3cjs.ParticleStroke; exports.PenDabWalker = _chunk4T47Z4J3cjs.PenDabWalker; exports.PenSmoother = _chunk4T47Z4J3cjs.PenSmoother; exports.PerspectiveSnapper = PerspectiveSnapper; exports.SNAP_DECIDE_DISTANCE = SNAP_DECIDE_DISTANCE; exports.STAMP_KINDS = _chunk4T47Z4J3cjs.STAMP_KINDS; exports.STAMP_LABELS = STAMP_LABELS; exports.STENCIL_KINDS = STENCIL_KINDS; exports.STENCIL_SHAPES = STENCIL_SHAPES; exports.STICKER_SLIDERS = STICKER_SLIDERS; exports.STROKE_SLIDERS = STROKE_SLIDERS; exports.SYMMETRY_MODES = SYMMETRY_MODES; exports.StencilSnapper = StencilSnapper; exports.StickerSpray = _chunk4T47Z4J3cjs.StickerSpray; exports.TRACING_NODE_ID = TRACING_NODE_ID; exports.ThickStrokeDriver = ThickStrokeDriver; exports.TileableNoise = _chunkPQ3H2AANcjs.TileableNoise; exports.WET_FLOW_KINDS = _chunkVMROIWLLcjs.WET_FLOW_KINDS; exports.WET_GPU_MODES = WET_GPU_MODES; exports.WET_GPU_OPTIONS = WET_GPU_OPTIONS; exports.WET_MEDIA = _chunk4T47Z4J3cjs.WET_MEDIA; exports.WET_MEDIUM_LABELS = WET_MEDIUM_LABELS; exports.WET_MEDIUM_PARAMS = WET_MEDIUM_PARAMS; exports.WET_PARAM_KEYS = _chunkVMROIWLLcjs.WET_PARAM_KEYS; exports.WET_PARAM_SCHEMA = WET_PARAM_SCHEMA; exports.WET_PARAM_SLIDERS = WET_PARAM_SLIDERS; exports.WET_SPEED_SLIDER = WET_SPEED_SLIDER; exports.WET_TILT_SLIDERS = WET_TILT_SLIDERS; exports.WET_TOOLS = _chunk4T47Z4J3cjs.WET_TOOLS; exports.WET_TOOL_LABELS = WET_TOOL_LABELS; exports.WetStrokeDriver = WetStrokeDriver; exports.addPaintGradientStop = _chunkPQ3H2AANcjs.addPaintGradientStop; exports.affineCopy = affineCopy; exports.applyAffine = applyAffine; exports.backlightOf = backlightOf; exports.brushEngineControls = brushEngineControls; exports.brushLoadColor = brushLoadColor; exports.brushLoadForStroke = brushLoadForStroke; exports.brushTakesPaint = _chunk4T47Z4J3cjs.brushTakesPaint; exports.brushToJSON = _chunk4T47Z4J3cjs.brushToJSON; exports.buildTimeLapse = buildTimeLapse; exports.checkPaintEffectPlace = checkPaintEffectPlace; exports.clonePaper = _chunk4T47Z4J3cjs.clonePaper; exports.colorHarmony = colorHarmony2; exports.composeAffine = composeAffine; exports.contactSheet = contactSheet; exports.createPaintCompositor = createPaintCompositor; exports.createPaintDocument = createPaintDocument; exports.createPaintEditorDocument = createPaintEditorDocument; exports.createPaintEditorToolProvider = createPaintEditorToolProvider; exports.createPaintEffectsToolProvider = createPaintEffectsToolProvider; exports.createPaintLayer = createPaintLayer; exports.createPaintReplayTools = createPaintReplayTools; exports.createPaintStickerTools = createPaintStickerTools; exports.createPaintThickTools = createPaintThickTools; exports.createPaintWetTools = createPaintWetTools; exports.decodeImageBlob = decodeImageBlob; exports.defaultGuides = defaultGuides; exports.defaultImageEncoder = defaultImageEncoder; exports.deserializePaintDocument = deserializePaintDocument; exports.deserializePaintDocumentAsync = deserializePaintDocumentAsync; exports.documentExtensions = documentExtensions; exports.documentToScreen = documentToScreen; exports.downloadBytes = downloadBytes; exports.downsampleRgba = downsampleRgba; exports.drawSticker = _chunk4T47Z4J3cjs.drawSticker; exports.drawWaterOverlay = drawWaterOverlay; exports.effectDabField = _chunk4T47Z4J3cjs.effectDabField; exports.effectLayersToJSON = effectLayersToJSON; exports.effectPaintKey = _chunk4T47Z4J3cjs.effectPaintKey; exports.effectPaintSize = _chunk4T47Z4J3cjs.effectPaintSize; exports.emptiedLayers = emptiedLayers; exports.emptyThickChannels = emptyThickChannels; exports.fitZoom = fitZoom; exports.grainCatch = _chunkPQ3H2AANcjs.grainCatch; exports.grainHeights = _chunkPQ3H2AANcjs.grainHeights; exports.guideOverlay = guideOverlay; exports.handlePaintShortcut = handlePaintShortcut; exports.hash2 = _chunkPQ3H2AANcjs.hash2; exports.hexToPaintRgb = _chunkPQ3H2AANcjs.hexToPaintRgb; exports.hexToRgb8 = _chunk4T47Z4J3cjs.hexToRgb8; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToWheel = _chunk7PT4RJL5cjs.hueToWheel; exports.invertAffine = invertAffine; exports.isBlendMode = _chunkOLNIPTB3cjs.isBlendMode; exports.isGradientPaint = _chunkPQ3H2AANcjs.isGradientPaint; exports.isPaintEffectPaint = _chunk4T47Z4J3cjs.isPaintEffectPaint; exports.isPainterlyBlendMode = _chunkOLNIPTB3cjs.isPainterlyBlendMode; exports.isPalmTouch = isPalmTouch; exports.isWetBrush = _chunk4T47Z4J3cjs.isWetBrush; exports.isWetCapable = _chunk4T47Z4J3cjs.isWetCapable; exports.lightTile = lightTile; exports.lightingKey = lightingKey; exports.liveStrokeBounds = liveStrokeBounds; exports.liveStrokeRefusal = liveStrokeRefusal; exports.mapPenPoint = mapPenPoint; exports.mix32 = _chunkPQ3H2AANcjs.mix32; exports.mixPixels = mixPixels; exports.mixerLoadForStroke = mixerLoadForStroke; exports.mixerTip = _chunk4T47Z4J3cjs.mixerTip; exports.multiColorForDab = multiColorForDab; exports.multiColorGradient = multiColorGradient; exports.multiColorPalette = multiColorPalette; exports.multiColorSliders = multiColorSliders; exports.multiColorToPaint = _chunk4T47Z4J3cjs.multiColorToPaint; exports.newPaintLayerId = newPaintLayerId; exports.nextPaperEffectVersion = nextPaperEffectVersion; exports.normalizeBehavior = _chunk4T47Z4J3cjs.normalizeBehavior; exports.normalizeBristle = _chunk4T47Z4J3cjs.normalizeBristle; exports.normalizeBrushStroke = normalizeBrushStroke; exports.normalizeCanvas = normalizeCanvas; exports.normalizeDynamics = _chunk4T47Z4J3cjs.normalizeDynamics; exports.normalizeFlow = _chunkVMROIWLLcjs.normalizeFlow; exports.normalizeHexColor = _chunkPQ3H2AANcjs.normalizeHexColor; exports.normalizeImpasto = _chunk4T47Z4J3cjs.normalizeImpasto; exports.normalizeLight = _chunk4T47Z4J3cjs.normalizeLight; exports.normalizeLighting = normalizeLighting; exports.normalizeMultiColor = _chunk4T47Z4J3cjs.normalizeMultiColor; exports.normalizePaintBrush = _chunk4T47Z4J3cjs.normalizePaintBrush; exports.normalizePaper = _chunk4T47Z4J3cjs.normalizePaper; exports.normalizeParticle = _chunk4T47Z4J3cjs.normalizeParticle; exports.normalizePerspective = normalizePerspective; exports.normalizeRotation = normalizeRotation; exports.normalizeStencil = normalizeStencil; exports.normalizeStickerSettings = _chunk4T47Z4J3cjs.normalizeStickerSettings; exports.normalizeStickerUpdate = _chunk4T47Z4J3cjs.normalizeStickerUpdate; exports.normalizeSymmetry = normalizeSymmetry; exports.normalizeView = normalizeView; exports.normalizeWetBrush = _chunk4T47Z4J3cjs.normalizeWetBrush; exports.normalizeWetParams = _chunkVMROIWLLcjs.normalizeWetParams; exports.overPixels = overPixels; exports.padSampleRadius = padSampleRadius; exports.paintGradientMappingFor = _chunkPQ3H2AANcjs.paintGradientMappingFor; exports.paintPlaybackPanel = paintPlaybackPanel; exports.paintSourceColor = _chunkPQ3H2AANcjs.paintSourceColor; exports.paintSourceCss = _chunkPQ3H2AANcjs.paintSourceCss; exports.paintToMultiColor = _chunk4T47Z4J3cjs.paintToMultiColor; exports.paperEffectFromJSON = paperEffectFromJSON; exports.paperEffectToJSON = paperEffectToJSON; exports.paperGrain = paperGrain; exports.paperKey = paperKey; exports.paperNode = paperNode; exports.paperPreset = _chunk4T47Z4J3cjs.paperPreset; exports.parseBrushLibrary = _chunk4T47Z4J3cjs.parseBrushLibrary; exports.parseHexColor = parseHexColor; exports.parsePaintSource = _chunkPQ3H2AANcjs.parsePaintSource; exports.patchBrushValue = patchBrushValue; exports.patchPath = patchPath; exports.penOrientation = _chunk4T47Z4J3cjs.penOrientation; exports.perspectiveDirections = perspectiveDirections; exports.perspectiveGuideLines = perspectiveGuideLines; exports.planPaintToolPlayback = planPaintToolPlayback; exports.pointerToPenPoint = pointerToPenPoint; exports.quickStencil = quickStencil; exports.rand01 = _chunkPQ3H2AANcjs.rand01; exports.randSigned = _chunkPQ3H2AANcjs.randSigned; exports.readEffectStrokeMap = _chunk4T47Z4J3cjs.readEffectStrokeMap; exports.readPaintEffectPaint = _chunk4T47Z4J3cjs.readPaintEffectPaint; exports.readPaintEffectSource = readPaintEffectSource; exports.readPaintSource = _chunkPQ3H2AANcjs.readPaintSource; exports.readPath = readPath; exports.readSwatch = readSwatch; exports.reliefInfo = reliefInfo; exports.removePaintGradientStop = _chunkPQ3H2AANcjs.removePaintGradientStop; exports.renderBrushThumbnail = renderBrushThumbnail; exports.renderColorWheel = renderColorWheel; exports.renderPaper = _chunk4T47Z4J3cjs.renderPaper; exports.renderStickers = _chunk4T47Z4J3cjs.renderStickers; exports.replayFrame = replayFrame; exports.replayItems = replayItems; exports.replayPainting = replayPainting; exports.resolvePaintGradient = _chunkPQ3H2AANcjs.resolvePaintGradient; exports.reversePaintGradient = _chunkPQ3H2AANcjs.reversePaintGradient; exports.rgbToHexColor = rgbToHexColor; exports.rgbToHsl = rgbToHsl; exports.rgbToHsv = rgbToHsv; exports.sampleEffectAt = _chunk4T47Z4J3cjs.sampleEffectAt; exports.sampleEffectField = _chunk4T47Z4J3cjs.sampleEffectField; exports.samplePressure = samplePressure; exports.scalePaintGradient = _chunkPQ3H2AANcjs.scalePaintGradient; exports.scaleStencil = scaleStencil; exports.screenToDocument = screenToDocument; exports.seedFromString = _chunkPQ3H2AANcjs.seedFromString; exports.serializePaintDocument = serializePaintDocument; exports.serializePaintDocumentExternal = serializePaintDocumentExternal; exports.solidPaint = _chunkPQ3H2AANcjs.solidPaint; exports.stampCoverage = _chunk4T47Z4J3cjs.stampCoverage; exports.standardBlendMode = _chunkOLNIPTB3cjs.standardBlendMode; exports.startWetClock = startWetClock; exports.stencilMask = stencilMask; exports.stencilOutline = stencilOutline; exports.stickerAt = _chunk4T47Z4J3cjs.stickerAt; exports.stickerRect = _chunk4T47Z4J3cjs.stickerRect; exports.stickerSurface = _chunk4T47Z4J3cjs.stickerSurface; exports.strokeBounds = strokeBounds; exports.strokeDuration = strokeDuration; exports.strokeSchedule = strokeSchedule; exports.sweepPath = sweepPath; exports.symmetryAxisAngles = symmetryAxisAngles; exports.symmetryAxisSegments = symmetryAxisSegments; exports.symmetryCopies = symmetryCopies; exports.thickFromJSON = thickFromJSON; exports.thickToJSON = thickToJSON; exports.thumbnailStroke = thumbnailStroke; exports.tiltToOrientation = _chunk4T47Z4J3cjs.tiltToOrientation; exports.timeLapseVideo = timeLapseVideo; exports.timeLapseZip = timeLapseZip; exports.toStrokePoint = _chunk4T47Z4J3cjs.toStrokePoint; exports.toggleStamp = toggleStamp; exports.translateStencil = translateStencil; exports.updatePaintGradientStop = _chunkPQ3H2AANcjs.updatePaintGradientStop; exports.usesPaintExchange = _chunk4T47Z4J3cjs.usesPaintExchange; exports.variationAffine = variationAffine; exports.varyStroke = varyStroke; exports.viewCssTransform = viewCssTransform; exports.viewMatrix = viewMatrix; exports.viewPenToDocument = viewPenToDocument; exports.wetEngineSummary = wetEngineSummary; exports.wetPaperInput = wetPaperInput; exports.wetPigmentOf = wetPigmentOf; exports.wetSupport = _chunkVMROIWLLcjs.wetSupport; exports.wheelAngle = wheelAngle; exports.wheelPick = wheelPick; exports.wheelPoint = wheelPoint; exports.wheelToHue = _chunk7PT4RJL5cjs.wheelToHue; exports.withPaintPlayback = withPaintPlayback;