asciify-engine 4.7.0 → 4.9.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.
- package/README.md +24 -3
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{model-CMKdRB30.d.ts → model-ChcdXIzJ.d.ts} +45 -2
- package/dist/{model-fP9NdG-w.d.cts → model-fv_acoD_.d.cts} +45 -2
- package/dist/studio.cjs +1 -1
- package/dist/studio.d.cts +168 -5
- package/dist/studio.d.ts +168 -5
- package/dist/studio.js +1 -1
- package/examples/layered-composition.ts +24 -0
- package/examples/print-composition.ts +15 -0
- package/package.json +3 -1
- package/skills/asciify-engine/SKILL.md +7 -3
- package/skills/asciify-engine/agents/openai.yaml +2 -2
- package/skills/asciify-engine/references/layered-projects.md +89 -0
- package/skills/asciify-engine/references/print-styles.md +63 -0
- package/skills/asciify-engine/references/project-integration.md +1 -0
- package/skills/asciify-engine/references/studio-workspace.md +6 -2
- package/skills/asciify-engine/references/upgrading.md +8 -0
package/dist/studio.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=[{value:"none",label:"Off",group:"Still",description:"Keep the artwork still under the pointer."},{value:"trail",label:"Trail",group:"Change characters",description:"A fluid wake changes character density and settles behind your cursor."},{value:"dissolve",label:"Dissolve",group:"Change characters",description:"Erase a soft path through the characters; the image gradually reforms."},{value:"contour",label:"Contour",group:"Change characters",description:"Fine tonal rings trace your path without moving the grid."},{value:"etch",label:"Emboss",group:"Change characters",description:"Press a light-and-shadow impression into the characters; the grid stays fixed."},{value:"water",label:"Water",group:"Move the image",description:"Soft ripples refract the image and settle after your stroke."},{value:"silk",label:"Silk",group:"Move the image",description:"Directional folds follow the movement of your hand."},{value:"vortex",label:"Vortex",group:"Move the image",description:"A swirling wake curls through the image."},{value:"magnetic",label:"Magnetic Pull",group:"Move the image",description:"The image gathers toward your stroke, then relaxes."},{value:"scatter",label:"Scatter",group:"Move the image",description:"A textured outward scatter settles behind your cursor."},{value:"elastic",label:"Elastic",group:"Move the image",description:"Push the image with your stroke; it recoils and springs back into place."},{value:"rake",label:"Rake",group:"Move the image",description:"Comb the image into alternating ribbons that glide back into alignment."}],e=[{value:"none",mode:"none",group:"Still",label:"Off",description:"Keep the image still. Hover stays available."},{value:"caustics",mode:"caustics",group:"Light and texture",label:"Caustics",description:"Soft ribbons of light travel across a stationary character grid."},{value:"current",mode:"current",group:"Flow and depth",label:"Slow Current",description:"A gentle flow through the image, with steady edges."},{value:"reform",mode:"reform",group:"Rebuild",label:"Reveal & Reform",description:"Disperse, gather, then hold the complete image."},{value:"sheen",mode:"sheen",group:"Light and texture",label:"Sheen",description:"A broad diagonal light sweep; characters stay anchored."},{value:"tidal",mode:"tidal",group:"Flow and depth",label:"Tidal Rings",description:"Concentric currents travel outward, with protected edges."},{value:"grain",mode:"grain",group:"Light and texture",label:"Living Grain",description:"Slow, individually phased tonal changes on a stationary grid."},{value:"parallax",mode:"parallax",group:"Flow and depth",label:"Parallax",description:"A shallow, continuous drift through the image, with the edges held in place."},{value:"weave",mode:"weave",group:"Flow and depth",label:"Woven Flow",description:"Interlaced bands move in opposing directions, like a flexible printed fabric."},{value:"print",mode:"print",group:"Rebuild",label:"Print Shift",description:"Staggered rows lift, soften and register back into the image."},{value:"trace",mode:"trace",group:"Light and texture",label:"Contour Light",description:"Light follows the source image’s tonal contours; every character stays anchored."}],i=t=>Math.max(0,Math.min(1,t)),a=(t,e,a)=>{const s=i((a-t)/(e-t));return s*s*(3-2*s)},s=(t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)},r=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){return Number.isFinite(t)?((e!==this.mode||null!==this.last&&t<this.last)&&(this.mode=e,this.phase=0,this.last=t),null!==this.last&&(this.phase+=Math.max(0,t-this.last)*Math.max(.1,Math.min(3,Number.isFinite(i)?i:1))),this.last=t,this.phase):this.phase}};function o(t,e,r,o,n,h=.5){if(n[0]=n[1]=n[2]=0,n[3]=1,"none"===t)return n;const l=o*Math.PI/6,c=a(0,.12,Math.min(e,1-e,r,1-r));if("caustics"===t){const t=Math.sin(9*e+5*r+l)+Math.sin(8*r-3*e-l),i=Math.pow(Math.max(0,1-.72*Math.abs(t)),3);n[2]=(.22*i-.045)*c}else if("current"===t)n[0]=Math.sin(9*r+l)*Math.cos(7*e-l)*10*c,n[1]=Math.cos(8*e+l)*Math.sin(6*r-l)*7*c;else if("sheen"===t)n[2]=.2*Math.pow(.5+.5*Math.cos(5*e+3*r-l),8)-.025;else if("tidal"===t){const t=e-.5,i=r-.5,a=Math.hypot(t,i),s=Math.sin(22*a-l)*c;n[0]=t*s*9,n[1]=i*s*9,n[2]=.035*s}else if("grain"===t){const t=s(Math.floor(160*e),Math.floor(100*r))*Math.PI*2;n[2]=.07*Math.sin(l+t)}else if("parallax"===t){const t=.45+.55*Math.max(0,1-1.4*Math.hypot(e-.5,r-.5));n[0]=12*Math.sin(l)*t*c,n[1]=6*(Math.cos(l)-1)*t*c}else if("weave"===t)n[0]=Math.sin(r*Math.PI*6+l)*Math.sin(l)*8*c,n[1]=Math.sin(e*Math.PI*6-l)*Math.sin(l)*6*c;else if("print"===t){const t=Math.floor(24*r),e=((o+3*s(t,3))%12+12)%12,i=a(1,2.5,e)*(1-a(3.5,5,e));n[0]=Math.sin(2.4*t)*i*9*c,n[1]=5*-i*c,n[2]=.22*-i,n[3]=1-.45*i}else if("trace"===t){const t=.5+.5*Math.cos(l);n[2]=.22*Math.pow(Math.max(0,1-Math.abs(i(h)-t)/.16),3)-.015}else if("reform"===t){const t=(o%12+12)%12,i=s(Math.floor(160*e),Math.floor(100*r)),h=.65*e+.2*r+.15*i+.08*Math.sin(8*e-5*r),f=a(1.8+1.2*h,3.8+1.2*h,t)*(1-a(5+1.7*h,7.2+1.7*h,t));n[0]=Math.sin(9*r+l)*f*(1-f)*24*c,n[1]=-f*(1-f)*(8+12*i)*c,n[2]=.45*-f,n[3]=1-.9*f}return n}function n(t,e){const a=Math.max(0,Math.min(2,Number.isFinite(e)?e:1));return t[0]*=a,t[1]*=a,t[2]*=a,t[3]=i(1+(t[3]-1)*a),t}var h=["rgb","red","green","blue"],l=t=>Math.max(0,Math.min(1,t));function c(t){const e=new Map([[0,0],[1,1]]);if(Array.isArray(t))for(const i of t.slice(0,64)){if(!Array.isArray(i)||i.length<2||"number"!=typeof i[0]||!Number.isFinite(i[0])||"number"!=typeof i[1]||!Number.isFinite(i[1]))continue;const t=Math.round(255*l(i[0]))/255;!e.has(t)&&e.size>=16||e.set(t,l(i[1]))}return[...e].sort((t,e)=>t[0]-e[0])}function f(t){const e=t&&"object"==typeof t?t:{};return Object.fromEntries(h.map(t=>[t,c(e[t])]))}function m(t){const e=c(t),i=e.length,a=e.slice(1).map((t,i)=>t[0]-e[i][0]),s=e.slice(1).map((t,i)=>(t[1]-e[i][1])/a[i]),r=new Float64Array(i);r[0]=s[0],r[i-1]=s[i-2];for(let t=1;t<i-1;t++){const e=s[t-1],i=s[t];if(e*i<=0)continue;const o=2*a[t]+a[t-1],n=a[t]+2*a[t-1];r[t]=(o+n)/(o/e+n/i)}const o=new Uint8Array(256);let n=0;for(let t=0;t<256;t++){const s=t/255;for(;n<i-2&&s>e[n+1][0];)n++;const h=a[n],c=(s-e[n][0])/h,f=c*c,m=f*c,d=(2*m-3*f+1)*e[n][1]+(m-2*f+c)*h*r[n]+(-2*m+3*f)*e[n+1][1]+(m-f)*h*r[n+1];o[t]=Math.round(255*l(d))}return o}function d(t,e,i,a,s,r){a=Math.max(0,Math.min(e-1,a)),s=Math.max(0,Math.min(i-1,s));const o=Math.floor(a),n=Math.floor(s),h=a-o,l=s-n,c=4*(n*e+o);if(0===h&&0===l){for(let e=0;e<4;e++)r[e]=t[c+e];return}const f=4*(n*e+Math.min(e-1,o+1)),m=4*(Math.min(i-1,n+1)*e+o),d=4*(Math.min(i-1,n+1)*e+Math.min(e-1,o+1)),u=(1-h)*(1-l)*t[c+3],g=h*(1-l)*t[f+3],p=(1-h)*l*t[m+3],M=h*l*t[d+3],v=u+g+p+M;for(let e=0;e<3;e++)r[e]=v?(t[c+e]*u+t[f+e]*g+t[m+e]*p+t[d+e]*M)/v:0;r[3]=v}function u(t,e,i,a,s,r){if(a>=0&&a<=e-1&&s>=0&&s<=i-1)return d(t,e,i,a,s,r);if(r[0]=r[1]=r[2]=r[3]=0,a<=-1||a>=e||s<=-1||s>=i)return;const o=Math.floor(a),n=Math.floor(s),h=a-o,l=s-n;for(let a=0;a<=1;a++)for(let s=0;s<=1;s++){const c=o+s,f=n+a;if(c<0||c>=e||f<0||f>=i)continue;const m=4*(f*e+c),d=(s?h:1-h)*(a?l:1-l)*t[m+3];r[0]+=t[m]*d,r[1]+=t[m+1]*d,r[2]+=t[m+2]*d,r[3]+=d}r[3]&&(r[0]/=r[3],r[1]/=r[3],r[2]/=r[3])}var g=[{value:"twirl",label:"Twirl",description:"Rotate the center into a smooth spiral; the outer boundary stays fixed.",direction:!1,frequency:!1},{value:"pinch",label:"Pinch",description:"Contract the center, or expand it with negative strength.",direction:!1,frequency:!1},{value:"sphere",label:"Spherize",description:"Magnify a rounded lens through the source; negative strength recedes.",direction:!1,frequency:!1},{value:"ripple",label:"Ripple",description:"Bend the image through concentric, soft-edged waves.",direction:!1,frequency:!0},{value:"zigzag",label:"Zigzag",description:"Alternate the twist in sharp, concentric bands.",direction:!1,frequency:!0},{value:"shear",label:"Shear",description:"Slant a region along an adjustable direction.",direction:!0,frequency:!1},{value:"smudge",label:"Smudge",description:"Draw a soft region of the source along one direction.",direction:!0,frequency:!1},{value:"polar",label:"Polar",description:"Unwrap a region into polar coordinates; negative strength wraps it.",direction:!0,frequency:!1},{value:"fragment",label:"Fragment",description:"Offset small source tiles into a stable fractured texture.",direction:!0,frequency:!0}],p=8,M=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.max(i,Math.min(a,t)):e;function v(t){if(!Array.isArray(t))return[];const e=[];for(const i of t.slice(0,64))if(i&&"object"==typeof i&&g.some(t=>t.value===i.type)&&(e.push({type:i.type,enabled:!1!==i.enabled,amount:M(i.amount,.35,-1,1),x:M(i.x,.5,0,1),y:M(i.y,.5,0,1),radius:M(i.radius,.55,.05,2),angle:M(i.angle,0,-180,180),frequency:M(i.frequency,5,1,24)}),8===e.length))break;return e}var x=2*Math.PI,b=(t,e)=>{let i=Math.imul(t,374761393)^Math.imul(e,668265263);return i=Math.imul(i^i>>>13,1274126177),((i^i>>>16)>>>0)/4294967296},w=class{constructor(t=[],e="clamp"){this.warps=[],this.signature="",this.geometry="",this.coordinates=new Float32Array(0),this.output=new Uint8ClampedArray(0),this.sampled=[0,0,0,0],this.edge="clamp",this.configure(t,e)}configure(t=[],e="clamp"){const i=v(t).filter(t=>t.enabled&&0!==t.amount),a=JSON.stringify(i);this.edge="transparent"===e?"transparent":"clamp",a!==this.signature&&(this.signature=a,this.geometry="",this.warps=i.map(t=>({...t,cos:Math.cos(t.angle*Math.PI/180),sin:Math.sin(t.angle*Math.PI/180)})),i.length||this.clear())}get active(){return this.warps.length>0}apply(t,e,i,a=e/i){if(!this.active)return t;if(!Number.isInteger(e)||!Number.isInteger(i)||e<1||i<1||e*i*4!==t.length||!Number.isFinite(a)||a<=0)throw new Error("Warp dimensions do not match the source.");const s=`${e}:${i}:${a}`;if(s!==this.geometry){this.coordinates.length!==e*i*2&&(this.coordinates=new Float32Array(e*i*2));const t=Math.max(1,a),r=Math.max(1,1/a);for(let a=0;a<i;a++)for(let s=0;s<e;s++){let o=(s+.5)/e,n=(a+.5)/i;for(let e=this.warps.length-1;e>=0;e--){const i=this.warps[e],a=(o-i.x)*t/i.radius,s=(n-i.y)*r/i.radius,h=a*a+s*s;if(h>=1)continue;const l=Math.sqrt(h),c=(1-h)*(1-h),f=i.amount;let m=a,d=s;if("twirl"===i.type||"zigzag"===i.type){const t="twirl"===i.type?-f*x*c:.65*f*(2/Math.PI*Math.asin(Math.sin(l*x*i.frequency)))*c,e=Math.cos(t),r=Math.sin(t);m=a*e-s*r,d=a*r+s*e}else if("pinch"===i.type){const t=Math.exp(2*f*c);m=a*t,d=s*t}else if("sphere"===i.type&&l>0){const t=1+f*c*(2*Math.asin(l)/Math.PI/l-1);m=a*t,d=s*t}else if("ripple"===i.type&&l>0){const t=1+.12*f*Math.sin(l*x*i.frequency)*c/l;m=a*t,d=s*t}else if("shear"===i.type){const t=-a*i.sin+s*i.cos;m-=f*t*.9*c*i.cos,d-=f*t*.9*c*i.sin}else if("smudge"===i.type)m-=.65*f*c*i.cos,d-=.65*f*c*i.sin;else if("polar"===i.type){const t=a*i.cos+s*i.sin,e=-a*i.sin+s*i.cos,r=Math.atan2(e,t),o=f>0?r/Math.PI:Math.cos(t*Math.PI)*(e+1)/2,n=f>0?2*l-1:Math.sin(t*Math.PI)*(e+1)/2,h=o*i.cos-n*i.sin,u=o*i.sin+n*i.cos;m+=(h-a)*Math.abs(f)*c,d+=(u-s)*Math.abs(f)*c}else if("fragment"===i.type){const t=Math.floor((a*i.cos+s*i.sin)*i.frequency),e=Math.floor((-a*i.sin+s*i.cos)*i.frequency),r=(b(t,e)-.5)*f*.5*c,o=(b(e+71,t-31)-.5)*f*.5*c;m+=r*i.cos-o*i.sin,d+=r*i.sin+o*i.cos}o=i.x+m*i.radius/t,n=i.y+d*i.radius/r}const h=2*(a*e+s);this.coordinates[h]=o*e-.5,this.coordinates[h+1]=n*i-.5}this.geometry=s}this.output.length!==t.length&&(this.output=new Uint8ClampedArray(t.length));const r=t===this.output?t.slice():t,o="transparent"===this.edge?u:d;for(let a=0,s=0;a<t.length;a+=4,s+=2){o(r,e,i,this.coordinates[s],this.coordinates[s+1],this.sampled);for(let t=0;t<4;t++)this.output[a+t]=this.sampled[t]}return this.output}clear(){this.coordinates=new Float32Array(0),this.output=new Uint8ClampedArray(0),this.geometry=""}},y=["ascii","blocks","braille","dots","lines","cross","diagonal","diamond","mixed","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk"],k=["none","bayer2","bayer4","bayer8","bayer16","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis","halftone","lines","noise","vertical-lines","diagonal-lines","radial","blue-noise"],S=["source-over","multiply","screen","overlay","soft-light","hard-light","color-dodge","color-burn","hue","saturation","color","luminosity"],A={original:[],gray4:["#000000","#555555","#aaaaaa","#ffffff"],gray8:["#000000","#242424","#494949","#6d6d6d","#929292","#b6b6b6","#dbdbdb","#ffffff"],rgb8:["#000000","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#ffffff"],cyberpunk:["#08081a","#3c1670","#ed299a","#29dfef","#fff7bf"],pastel:["#393448","#a5b4d4","#9ed9c6","#e7aac1","#f5e8be"],mono:["#080808","#f2f2e8"],asciify:["#080808","#625b38","#a19558","#e8b900"],gameboy:["#0f380f","#306230","#8bac0f","#9bbc0f"],cga:["#000000","#55ffff","#ff55ff","#ffffff"],pico8:["#000000","#1d2b53","#7e2553","#008751","#ab5236","#5f574f","#c2c3c7","#fff1e8","#ff004d","#ffa300","#ffec27","#00e436","#29adff","#83769c","#ff77a8","#ffccaa"],c64:["#000000","#ffffff","#880000","#aaffee","#cc44cc","#00cc55","#0000aa","#eeee77","#dd8855","#664400","#ff7777","#333333","#777777","#aaff66","#0088ff","#bbbbbb"],amber:["#100b00","#5f3b00","#c98014","#ffd17c"],ice:["#081b29","#25586e","#69a6b3","#d9ece7"],risograph:["#f4ebd0","#f2594b","#2853a5","#29232e"],sepia:["#201b17","#6b5039","#b49868","#f6e6c5"],nord:["#2e3440","#4c566a","#88c0d0","#eceff4"],dusk:["#211b35","#654271","#c3788c","#f5c9a3"],forest:["#101f1b","#355747","#87a16f","#e4e3ba"],ocean:["#071b33","#17577f","#3fa7a4","#d9efde"],newsprint:["#191919","#666666","#aaaaaa","#eee9df"],custom:["#080808","#e8b900"]},E={version:1,aspectRatio:"original",style:"ascii",cellSize:6,charset:" .:-=+*#%@",colorMode:"accent",ink:"#e8b900",crop:{x:.5,y:.5,zoom:1,rotation:0},warps:[],warpEdge:"clamp",backdrop:{mode:"solid",color:"#080808",color2:"#393323",blur:12,opacity:1},color:{brightness:0,contrast:1,saturation:1,grayscale:0,tint:"#e8b900",amount:0,blend:"source-over",blackPoint:0,whitePoint:1,gamma:1,shadows:0,highlights:0,curves:{rgb:[[0,0],[1,1]],red:[[0,0],[1,1]],green:[[0,0],[1,1]],blue:[[0,0],[1,1]]},denoise:0},dither:{algorithm:"none",palette:"mono",colors:["#080808","#e8b900"],amount:1,scale:2,threshold:.5,motion:"none",speed:1,direction:45,colorSpace:"rgb"},mask:{enabled:!1,invert:!1,shapes:[]},lights:[],effects:{bloom:0,characterBloom:0,grain:0,dust:0,scanlines:0,crt:0,prism:0,rgbSplit:0,sharpen:0,vignette:0,glitch:0,pixelate:0,blur:0,blurType:"gaussian",angle:0,focus:.5,halftone:0},motion:{type:"none",speed:1,amount:1},hover:{effect:"trail",strength:.55,radius:.2,edgeSafe:!1}},F=t=>t&&"object"==typeof t&&!Array.isArray(t)?t:{},T=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.min(a,Math.max(i,t)):e,P=(t,e)=>"string"==typeof t&&/^#[\da-f]{6}$/i.test(t)?t:e,I=(t,e,i)=>e.includes(t)?t:i;function R(i={}){const a=F(i),s=E;if(void 0!==a.version&&1!==a.version)throw new Error("Unsupported studio settings version. Update asciify-engine.");const r=F(a.crop),o=F(a.backdrop),n=F(a.color),h=F(a.dither),l=F(a.mask),c=F(a.effects),m=F(a.motion),d=F(a.hover),u={...s.effects};for(const t of["bloom","characterBloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","halftone"])u[t]=T(c[t],0,0,1);u.blur=T(c.blur,0,0,24),u.blurType=I(c.blurType,["gaussian","directional","radial","progressive"],s.effects.blurType),u.angle=T(c.angle,0,-180,180),u.focus=T(c.focus,.5,0,1);let g=2048;return{version:1,aspectRatio:I(a.aspectRatio,["original","16:9","9:16","1:1","4:3","3:4","21:9"],"original"),style:I(a.style,y,s.style),cellSize:T(a.cellSize,s.cellSize,["pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(String(a.style))?1:3,60),charset:"string"==typeof a.charset&&a.charset.length?Array.from(a.charset).slice(0,128).join(""):s.charset,colorMode:I(a.colorMode,["accent","source","gray"],s.colorMode),ink:P(a.ink,s.ink),warps:v(a.warps),warpEdge:I(a.warpEdge,["clamp","transparent"],"clamp"),crop:{x:T(r.x,.5,0,1),y:T(r.y,.5,0,1),zoom:T(r.zoom,1,1,5),rotation:90*Math.round(T(r.rotation,0,-360,360)/90)},backdrop:{mode:I(o.mode,["solid","transparent","source","blurred","gradient"],s.backdrop.mode),color:P(o.color,s.backdrop.color),color2:P(o.color2,s.backdrop.color2),blur:T(o.blur,12,0,32),opacity:T(o.opacity,1,0,1)},color:{brightness:T(n.brightness,0,-1,1),contrast:T(n.contrast,1,0,3),saturation:T(n.saturation,1,0,3),grayscale:T(n.grayscale,0,0,1),tint:P(n.tint,s.color.tint),amount:T(n.amount,0,0,1),blend:I(n.blend,S,s.color.blend),blackPoint:T(n.blackPoint,0,0,.99),whitePoint:Math.max(T(n.blackPoint,0,0,.99)+1/255,T(n.whitePoint,1,1/255,1)),gamma:T(n.gamma,1,.25,4),shadows:T(n.shadows,0,-1,1),highlights:T(n.highlights,0,-1,1),curves:f(n.curves),denoise:T(n.denoise,0,0,1)},dither:{algorithm:I(h.algorithm,k,"none"),palette:"string"==typeof h.palette&&Object.prototype.hasOwnProperty.call(A,h.palette)?h.palette:"mono",colors:Array.isArray(h.colors)&&h.colors.length>=2?h.colors.slice(0,32).map(t=>P(t,"#000000")):[...s.dither.colors],amount:T(h.amount,1,0,2),scale:Math.round(T(h.scale,2,1,12)),threshold:T(h.threshold,.5,0,1),motion:I(h.motion,["none","drift","shimmer"],"none"),speed:T(h.speed,1,.1,3),direction:T(h.direction,45,-180,180),colorSpace:I(h.colorSpace,["rgb","luminance"],"rgb")},mask:{enabled:!0===l.enabled,invert:!0===l.invert,shapes:Array.isArray(l.shapes)?l.shapes.slice(0,64).map(t=>{const e=F(t),i=I(e.kind,["rectangle","ellipse","brush"],"rectangle"),a="brush"===i&&Array.isArray(e.points)?e.points.slice(0,g).map(t=>Array.isArray(t)?[Math.round(1e4*T(t[0],0,0,1))/1e4,Math.round(1e4*T(t[1],0,0,1))/1e4]:[0,0]):[];return g-=a.length,{kind:i,x:T(e.x,0,0,1),y:T(e.y,0,0,1),width:T(e.width,.5,0,1),height:T(e.height,.5,0,1),size:T(e.size,.05,.005,.5),points:a}}):[]},lights:Array.isArray(a.lights)?a.lights.slice(0,4).map(t=>{const e=F(t);return{x:T(e.x,.5,0,1),y:T(e.y,.5,0,1),radius:T(e.radius,.3,.02,1),intensity:T(e.intensity,.5,0,1),color:P(e.color,"#ffffff")}}):[],effects:u,motion:{type:I(m.type,e.map(t=>t.mode),"none"),speed:T(m.speed,1,.1,3),amount:T(m.amount,1,0,2)},hover:{effect:I(d.effect,t.map(t=>t.value),"trail"),strength:T(d.strength,.55,0,1),radius:T(d.radius,.2,.1,1),edgeSafe:!0===d.edgeSafe}}}function C(t){return JSON.stringify(R(t))}function L(t){if(t.length>1e5)throw new Error("Settings exceed 100 KB.");return R(JSON.parse(t))}function N(t,e,i,a,s){const r=Math.abs(s.rotation/90)%2==1,o=r?e:t,n=r?t:e,h=Math.max(i/o,a/n)*s.zoom;return{width:o*h,height:n*h,x:(i-o*h)*s.x,y:(a-n*h)*s.y,scale:h,rotated:r}}function X(t,e,i){if(Math.abs(i.crop.rotation/90)%2==1&&([t,e]=[e,t]),"original"===i.aspectRatio)return[t,e];const[a,s]=i.aspectRatio.split(":").map(Number);return t/e>a/s?[Math.round(e*a/s),e]:[t,Math.round(t*s/a)]}function U(t,e){const i={...t,...e};for(const a of["crop","backdrop","color","dither","mask","effects","motion","hover"])e[a]&&Object.assign(i,{[a]:{...t[a],...e[a]}});return e.color?.curves&&(i.color.curves={...t.color.curves,...e.color.curves}),R(i)}function D(t,e,i,a=12e3,s=1){const r=Math.max(2,Number.isFinite(t)?t:960),o=Math.max(2,Number.isFinite(e)?e:540),n=Math.max(1,Math.floor(Number.isFinite(a)?a:12e3)),h=Math.max(.01,Number.isFinite(s)?s:1),l=["dither","pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(i.style)?1:1.65;let c=Math.max(1,Math.ceil(Math.sqrt(r*o/(n*l))/h));for(;Math.ceil(r/(c*h))*Math.ceil(o/(c*h*l))>n;)c++;const f="dither"===i.style?i.dither.scale:i.cellSize,m=Math.max(c,f)*h;return{cell:m,rowHeight:m*l,columns:Math.ceil(r/m),rows:Math.ceil(o/(m*l)),minimum:c,limited:f<c}}var O=[["ascii","Signature ASCII","Brand ink and clean characters.",{}],["print","Newsprint","Fine diffusion on warm paper.",{style:"dither",dither:{algorithm:"floyd-steinberg",palette:"newsprint"}}],["handheld","Pocket camera","Four-tone ordered dither.",{style:"dither",dither:{algorithm:"bayer4",palette:"gameboy",scale:3}}],["riso","Two inks","Limited-color print texture.",{style:"dither",dither:{algorithm:"atkinson",palette:"risograph",scale:2}}],["night","Night signal","Gray characters and optical fringe.",{ink:"#888888",effects:{prism:.7,scanlines:.2,vignette:.3}}],["terminal","Phosphor","Green glyphs with a soft glow.",{ink:"#83efad",effects:{bloom:.4,scanlines:.35,crt:.2}}],["mosaic","Mosaic study","Separated color tiles.",{style:"mosaic",cellSize:14,colorMode:"source"}],["bricks","Brickwork","Colorful studded cells.",{style:"lego",cellSize:18,colorMode:"source"}],["voxel","Little volumes","Three-face isometric tiles.",{style:"voxel",cellSize:22,colorMode:"source"}],["disco","Mirror room","Faceted tiles and warm light.",{style:"disco",cellSize:18,colorMode:"source",lights:[{x:.35,y:.25,radius:.25,intensity:.45,color:"#fff2d4"}]}],["wallpaper","Wallpaper","Living ASCII over a softened source.",{backdrop:{mode:"blurred",blur:18,opacity:.55},ink:"#f2e9c9",motion:{type:"caustics",speed:.5}}],["blueprint","Blueprint","Linework in a cool monochrome.",{style:"lines",ink:"#9bccdf",backdrop:{mode:"solid",color:"#0a1e30"}}]].map(([t,e,i,a])=>({id:t,name:e,description:i,settings:R(a)}));function Y(t){const e=O.find(e=>e.id===t);if(!e)throw new Error("Unknown studio look.");return R(e.settings)}function q(t,e=Math.random){const i=O.filter(e=>e.settings.style!==t.style||e.settings.ink!==t.ink),a=Y(i[Math.min(i.length-1,Math.max(0,Math.floor(e()*i.length)))].id);return a.aspectRatio=t.aspectRatio,a.crop={...t.crop},a.mask=R(t).mask,a}function B(t){const e=function(t){const e=t.blackPoint??0,i=t.whitePoint??1,a=t.gamma??1,s=t.shadows??0,r=t.highlights??0;if(0===e&&1===i&&1===a&&0===s&&0===r)return null;const o=[0,.25+.2*s,.5,.75+.2*r,1],n=o.slice(1).map((t,e)=>4*(t-o[e])),h=[n[0],...n.slice(1).map((t,e)=>2*t*n[e]/(t+n[e])),n[3]],l=new Uint8Array(256);for(let t=0;t<256;t++){const s=Math.pow(Math.max(0,Math.min(1,(t/255-e)/(i-e))),1/a),r=Math.min(3,Math.floor(4*s)),n=4*s-r,c=n*n,f=c*n,m=(2*f-3*c+1)*o[r]+(f-2*c+n)*h[r]/4+(-2*f+3*c)*o[r+1]+(f-c)*h[r+1]/4;l[t]=Math.round(255*Math.max(0,Math.min(1,m)))}return l}(t),i=t.curves;if(!e&&(!i||Object.values(i).every(t=>t.every(([t,e])=>t===e))))return null;const a=m(i?.rgb),s=[i?.red,i?.green,i?.blue].map(m),r=new Uint8Array(768);for(let t=0;t<256;t++)for(let i=0;i<3;i++)r[256*i+t]=s[i][a[e?e[t]:t]];return r}var z=class{constructor(t=0){this.amount=0,this.weights=new Float32Array(256),this.source=new Uint8ClampedArray(0),this.configure(t)}configure(t=0){const e=Math.max(0,Math.min(1,Number.isFinite(t)?t:0));if(e===this.amount)return;if(this.amount=e,0===e)return void(this.source=new Uint8ClampedArray(0));const i=8+24*e;for(let t=0;t<256;t++)this.weights[t]=Math.exp(-t*t/(2*i*i))}apply(t,e,i){if(!this.amount)return;if(!Number.isInteger(e)||!Number.isInteger(i)||e<1||i<1||e*i*4!==t.length)throw new Error("Denoise dimensions do not match the source.");this.source.length!==t.length&&(this.source=new Uint8ClampedArray(t.length));const a=this.source;a.set(t);for(let s=0;s<i;s++)for(let r=0;r<e;r++){const o=4*(s*e+r);if(!a[o+3])continue;const n=a[o],h=a[o+1],l=a[o+2];let c=0,f=0,m=0,d=0;for(let t=-1;t<=1;t++){const o=s+t;if(!(o<0||o>=i))for(let i=-1;i<=1;i++){const s=r+i;if(s<0||s>=e)continue;const u=4*(o*e+s);if(!a[u+3])continue;const g=Math.max(Math.abs(a[u]-n),Math.abs(a[u+1]-h),Math.abs(a[u+2]-l)),p=this.weights[g]*(0===i?1:.6)*(0===t?1:.6)*a[u+3];c+=a[u]*p,f+=a[u+1]*p,m+=a[u+2]*p,d+=p}}t[o]=n+(c/d-n)*this.amount,t[o+1]=h+(f/d-h)*this.amount,t[o+2]=l+(m/d-l)*this.amount}}},W=new Set(["none","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis"]);function G(t){return"dither"===t.style&&("shimmer"===t.dither.motion||"drift"===t.dither.motion&&t.dither.amount>0&&!W.has(t.dither.algorithm))}function j(t){return"none"!==t.motion.type&&(t.motion.amount??1)>0}var V="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",H="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",J=new Uint16Array(4096);for(let t=0;t<J.length;t++)J[t]=V.indexOf(H[2*t])<<6|V.indexOf(H[2*t+1]);var K=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};var Q=new Map([2,4,8,16].map(t=>[t,Float64Array.from({length:t*t},(e,i)=>function(t,e,i){let a=0;for(let s=1;s<i;s*=2){const i=(Math.floor(t/s)%2+2)%2;a=4*a+[[0,2],[3,1]][(Math.floor(e/s)%2+2)%2][i]}return(a+.5)/(i*i)-.5}(i%t,Math.floor(i/t),t))])),Z={"floyd-steinberg":[[1,0,7/16],[-1,1,3/16],[0,1,5/16],[1,1,1/16]],atkinson:[[1,0,.125],[2,0,.125],[-1,1,.125],[0,1,.125],[1,1,.125],[0,2,.125]],stucki:[[1,0,8/42],[2,0,4/42],[-2,1,2/42],[-1,1,4/42],[0,1,8/42],[1,1,4/42],[2,1,2/42],[-2,2,1/42],[-1,2,2/42],[0,2,4/42],[1,2,2/42],[2,2,1/42]],sierra:[[1,0,5/32],[2,0,3/32],[-2,1,2/32],[-1,1,4/32],[0,1,5/32],[1,1,4/32],[2,1,2/32],[-1,2,2/32],[0,2,3/32],[1,2,2/32]],"sierra-lite":[[1,0,.5],[-1,1,.25],[0,1,.25]],burkes:[[1,0,.25],[2,0,4/32],[-2,1,2/32],[-1,1,4/32],[0,1,.25],[1,1,4/32],[2,1,2/32]],jarvis:[[1,0,7/48],[2,0,5/48],[-2,1,3/48],[-1,1,5/48],[0,1,7/48],[1,1,5/48],[2,1,3/48],[-2,2,1/48],[-1,2,3/48],[0,2,5/48],[1,2,3/48],[2,2,1/48]]},_=t=>[parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16)];function $(t,e,i){const a=Math.min(t*Math.max(1,i),(1-t)*Math.max(1,i),e*Math.max(1,1/i),(1-e)*Math.max(1,1/i)),s=Math.max(0,Math.min(1,(a-.035)/.105));return s*s*s*(s*(6*s-15)+10)}var tt=t=>["dissolve","silk","vortex","magnetic","scatter","etch","elastic","rake"].includes(t),et=class{constructor(t,e){this.edgeSafe=!1,this.previous=null,this.peak=0,this.scatterDirections=null,this.springX=null,this.springY=null,this.mode="dissolve",this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.ink=new Float32Array(i),this.targetX=new Float32Array(i),this.targetY=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.edge=new Float32Array(i);for(let i=0;i<e;i++)for(let a=0;a<t;a++)this.edge[i*t+a]=$(a/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){if("elastic"!==t||this.springX||(this.springX=new Float32Array(this.ink.length),this.springY=new Float32Array(this.ink.length)),"scatter"===t&&!this.scatterDirections){const t=this.scatterDirections=new Float64Array(this.width*this.height*2);for(let e=0;e<this.height;e++)for(let i=0;i<this.width;i++){const a=43758.5453*Math.sin(127.1*i+311.7*e),s=(a-Math.floor(a))*Math.PI*2,r=2*(e*this.width+i);t[r]=.7*Math.cos(s),t[r+1]=.7*Math.sin(s)}}t!==this.mode&&(this.mode=t,this.clear())}clear(){for(const t of[this.ink,this.targetX,this.targetY,this.offsetX,this.offsetY,this.pixels])t.fill(0);if(this.previous=null,this.peak=0,this.springX?.fill(0),this.springY?.fill(0),"dissolve"!==this.mode)for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=this.pixels[t+2]=128}leave(){this.previous=null}move(t,e,i){if(!Number.isFinite(t+e+i))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const a=this.previous;this.previous={x:t,y:e};const s=this.width,r=this.height,o=Math.max(1,s/r),n=Math.max(1,r/s),h=a?(t-a.x)*o:0,l=a?(e-a.y)*n:0,c=Math.hypot(h,l);if(!a&&"dissolve"!==this.mode&&"etch"!==this.mode)return;if(a&&c<1e-4)return;const f=.035+.11*Math.max(.1,Math.min(1,i)),m=Math.min(128,Math.max(1,Math.ceil(c/(.45*f)))),d=c?h/c:1,u=c?l/c:0,g=Math.min(1,c/(f*m)*2.2);for(let i=0;i<m;i++){const h=(i+.5)/m,l=a?a.x+(t-a.x)*h:t,c=a?a.y+(e-a.y)*h:e,p=Math.max(0,Math.floor((l-2.5*f/o)*(s-1))),M=Math.min(s-1,Math.ceil((l+2.5*f/o)*(s-1))),v=Math.max(0,Math.floor((c-2.5*f/n)*(r-1))),x=Math.min(r-1,Math.ceil((c+2.5*f/n)*(r-1)));for(let t=v;t<=x;t++)for(let e=p;e<=M;e++){const i=(e/(s-1)-l)*o/f,a=(t/(r-1)-c)*n/f,h=Math.exp(1.5*-(i*i+a*a)),m=t*s+e;if("dissolve"===this.mode||"etch"===this.mode)this.ink[m]=Math.max(this.ink[m],h);else if("elastic"===this.mode)this.springX[m]=Math.max(-24,Math.min(24,this.springX[m]+d*h*g*8)),this.springY[m]=Math.max(-24,Math.min(24,this.springY[m]+u*h*g*8));else{const s=(-i*u+a*d)*h*2.8,r="rake"===this.mode?d*Math.sin(t*Math.PI/3)*h*2:"magnetic"===this.mode?-i*h*2.5:"scatter"===this.mode?(i+this.scatterDirections[2*m])*h*2:"silk"===this.mode?d*s:-a*h*2.5,o="rake"===this.mode?u*Math.sin(e*Math.PI/3)*h*2:"magnetic"===this.mode?-a*h*2.5:"scatter"===this.mode?(a+this.scatterDirections[2*m+1])*h*2:"silk"===this.mode?u*s:i*h*2.5;this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+r*g)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+o*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i=Math.exp(-("dissolve"===this.mode?2.15:3.2)*e),a=1-Math.exp(-22*e);let s=0;const r=Math.sqrt(336),o=Math.exp(-8*e),n=Math.cos(r*e),h=Math.sin(r*e)/r;for(let t=0;t<this.ink.length;t++)if("etch"===this.mode)this.ink[t]*=i,s=Math.max(s,this.ink[t]);else if("dissolve"===this.mode){this.ink[t]*=i,s=Math.max(s,this.ink[t]);const e=Math.round(65535*this.ink[t]);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e}else{if("elastic"===this.mode){const e=this.offsetX[t],i=this.offsetY[t],a=this.springX[t],r=this.springY[t];this.offsetX[t]=Math.max(-1,Math.min(1,o*(e*n+(a+8*e)*h))),this.offsetY[t]=Math.max(-1,Math.min(1,o*(i*n+(r+8*i)*h))),this.springX[t]=o*(a*n-(8*a+400*e)*h),this.springY[t]=o*(r*n-(8*r+400*i)*h),s=Math.max(s,.05*Math.abs(this.springX[t]),.05*Math.abs(this.springY[t]))}else this.targetX[t]*=i,this.targetY[t]*=i,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*a,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*a;s=Math.max(s,Math.abs(this.offsetX[t]),Math.abs(this.offsetY[t]),Math.abs(this.targetX[t]),Math.abs(this.targetY[t]));const e=Math.round(this.offsetX[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768),r=Math.round(this.offsetY[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=r>>>8,this.pixels[4*t+3]=255&r}if("etch"===this.mode)for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const i=t*this.width+e,a=3*(this.ink[t*this.width+Math.max(0,e-1)]-this.ink[t*this.width+Math.min(this.width-1,e+1)]+this.ink[Math.max(0,t-1)*this.width+e]-this.ink[Math.min(this.height-1,t+1)*this.width+e]);this.offsetX[i]=Math.max(-1,Math.min(1,a))*(this.edgeSafe?this.edge[i]:1);const s=Math.round(32767*this.offsetX[i]+32768);this.pixels[4*i]=s>>>8,this.pixels[4*i+1]=255&s}this.peak=s,this.active||this.clear()}sample(t,e,i){const a=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),s=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),r=Math.floor(a),o=Math.floor(s),n=a-r,h=s-o,l=o*this.width+r,c=l+this.width,f=t=>(t[l]*(1-n)+t[l+1]*n)*(1-h)+(t[c]*(1-n)+t[c+1]*n)*h;if("etch"===this.mode)return i[0]=i[1]=0,void(i[2]=3*f(this.offsetX));i[0]=f(this.offsetX)*(this.edgeSafe?$(t,e,this.width/this.height):1)*.08,i[1]=f(this.offsetY)*(this.edgeSafe?$(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-f(this.ink):0}},it=class{constructor(t,e){this.rings=[],this.previous=null,this.elapsed=1,this.echoPeak=0,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.echo=new Float32Array(t*e)}get active(){return this.rings.length>0||this.echoPeak>2e-4}clear(){this.rings=[],this.previous=null,this.elapsed=1,this.pixels.fill(0),this.echo.fill(0),this.echoPeak=0}leave(){this.previous=null}move(t,e,i){const a=Math.max(1,this.width/this.height),s=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*a,(e-this.previous.y)*s)<.065||this.elapsed<.3)||4!==this.rings.length&&(this.previous={x:t,y:e},this.elapsed=0,this.rings.push({x:t,y:e,age:0,radius:i}))}ringSample(t,e){const i=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);let s=0;for(const r of this.rings){const o=.015+r.age*(.15+.22*r.radius),n=.009+.014*r.radius,h=(Math.hypot((t-r.x)*i,(e-r.y)*a)-o)/n,l=Math.sin(Math.min(1,r.age/.07)*Math.PI/2)*Math.max(0,1-r.age/1.35)**2;s=Math.max(s,Math.exp(-h*h)*l)}return s}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),a=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[a*this.width+i])}step(t){if(!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t));this.elapsed+=e;for(const t of this.rings)t.age+=e;if(this.rings=this.rings.filter(t=>t.age<1.35),!this.active)return void this.pixels.fill(0);const i=Math.exp(-5.5*e);let a=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const s=t*this.width+e;this.echo[s]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[s]*i),a=Math.max(a,this.echo[s]);const r=Math.round(65535*this.echo[s]),o=4*s;this.pixels[o]=r>>>8,this.pixels[o+1]=255&r}this.echoPeak=a,this.active||(this.echo.fill(0),this.pixels.fill(0))}},at=class{constructor(t,e){this.previous=null,this.peak=0,this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.signal=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.driftX=new Float32Array(i),this.driftY=new Float32Array(i),this.u=new Float32Array(i),this.v=new Float32Array(i),this.ink=new Float32Array(i),this.a=new Float32Array(i),this.b=new Float32Array(i),this.c=new Float32Array(i),this.pressure=new Float32Array(i),this.pressureNext=new Float32Array(i),this.divergence=new Float32Array(i),this.curl=new Float32Array(i)}get active(){return this.peak>2e-4}clear(){for(const t of[this.u,this.v,this.ink,this.a,this.b,this.c,this.pressure,this.pressureNext,this.divergence,this.curl,this.signal,this.pixels,this.offsetX,this.offsetY,this.driftX,this.driftY])t.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(t,e,i,a=performance.now()){if(!Number.isFinite(t+e+i+a))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),i=Math.max(.1,Math.min(1,i));const s=this.previous;if(this.previous={x:t,y:e,time:a},!s)return;const r=(t-s.x)*(this.width-1),o=(e-s.y)*(this.height-1),n=Math.hypot(r,o);if(n<.001)return;const h=Math.min(this.width,this.height),l=a>s.time?Math.max(1/240,(a-s.time)/1e3):1/60,c=Math.min(12,n/h/l),f=1-Math.exp(-c/2.2),m=h*(.022+.075*i)*(.65+.95*f),d=Math.min(128,Math.max(1,Math.ceil(n/(.4*m)))),u=n/m*(.32+.22*f)/d,g=r/n,p=o/n,M=-p,v=g,x=n*(2+18*f)/d;for(let i=0;i<d;i++){const a=(i+.5)/d,r=(s.x+(t-s.x)*a)*(this.width-1),o=(s.y+(e-s.y)*a)*(this.height-1),n=Math.max(1,Math.floor(r-3*m)),h=Math.min(this.width-2,Math.ceil(r+3*m)),l=Math.max(1,Math.floor(o-3*m)),c=Math.min(this.height-2,Math.ceil(o+3*m));for(let t=l;t<=c;t++)for(let e=n;e<=h;e++){const i=((e-r)*g+(t-o)*p)/m,a=((e-r)*M+(t-o)*v)/m,s=Math.exp(-i*i*.65-a*a*1.7),n=t*this.width+e;this.ink[n]=1-(1-this.ink[n])*Math.exp(-s*u);const h=1-a*a*.55,l=i*a*.7;this.u[n]=Math.max(-80,Math.min(80,this.u[n]+(g*h+M*l)*s*x)),this.v[n]=Math.max(-80,Math.min(80,this.v[n]+(p*h+v*l)*s*x))}}this.peak=1}read(t,e,i){const a=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),s=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),r=e-a,o=i-s,n=s*this.width+a;return(t[n]*(1-r)+t[n+1]*r)*(1-o)+(t[n+this.width]*(1-r)+t[n+this.width+1]*r)*o}sample(t,e){return this.read(this.signal,t*(this.width-1),e*(this.height-1))}displacement(t,e,i){i[0]=this.read(this.offsetX,t*(this.width-1),e*(this.height-1)),i[1]=this.read(this.offsetY,t*(this.width-1),e*(this.height-1))}step(t){if(!this.active||!Number.isFinite(t))return;let e=Math.max(0,Math.min(.05,t));const i=this.width,a=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const s=Math.exp(-1.9*t),r=Math.exp(-3.2*t);for(let e=1;e<a-1;e++)for(let o=1;o<i-1;o++){const n=e*i+o,h=Math.max(.5,Math.min(i-1.5,o-this.u[n]*t)),l=Math.max(.5,Math.min(a-1.5,e-this.v[n]*t)),c=0|h,f=0|l,m=h-c,d=l-f,u=f*i+c,g=(1-m)*(1-d),p=m*(1-d),M=(1-m)*d,v=m*d;this.a[n]=(this.u[u]*g+this.u[u+1]*p+this.u[u+i]*M+this.u[u+i+1]*v)*s,this.b[n]=(this.v[u]*g+this.v[u+1]*p+this.v[u+i]*M+this.v[u+i+1]*v)*s,this.c[n]=(this.ink[u]*g+this.ink[u+1]*p+this.ink[u+i]*M+this.ink[u+i+1]*v)*r}[this.u,this.a]=[this.a,this.u],[this.v,this.b]=[this.b,this.v],[this.ink,this.c]=[this.c,this.ink];for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.curl[a]=.5*(this.v[a+1]-this.v[a-1]-this.u[a+i]+this.u[a-i])}for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a,r=Math.abs(this.curl[s+1])-Math.abs(this.curl[s-1]),o=Math.abs(this.curl[s+i])-Math.abs(this.curl[s-i]),n=Math.hypot(r,o)+1e-4,h=this.curl[s]*t*10,l=Math.hypot(this.u[s],this.v[s]);this.u[s]+=o/n*h,this.v[s]-=r/n*h;const c=Math.min(1,l/(Math.hypot(this.u[s],this.v[s])+1e-6));this.u[s]*=c,this.v[s]*=c,this.divergence[s]=-.5*(this.u[s+1]-this.u[s-1]+this.v[s+i]-this.v[s-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.pressureNext[a]=.25*(this.divergence[a]+this.pressure[a-1]+this.pressure[a+1]+this.pressure[a-i]+this.pressure[a+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let o=0;for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a;this.u[s]=Math.max(-80,Math.min(80,this.u[s]-.5*(this.pressure[s+1]-this.pressure[s-1]))),this.v[s]=Math.max(-80,Math.min(80,this.v[s]-.5*(this.pressure[s+i]-this.pressure[s-i]))),this.driftX[s]+=(3.6*this.u[s]-58*this.offsetX[s]-12*this.driftX[s])*t,this.driftY[s]+=(3.6*this.v[s]-58*this.offsetY[s]-12*this.driftY[s])*t,this.offsetX[s]=Math.max(-2,Math.min(2,this.offsetX[s]+this.driftX[s]*t)),this.offsetY[s]=Math.max(-2,Math.min(2,this.offsetY[s]+this.driftY[s]*t)),this.signal[s]=1-Math.exp(.06*-Math.hypot(this.u[s],this.v[s])-.16*this.ink[s]),o=Math.max(o,this.signal[s])}this.peak=o}if(this.active)for(let t=0;t<this.ink.length;t++){const e=Math.round(65535*Math.min(1,this.signal[t]));this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=Math.round(128+63.5*this.offsetX[t]),this.pixels[4*t+3]=Math.round(128+63.5*this.offsetY[t])}else this.clear()}};function st(t,e){const i=Math.max(0,Math.min(1,e/.38));return t+(1-2*t)*(i*i*(3-2*i))}var rt=(t,e)=>"water"===t?30*e/.55:"silk"===t?28*e:"vortex"===t?38*e:["magnetic","scatter","elastic","rake"].includes(t)?32*e:0,ot=class{constructor(t=1){this.mode="water",this.amount=.55,this.radius=.2,this.lensX=.5,this.lensY=.5,this.lensStrength=0,this.previous=null,this.energy=0,this.pending=!1,this.remainder=0,t=Math.max(.25,Math.min(4,t)),this.columns=Math.round(t>=1?128:128*t),this.rows=Math.round(t>=1?128/t:128),this.xScale=Math.max(1,t),this.yScale=Math.max(1,1/t),this.heights=new Float32Array(this.columns*this.rows),this.velocity=new Float32Array(this.heights.length),this.next=new Float32Array(this.heights.length),this.normals=new Float32Array(2*this.heights.length),this.edgeMask=new Float32Array(this.heights.length);for(let e=0;e<this.rows;e++)for(let i=0;i<this.columns;i++)this.edgeMask[e*this.columns+i]=$(i/(this.columns-1),e/(this.rows-1),t);this.refraction={width:this.columns,height:this.rows,pixels:new Uint8Array(4*this.heights.length),strength:30,mode:"water",focus:[.5,.5,0,.2]},this.waterPixels=this.refraction.pixels,this.trail=new at(this.columns,this.rows),this.contour=new it(this.columns,this.rows),this.afterimage=new et(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve","etch"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get active(){return tt(this.mode)?this.afterimage.active:"contour"===this.mode?this.contour.active:"trail"===this.mode?this.trail.active:this.pending||this.energy>15e-5}setMode(t){t!==this.mode&&(this.clear(),this.mode=t,this.refraction.mode=t,tt(t)&&this.afterimage.setMode(t),this.refraction.pixels="trail"===t?this.trail.pixels:"contour"===t?this.contour.pixels:tt(t)?this.afterimage.pixels:this.waterPixels,this.refraction.strength=rt(t,this.amount))}configure(t,e=.55,i=.2,a=!1){this.setMode(t),this.refraction.edgeSafe=a,this.afterimage.edgeSafe=a,this.amount=Number.isFinite(e)?Math.max(0,Math.min(1,e)):.55,this.radius=Number.isFinite(i)?Math.max(.1,Math.min(1,i)):.2,this.refraction.strength=rt(t,this.amount),this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius}move(t,e,i){if("none"===this.mode||0===this.amount)return;if(!Number.isFinite(t+e))return;if(t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),tt(this.mode))return void this.afterimage.move(t,e,this.radius);if("contour"===this.mode)return void this.contour.move(t,e,this.radius);if("trail"===this.mode)return void this.trail.move(t,e,this.radius,i);if("water"!==this.mode)return!this.previous&&this.lensStrength<.001&&(this.lensX=t,this.lensY=e),this.previous={x:t,y:e},void(this.pending=!0);if(!this.previous)return void(this.previous={x:t,y:e});const a=this.previous;this.previous={x:t,y:e};const s=(t-a.x)*this.xScale,r=(e-a.y)*this.yScale,o=Math.hypot(s,r);if(o<1e-5)return;const n=.035+.1*this.radius,h=3*n,l=Math.min(192,Math.max(1,Math.ceil(o/(.5*n)))),c=95*Math.min(o,1)/l;for(let i=0;i<l;i++){const s=(i+.5)/l,r=a.x+(t-a.x)*s,o=a.y+(e-a.y)*s,f=Math.max(1,Math.floor((r-h/this.xScale)*(this.columns-1))),m=Math.min(this.columns-2,Math.ceil((r+h/this.xScale)*(this.columns-1))),d=Math.max(1,Math.floor((o-h/this.yScale)*(this.rows-1))),u=Math.min(this.rows-2,Math.ceil((o+h/this.yScale)*(this.rows-1)));for(let t=d;t<=u;t++)for(let e=f;e<=m;e++){const i=(e/(this.columns-1)-r)*this.xScale,a=(t/(this.rows-1)-o)*this.yScale,s=Math.exp(-(i*i+a*a)/(n*n))*c,h=t*this.columns+e;this.velocity[h]=Math.max(-12,this.velocity[h]-s)}}this.pending=!0}leave(){this.afterimage.leave(),this.contour.leave(),this.trail.leave(),this.previous=null,"water"!==this.mode&&this.lensStrength&&(this.pending=!0)}clear(){this.trail.clear(),this.contour.clear(),this.afterimage.clear(),this.heights.fill(0),this.velocity.fill(0),this.next.fill(0),this.normals.fill(0),this.refraction.focus[2]=0,this.previous=null,this.lensStrength=0,this.energy=0,this.pending=!1,this.remainder=0;for(let t=0;t<this.waterPixels.length;t+=4)this.waterPixels[t]=this.waterPixels[t+2]=128,this.waterPixels[t+1]=this.waterPixels[t+3]=0}step(t){if(!this.active||!Number.isFinite(t))return;if(tt(this.mode))return void this.afterimage.step(t);if("contour"===this.mode)return void this.contour.step(t);if("trail"===this.mode)return void this.trail.step(t);if("water"!==this.mode)return void this.stepLight(Math.max(0,Math.min(.05,t)));this.remainder+=Math.max(0,Math.min(.05,t));const e=1/120,i=Math.exp(-3.8*e),a=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e;let t=0;for(let s=1;s<this.rows-1;s++)for(let r=1;r<this.columns-1;r++){const o=s*this.columns+r,n=this.heights[o],h=this.heights[o-1]+this.heights[o+1]+this.heights[o-this.columns]+this.heights[o+this.columns]-4*n,l=Math.min(r,s,this.columns-1-r,this.rows-1-s),c=l<5?.88+.024*l:1,f=(this.velocity[o]+(h*a*a-8*n)*e)*i*c;this.velocity[o]=f,this.next[o]=(n+f*e)*c,t=Math.max(t,Math.abs(this.next[o]),.1*Math.abs(f))}this.heights.set(this.next),this.energy=t,this.pending=!1}if(!this.active)return void this.clear();const s=.18*Math.min(this.columns,this.rows);for(let t=0;t<this.rows;t++)for(let e=0;e<this.columns;e++){const i=t*this.columns+e,a=(this.heights[t*this.columns+Math.max(0,e-1)]-this.heights[t*this.columns+Math.min(this.columns-1,e+1)])*s,r=(this.heights[Math.max(0,t-1)*this.columns+e]-this.heights[Math.min(this.rows-1,t+1)*this.columns+e])*s,o=Math.tanh(a)*(this.refraction.edgeSafe?this.edgeMask[i]:1),n=Math.tanh(r)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=o,this.normals[2*i+1]=n;const h=Math.round(32767*o+32768),l=Math.round(32767*n+32768);this.refraction.pixels[4*i]=h>>>8,this.refraction.pixels[4*i+1]=255&h,this.refraction.pixels[4*i+2]=l>>>8,this.refraction.pixels[4*i+3]=255&l}}stepLight(t){const e=this.previous,i=1-Math.exp(-30*t),a=1-Math.exp(-12*t);e&&(this.lensX+=(e.x-this.lensX)*i,this.lensY+=(e.y-this.lensY)*i),this.lensStrength+=((e?1:0)-this.lensStrength)*a,this.energy=Math.max(e?Math.abs(e.x-this.lensX)+Math.abs(e.y-this.lensY):0,Math.abs((e?1:0)-this.lensStrength)),this.pending=!1,e||this.active?this.refraction.focus=[this.lensX,this.lensY,this.lensStrength*this.amount,this.radius]:this.clear()}sample(t,e,i){if(tt(this.mode))return this.afterimage.sample(t,e,i),i[0]*=this.amount,i[1]*=this.amount,void(i[2]*=this.amount);if("contour"===this.mode)return i[0]=i[1]=0,void(i[2]=this.contour.sample(t,e)*this.amount*3);if("trail"===this.mode)return i[0]=i[1]=0,void(i[2]=this.trail.sample(t,e)*this.amount*3);const a=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),s=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),r=Math.floor(a),o=Math.floor(s),n=a-r,h=s-o,l=2*(o*this.columns+r),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-n)+this.normals[l+2+t]*n)*(1-h)+(this.normals[c+t]*(1-n)+this.normals[c+2+t]*n)*h);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,a){const[s,r,o,n]=i.focus,h=(t-s)*Math.max(1,a)/n,l=(e-r)*Math.max(1,1/a)/n;return"light"===i.mode?Math.exp(-3*(h*h+l*l))*o:"scan"===i.mode?(1.3*Math.exp(-h*h*110)-.3*Math.exp(-h*h*12))*Math.exp(-l*l*1.8)*o:0}(t,e,this.refraction,this.xScale/this.yScale):0}};function nt(t){return"videoWidth"in t?[t.videoWidth,t.videoHeight]:"naturalWidth"in t?[t.naturalWidth,t.naturalHeight]:[t.width,t.height]}var ht=(t=!1)=>{const e=document.createElement("canvas"),i=e.getContext("2d",{willReadFrequently:t});if(!i)throw new Error("Canvas 2D is unavailable.");return{canvas:e,ctx:i}},lt=(t,e,i)=>{t.width===e&&t.height===i||(t.width=e,t.height=i)},ct={blocks:" ░▒▓█",braille:" ⠁⠃⠇⡇⣇⣧⣷⣿",lines:" -═╪╬",cross:" ·+xX#",diagonal:" /╱╳",diamond:" ·◇◈◆",mixed:" .:+/◇#@"};function ft(t,e={},i={}){const a=t.getContext("2d");if(!a)throw new Error("Canvas is already owned by another renderer.");const s=ht(),r=ht(!0),h=ht(),l=ht(),c=ht(),f=ht(),m=ht(),u=ht(),g=ht(),p=ht();let M,v=0,x=R(e),b=0,y="",k="",S="",E=new Uint8ClampedArray(0),F=new Uint8ClampedArray(0),T=0,P=0,I=0,C=null,L="",X=new ot,U=0;const O=[0,0,0],Y=[0,0,0,1],q=[0,0,0,0];let W=B(x.color);const V=new z(x.color.denoise),H=new w(x.warps,x.warpEdge),$=Math.max(64,Math.min(4096,Number.isFinite(i.maxDimension)?i.maxDimension:960)),tt=Math.max(256,Math.min(1048576,Number.isFinite(i.maxCells)?i.maxCells:12e3));let et=tt,it=Math.max(.1,Math.min(8,i.pixelRatio??1));return{canvas:t,render:function(e,i=0,w=960,R=540,B=i*x.motion.speed){if(Number.isFinite(i)||(i=0),!Number.isFinite(w)||!Number.isFinite(R)||w<1||R<1)throw new Error("Render dimensions must be positive finite numbers.");const[z,tt]=nt(e);if(!z||!tt)return;const at=Math.min(1,$/Math.max(w,R)),rt=Math.max(2,Math.round(w*at)),ht=Math.max(2,Math.round(R*at));lt(t,rt,ht),lt(s.canvas,rt,ht),lt(h.canvas,rt,ht),lt(l.canvas,rt,ht),lt(c.canvas,rt,ht),U!==rt/ht&&(U=rt/ht,X=new ot(U)),X.configure(x.hover.effect,x.hover.strength,x.hover.radius,x.hover.edgeSafe),X.step(Math.max(0,Math.min(.05,i-I))),I=i;const ft="currentTime"in e?e.getVideoPlaybackQuality?.().totalVideoFrames??e.currentTime:0,mt=[b,rt,ht,ft].join(":"),dt="dither"===x.style,ut=D(rt,ht,x,et,it),gt=ut.cell,pt=ut.rowHeight,Mt=ut.columns,vt=ut.rows;if(y!==mt||C!==e||T!==Mt||P!==vt){C=e,y=mt,k="",S="",T=Mt,P=vt,s.ctx.clearRect(0,0,rt,ht),s.ctx.save();const t=N(z,tt,rt,ht,x.crop);s.ctx.translate(t.x+t.width/2,t.y+t.height/2),s.ctx.rotate(x.crop.rotation*Math.PI/180),s.ctx.drawImage(e,-z*t.scale/2,-tt*t.scale/2,z*t.scale,tt*t.scale),s.ctx.restore(),lt(r.canvas,T,P),r.ctx.clearRect(0,0,T,P),r.ctx.drawImage(s.canvas,0,0,T,P),E=r.ctx.getImageData(0,0,T,P).data,V.apply(E,T,P);const i=x.color;for(let t=0;t<E.length;t+=4){const e=.299*E[t]+.587*E[t+1]+.114*E[t+2];for(let a=0;a<3;a++){const s=e+(E[t+a]-e)*i.saturation;E[t+a]=((s*(1-i.grayscale)+e*i.grayscale)/255-.5)*i.contrast*255+127.5+255*i.brightness}}W&&function(t,e){for(let i=0;i<t.length;i+=4)t[i+3]&&(t[i]=e[t[i]],t[i+1]=e[256+t[i+1]],t[i+2]=e[512+t[i+2]])}(E,W),E=H.apply(E,T,P,rt/ht)}const xt=j(x),bt=G(x),wt=!X.active&&!xt&&!bt,yt=[mt,T,P,gt,pt,it].join(":");if(!wt||S!==yt){h.ctx.clearRect(0,0,rt,ht),h.ctx.globalAlpha=1,h.ctx.globalCompositeOperation="source-over";const t=B,e=xt?x.motion.type:"none",a=["none","caustics","sheen","grain","trace"].includes(e);if(dt){const a=wt;if(!a||k!==mt){F.length!==E.length&&(F=new Uint8ClampedArray(E.length));const s=F;if(s.set(E),X.active||"none"!==e)for(let i=0;i<P;i++)for(let a=0;a<T;a++){const r=a/T,h=i/P;let l=a,c=i,f=0,m=1,u=1;X.active&&(X.sample(r,h,O),l-=O[0]*T,c-=O[1]*P,f=O[2]/3);const g=4*(i*T+a);o(e,r,h,t,Y,(.299*E[g]+.587*E[g+1]+.114*E[g+2])/255),n(Y,x.motion.amount??1),l-=Y[0]/960*T,c-=Y[1]/960*P,m=1+Y[2],u=Y[3];const p=4*(i*T+a);d(E,T,P,l,c,q);for(let t=0;t<3;t++){const e=q[t]/255;let i=(["trail","contour"].includes(x.hover.effect)?st(e,f):"etch"===x.hover.effect?Math.max(0,Math.min(1,e+.35*f)):"dissolve"===x.hover.effect?e*Math.max(0,1+f):e)*m;s[p+t]=255*i}s[p+3]=q[3]*u}!function(t,e,i,a,s=0){const{algorithm:r,amount:o,threshold:n}=a,h="blue-noise"===r,l=r.startsWith("bayer")?Number(r.slice(5)):0,c=Q.get(l),f=l-1,m="luminance"===a.colorSpace,d=("custom"===a.palette?a.colors:A[a.palette]??A.mono).map(_),u=Z[r],g=u?new Float32Array(3*e*3):null,p="drift"===a.motion?s*a.speed*3:0,M=(a.direction??45)*Math.PI/180,v=Math.round(Math.cos(M)*p),x=Math.round(Math.sin(M)*p),b=(t,e)=>(t%e+e)%e,w=d.map(t=>.299*t[0]+.587*t[1]+.114*t[2]),y="shimmer"===a.motion?.15*Math.sin(s*a.speed*2):0;for(let a=0;a<i;a++)for(let s=0;s<e;s++){const M=4*(a*e+s),k=3*(a%3*e+s);if(0===t[M+3]){g&&(g[k]=g[k+1]=g[k+2]=0);continue}let S=0;const A=h?(J[64*(a-x&63)+(s-v&63)]+.5)/J.length:0;c?S=c[(a-x&f)*l+(s-v&f)]:"noise"===r?S=K(s-v,a-x)-.5:"lines"===r?S=b(a-x,4)/3-.5:"vertical-lines"===r?S=b(s-v,4)/3-.5:"diagonal-lines"===r?S=b(s-v+a-x,4)/3-.5:"radial"===r?S=b(Math.hypot(s-e/2,a-i/2)-p,6)/6-.5:"halftone"===r&&(S=Math.hypot(b(s-v,6)-2.5,b(a-x,6)-2.5)/3.54-.5);const E=128*(S*o+y+(.5-n)),F=t[M]+E+(g?.[k]??0),T=t[M+1]+E+(g?.[k+1]??0),P=t[M+2]+E+(g?.[k+2]??0);let I=0,R=0,C=0;if(d.length){let t=1/0,e=1/0,i=0,a=0;const s=.299*F+.587*T+.114*P;for(let r=0;r<d.length;r++){const o=d[r],n=m?(s-w[r])**2:(F-o[0])**2*.299+(T-o[1])**2*.587+(P-o[2])**2*.114;n<t?(h&&(e=t,a=i,i=r),t=n,[I,R,C]=o):h&&n<e&&(e=n,a=r)}if(h&&o>0&&Number.isFinite(e)){const t=d[a],e=t[0]-I,r=t[1]-R,n=t[2]-C,h=w[a]-w[i],l=m?h*h:e*e*.299+r*r*.587+n*n*.114,c=m?(s-w[i])*h:(F-I)*e*.299+(T-R)*r*.587+(P-C)*n*.114;A<(l?Math.max(0,Math.min(1,c/l*o)):0)&&([I,R,C]=t)}}else if(h){const t=Math.max(0,Math.min(1,.5+(A-.5)*o));I=51*Math.floor(F/51+1-t),R=51*Math.floor(T/51+1-t),C=51*Math.floor(P/51+1-t)}else I=51*Math.round(F/51),R=51*Math.round(T/51),C=51*Math.round(P/51);if(t[M]=I,t[M+1]=R,t[M+2]=C,g&&u){g[k]=g[k+1]=g[k+2]=0;for(const[t,r,n]of u){const h=s+t;if(h<0||h>=e||a+r>=i)continue;const l=3*((a+r)%3*e+h);g[l]+=(F-I)*n*o,g[l+1]+=(T-R)*n*o,g[l+2]+=(P-C)*n*o}}}}(s,T,P,x.dither,i),r.ctx.putImageData(new ImageData(s,T,P),0,0),k=a?mt:""}h.ctx.imageSmoothingEnabled=!1,h.ctx.drawImage(r.canvas,0,0,rt,ht)}else{const i=Array.from(ct[x.style]??x.charset),s=h.ctx,r=_(x.ink),l="ascii"===x.style||!!ct[x.style],c=Math.max(3,Math.round(.92*pt)),f=Math.ceil(gt+4),u=Math.ceil(pt+4),g=[i.join(""),c,f,u,x.ink,x.colorMode].join(":");if(l&&g!==L&&(L=g,lt(m.canvas,f*i.length,u),m.ctx.clearRect(0,0,m.canvas.width,u),m.ctx.font=`${c}px monospace`,m.ctx.textBaseline="middle",m.ctx.textAlign="center",m.ctx.fillStyle="accent"===x.colorMode?x.ink:"#ffffff",i.forEach((t,e)=>m.ctx.fillText(t,e*f+f/2,u/2))),"lego"===x.style&&v!==gt){v=gt,lt(p.canvas,Math.ceil(gt),Math.ceil(pt));const t=p.ctx;t.clearRect(0,0,p.canvas.width,p.canvas.height),t.fillStyle="rgba(255,255,255,.2)",t.strokeStyle="rgba(0,0,0,.25)",t.lineWidth=Math.max(.5,.6*it),t.beginPath(),t.arc(gt/2,pt/2,.28*gt,0,2*Math.PI),t.fill(),t.stroke()}s.font=`${c}px monospace`,s.textBaseline="middle",s.textAlign="center";for(let h=0;h<P;h++)for(let c=0;c<T;c++){let g=c,M=h,v=0;if(X.active&&(X.sample(c/T,h/P,O),g=Math.max(0,Math.min(T-1,c-O[0]*T)),M=Math.max(0,Math.min(P-1,h-O[1]*P)),v=O[2]/3),d(E,T,P,g,M,q),!q[3])continue;const b=q[0],w=q[1],y=q[2],k=(.299*b+.587*w+.114*y)/255;let S=k;["trail","contour"].includes(x.hover.effect)&&v?S=st(S,v):"etch"===x.hover.effect?S=Math.max(0,Math.min(1,S+.35*v)):"dissolve"===x.hover.effect&&(S*=Math.max(0,1+v));let A=c*gt,F=h*pt,I=1;o(e,c/T,h/P,t,Y,k),n(Y,x.motion.amount??1),A+=Y[0]*rt/960,F+=Y[1]*ht/960,S=Math.max(0,Math.min(1,S+Y[2])),I=Y[3]*q[3]/255,l||"accent"!==x.colorMode||"cmyk"===x.style||(I*=S),s.globalAlpha=I;const R=255*(S-k),C="source"===x.colorMode?`rgb(${b+R},${w+R},${y+R})`:"gray"===x.colorMode?`rgb(${Math.round(255*S)},${Math.round(255*S)},${Math.round(255*S)})`:x.ink;if(s.fillStyle=C,l){const t=Math.max(0,Math.min(i.length-1,Math.round(S*(i.length-1))));"accent"===x.colorMode?s.drawImage(m.canvas,t*f,0,f,u,a?Math.round(A+(gt-f)/2):A+(gt-f)/2,a?Math.round(F+(pt-u)/2):F+(pt-u)/2,f,u):s.fillText(i[t],A+gt/2,F+pt/2)}else if("dots"===x.style)s.beginPath(),s.arc(A+gt/2,F+pt/2,.48*gt*Math.sqrt(S),0,2*Math.PI),s.fill();else if("led"===x.style)s.beginPath(),s.arc(A+gt/2,F+pt/2,.39*gt,0,2*Math.PI),s.fill(),s.globalAlpha=.35*I,s.fillStyle="#ffffff",s.beginPath(),s.arc(A+.43*gt,F+.4*pt,.11*gt,0,2*Math.PI),s.fill();else if("hex"===x.style){const t=A+gt/2,e=F+pt/2;s.beginPath();for(let i=0;i<6;i++){const a=Math.PI/3*i,r=t+Math.cos(a)*gt*.49,o=e+Math.sin(a)*pt*.49;0===i?s.moveTo(r,o):s.lineTo(r,o)}s.closePath(),s.fill()}else if("cmyk"===x.style){s.fillStyle="#ffffff",s.fillRect(A,F,gt,pt);const t=(t,e)=>Math.max(0,Math.min(255,"source"===x.colorMode?t+R:"gray"===x.colorMode?255*S:e*S)),e=t(b,r[0]),i=t(w,r[1]),a=t(y,r[2]),o=1-Math.max(e,i,a)/255,n=Math.max(.001,1-o),h=[["#00ffff",(1-e/255-o)/n,.36,.36],["#ff00ff",(1-i/255-o)/n,.64,.36],["#ffff00",(1-a/255-o)/n,.5,.66],["#000000",o,.5,.5]];s.globalCompositeOperation="multiply";for(const[t,e,i,a]of h)s.fillStyle=t,s.beginPath(),s.arc(A+gt*i,F+pt*a,.48*gt*Math.sqrt(Math.max(0,e)),0,2*Math.PI),s.fill();s.globalCompositeOperation="source-over"}else if("voxel"===x.style){const t=A+gt/2,e=F+pt/2;s.beginPath(),s.moveTo(t,F),s.lineTo(A+gt,F+.25*pt),s.lineTo(t,e),s.lineTo(A,F+.25*pt),s.closePath(),s.fill(),s.globalAlpha=.72*I,s.beginPath(),s.moveTo(A,F+.25*pt),s.lineTo(t,e),s.lineTo(t,F+pt),s.lineTo(A,F+.75*pt),s.closePath(),s.fill(),s.globalAlpha=.42*I,s.beginPath(),s.moveTo(t,e),s.lineTo(A+gt,F+.25*pt),s.lineTo(A+gt,F+.75*pt),s.lineTo(t,F+pt),s.closePath(),s.fill()}else{const t="pixel"===x.style?0:Math.max(.5,.06*gt);s.fillRect(A,F,gt-t,pt-t),"lego"===x.style&&s.drawImage(p.canvas,A,F),"disco"===x.style&&(s.fillStyle=`rgba(255,255,255,${.1+.25*K(c,h)})`,s.fillRect(A,F,gt-t,.35*pt),s.fillStyle="rgba(0,0,0,.25)",s.fillRect(A,F+.65*pt,gt-t,.35*pt-t))}}}h.ctx.globalAlpha=1,(x.color.amount||x.lights.length)&&(lt(u.canvas,rt,ht),u.ctx.clearRect(0,0,rt,ht),u.ctx.drawImage(h.canvas,0,0)),x.color.amount&&(h.ctx.save(),h.ctx.globalCompositeOperation=x.color.blend,h.ctx.globalAlpha=x.color.amount,h.ctx.fillStyle=x.color.tint,h.ctx.fillRect(0,0,rt,ht),h.ctx.restore());for(const t of x.lights){const e=t.radius*Math.max(rt,ht),i=h.ctx.createRadialGradient(t.x*rt,t.y*ht,0,t.x*rt,t.y*ht,e);i.addColorStop(0,t.color),i.addColorStop(1,"transparent"),h.ctx.save(),h.ctx.globalCompositeOperation="screen",h.ctx.globalAlpha=t.intensity,h.ctx.fillStyle=i,h.ctx.fillRect(0,0,rt,ht),h.ctx.restore()}if((x.color.amount||x.lights.length)&&(h.ctx.globalCompositeOperation="destination-in",h.ctx.drawImage(u.canvas,0,0),h.ctx.globalCompositeOperation="source-over"),x.mask.enabled&&x.mask.shapes.length){const t=c.ctx;t.clearRect(0,0,rt,ht),t.fillStyle="#fff",t.strokeStyle="#fff",t.lineCap="round",t.lineJoin="round";for(const e of x.mask.shapes){if(t.beginPath(),"ellipse"===e.kind)t.ellipse((e.x+e.width/2)*rt,(e.y+e.height/2)*ht,e.width*rt/2,e.height*ht/2,0,0,2*Math.PI);else{if("rectangle"!==e.kind){if(t.lineWidth=(e.size??.05)*rt,1===e.points?.length){t.arc(e.points[0][0]*rt,e.points[0][1]*ht,t.lineWidth/2,0,2*Math.PI),t.fill();continue}e.points?.forEach(([e,i],a)=>a?t.lineTo(e*rt,i*ht):t.moveTo(e*rt,i*ht)),t.stroke();continue}t.rect(e.x*rt,e.y*ht,e.width*rt,e.height*ht)}t.fill()}h.ctx.globalCompositeOperation=x.mask.invert?"destination-out":"destination-in",h.ctx.drawImage(c.canvas,0,0),h.ctx.globalCompositeOperation="source-over"}const M=l.ctx;M.clearRect(0,0,rt,ht),M.globalAlpha=x.backdrop.opacity;const b=x.backdrop;if("solid"===b.mode&&(M.fillStyle=b.color,M.fillRect(0,0,rt,ht)),"gradient"===b.mode){const t=M.createLinearGradient(0,0,rt,ht);t.addColorStop(0,b.color),t.addColorStop(1,b.color2),M.fillStyle=t,M.fillRect(0,0,rt,ht)}if("source"===b.mode&&M.drawImage(s.canvas,0,0),"blurred"===b.mode){const t=Math.max(1,b.blur);lt(f.canvas,Math.max(2,Math.round(rt/t)),Math.max(2,Math.round(ht/t))),f.ctx.drawImage(s.canvas,0,0,f.canvas.width,f.canvas.height),M.imageSmoothingEnabled=!0,M.drawImage(f.canvas,0,0,rt,ht)}M.globalAlpha=1,x.effects.characterBloom>0&&(lt(g.canvas,Math.max(2,Math.round(rt/3)),Math.max(2,Math.round(ht/3))),g.ctx.clearRect(0,0,g.canvas.width,g.canvas.height),g.ctx.drawImage(h.canvas,0,0,g.canvas.width,g.canvas.height),M.save(),M.globalAlpha=.8*x.effects.characterBloom,M.globalCompositeOperation="screen",M.filter=`blur(${1+4*x.effects.characterBloom}px)`,M.drawImage(g.canvas,0,0,rt,ht),M.restore()),M.drawImage(h.canvas,0,0),S=wt?yt:""}const kt=Object.entries(x.effects).some(([t,e])=>!["angle","focus","blurType","characterBloom"].includes(t)&&"number"==typeof e&&e>0);a.clearRect(0,0,rt,ht),kt?(void 0===M&&(M=function(){const t=document.createElement("canvas"),e=t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,antialias:!1,preserveDrawingBuffer:!0});if(!e)return null;const i=[],a=(t,a)=>{const s=e.createShader(t);if(i.push(s),e.shaderSource(s,a),e.compileShader(s),!e.getShaderParameter(s,e.COMPILE_STATUS))throw new Error(e.getShaderInfoLog(s)||"Finish shader failed");return s},s=e.createProgram();if(e.attachShader(s,a(e.VERTEX_SHADER,"attribute vec2 p;varying vec2 uv;void main(){uv=(p+1.)*.5;gl_Position=vec4(p,0.,1.);}")),e.attachShader(s,a(e.FRAGMENT_SHADER,"precision mediump float;varying vec2 uv;uniform sampler2D src;uniform vec2 size;uniform float t,bloom,grain,dust,scanlines,crt,prism,vignette,glitch,pixelate,blur,blurMode,angle,focus,halftone,rgbSplit,sharpen;\n float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}\n vec4 sampleAt(vec2 p){if(min(min(p.x,p.y),min(1.-p.x,1.-p.y))<0.)return vec4(0.);return texture2D(src,vec2(p.x,1.-p.y));}\n void main(){vec2 q=uv,c=q-.5;q=c*(1.+dot(c,c)*crt*.25)+.5;\n if(glitch>0.)q.x+=(hash(vec2(floor(q.y*35.),floor(t*5.)))-.5)*.07*glitch*step(.82,hash(vec2(floor(q.y*35.),floor(t*5.)+3.)));\n if(pixelate>0.){vec2 grid=size/(1.+pixelate*20.);q=(floor(q*grid)+.5)/grid;}\n vec4 base=sampleAt(q);float edge=smoothstep(.12,.65,length(c));\n vec2 shift=vec2((prism*3.*edge+rgbSplit*8.)/size.x,prism*edge/size.y);\n if(prism>0.||rgbSplit>0.)base.rgb=vec3(sampleAt(q+shift).r,base.g,sampleAt(q-shift).b);\n vec2 dir=vec2(cos(angle),sin(angle))/size;float amount=blur;\n if(blurMode>1.5&&blurMode<2.5){dir=normalize(c+vec2(.0001))/size;amount*=length(c)*2.;}\n if(blurMode>2.5)amount*=smoothstep(.05,.5,abs(q.y-focus));\n vec4 blurred=base;\n if(amount>0.){blurred=base*.2;for(int i=1;i<=4;i++){float f=float(i)*amount*.35;vec2 off=dir*f;if(blurMode<.5)off=vec2(cos(float(i)*1.57),sin(float(i)*1.57))*amount/size;blurred+=sampleAt(q+off)*.1+sampleAt(q-off)*.1;}}\n vec3 light=vec3(0.);if(bloom>0.)for(int i=0;i<4;i++){float a=float(i)*1.5708;vec3 s=sampleAt(q+vec2(cos(a),sin(a))*6./size).rgb;light+=max(vec3(0.),s-.35)*.25;}\n vec3 col=blurred.rgb+light*bloom;\n if(sharpen>0.){vec2 px=1./size;vec3 near=sampleAt(q+vec2(px.x,0.)).rgb+sampleAt(q-vec2(px.x,0.)).rgb+sampleAt(q+vec2(0.,px.y)).rgb+sampleAt(q-vec2(0.,px.y)).rgb;col+=(base.rgb*4.-near)*sharpen*.5;}\ncol*=1.-scanlines*.4*(.5+.5*cos(q.y*size.y*3.14159));\n col*=1.-vignette*smoothstep(.15,.72,length(c));\n col+=(hash(floor(q*size)+floor(t*12.))-.5)*grain*.2;\n if(dust>0.)col+=step(1.-dust*.002,hash(floor(q*size*.25)+floor(t*2.)))*.4;\n if(halftone>0.)col*=mix(1.,smoothstep(.1,.65,length(fract(q*size/6.)-.5)),halftone);\n gl_FragColor=vec4(clamp(col,0.,1.),blurred.a);}")),e.linkProgram(s),!e.getProgramParameter(s,e.LINK_STATUS))throw new Error("Finish link failed");e.useProgram(s);const r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW);const o=e.getAttribLocation(s,"p");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0);const n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);const h=["t","bloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","blur","blurMode","angle","focus","halftone"],l=Object.fromEntries(h.map(t=>[t,e.getUniformLocation(s,t)])),c=e.getUniformLocation(s,"size");return{canvas:t,render(i,a,r,o=1){t.width===i.width&&t.height===i.height||(t.width=i.width,t.height=i.height,e.viewport(0,0,t.width,t.height)),e.useProgram(s),e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,i),e.uniform2f(c,t.width/o,t.height/o);for(const t of h)e.uniform1f(l[t],"t"===t?r:"blurMode"===t?["gaussian","directional","radial","progressive"].indexOf(a.blurType):"angle"===t?a.angle*Math.PI/180:a[t]??0);return e.drawArrays(e.TRIANGLE_STRIP,0,4),t},destroy(){e.deleteTexture(n),e.deleteBuffer(r),e.deleteProgram(s),i.forEach(t=>e.deleteShader(t)),t.width=t.height=1,e.getExtension("WEBGL_lose_context")?.loseContext()}}}()),M?a.drawImage(M.render(l.canvas,x.effects,i,it),0,0):a.drawImage(l.canvas,0,0),t.dataset.studioFinish=M?"gpu":"unavailable"):(a.drawImage(l.canvas,0,0),t.dataset.studioFinish="none")},setPixelRatio(t){it=Math.max(.1,Math.min(8,Number.isFinite(t)?t:1))},get pixelRatio(){return it},setBudget(t){et=Math.max(256,Math.min(tt,Number.isFinite(t)?Math.round(t):tt))},get maxCells(){return et},configure(t){x=R(t),W=B(x.color),V.configure(x.color.denoise),H.configure(x.warps,x.warpEdge),b++},pointer:(t,e,i)=>{X.configure(x.hover.effect,x.hover.strength,x.hover.radius,x.hover.edgeSafe),X.move(t,e,i)},leave(){X.leave()},get active(){return X.active},get settings(){return R(x)},get capabilities(){return{gpuFinish:null!==M}},invalidate(){y=""},destroy(){M?.destroy(),H.clear(),V.configure(0);for(const t of[s,r,h,l,c,f,m,u,g,p])t.canvas.width=t.canvas.height=1;C=null,E=new Uint8ClampedArray(0),F=new Uint8ClampedArray(0)}}}function mt(t,e,i){return new Promise((a,s)=>{const r=()=>{l(),a()},o=()=>{l(),s(new Error("Unable to load this media. Check its format and cross-origin permissions."))},n=()=>{l(),s(new DOMException("Cancelled","AbortError"))},h=setTimeout(o,2e4),l=()=>{clearTimeout(h),t.removeEventListener(e,r),t.removeEventListener("error",o),i?.removeEventListener("abort",n)};t.addEventListener(e,r,{once:!0}),t.addEventListener("error",o,{once:!0}),i?.addEventListener("abort",n,{once:!0}),i?.aborted&&n()})}async function dt(t,e){if("string"==typeof t&&t.startsWith("blob:")){const i=await fetch(t,{signal:e}),a=await i.blob();return dt(new File([a],"Imported media",{type:a.type}),e)}const i="string"!=typeof t,a=i?t.name:t;if(i?"image/gif"===t.type:/\.gif(?:[?#]|$)/i.test(a)){const a=await import("gifuct-js"),{parseGIF:s,decompressFrames:r}="function"==typeof a.parseGIF?a:a.default,o=i?await t.arrayBuffer():await fetch(t,{signal:e}).then(t=>{if(!t.ok)throw new Error("GIF download failed.");return t.arrayBuffer()});if(e?.aborted)throw new DOMException("Cancelled","AbortError");const n=s(o),h=n.lsd.width,l=n.lsd.height;if(h*l>4e6)throw new Error("GIF is too large. Use a smaller GIF or an MP4.");const c=n.frames.filter(t=>"image"in t).length;if(!c||c*h*l*4>128e6)throw new Error("GIF exceeds the decoded memory budget. Use MP4 for long animations.");const f=r(n,!0);if(f.length*h*l*4>128e6)throw new Error("GIF exceeds the 128 MB decoded budget. Use MP4 for long animations.");const m=document.createElement("canvas");m.width=h,m.height=l;const d=m.getContext("2d"),u=document.createElement("canvas"),g=u.getContext("2d"),p=f.reduce((t,e)=>t+Math.max(20,e.delay),0)/1e3;let M=-1,v=null;const x=t=>{const e=(t%p+p)%p*1e3;let i=0,a=0;for(;a<f.length-1&&(i+=Math.max(20,f[a].delay),!(e<i));a++);a<M&&(d.clearRect(0,0,h,l),M=-1,v=null);for(let t=M+1;t<=a;t++){const e=f[t-1];2===e?.disposalType&&d.clearRect(e.dims.left,e.dims.top,e.dims.width,e.dims.height),3===e?.disposalType&&v&&d.putImageData(v,0,0);const i=f[t];v=3===i.disposalType?d.getImageData(0,0,h,l):null,u.width=i.dims.width,u.height=i.dims.height,g.putImageData(new ImageData(new Uint8ClampedArray(i.patch),u.width,u.height),0,0),d.drawImage(u,i.dims.left,i.dims.top)}return M=a,m};return x(0),{source:m,width:h,height:l,duration:p,animated:!0,seek:async()=>{},frame:x,destroy(){m.width=u.width=1,f.length=0,v=null}}}const s=i?t.type.startsWith("video/"):/\.(mp4|webm|mov)(?:[?#]|$)/i.test(a),r=i?URL.createObjectURL(t):t,o=s?document.createElement("video"):new Image;o.crossOrigin="anonymous",o instanceof HTMLVideoElement&&(o.muted=!0,o.playsInline=!0,o.preload="auto");const n=()=>{o instanceof HTMLVideoElement?(o.pause(),o.removeAttribute("src"),o.load()):o.src="",i&&URL.revokeObjectURL(r)};try{const t=mt(o,s?"loadeddata":"load",e);o.src=r,await t;const i=o instanceof HTMLVideoElement?o.videoWidth:o.naturalWidth,a=o instanceof HTMLVideoElement?o.videoHeight:o.naturalHeight;return{source:o,width:i,height:a,duration:o instanceof HTMLVideoElement?o.duration:0,animated:s,async seek(t,e){if(!(o instanceof HTMLVideoElement))return;if(!Number.isFinite(o.duration)||o.duration<=0)throw new Error("Video duration is unavailable.");const i=Math.max(0,Math.min(o.duration-.001,t%o.duration));if(Math.abs(o.currentTime-i)<.001&&o.readyState>=2)return;const a=mt(o,"seeked",e);o.currentTime=i,await a},frame:()=>o,destroy:n}}catch(t){throw n(),t}}var ut=t=>{if(t?.aborted)throw new DOMException("Export cancelled","AbortError")};async function gt(t,e,i){const{format:a,signal:s}=i,r=Math.round(i.width),o=Math.round(i.height);if(!Number.isFinite(r)||!Number.isFinite(o)||r<2||o<2||r>4096||o>4096||r*o>16777216)throw new Error("Choose export dimensions between 2 and 4096 pixels.");if(!["png","jpeg","mp4","webm","gif"].includes(a))throw new Error("Unknown export format.");if(void 0!==i.fps&&!Number.isFinite(i.fps))throw new Error("Frames per second must be finite.");const n=Math.max(1,Math.min(60,Math.round(i.fps??24))),h=i.duration??5;if(!Number.isFinite(h)||h<=0||h>60)throw new Error("Choose a duration from 0 to 60 seconds.");const l="png"===a||"jpeg"===a,c=i.time??0;if(!Number.isFinite(c)||c<0)throw new Error("Image time must be a finite non-negative number.");if(void 0!==i.motionTime&&(!Number.isFinite(i.motionTime)||i.motionTime<0))throw new Error("Motion time must be a finite non-negative number.");if(!l&&r*o>8294400)throw new Error("Video exports support up to 3840 × 2160 pixels.");if("gif"===a&&(r*o>921600||h*n>600))throw new Error("GIF export supports up to 1280 × 720 and 600 frames. Use MP4 for larger exports.");if(void 0!==i.referenceWidth&&(!Number.isFinite(i.referenceWidth)||i.referenceWidth<1))throw new Error("Reference width must be a positive number.");if("gif"===a&&n>30)throw new Error("GIF exports support up to 30 fps. Choose MP4 or WebM for higher frame rates.");const f=document.createElement("canvas"),m=ft(f,R(e),{maxDimension:4096,maxCells:i.maxCells??12e3,pixelRatio:r/(i.referenceWidth??Math.min(r,960))});let d;try{if(ut(s),i.onProgress?.(0),l){if(m.render(await t.frame(c,s),c,r,o,i.motionTime),"unavailable"===f.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");ut(s);const e=await new Promise((t,e)=>f.toBlob(i=>i?t(i):e(new Error("Image export failed.")),"png"===a?"image/png":"image/jpeg",i.quality??.92));return i.onProgress?.(1),e}const e=Math.ceil(h*n);if("gif"===a){const a=await import("gifenc"),{GIFEncoder:l,quantize:c,applyPalette:d}="function"==typeof a.GIFEncoder?a:a.default,u=l(),g=f.getContext("2d");for(let a=0;a<e;a++){ut(s);const l=a/n;if(m.invalidate(),m.render(await t.frame(l,s),l,r,o),"unavailable"===f.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");const p=g.getImageData(0,0,r,o).data,M=c(p,256),v=d(p,M);u.writeFrame(v,r,o,{palette:M,delay:10*(Math.round(100*Math.min((a+1)/n,h))-Math.round(100*a/n)),repeat:0}),i.onProgress?.((a+1)/e*.98),await new Promise(t=>setTimeout(t,0))}return u.finish(),i.onProgress?.(1),new Blob([new Uint8Array(u.bytes())],{type:"image/gif"})}const{Output:u,Mp4OutputFormat:g,WebMOutputFormat:p,BufferTarget:M,CanvasSource:v,canEncodeVideo:x}=await import("mediabunny"),b="mp4"===a?"avc":"vp9";if(!await x(b,{width:r,height:o}))throw new Error(`${a.toUpperCase()} encoding is unavailable in this browser. Try another format or a current browser with WebCodecs.`);const w=new u({format:"mp4"===a?new g({fastStart:"in-memory"}):new p,target:new M});f.width=r,f.height=o,d=()=>w.cancel();const y=new v(f,{codec:b,bitrate:Math.max(5e5,Math.round(r*o*n*.15))});w.addVideoTrack(y,{frameRate:n}),f.width=r,f.height=o,await w.start();for(let a=0;a<e;a++){ut(s);const l=a/n;if(m.invalidate(),m.render(await t.frame(l,s),l,r,o),"unavailable"===f.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");await y.add(l,Math.min(1/n,h-l)),i.onProgress?.((a+1)/e*.98),a%4==0&&await new Promise(t=>setTimeout(t,0))}return y.close(),ut(s),await w.finalize(),d=void 0,i.onProgress?.(1),new Blob([w.target.buffer],{type:"mp4"===a?"video/mp4":"video/webm"})}catch(t){throw await(d?.().catch(()=>{})),t}finally{m.destroy(),f.width=f.height=1}}async function pt(t,e,i={}){const a=await dt(e,i.signal);try{return Mt(t,a,i)}catch(t){throw a.destroy(),t}}function Mt(t,e,i={}){let a=R(i.settings),s=i.width??e.width,o=i.height??e.height;const n=ft(t,a,i),h=new r;let l=0,c=!1,f=!0,m=!1,d=!0,u=0,g=0,p=0,M=0,v=-1,x=!1!==i.adaptive,b=0,w=0,y=0;const k=matchMedia("(prefers-reduced-motion: reduce)"),S=e.source instanceof HTMLVideoElement?e.source:null,A=()=>{c||l||!d||document.hidden||(l=requestAnimationFrame(T))},E=()=>!m&&!k.matches&&d&&!document.hidden,F=()=>{S&&(S.loop=!0,E()?S.play().catch(()=>{m=!0,f=!0,A()}):S.pause()),p=0,f=!0,A()};function T(t){if(l=0,c||!d||document.hidden)return;const r=E();r&&(u+=p?Math.min(.1,(t-p)/1e3):0),p=t;const k=function(t){return j(t)||G(t)||t.effects.grain>0||t.effects.dust>0||t.effects.glitch>0}(a),F=r&&(e.animated||k),T=S?.getVideoPlaybackQuality?.().totalVideoFrames??-1,P=!S||T<0||T!==v;if(f||n.active||F&&(P||k)&&t-M>=1e3/Math.max(1,Math.min(60,i.fps??60))-.5){const r=performance.now();try{e.animated&&!S&&n.invalidate();const[t,l]=X(s,o,a);g=h.update(u,a.motion.type,a.motion.speed),n.render(e.frame(S?.currentTime??u),u,t,l,g);const c=performance.now()-r;i.onFrame?.(S?.currentTime??u,c),w=w?.9*w+.1*c:c,++b>20&&x&&(F||n.active)&&(y=w>13?y+1:0,y>=12&&n.maxCells>3e3&&(n.setBudget(Math.max(3e3,.8*n.maxCells)),i.onQualityChange?.(n.maxCells),y=0,w=0))}catch(t){m=!0,i.onError?.(t instanceof Error?t:new Error(String(t)))}f=!1,M=t,v=T}r&&(F||n.active)&&A()}const P=e=>{if(!E())return;const i=t.getBoundingClientRect();n.pointer((e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height,e.timeStamp),A()},I=()=>{n.leave(),A()},C=new IntersectionObserver(([t])=>{d=t.isIntersecting,F()});C.observe(t),t.addEventListener("pointermove",P),t.addEventListener("pointerleave",I),t.addEventListener("pointercancel",I),document.addEventListener("visibilitychange",F),k.addEventListener("change",F);const L=()=>{c||(c=!0,cancelAnimationFrame(l),C.disconnect(),t.removeEventListener("pointermove",P),t.removeEventListener("pointerleave",I),t.removeEventListener("pointercancel",I),document.removeEventListener("visibilitychange",F),k.removeEventListener("change",F),i.signal?.removeEventListener("abort",L),n.destroy(),e.destroy())};if(i.signal?.addEventListener("abort",L,{once:!0}),i.signal?.aborted)throw L(),new DOMException("Cancelled","AbortError");return F(),{canvas:t,media:e,update(t){a=U(a,t),n.configure(a),f=!0,A()},resize(t,e,i){void 0!==i&&n.setPixelRatio(i),s=Math.max(2,t),o=Math.max(2,e),f=!0,A()},pause(t=!0){m=t,F()},async seek(t){u=Math.max(0,t),await e.seek(u),n.invalidate(),f=!0,A()},redraw(){n.invalidate(),f=!0,A()},get time(){return S?.currentTime??u},get settings(){return R(a)},get motionTime(){return g},get paused(){return m||k.matches},setAdaptive(t){x=t,b=y=w=0},setBudget(t){n.setBudget(t),i.onQualityChange?.(n.maxCells),f=!0,A()},get pixelRatio(){return n.pixelRatio},get maxCells(){return n.maxCells},get capabilities(){return n.capabilities},destroy:L}}var vt={Standard:()=>import("figlet/fonts/Standard"),Slant:()=>import("figlet/fonts/Slant"),Small:()=>import("figlet/fonts/Small"),Big:()=>import("figlet/fonts/Big"),Banner:()=>import("figlet/fonts/Banner"),Block:()=>import("figlet/fonts/Block"),Bubble:()=>import("figlet/fonts/Bubble"),Digital:()=>import("figlet/fonts/Digital"),Doom:()=>import("figlet/fonts/Doom"),Lean:()=>import("figlet/fonts/Lean"),Mini:()=>import("figlet/fonts/Mini"),Script:()=>import("figlet/fonts/Script"),Shadow:()=>import("figlet/fonts/Shadow"),Speed:()=>import("figlet/fonts/Speed"),Starwars:()=>import("figlet/fonts/Star Wars"),Stop:()=>import("figlet/fonts/Stop"),Straight:()=>import("figlet/fonts/Straight"),Thin:()=>import("figlet/fonts/Thin"),ThreeD:()=>import("figlet/fonts/3-D"),Univers:()=>import("figlet/fonts/Univers"),Wavy:()=>import("figlet/fonts/Wavy")},xt=Object.keys(vt);async function bt(t,e="Standard",i="#ffffff"){if(!Object.prototype.hasOwnProperty.call(vt,e))throw new Error("Unknown text font.");const{default:a}=await import("figlet/browser"),s=await vt[e]();a.parseFont(e,s.default),a.defaults({fetchFontIfMissing:!1});const r=a.textSync(t.slice(0,120),{font:e}),o=r.split("\n"),n=Math.max(1,...o.map(t=>t.length)),h=Math.max(1,o.length),l=Math.min(1,2048/(9*n)),c=document.createElement("canvas");c.width=Math.ceil(9*n*l+32),c.height=Math.ceil(15*h*l+32);const f=c.getContext("2d");return f.fillStyle="#080808",f.fillRect(0,0,c.width,c.height),f.fillStyle=i,f.font=15*l+"px monospace",f.textBaseline="top",o.forEach((t,e)=>f.fillText(t,16,16+15*e*l)),{canvas:c,ascii:r}}var wt={standard:{label:"Classic ASCII",chars:" .:-=+*#%@"},asciify:{label:"Asciify",chars:" .:-=+ASCIIFY#@"},minimal:{label:"Minimal",chars:" .:+"},detailed:{label:"Detailed",chars:" .,:;i1tfLCG08@"},letters:{label:"Letters",chars:" .ilLCFTYASMW"},technical:{label:"Technical",chars:" .:;>_/[{}]=+*#@$"},blocks:{label:"Tonal blocks",chars:" ░▒▓█"},braille:{label:"Braille",chars:" ⠁⠃⠇⡇⣇⣧⣷⣿"}},yt=wt;export{S as BLEND_MODES,wt as CHARACTER_SETS,E as DEFAULT_STUDIO_SETTINGS,k as DITHER_ALGORITHMS,p as MAX_STUDIO_WARPS,yt as STUDIO_CHARACTER_SETS,h as STUDIO_CURVE_CHANNELS,t as STUDIO_HOVERS,O as STUDIO_LOOKS,e as STUDIO_MOTIONS,A as STUDIO_PALETTES,y as STUDIO_STYLES,xt as STUDIO_TEXT_FONTS,g as STUDIO_WARPS,m as createStudioCurveLookup,ft as createStudioRenderer,bt as createStudioText,gt as exportStudio,dt as loadStudioMedia,pt as mountStudio,Mt as mountStudioMedia,c as normalizeStudioCurve,f as normalizeStudioCurves,R as normalizeStudioSettings,v as normalizeStudioWarps,L as parseStudioSettings,q as restyleStudio,C as serializeStudioSettings,N as studioCrop,X as studioDimensions,D as studioGrid,Y as studioLook,nt as studioSourceSize,U as updateStudioSettings};//# sourceMappingURL=studio.js.map
|
|
1
|
+
var t=[{value:"none",label:"Off",group:"Still",description:"Keep the artwork still under the pointer."},{value:"trail",label:"Trail",group:"Change characters",description:"A fluid wake changes character density and settles behind your cursor."},{value:"dissolve",label:"Dissolve",group:"Change characters",description:"Erase a soft path through the characters; the image gradually reforms."},{value:"contour",label:"Contour",group:"Change characters",description:"Fine tonal rings trace your path without moving the grid."},{value:"etch",label:"Emboss",group:"Change characters",description:"Press a light-and-shadow impression into the characters; the grid stays fixed."},{value:"water",label:"Water",group:"Move the image",description:"Soft ripples refract the image and settle after your stroke."},{value:"silk",label:"Silk",group:"Move the image",description:"Directional folds follow the movement of your hand."},{value:"vortex",label:"Vortex",group:"Move the image",description:"A swirling wake curls through the image."},{value:"magnetic",label:"Magnetic Pull",group:"Move the image",description:"The image gathers toward your stroke, then relaxes."},{value:"scatter",label:"Scatter",group:"Move the image",description:"A textured outward scatter settles behind your cursor."},{value:"elastic",label:"Elastic",group:"Move the image",description:"Push the image with your stroke; it recoils and springs back into place."},{value:"rake",label:"Rake",group:"Move the image",description:"Comb the image into alternating ribbons that glide back into alignment."}],e=[{value:"none",mode:"none",group:"Still",label:"Off",description:"Keep the image still. Hover stays available."},{value:"caustics",mode:"caustics",group:"Light and texture",label:"Caustics",description:"Soft ribbons of light travel across a stationary character grid."},{value:"current",mode:"current",group:"Flow and depth",label:"Slow Current",description:"A gentle flow through the image, with steady edges."},{value:"reform",mode:"reform",group:"Rebuild",label:"Reveal & Reform",description:"Disperse, gather, then hold the complete image."},{value:"sheen",mode:"sheen",group:"Light and texture",label:"Sheen",description:"A broad diagonal light sweep; characters stay anchored."},{value:"tidal",mode:"tidal",group:"Flow and depth",label:"Tidal Rings",description:"Concentric currents travel outward, with protected edges."},{value:"grain",mode:"grain",group:"Light and texture",label:"Living Grain",description:"Slow, individually phased tonal changes on a stationary grid."},{value:"parallax",mode:"parallax",group:"Flow and depth",label:"Parallax",description:"A shallow, continuous drift through the image, with the edges held in place."},{value:"weave",mode:"weave",group:"Flow and depth",label:"Woven Flow",description:"Interlaced bands move in opposing directions, like a flexible printed fabric."},{value:"print",mode:"print",group:"Rebuild",label:"Print Shift",description:"Staggered rows lift, soften and register back into the image."},{value:"trace",mode:"trace",group:"Light and texture",label:"Contour Light",description:"Light follows the source image’s tonal contours; every character stays anchored."}],i=t=>Math.max(0,Math.min(1,t)),a=(t,e,a)=>{const s=i((a-t)/(e-t));return s*s*(3-2*s)},s=(t,e)=>{const i=(.06711056*t+.00583715*e)%1*52.9829189;return i-Math.floor(i)},r=class{constructor(){this.last=null,this.mode="none",this.phase=0}update(t,e,i=1){return Number.isFinite(t)?((e!==this.mode||null!==this.last&&t<this.last)&&(this.mode=e,this.phase=0,this.last=t),null!==this.last&&(this.phase+=Math.max(0,t-this.last)*Math.max(.1,Math.min(3,Number.isFinite(i)?i:1))),this.last=t,this.phase):this.phase}};function n(t,e,r,n,o,h=.5){if(o[0]=o[1]=o[2]=0,o[3]=1,"none"===t)return o;const l=n*Math.PI/6,c=a(0,.12,Math.min(e,1-e,r,1-r));if("caustics"===t){const t=Math.sin(9*e+5*r+l)+Math.sin(8*r-3*e-l),i=Math.pow(Math.max(0,1-.72*Math.abs(t)),3);o[2]=(.22*i-.045)*c}else if("current"===t)o[0]=Math.sin(9*r+l)*Math.cos(7*e-l)*10*c,o[1]=Math.cos(8*e+l)*Math.sin(6*r-l)*7*c;else if("sheen"===t)o[2]=.2*Math.pow(.5+.5*Math.cos(5*e+3*r-l),8)-.025;else if("tidal"===t){const t=e-.5,i=r-.5,a=Math.hypot(t,i),s=Math.sin(22*a-l)*c;o[0]=t*s*9,o[1]=i*s*9,o[2]=.035*s}else if("grain"===t){const t=s(Math.floor(160*e),Math.floor(100*r))*Math.PI*2;o[2]=.07*Math.sin(l+t)}else if("parallax"===t){const t=.45+.55*Math.max(0,1-1.4*Math.hypot(e-.5,r-.5));o[0]=12*Math.sin(l)*t*c,o[1]=6*(Math.cos(l)-1)*t*c}else if("weave"===t)o[0]=Math.sin(r*Math.PI*6+l)*Math.sin(l)*8*c,o[1]=Math.sin(e*Math.PI*6-l)*Math.sin(l)*6*c;else if("print"===t){const t=Math.floor(24*r),e=((n+3*s(t,3))%12+12)%12,i=a(1,2.5,e)*(1-a(3.5,5,e));o[0]=Math.sin(2.4*t)*i*9*c,o[1]=5*-i*c,o[2]=.22*-i,o[3]=1-.45*i}else if("trace"===t){const t=.5+.5*Math.cos(l);o[2]=.22*Math.pow(Math.max(0,1-Math.abs(i(h)-t)/.16),3)-.015}else if("reform"===t){const t=(n%12+12)%12,i=s(Math.floor(160*e),Math.floor(100*r)),h=.65*e+.2*r+.15*i+.08*Math.sin(8*e-5*r),d=a(1.8+1.2*h,3.8+1.2*h,t)*(1-a(5+1.7*h,7.2+1.7*h,t));o[0]=Math.sin(9*r+l)*d*(1-d)*24*c,o[1]=-d*(1-d)*(8+12*i)*c,o[2]=.45*-d,o[3]=1-.9*d}return o}function o(t,e){const a=Math.max(0,Math.min(2,Number.isFinite(e)?e:1));return t[0]*=a,t[1]*=a,t[2]*=a,t[3]=i(1+(t[3]-1)*a),t}var h=["rgb","red","green","blue"],l=t=>Math.max(0,Math.min(1,t));function c(t){const e=new Map([[0,0],[1,1]]);if(Array.isArray(t))for(const i of t.slice(0,64)){if(!Array.isArray(i)||i.length<2||"number"!=typeof i[0]||!Number.isFinite(i[0])||"number"!=typeof i[1]||!Number.isFinite(i[1]))continue;const t=Math.round(255*l(i[0]))/255;!e.has(t)&&e.size>=16||e.set(t,l(i[1]))}return[...e].sort((t,e)=>t[0]-e[0])}function d(t){const e=t&&"object"==typeof t?t:{};return Object.fromEntries(h.map(t=>[t,c(e[t])]))}function m(t){const e=c(t),i=e.length,a=e.slice(1).map((t,i)=>t[0]-e[i][0]),s=e.slice(1).map((t,i)=>(t[1]-e[i][1])/a[i]),r=new Float64Array(i);r[0]=s[0],r[i-1]=s[i-2];for(let t=1;t<i-1;t++){const e=s[t-1],i=s[t];if(e*i<=0)continue;const n=2*a[t]+a[t-1],o=a[t]+2*a[t-1];r[t]=(n+o)/(n/e+o/i)}const n=new Uint8Array(256);let o=0;for(let t=0;t<256;t++){const s=t/255;for(;o<i-2&&s>e[o+1][0];)o++;const h=a[o],c=(s-e[o][0])/h,d=c*c,m=d*c,f=(2*m-3*d+1)*e[o][1]+(m-2*d+c)*h*r[o]+(-2*m+3*d)*e[o+1][1]+(m-d)*h*r[o+1];n[t]=Math.round(255*l(f))}return n}function f(t,e,i,a,s,r){a=Math.max(0,Math.min(e-1,a)),s=Math.max(0,Math.min(i-1,s));const n=Math.floor(a),o=Math.floor(s),h=a-n,l=s-o,c=4*(o*e+n);if(0===h&&0===l){for(let e=0;e<4;e++)r[e]=t[c+e];return}const d=4*(o*e+Math.min(e-1,n+1)),m=4*(Math.min(i-1,o+1)*e+n),f=4*(Math.min(i-1,o+1)*e+Math.min(e-1,n+1)),u=(1-h)*(1-l)*t[c+3],g=h*(1-l)*t[d+3],p=(1-h)*l*t[m+3],M=h*l*t[f+3],w=u+g+p+M;for(let e=0;e<3;e++)r[e]=w?(t[c+e]*u+t[d+e]*g+t[m+e]*p+t[f+e]*M)/w:0;r[3]=w}function u(t,e,i,a,s,r){if(a>=0&&a<=e-1&&s>=0&&s<=i-1)return f(t,e,i,a,s,r);if(r[0]=r[1]=r[2]=r[3]=0,a<=-1||a>=e||s<=-1||s>=i)return;const n=Math.floor(a),o=Math.floor(s),h=a-n,l=s-o;for(let a=0;a<=1;a++)for(let s=0;s<=1;s++){const c=n+s,d=o+a;if(c<0||c>=e||d<0||d>=i)continue;const m=4*(d*e+c),f=(s?h:1-h)*(a?l:1-l)*t[m+3];r[0]+=t[m]*f,r[1]+=t[m+1]*f,r[2]+=t[m+2]*f,r[3]+=f}r[3]&&(r[0]/=r[3],r[1]/=r[3],r[2]/=r[3])}var g=[{value:"twirl",label:"Twirl",description:"Rotate the center into a smooth spiral; the outer boundary stays fixed.",direction:!1,frequency:!1},{value:"pinch",label:"Pinch",description:"Contract the center, or expand it with negative strength.",direction:!1,frequency:!1},{value:"sphere",label:"Spherize",description:"Magnify a rounded lens through the source; negative strength recedes.",direction:!1,frequency:!1},{value:"ripple",label:"Ripple",description:"Bend the image through concentric, soft-edged waves.",direction:!1,frequency:!0},{value:"zigzag",label:"Zigzag",description:"Alternate the twist in sharp, concentric bands.",direction:!1,frequency:!0},{value:"shear",label:"Shear",description:"Slant a region along an adjustable direction.",direction:!0,frequency:!1},{value:"smudge",label:"Smudge",description:"Draw a soft region of the source along one direction.",direction:!0,frequency:!1},{value:"polar",label:"Polar",description:"Unwrap a region into polar coordinates; negative strength wraps it.",direction:!0,frequency:!1},{value:"fragment",label:"Fragment",description:"Offset small source tiles into a stable fractured texture.",direction:!0,frequency:!0}],p=8,M=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.max(i,Math.min(a,t)):e;function w(t){if(!Array.isArray(t))return[];const e=[];for(const i of t.slice(0,64))if(i&&"object"==typeof i&&g.some(t=>t.value===i.type)&&(e.push({type:i.type,enabled:!1!==i.enabled,amount:M(i.amount,.35,-1,1),x:M(i.x,.5,0,1),y:M(i.y,.5,0,1),radius:M(i.radius,.55,.05,2),angle:M(i.angle,0,-180,180),frequency:M(i.frequency,5,1,24)}),8===e.length))break;return e}var v=2*Math.PI,b=(t,e)=>{let i=Math.imul(t,374761393)^Math.imul(e,668265263);return i=Math.imul(i^i>>>13,1274126177),((i^i>>>16)>>>0)/4294967296},y=class{constructor(t=[],e="clamp"){this.warps=[],this.signature="",this.geometry="",this.coordinates=new Float32Array(0),this.output=new Uint8ClampedArray(0),this.sampled=[0,0,0,0],this.edge="clamp",this.configure(t,e)}configure(t=[],e="clamp"){const i=w(t).filter(t=>t.enabled&&0!==t.amount),a=JSON.stringify(i);this.edge="transparent"===e?"transparent":"clamp",a!==this.signature&&(this.signature=a,this.geometry="",this.warps=i.map(t=>({...t,cos:Math.cos(t.angle*Math.PI/180),sin:Math.sin(t.angle*Math.PI/180)})),i.length||this.clear())}get active(){return this.warps.length>0}apply(t,e,i,a=e/i){if(!this.active)return t;if(!Number.isInteger(e)||!Number.isInteger(i)||e<1||i<1||e*i*4!==t.length||!Number.isFinite(a)||a<=0)throw new Error("Warp dimensions do not match the source.");const s=`${e}:${i}:${a}`;if(s!==this.geometry){this.coordinates.length!==e*i*2&&(this.coordinates=new Float32Array(e*i*2));const t=Math.max(1,a),r=Math.max(1,1/a);for(let a=0;a<i;a++)for(let s=0;s<e;s++){let n=(s+.5)/e,o=(a+.5)/i;for(let e=this.warps.length-1;e>=0;e--){const i=this.warps[e],a=(n-i.x)*t/i.radius,s=(o-i.y)*r/i.radius,h=a*a+s*s;if(h>=1)continue;const l=Math.sqrt(h),c=(1-h)*(1-h),d=i.amount;let m=a,f=s;if("twirl"===i.type||"zigzag"===i.type){const t="twirl"===i.type?-d*v*c:.65*d*(2/Math.PI*Math.asin(Math.sin(l*v*i.frequency)))*c,e=Math.cos(t),r=Math.sin(t);m=a*e-s*r,f=a*r+s*e}else if("pinch"===i.type){const t=Math.exp(2*d*c);m=a*t,f=s*t}else if("sphere"===i.type&&l>0){const t=1+d*c*(2*Math.asin(l)/Math.PI/l-1);m=a*t,f=s*t}else if("ripple"===i.type&&l>0){const t=1+.12*d*Math.sin(l*v*i.frequency)*c/l;m=a*t,f=s*t}else if("shear"===i.type){const t=-a*i.sin+s*i.cos;m-=d*t*.9*c*i.cos,f-=d*t*.9*c*i.sin}else if("smudge"===i.type)m-=.65*d*c*i.cos,f-=.65*d*c*i.sin;else if("polar"===i.type){const t=a*i.cos+s*i.sin,e=-a*i.sin+s*i.cos,r=Math.atan2(e,t),n=d>0?r/Math.PI:Math.cos(t*Math.PI)*(e+1)/2,o=d>0?2*l-1:Math.sin(t*Math.PI)*(e+1)/2,h=n*i.cos-o*i.sin,u=n*i.sin+o*i.cos;m+=(h-a)*Math.abs(d)*c,f+=(u-s)*Math.abs(d)*c}else if("fragment"===i.type){const t=Math.floor((a*i.cos+s*i.sin)*i.frequency),e=Math.floor((-a*i.sin+s*i.cos)*i.frequency),r=(b(t,e)-.5)*d*.5*c,n=(b(e+71,t-31)-.5)*d*.5*c;m+=r*i.cos-n*i.sin,f+=r*i.sin+n*i.cos}n=i.x+m*i.radius/t,o=i.y+f*i.radius/r}const h=2*(a*e+s);this.coordinates[h]=n*e-.5,this.coordinates[h+1]=o*i-.5}this.geometry=s}this.output.length!==t.length&&(this.output=new Uint8ClampedArray(t.length));const r=t===this.output?t.slice():t,n="transparent"===this.edge?u:f;for(let a=0,s=0;a<t.length;a+=4,s+=2){n(r,e,i,this.coordinates[s],this.coordinates[s+1],this.sampled);for(let t=0;t<4;t++)this.output[a+t]=this.sampled[t]}return this.output}clear(){this.coordinates=new Float32Array(0),this.output=new Uint8ClampedArray(0),this.geometry=""}},x=["stipple","engraving","crosshatch","woodblock","risograph","pointillism"],k=[{value:"stipple",label:"Stipple",description:"Scattered ink dots shape the image through their size."},{value:"engraving",label:"Engraving",description:"Continuous parallel cuts change weight with the image."},{value:"crosshatch",label:"Crosshatch",description:"Crossing layers of fine lines build the tonal range."},{value:"woodblock",label:"Woodblock",description:"Broad carved bands with irregular edges and stepped tones."},{value:"risograph",label:"Risograph",description:"Two offset ink screens with adjustable registration."},{value:"pointillism",label:"Pointillism",description:"Small pigment strokes mix source colors into the image."}];function E(t){return x.includes(t)}var S={density:1,weight:1,angle:-35,roughness:.35,invert:!1,secondaryInk:"#ec6752",registration:.2,seed:7};function A(t){const e=t&&"object"==typeof t&&!Array.isArray(t)?t:{},i=(t,i,a)=>{const s=e[t];return"number"==typeof s&&Number.isFinite(s)?Math.max(i,Math.min(a,s)):S[t]};return{density:i("density",0,2),weight:i("weight",.25,2),angle:i("angle",-180,180),roughness:i("roughness",0,1),invert:!0===e.invert,secondaryInk:"string"==typeof e.secondaryInk&&/^#[\da-f]{6}$/i.test(e.secondaryInk)?e.secondaryInk:S.secondaryInk,registration:i("registration",0,1),seed:Math.round(i("seed",0,65535))}}var F=["ascii","blocks","braille","dots","lines","cross","diagonal","diamond","mixed","pixel","mosaic","lego","voxel","disco","dither","hex","led","cmyk",...x],P=["none","bayer2","bayer4","bayer8","bayer16","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis","halftone","lines","noise","vertical-lines","diagonal-lines","radial","blue-noise"],T=["source-over","multiply","screen","overlay","soft-light","hard-light","color-dodge","color-burn","hue","saturation","color","luminosity"],I={original:[],gray4:["#000000","#555555","#aaaaaa","#ffffff"],gray8:["#000000","#242424","#494949","#6d6d6d","#929292","#b6b6b6","#dbdbdb","#ffffff"],rgb8:["#000000","#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#ffffff"],cyberpunk:["#08081a","#3c1670","#ed299a","#29dfef","#fff7bf"],pastel:["#393448","#a5b4d4","#9ed9c6","#e7aac1","#f5e8be"],mono:["#080808","#f2f2e8"],asciify:["#080808","#625b38","#a19558","#e8b900"],gameboy:["#0f380f","#306230","#8bac0f","#9bbc0f"],cga:["#000000","#55ffff","#ff55ff","#ffffff"],pico8:["#000000","#1d2b53","#7e2553","#008751","#ab5236","#5f574f","#c2c3c7","#fff1e8","#ff004d","#ffa300","#ffec27","#00e436","#29adff","#83769c","#ff77a8","#ffccaa"],c64:["#000000","#ffffff","#880000","#aaffee","#cc44cc","#00cc55","#0000aa","#eeee77","#dd8855","#664400","#ff7777","#333333","#777777","#aaff66","#0088ff","#bbbbbb"],amber:["#100b00","#5f3b00","#c98014","#ffd17c"],ice:["#081b29","#25586e","#69a6b3","#d9ece7"],risograph:["#f4ebd0","#f2594b","#2853a5","#29232e"],sepia:["#201b17","#6b5039","#b49868","#f6e6c5"],nord:["#2e3440","#4c566a","#88c0d0","#eceff4"],dusk:["#211b35","#654271","#c3788c","#f5c9a3"],forest:["#101f1b","#355747","#87a16f","#e4e3ba"],ocean:["#071b33","#17577f","#3fa7a4","#d9efde"],newsprint:["#191919","#666666","#aaaaaa","#eee9df"],custom:["#080808","#e8b900"]},C={version:1,aspectRatio:"original",style:"ascii",cellSize:6,charset:" .:-=+*#%@",colorMode:"accent",ink:"#e8b900",print:{...S},crop:{x:.5,y:.5,zoom:1,rotation:0},warps:[],warpEdge:"clamp",backdrop:{mode:"solid",color:"#080808",color2:"#393323",blur:12,opacity:1},color:{brightness:0,contrast:1,saturation:1,grayscale:0,tint:"#e8b900",amount:0,blend:"source-over",blackPoint:0,whitePoint:1,gamma:1,shadows:0,highlights:0,curves:{rgb:[[0,0],[1,1]],red:[[0,0],[1,1]],green:[[0,0],[1,1]],blue:[[0,0],[1,1]]},denoise:0},dither:{algorithm:"none",palette:"mono",colors:["#080808","#e8b900"],amount:1,scale:2,threshold:.5,motion:"none",speed:1,direction:45,colorSpace:"rgb"},mask:{enabled:!1,invert:!1,shapes:[]},lights:[],effects:{bloom:0,characterBloom:0,grain:0,dust:0,scanlines:0,crt:0,prism:0,rgbSplit:0,sharpen:0,vignette:0,glitch:0,pixelate:0,blur:0,blurType:"gaussian",angle:0,focus:.5,halftone:0},motion:{type:"none",speed:1,amount:1},hover:{effect:"trail",strength:.55,radius:.2,edgeSafe:!1}},R=t=>t&&"object"==typeof t&&!Array.isArray(t)?t:{},L=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.min(a,Math.max(i,t)):e,N=(t,e)=>"string"==typeof t&&/^#[\da-f]{6}$/i.test(t)?t:e,O=(t,e,i)=>e.includes(t)?t:i;function D(i={}){const a=R(i),s=C;if(void 0!==a.version&&1!==a.version)throw new Error("Unsupported studio settings version. Update asciify-engine.");const r=R(a.crop),n=R(a.backdrop),o=R(a.color),h=R(a.dither),l=R(a.mask),c=R(a.effects),m=R(a.motion),f=R(a.hover),u={...s.effects};for(const t of["bloom","characterBloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","halftone"])u[t]=L(c[t],0,0,1);u.blur=L(c.blur,0,0,24),u.blurType=O(c.blurType,["gaussian","directional","radial","progressive"],s.effects.blurType),u.angle=L(c.angle,0,-180,180),u.focus=L(c.focus,.5,0,1);let g=2048;return{version:1,aspectRatio:O(a.aspectRatio,["original","16:9","9:16","1:1","4:3","3:4","21:9"],"original"),style:O(a.style,F,s.style),cellSize:L(a.cellSize,s.cellSize,E(String(a.style))||["pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(String(a.style))?1:3,60),charset:"string"==typeof a.charset&&a.charset.length?Array.from(a.charset).slice(0,128).join(""):s.charset,colorMode:O(a.colorMode,["accent","source","gray"],s.colorMode),ink:N(a.ink,s.ink),print:A(a.print),warps:w(a.warps),warpEdge:O(a.warpEdge,["clamp","transparent"],"clamp"),crop:{x:L(r.x,.5,0,1),y:L(r.y,.5,0,1),zoom:L(r.zoom,1,1,5),rotation:90*Math.round(L(r.rotation,0,-360,360)/90)},backdrop:{mode:O(n.mode,["solid","transparent","source","blurred","gradient"],s.backdrop.mode),color:N(n.color,s.backdrop.color),color2:N(n.color2,s.backdrop.color2),blur:L(n.blur,12,0,32),opacity:L(n.opacity,1,0,1)},color:{brightness:L(o.brightness,0,-1,1),contrast:L(o.contrast,1,0,3),saturation:L(o.saturation,1,0,3),grayscale:L(o.grayscale,0,0,1),tint:N(o.tint,s.color.tint),amount:L(o.amount,0,0,1),blend:O(o.blend,T,s.color.blend),blackPoint:L(o.blackPoint,0,0,.99),whitePoint:Math.max(L(o.blackPoint,0,0,.99)+1/255,L(o.whitePoint,1,1/255,1)),gamma:L(o.gamma,1,.25,4),shadows:L(o.shadows,0,-1,1),highlights:L(o.highlights,0,-1,1),curves:d(o.curves),denoise:L(o.denoise,0,0,1)},dither:{algorithm:O(h.algorithm,P,"none"),palette:"string"==typeof h.palette&&Object.prototype.hasOwnProperty.call(I,h.palette)?h.palette:"mono",colors:Array.isArray(h.colors)&&h.colors.length>=2?h.colors.slice(0,32).map(t=>N(t,"#000000")):[...s.dither.colors],amount:L(h.amount,1,0,2),scale:Math.round(L(h.scale,2,1,12)),threshold:L(h.threshold,.5,0,1),motion:O(h.motion,["none","drift","shimmer"],"none"),speed:L(h.speed,1,.1,3),direction:L(h.direction,45,-180,180),colorSpace:O(h.colorSpace,["rgb","luminance"],"rgb")},mask:{enabled:!0===l.enabled,invert:!0===l.invert,shapes:Array.isArray(l.shapes)?l.shapes.slice(0,64).map(t=>{const e=R(t),i=O(e.kind,["rectangle","ellipse","brush"],"rectangle"),a="brush"===i&&Array.isArray(e.points)?e.points.slice(0,g).map(t=>Array.isArray(t)?[Math.round(1e4*L(t[0],0,0,1))/1e4,Math.round(1e4*L(t[1],0,0,1))/1e4]:[0,0]):[];return g-=a.length,{kind:i,x:L(e.x,0,0,1),y:L(e.y,0,0,1),width:L(e.width,.5,0,1),height:L(e.height,.5,0,1),size:L(e.size,.05,.005,.5),points:a}}):[]},lights:Array.isArray(a.lights)?a.lights.slice(0,4).map(t=>{const e=R(t);return{x:L(e.x,.5,0,1),y:L(e.y,.5,0,1),radius:L(e.radius,.3,.02,1),intensity:L(e.intensity,.5,0,1),color:N(e.color,"#ffffff")}}):[],effects:u,motion:{type:O(m.type,e.map(t=>t.mode),"none"),speed:L(m.speed,1,.1,3),amount:L(m.amount,1,0,2)},hover:{effect:O(f.effect,t.map(t=>t.value),"trail"),strength:L(f.strength,.55,0,1),radius:L(f.radius,.2,.1,1),edgeSafe:!0===f.edgeSafe}}}function X(t){return JSON.stringify(D(t))}function U(t){if(t.length>1e5)throw new Error("Settings exceed 100 KB.");return D(JSON.parse(t))}function j(t,e,i,a,s){const r=Math.abs(s.rotation/90)%2==1,n=r?e:t,o=r?t:e,h=Math.max(i/n,a/o)*s.zoom;return{width:n*h,height:o*h,x:(i-n*h)*s.x,y:(a-o*h)*s.y,scale:h,rotated:r}}function q(t,e,i){if(Math.abs(i.crop.rotation/90)%2==1&&([t,e]=[e,t]),"original"===i.aspectRatio)return[t,e];const[a,s]=i.aspectRatio.split(":").map(Number);return t/e>a/s?[Math.round(e*a/s),e]:[t,Math.round(t*s/a)]}function B(t,e){const i={...t,...e};for(const a of["crop","backdrop","color","dither","mask","effects","motion","hover","print"])e[a]&&Object.assign(i,{[a]:{...t[a],...e[a]}});return e.color?.curves&&(i.color.curves={...t.color.curves,...e.color.curves}),D(i)}function Y(t,e,i,a=12e3,s=1){const r=Math.max(2,Number.isFinite(t)?t:960),n=Math.max(2,Number.isFinite(e)?e:540),o=Math.max(1,Math.floor(Number.isFinite(a)?a:12e3)),h=Math.max(.01,Number.isFinite(s)?s:1),l=E(i.style)||["dither","pixel","mosaic","lego","voxel","disco","dots","hex","led","cmyk"].includes(i.style)?1:1.65;let c=Math.max(1,Math.ceil(Math.sqrt(r*n/(o*l))/h));for(;Math.ceil(r/(c*h))*Math.ceil(n/(c*h*l))>o;)c++;const d="dither"===i.style?i.dither.scale:i.cellSize,m=Math.max(c,d)*h;return{cell:m,rowHeight:m*l,columns:Math.ceil(r/m),rows:Math.ceil(n/(m*l)),minimum:c,limited:d<c}}var z=[["ascii","Signature ASCII","Brand ink and clean characters.",{}],["print","Newsprint","Fine diffusion on warm paper.",{style:"dither",dither:{algorithm:"floyd-steinberg",palette:"newsprint"}}],["handheld","Pocket camera","Four-tone ordered dither.",{style:"dither",dither:{algorithm:"bayer4",palette:"gameboy",scale:3}}],["riso","Two inks","Limited-color print texture.",{style:"dither",dither:{algorithm:"atkinson",palette:"risograph",scale:2}}],["night","Night signal","Gray characters and optical fringe.",{ink:"#888888",effects:{prism:.7,scanlines:.2,vignette:.3}}],["terminal","Phosphor","Green glyphs with a soft glow.",{ink:"#83efad",effects:{bloom:.4,scanlines:.35,crt:.2}}],["mosaic","Mosaic study","Separated color tiles.",{style:"mosaic",cellSize:14,colorMode:"source"}],["bricks","Brickwork","Colorful studded cells.",{style:"lego",cellSize:18,colorMode:"source"}],["voxel","Little volumes","Three-face isometric tiles.",{style:"voxel",cellSize:22,colorMode:"source"}],["disco","Mirror room","Faceted tiles and warm light.",{style:"disco",cellSize:18,colorMode:"source",lights:[{x:.35,y:.25,radius:.25,intensity:.45,color:"#fff2d4"}]}],["wallpaper","Wallpaper","Living ASCII over a softened source.",{backdrop:{mode:"blurred",blur:18,opacity:.55},ink:"#f2e9c9",motion:{type:"caustics",speed:.5}}],["blueprint","Blueprint","Linework in a cool monochrome.",{style:"lines",ink:"#9bccdf",backdrop:{mode:"solid",color:"#0a1e30"}}]].map(([t,e,i,a])=>({id:t,name:e,description:i,settings:D(a)}));function W(t){const e=z.find(e=>e.id===t);if(!e)throw new Error("Unknown studio look.");return D(e.settings)}function G(t,e=Math.random){const i=z.filter(e=>e.settings.style!==t.style||e.settings.ink!==t.ink),a=W(i[Math.min(i.length-1,Math.max(0,Math.floor(e()*i.length)))].id);return a.aspectRatio=t.aspectRatio,a.crop={...t.crop},a.mask=D(t).mask,a}function V(t){const e=function(t){const e=t.blackPoint??0,i=t.whitePoint??1,a=t.gamma??1,s=t.shadows??0,r=t.highlights??0;if(0===e&&1===i&&1===a&&0===s&&0===r)return null;const n=[0,.25+.2*s,.5,.75+.2*r,1],o=n.slice(1).map((t,e)=>4*(t-n[e])),h=[o[0],...o.slice(1).map((t,e)=>2*t*o[e]/(t+o[e])),o[3]],l=new Uint8Array(256);for(let t=0;t<256;t++){const s=Math.pow(Math.max(0,Math.min(1,(t/255-e)/(i-e))),1/a),r=Math.min(3,Math.floor(4*s)),o=4*s-r,c=o*o,d=c*o,m=(2*d-3*c+1)*n[r]+(d-2*c+o)*h[r]/4+(-2*d+3*c)*n[r+1]+(d-c)*h[r+1]/4;l[t]=Math.round(255*Math.max(0,Math.min(1,m)))}return l}(t),i=t.curves;if(!e&&(!i||Object.values(i).every(t=>t.every(([t,e])=>t===e))))return null;const a=m(i?.rgb),s=[i?.red,i?.green,i?.blue].map(m),r=new Uint8Array(768);for(let t=0;t<256;t++)for(let i=0;i<3;i++)r[256*i+t]=s[i][a[e?e[t]:t]];return r}var H=class{constructor(t=0){this.amount=0,this.weights=new Float32Array(256),this.source=new Uint8ClampedArray(0),this.configure(t)}configure(t=0){const e=Math.max(0,Math.min(1,Number.isFinite(t)?t:0));if(e===this.amount)return;if(this.amount=e,0===e)return void(this.source=new Uint8ClampedArray(0));const i=8+24*e;for(let t=0;t<256;t++)this.weights[t]=Math.exp(-t*t/(2*i*i))}apply(t,e,i){if(!this.amount)return;if(!Number.isInteger(e)||!Number.isInteger(i)||e<1||i<1||e*i*4!==t.length)throw new Error("Denoise dimensions do not match the source.");this.source.length!==t.length&&(this.source=new Uint8ClampedArray(t.length));const a=this.source;a.set(t);for(let s=0;s<i;s++)for(let r=0;r<e;r++){const n=4*(s*e+r);if(!a[n+3])continue;const o=a[n],h=a[n+1],l=a[n+2];let c=0,d=0,m=0,f=0;for(let t=-1;t<=1;t++){const n=s+t;if(!(n<0||n>=i))for(let i=-1;i<=1;i++){const s=r+i;if(s<0||s>=e)continue;const u=4*(n*e+s);if(!a[u+3])continue;const g=Math.max(Math.abs(a[u]-o),Math.abs(a[u+1]-h),Math.abs(a[u+2]-l)),p=this.weights[g]*(0===i?1:.6)*(0===t?1:.6)*a[u+3];c+=a[u]*p,d+=a[u+1]*p,m+=a[u+2]*p,f+=p}}t[n]=o+(c/f-o)*this.amount,t[n+1]=h+(d/f-h)*this.amount,t[n+2]=l+(m/f-l)*this.amount}}},J=2*Math.PI,Q=t=>Math.max(0,Math.min(1,t)),K=Float32Array.from({length:2048},(t,e)=>Math.sin(e/2048*J)),Z=t=>K[2047&Math.floor(t*(2048/J))];function $(t,e,i){let a=Math.imul(t,374761393)^Math.imul(e,668265263)^Math.imul(i,1442695041);return a=Math.imul(a^a>>>13,1274126177),((a^a>>>16)>>>0)/4294967296}function _(t){const e=A(t),{density:i,weight:a,angle:s,roughness:r,invert:n,secondaryInk:o,registration:h,seed:l}=e,c=s*Math.PI/180,d=[c,c+Math.PI/2,c+Math.PI/4].map(t=>[Math.cos(t),Math.sin(t)]),m=new Float32Array(6);function f(t,e,i,s,n,o,h,c,f=!1){if(h<=0)return;const[u,g]=d[c],p=-g,M=u,w=p*(e+.5)+M*(i+.5),v=.5*(Math.abs(p)+Math.abs(M)),b=f?1:.5,y=Math.ceil((w-v)/b),x=Math.floor((w+v)/b),k=Math.min(.94*b,.72*b*h*a);t.lineWidth=o*k,t.beginPath();for(let a=y;a<=x;a++){const h=a*b-w,c=.5+p*h,d=.5+M*h;let v=-2,y=2;if(Math.abs(u)>1e-8){const t=-c/u,e=(1-c)/u;v=Math.max(v,Math.min(t,e)),y=Math.min(y,Math.max(t,e))}else if(c<0||c>1)continue;if(Math.abs(g)>1e-8){const t=-d/g,e=(1-d)/g;v=Math.max(v,Math.min(t,e)),y=Math.min(y,Math.max(t,e))}else if(d<0||d>1)continue;if(!(y<=v))if(f){for(let t=0;t<6;t++){const s=v+(y-v)*t/5,r=u*(e+c+u*s)+g*(i+d+g*s);m[t]=.5*Z(5.3*r+1.9*a+l)+.25*Z(13.1*r+a)}for(let e=0;e<2;e++)for(let i=0;i<6;i++){const a=v+(y-v)*(e?5-i:i)/5,h=m[e?5-i:i],l=.5*k*(1+r*h*.5)*(e?-1:1),f=s+Q(c+u*a+p*l)*o,w=n+Q(d+g*a+M*l)*o;e||i?t.lineTo(f,w):t.moveTo(f,w)}t.closePath()}else t.moveTo(s+(c+u*v)*o,n+(d+g*v)*o),t.lineTo(s+(c+u*y)*o,n+(d+g*y)*o)}f?t.fill():t.stroke()}return{settings:e,paint(t,e,s,c,m,u,g,p,M,w,v,b,y){const x=Q((n?1-p:p)*i);if(x<=0||t.globalAlpha<=0)return;t.fillStyle=M,t.strokeStyle=M;const k=$(s,c,l);if("engraving"===e||"crosshatch"===e||"woodblock"===e){const i=x*(1-r*k*.3);"woodblock"===e?f(t,s,c,m,u,g,Math.ceil(5*i)/5,0,!0):(f(t,s,c,m,u,g,i,0),"crosshatch"===e&&(f(t,s,c,m,u,g,Math.max(0,1.5*i-.3),1),f(t,s,c,m,u,g,Math.max(0,2*i-1.2),2)))}else if("risograph"===e){const e="source"===y?Q(.5+(w-b)/510):.5,i=.38*h*g,n=g*Math.min(.48,.44*Math.sqrt(x)*a);t.beginPath(),t.arc(m+.5*g,u+.5*g,n*Math.sqrt(.35+.65*(1-e)),0,J),t.fill(),t.globalCompositeOperation="multiply",t.fillStyle=o;const f=1-r*$(s,c,l+13)*.3;t.beginPath(),t.arc(m+.5*g+i*d[0][0],u+.5*g+i*d[0][1],n*Math.sqrt(.3+.7*e)*f,0,J),t.fill(),t.globalCompositeOperation="source-over"}else{"stipple"===e&&t.beginPath();for(let i=0;i<4;i++){const n=$(2*s+i%2,2*c+(i>>1),l),o=$(s,c,l+11*i+1),h=m+((i%2+.5)/2+(n-.5)*r*.28)*g,d=u+((.5+(i>>1))/2+(o-.5)*r*.28)*g,f=Math.min(h-m,m+g-h,d-u,u+g-d,g*Math.min(.245,.21*a*Math.sqrt(x)*(1-r*n*.35)));if("stipple"===e)t.moveTo(h+f,d),t.arc(h,d,f,0,J);else{const e=(n-.5)*r*64;t.fillStyle="source"===y?`rgb(${Math.round(w+e)},${Math.round(v-.4*e)},${Math.round(b-e)})`:"gray"===y?`rgb(${Math.round(w+e)},${Math.round(w+e)},${Math.round(w+e)})`:M,t.beginPath(),t.ellipse(h,d,f,.64*f,n*Math.PI,0,J),t.fill()}}"stipple"===e&&t.fill()}}}}var tt=new Set(["none","floyd-steinberg","atkinson","stucki","sierra","sierra-lite","burkes","jarvis"]);function et(t){return"dither"===t.style&&("shimmer"===t.dither.motion||"drift"===t.dither.motion&&t.dither.amount>0&&!tt.has(t.dither.algorithm))}function it(t){return"none"!==t.motion.type&&(t.motion.amount??1)>0}function at(t){return it(t)||et(t)||t.effects.grain>0||t.effects.dust>0||t.effects.glitch>0}var st="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",rt="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",nt=new Uint16Array(4096);for(let t=0;t<nt.length;t++)nt[t]=st.indexOf(rt[2*t])<<6|st.indexOf(rt[2*t+1]);var ot=(t,e)=>{const i=43758.5453*Math.sin(127.1*t+311.7*e);return i-Math.floor(i)};var ht=new Map([2,4,8,16].map(t=>[t,Float64Array.from({length:t*t},(e,i)=>function(t,e,i){let a=0;for(let s=1;s<i;s*=2){const i=(Math.floor(t/s)%2+2)%2;a=4*a+[[0,2],[3,1]][(Math.floor(e/s)%2+2)%2][i]}return(a+.5)/(i*i)-.5}(i%t,Math.floor(i/t),t))])),lt={"floyd-steinberg":[[1,0,7/16],[-1,1,3/16],[0,1,5/16],[1,1,1/16]],atkinson:[[1,0,.125],[2,0,.125],[-1,1,.125],[0,1,.125],[1,1,.125],[0,2,.125]],stucki:[[1,0,8/42],[2,0,4/42],[-2,1,2/42],[-1,1,4/42],[0,1,8/42],[1,1,4/42],[2,1,2/42],[-2,2,1/42],[-1,2,2/42],[0,2,4/42],[1,2,2/42],[2,2,1/42]],sierra:[[1,0,5/32],[2,0,3/32],[-2,1,2/32],[-1,1,4/32],[0,1,5/32],[1,1,4/32],[2,1,2/32],[-1,2,2/32],[0,2,3/32],[1,2,2/32]],"sierra-lite":[[1,0,.5],[-1,1,.25],[0,1,.25]],burkes:[[1,0,.25],[2,0,4/32],[-2,1,2/32],[-1,1,4/32],[0,1,.25],[1,1,4/32],[2,1,2/32]],jarvis:[[1,0,7/48],[2,0,5/48],[-2,1,3/48],[-1,1,5/48],[0,1,7/48],[1,1,5/48],[2,1,3/48],[-2,2,1/48],[-1,2,3/48],[0,2,5/48],[1,2,3/48],[2,2,1/48]]},ct=t=>[parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16)];function dt(t,e,i){const a=Math.min(t*Math.max(1,i),(1-t)*Math.max(1,i),e*Math.max(1,1/i),(1-e)*Math.max(1,1/i)),s=Math.max(0,Math.min(1,(a-.035)/.105));return s*s*s*(s*(6*s-15)+10)}var mt=t=>["dissolve","silk","vortex","magnetic","scatter","etch","elastic","rake"].includes(t),ft=class{constructor(t,e){this.edgeSafe=!1,this.previous=null,this.peak=0,this.scatterDirections=null,this.springX=null,this.springY=null,this.mode="dissolve",this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.ink=new Float32Array(i),this.targetX=new Float32Array(i),this.targetY=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.edge=new Float32Array(i);for(let i=0;i<e;i++)for(let a=0;a<t;a++)this.edge[i*t+a]=dt(a/(t-1),i/(e-1),t/e);this.clear()}get active(){return this.peak>2e-4}setMode(t){if("elastic"!==t||this.springX||(this.springX=new Float32Array(this.ink.length),this.springY=new Float32Array(this.ink.length)),"scatter"===t&&!this.scatterDirections){const t=this.scatterDirections=new Float64Array(this.width*this.height*2);for(let e=0;e<this.height;e++)for(let i=0;i<this.width;i++){const a=43758.5453*Math.sin(127.1*i+311.7*e),s=(a-Math.floor(a))*Math.PI*2,r=2*(e*this.width+i);t[r]=.7*Math.cos(s),t[r+1]=.7*Math.sin(s)}}t!==this.mode&&(this.mode=t,this.clear())}clear(){for(const t of[this.ink,this.targetX,this.targetY,this.offsetX,this.offsetY,this.pixels])t.fill(0);if(this.previous=null,this.peak=0,this.springX?.fill(0),this.springY?.fill(0),"dissolve"!==this.mode)for(let t=0;t<this.pixels.length;t+=4)this.pixels[t]=this.pixels[t+2]=128}leave(){this.previous=null}move(t,e,i){if(!Number.isFinite(t+e+i))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e));const a=this.previous;this.previous={x:t,y:e};const s=this.width,r=this.height,n=Math.max(1,s/r),o=Math.max(1,r/s),h=a?(t-a.x)*n:0,l=a?(e-a.y)*o:0,c=Math.hypot(h,l);if(!a&&"dissolve"!==this.mode&&"etch"!==this.mode)return;if(a&&c<1e-4)return;const d=.035+.11*Math.max(.1,Math.min(1,i)),m=Math.min(128,Math.max(1,Math.ceil(c/(.45*d)))),f=c?h/c:1,u=c?l/c:0,g=Math.min(1,c/(d*m)*2.2);for(let i=0;i<m;i++){const h=(i+.5)/m,l=a?a.x+(t-a.x)*h:t,c=a?a.y+(e-a.y)*h:e,p=Math.max(0,Math.floor((l-2.5*d/n)*(s-1))),M=Math.min(s-1,Math.ceil((l+2.5*d/n)*(s-1))),w=Math.max(0,Math.floor((c-2.5*d/o)*(r-1))),v=Math.min(r-1,Math.ceil((c+2.5*d/o)*(r-1)));for(let t=w;t<=v;t++)for(let e=p;e<=M;e++){const i=(e/(s-1)-l)*n/d,a=(t/(r-1)-c)*o/d,h=Math.exp(1.5*-(i*i+a*a)),m=t*s+e;if("dissolve"===this.mode||"etch"===this.mode)this.ink[m]=Math.max(this.ink[m],h);else if("elastic"===this.mode)this.springX[m]=Math.max(-24,Math.min(24,this.springX[m]+f*h*g*8)),this.springY[m]=Math.max(-24,Math.min(24,this.springY[m]+u*h*g*8));else{const s=(-i*u+a*f)*h*2.8,r="rake"===this.mode?f*Math.sin(t*Math.PI/3)*h*2:"magnetic"===this.mode?-i*h*2.5:"scatter"===this.mode?(i+this.scatterDirections[2*m])*h*2:"silk"===this.mode?f*s:-a*h*2.5,n="rake"===this.mode?u*Math.sin(e*Math.PI/3)*h*2:"magnetic"===this.mode?-a*h*2.5:"scatter"===this.mode?(a+this.scatterDirections[2*m+1])*h*2:"silk"===this.mode?u*s:i*h*2.5;this.targetX[m]=Math.max(-1,Math.min(1,this.targetX[m]+r*g)),this.targetY[m]=Math.max(-1,Math.min(1,this.targetY[m]+n*g))}}}this.peak=1}step(t){if(!this.active||!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t)),i=Math.exp(-("dissolve"===this.mode?2.15:3.2)*e),a=1-Math.exp(-22*e);let s=0;const r=Math.sqrt(336),n=Math.exp(-8*e),o=Math.cos(r*e),h=Math.sin(r*e)/r;for(let t=0;t<this.ink.length;t++)if("etch"===this.mode)this.ink[t]*=i,s=Math.max(s,this.ink[t]);else if("dissolve"===this.mode){this.ink[t]*=i,s=Math.max(s,this.ink[t]);const e=Math.round(65535*this.ink[t]);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e}else{if("elastic"===this.mode){const e=this.offsetX[t],i=this.offsetY[t],a=this.springX[t],r=this.springY[t];this.offsetX[t]=Math.max(-1,Math.min(1,n*(e*o+(a+8*e)*h))),this.offsetY[t]=Math.max(-1,Math.min(1,n*(i*o+(r+8*i)*h))),this.springX[t]=n*(a*o-(8*a+400*e)*h),this.springY[t]=n*(r*o-(8*r+400*i)*h),s=Math.max(s,.05*Math.abs(this.springX[t]),.05*Math.abs(this.springY[t]))}else this.targetX[t]*=i,this.targetY[t]*=i,this.offsetX[t]+=(this.targetX[t]-this.offsetX[t])*a,this.offsetY[t]+=(this.targetY[t]-this.offsetY[t])*a;s=Math.max(s,Math.abs(this.offsetX[t]),Math.abs(this.offsetY[t]),Math.abs(this.targetX[t]),Math.abs(this.targetY[t]));const e=Math.round(this.offsetX[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768),r=Math.round(this.offsetY[t]*(this.edgeSafe?this.edge[t]:1)*32767+32768);this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=r>>>8,this.pixels[4*t+3]=255&r}if("etch"===this.mode)for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const i=t*this.width+e,a=3*(this.ink[t*this.width+Math.max(0,e-1)]-this.ink[t*this.width+Math.min(this.width-1,e+1)]+this.ink[Math.max(0,t-1)*this.width+e]-this.ink[Math.min(this.height-1,t+1)*this.width+e]);this.offsetX[i]=Math.max(-1,Math.min(1,a))*(this.edgeSafe?this.edge[i]:1);const s=Math.round(32767*this.offsetX[i]+32768);this.pixels[4*i]=s>>>8,this.pixels[4*i+1]=255&s}this.peak=s,this.active||this.clear()}sample(t,e,i){const a=Math.max(0,Math.min(this.width-1.001,t*(this.width-1))),s=Math.max(0,Math.min(this.height-1.001,e*(this.height-1))),r=Math.floor(a),n=Math.floor(s),o=a-r,h=s-n,l=n*this.width+r,c=l+this.width,d=t=>(t[l]*(1-o)+t[l+1]*o)*(1-h)+(t[c]*(1-o)+t[c+1]*o)*h;if("etch"===this.mode)return i[0]=i[1]=0,void(i[2]=3*d(this.offsetX));i[0]=d(this.offsetX)*(this.edgeSafe?dt(t,e,this.width/this.height):1)*.08,i[1]=d(this.offsetY)*(this.edgeSafe?dt(t,e,this.width/this.height):1)*.08,i[2]="dissolve"===this.mode?6*-d(this.ink):0}},ut=class{constructor(t,e){this.rings=[],this.previous=null,this.elapsed=1,this.echoPeak=0,this.width=t,this.height=e,this.pixels=new Uint8Array(t*e*4),this.echo=new Float32Array(t*e)}get active(){return this.rings.length>0||this.echoPeak>2e-4}clear(){this.rings=[],this.previous=null,this.elapsed=1,this.pixels.fill(0),this.echo.fill(0),this.echoPeak=0}leave(){this.previous=null}move(t,e,i){const a=Math.max(1,this.width/this.height),s=Math.max(1,this.height/this.width);this.previous&&(Math.hypot((t-this.previous.x)*a,(e-this.previous.y)*s)<.065||this.elapsed<.3)||4!==this.rings.length&&(this.previous={x:t,y:e},this.elapsed=0,this.rings.push({x:t,y:e,age:0,radius:i}))}ringSample(t,e){const i=Math.max(1,this.width/this.height),a=Math.max(1,this.height/this.width);let s=0;for(const r of this.rings){const n=.015+r.age*(.15+.22*r.radius),o=.009+.014*r.radius,h=(Math.hypot((t-r.x)*i,(e-r.y)*a)-n)/o,l=Math.sin(Math.min(1,r.age/.07)*Math.PI/2)*Math.max(0,1-r.age/1.35)**2;s=Math.max(s,Math.exp(-h*h)*l)}return s}sample(t,e){const i=Math.max(0,Math.min(this.width-1,Math.round(t*(this.width-1)))),a=Math.max(0,Math.min(this.height-1,Math.round(e*(this.height-1))));return Math.max(this.ringSample(t,e),this.echo[a*this.width+i])}step(t){if(!Number.isFinite(t))return;const e=Math.max(0,Math.min(.05,t));this.elapsed+=e;for(const t of this.rings)t.age+=e;if(this.rings=this.rings.filter(t=>t.age<1.35),!this.active)return void this.pixels.fill(0);const i=Math.exp(-5.5*e);let a=0;for(let t=0;t<this.height;t++)for(let e=0;e<this.width;e++){const s=t*this.width+e;this.echo[s]=Math.max(this.ringSample(e/(this.width-1),t/(this.height-1)),this.echo[s]*i),a=Math.max(a,this.echo[s]);const r=Math.round(65535*this.echo[s]),n=4*s;this.pixels[n]=r>>>8,this.pixels[n+1]=255&r}this.echoPeak=a,this.active||(this.echo.fill(0),this.pixels.fill(0))}},gt=class{constructor(t,e){this.previous=null,this.peak=0,this.width=t,this.height=e;const i=t*e;this.pixels=new Uint8Array(4*i),this.signal=new Float32Array(i),this.offsetX=new Float32Array(i),this.offsetY=new Float32Array(i),this.driftX=new Float32Array(i),this.driftY=new Float32Array(i),this.u=new Float32Array(i),this.v=new Float32Array(i),this.ink=new Float32Array(i),this.a=new Float32Array(i),this.b=new Float32Array(i),this.c=new Float32Array(i),this.pressure=new Float32Array(i),this.pressureNext=new Float32Array(i),this.divergence=new Float32Array(i),this.curl=new Float32Array(i)}get active(){return this.peak>2e-4}clear(){for(const t of[this.u,this.v,this.ink,this.a,this.b,this.c,this.pressure,this.pressureNext,this.divergence,this.curl,this.signal,this.pixels,this.offsetX,this.offsetY,this.driftX,this.driftY])t.fill(0);this.previous=null,this.peak=0}leave(){this.previous=null}move(t,e,i,a=performance.now()){if(!Number.isFinite(t+e+i+a))return;t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),i=Math.max(.1,Math.min(1,i));const s=this.previous;if(this.previous={x:t,y:e,time:a},!s)return;const r=(t-s.x)*(this.width-1),n=(e-s.y)*(this.height-1),o=Math.hypot(r,n);if(o<.001)return;const h=Math.min(this.width,this.height),l=a>s.time?Math.max(1/240,(a-s.time)/1e3):1/60,c=Math.min(12,o/h/l),d=1-Math.exp(-c/2.2),m=h*(.022+.075*i)*(.65+.95*d),f=Math.min(128,Math.max(1,Math.ceil(o/(.4*m)))),u=o/m*(.32+.22*d)/f,g=r/o,p=n/o,M=-p,w=g,v=o*(2+18*d)/f;for(let i=0;i<f;i++){const a=(i+.5)/f,r=(s.x+(t-s.x)*a)*(this.width-1),n=(s.y+(e-s.y)*a)*(this.height-1),o=Math.max(1,Math.floor(r-3*m)),h=Math.min(this.width-2,Math.ceil(r+3*m)),l=Math.max(1,Math.floor(n-3*m)),c=Math.min(this.height-2,Math.ceil(n+3*m));for(let t=l;t<=c;t++)for(let e=o;e<=h;e++){const i=((e-r)*g+(t-n)*p)/m,a=((e-r)*M+(t-n)*w)/m,s=Math.exp(-i*i*.65-a*a*1.7),o=t*this.width+e;this.ink[o]=1-(1-this.ink[o])*Math.exp(-s*u);const h=1-a*a*.55,l=i*a*.7;this.u[o]=Math.max(-80,Math.min(80,this.u[o]+(g*h+M*l)*s*v)),this.v[o]=Math.max(-80,Math.min(80,this.v[o]+(p*h+w*l)*s*v))}}this.peak=1}read(t,e,i){const a=0|(e=Math.max(.5,Math.min(this.width-1.5,e))),s=0|(i=Math.max(.5,Math.min(this.height-1.5,i))),r=e-a,n=i-s,o=s*this.width+a;return(t[o]*(1-r)+t[o+1]*r)*(1-n)+(t[o+this.width]*(1-r)+t[o+this.width+1]*r)*n}sample(t,e){return this.read(this.signal,t*(this.width-1),e*(this.height-1))}displacement(t,e,i){i[0]=this.read(this.offsetX,t*(this.width-1),e*(this.height-1)),i[1]=this.read(this.offsetY,t*(this.width-1),e*(this.height-1))}step(t){if(!this.active||!Number.isFinite(t))return;let e=Math.max(0,Math.min(.05,t));const i=this.width,a=this.height;for(;e>1e-7;){const t=Math.min(1/60,e);e-=t;const s=Math.exp(-1.9*t),r=Math.exp(-3.2*t);for(let e=1;e<a-1;e++)for(let n=1;n<i-1;n++){const o=e*i+n,h=Math.max(.5,Math.min(i-1.5,n-this.u[o]*t)),l=Math.max(.5,Math.min(a-1.5,e-this.v[o]*t)),c=0|h,d=0|l,m=h-c,f=l-d,u=d*i+c,g=(1-m)*(1-f),p=m*(1-f),M=(1-m)*f,w=m*f;this.a[o]=(this.u[u]*g+this.u[u+1]*p+this.u[u+i]*M+this.u[u+i+1]*w)*s,this.b[o]=(this.v[u]*g+this.v[u+1]*p+this.v[u+i]*M+this.v[u+i+1]*w)*s,this.c[o]=(this.ink[u]*g+this.ink[u+1]*p+this.ink[u+i]*M+this.ink[u+i+1]*w)*r}[this.u,this.a]=[this.a,this.u],[this.v,this.b]=[this.b,this.v],[this.ink,this.c]=[this.c,this.ink];for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.curl[a]=.5*(this.v[a+1]-this.v[a-1]-this.u[a+i]+this.u[a-i])}for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a,r=Math.abs(this.curl[s+1])-Math.abs(this.curl[s-1]),n=Math.abs(this.curl[s+i])-Math.abs(this.curl[s-i]),o=Math.hypot(r,n)+1e-4,h=this.curl[s]*t*10,l=Math.hypot(this.u[s],this.v[s]);this.u[s]+=n/o*h,this.v[s]-=r/o*h;const c=Math.min(1,l/(Math.hypot(this.u[s],this.v[s])+1e-6));this.u[s]*=c,this.v[s]*=c,this.divergence[s]=-.5*(this.u[s+1]-this.u[s-1]+this.v[s+i]-this.v[s-i])}this.pressure.fill(0);for(let t=0;t<4;t++){for(let t=1;t<a-1;t++)for(let e=1;e<i-1;e++){const a=t*i+e;this.pressureNext[a]=.25*(this.divergence[a]+this.pressure[a-1]+this.pressure[a+1]+this.pressure[a-i]+this.pressure[a+i])}[this.pressure,this.pressureNext]=[this.pressureNext,this.pressure]}let n=0;for(let e=1;e<a-1;e++)for(let a=1;a<i-1;a++){const s=e*i+a;this.u[s]=Math.max(-80,Math.min(80,this.u[s]-.5*(this.pressure[s+1]-this.pressure[s-1]))),this.v[s]=Math.max(-80,Math.min(80,this.v[s]-.5*(this.pressure[s+i]-this.pressure[s-i]))),this.driftX[s]+=(3.6*this.u[s]-58*this.offsetX[s]-12*this.driftX[s])*t,this.driftY[s]+=(3.6*this.v[s]-58*this.offsetY[s]-12*this.driftY[s])*t,this.offsetX[s]=Math.max(-2,Math.min(2,this.offsetX[s]+this.driftX[s]*t)),this.offsetY[s]=Math.max(-2,Math.min(2,this.offsetY[s]+this.driftY[s]*t)),this.signal[s]=1-Math.exp(.06*-Math.hypot(this.u[s],this.v[s])-.16*this.ink[s]),n=Math.max(n,this.signal[s])}this.peak=n}if(this.active)for(let t=0;t<this.ink.length;t++){const e=Math.round(65535*Math.min(1,this.signal[t]));this.pixels[4*t]=e>>>8,this.pixels[4*t+1]=255&e,this.pixels[4*t+2]=Math.round(128+63.5*this.offsetX[t]),this.pixels[4*t+3]=Math.round(128+63.5*this.offsetY[t])}else this.clear()}};function pt(t,e){const i=Math.max(0,Math.min(1,e/.38));return t+(1-2*t)*(i*i*(3-2*i))}var Mt=(t,e)=>"water"===t?30*e/.55:"silk"===t?28*e:"vortex"===t?38*e:["magnetic","scatter","elastic","rake"].includes(t)?32*e:0,wt=class{constructor(t=1){this.mode="water",this.amount=.55,this.radius=.2,this.lensX=.5,this.lensY=.5,this.lensStrength=0,this.previous=null,this.energy=0,this.pending=!1,this.remainder=0,t=Math.max(.25,Math.min(4,t)),this.columns=Math.round(t>=1?128:128*t),this.rows=Math.round(t>=1?128/t:128),this.xScale=Math.max(1,t),this.yScale=Math.max(1,1/t),this.heights=new Float32Array(this.columns*this.rows),this.velocity=new Float32Array(this.heights.length),this.next=new Float32Array(this.heights.length),this.normals=new Float32Array(2*this.heights.length),this.edgeMask=new Float32Array(this.heights.length);for(let e=0;e<this.rows;e++)for(let i=0;i<this.columns;i++)this.edgeMask[e*this.columns+i]=dt(i/(this.columns-1),e/(this.rows-1),t);this.refraction={width:this.columns,height:this.rows,pixels:new Uint8Array(4*this.heights.length),strength:30,mode:"water",focus:[.5,.5,0,.2]},this.waterPixels=this.refraction.pixels,this.trail=new gt(this.columns,this.rows),this.contour=new ut(this.columns,this.rows),this.afterimage=new ft(this.columns,this.rows),this.clear()}get invertsDensity(){return"trail"===this.mode}get densityTrail(){return["trail","contour","dissolve","etch"].includes(this.mode)}get hasRefraction(){return this.active||this.lensStrength>15e-5}get active(){return mt(this.mode)?this.afterimage.active:"contour"===this.mode?this.contour.active:"trail"===this.mode?this.trail.active:this.pending||this.energy>15e-5}setMode(t){t!==this.mode&&(this.clear(),this.mode=t,this.refraction.mode=t,mt(t)&&this.afterimage.setMode(t),this.refraction.pixels="trail"===t?this.trail.pixels:"contour"===t?this.contour.pixels:mt(t)?this.afterimage.pixels:this.waterPixels,this.refraction.strength=Mt(t,this.amount))}configure(t,e=.55,i=.2,a=!1){this.setMode(t),this.refraction.edgeSafe=a,this.afterimage.edgeSafe=a,this.amount=Number.isFinite(e)?Math.max(0,Math.min(1,e)):.55,this.radius=Number.isFinite(i)?Math.max(.1,Math.min(1,i)):.2,this.refraction.strength=Mt(t,this.amount),this.refraction.focus[2]=this.densityTrail?this.amount:this.lensStrength*this.amount,this.refraction.focus[3]=this.radius}move(t,e,i){if("none"===this.mode||0===this.amount)return;if(!Number.isFinite(t+e))return;if(t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),mt(this.mode))return void this.afterimage.move(t,e,this.radius);if("contour"===this.mode)return void this.contour.move(t,e,this.radius);if("trail"===this.mode)return void this.trail.move(t,e,this.radius,i);if("water"!==this.mode)return!this.previous&&this.lensStrength<.001&&(this.lensX=t,this.lensY=e),this.previous={x:t,y:e},void(this.pending=!0);if(!this.previous)return void(this.previous={x:t,y:e});const a=this.previous;this.previous={x:t,y:e};const s=(t-a.x)*this.xScale,r=(e-a.y)*this.yScale,n=Math.hypot(s,r);if(n<1e-5)return;const o=.035+.1*this.radius,h=3*o,l=Math.min(192,Math.max(1,Math.ceil(n/(.5*o)))),c=95*Math.min(n,1)/l;for(let i=0;i<l;i++){const s=(i+.5)/l,r=a.x+(t-a.x)*s,n=a.y+(e-a.y)*s,d=Math.max(1,Math.floor((r-h/this.xScale)*(this.columns-1))),m=Math.min(this.columns-2,Math.ceil((r+h/this.xScale)*(this.columns-1))),f=Math.max(1,Math.floor((n-h/this.yScale)*(this.rows-1))),u=Math.min(this.rows-2,Math.ceil((n+h/this.yScale)*(this.rows-1)));for(let t=f;t<=u;t++)for(let e=d;e<=m;e++){const i=(e/(this.columns-1)-r)*this.xScale,a=(t/(this.rows-1)-n)*this.yScale,s=Math.exp(-(i*i+a*a)/(o*o))*c,h=t*this.columns+e;this.velocity[h]=Math.max(-12,this.velocity[h]-s)}}this.pending=!0}leave(){this.afterimage.leave(),this.contour.leave(),this.trail.leave(),this.previous=null,"water"!==this.mode&&this.lensStrength&&(this.pending=!0)}clear(){this.trail.clear(),this.contour.clear(),this.afterimage.clear(),this.heights.fill(0),this.velocity.fill(0),this.next.fill(0),this.normals.fill(0),this.refraction.focus[2]=0,this.previous=null,this.lensStrength=0,this.energy=0,this.pending=!1,this.remainder=0;for(let t=0;t<this.waterPixels.length;t+=4)this.waterPixels[t]=this.waterPixels[t+2]=128,this.waterPixels[t+1]=this.waterPixels[t+3]=0}step(t){if(!this.active||!Number.isFinite(t))return;if(mt(this.mode))return void this.afterimage.step(t);if("contour"===this.mode)return void this.contour.step(t);if("trail"===this.mode)return void this.trail.step(t);if("water"!==this.mode)return void this.stepLight(Math.max(0,Math.min(.05,t)));this.remainder+=Math.max(0,Math.min(.05,t));const e=1/120,i=Math.exp(-3.8*e),a=.3*Math.min(this.columns,this.rows);for(;this.remainder+1e-8>=e;){this.remainder-=e;let t=0;for(let s=1;s<this.rows-1;s++)for(let r=1;r<this.columns-1;r++){const n=s*this.columns+r,o=this.heights[n],h=this.heights[n-1]+this.heights[n+1]+this.heights[n-this.columns]+this.heights[n+this.columns]-4*o,l=Math.min(r,s,this.columns-1-r,this.rows-1-s),c=l<5?.88+.024*l:1,d=(this.velocity[n]+(h*a*a-8*o)*e)*i*c;this.velocity[n]=d,this.next[n]=(o+d*e)*c,t=Math.max(t,Math.abs(this.next[n]),.1*Math.abs(d))}this.heights.set(this.next),this.energy=t,this.pending=!1}if(!this.active)return void this.clear();const s=.18*Math.min(this.columns,this.rows);for(let t=0;t<this.rows;t++)for(let e=0;e<this.columns;e++){const i=t*this.columns+e,a=(this.heights[t*this.columns+Math.max(0,e-1)]-this.heights[t*this.columns+Math.min(this.columns-1,e+1)])*s,r=(this.heights[Math.max(0,t-1)*this.columns+e]-this.heights[Math.min(this.rows-1,t+1)*this.columns+e])*s,n=Math.tanh(a)*(this.refraction.edgeSafe?this.edgeMask[i]:1),o=Math.tanh(r)*(this.refraction.edgeSafe?this.edgeMask[i]:1);this.normals[2*i]=n,this.normals[2*i+1]=o;const h=Math.round(32767*n+32768),l=Math.round(32767*o+32768);this.refraction.pixels[4*i]=h>>>8,this.refraction.pixels[4*i+1]=255&h,this.refraction.pixels[4*i+2]=l>>>8,this.refraction.pixels[4*i+3]=255&l}}stepLight(t){const e=this.previous,i=1-Math.exp(-30*t),a=1-Math.exp(-12*t);e&&(this.lensX+=(e.x-this.lensX)*i,this.lensY+=(e.y-this.lensY)*i),this.lensStrength+=((e?1:0)-this.lensStrength)*a,this.energy=Math.max(e?Math.abs(e.x-this.lensX)+Math.abs(e.y-this.lensY):0,Math.abs((e?1:0)-this.lensStrength)),this.pending=!1,e||this.active?this.refraction.focus=[this.lensX,this.lensY,this.lensStrength*this.amount,this.radius]:this.clear()}sample(t,e,i){if(mt(this.mode))return this.afterimage.sample(t,e,i),i[0]*=this.amount,i[1]*=this.amount,void(i[2]*=this.amount);if("contour"===this.mode)return i[0]=i[1]=0,void(i[2]=this.contour.sample(t,e)*this.amount*3);if("trail"===this.mode)return i[0]=i[1]=0,void(i[2]=this.trail.sample(t,e)*this.amount*3);const a=Math.max(0,Math.min(this.columns-1.001,t*(this.columns-1))),s=Math.max(0,Math.min(this.rows-1.001,e*(this.rows-1))),r=Math.floor(a),n=Math.floor(s),o=a-r,h=s-n,l=2*(n*this.columns+r),c=l+2*this.columns;for(let t=0;t<2;t++)i[t]=.08*((this.normals[l+t]*(1-o)+this.normals[l+2+t]*o)*(1-h)+(this.normals[c+t]*(1-o)+this.normals[c+2+t]*o)*h);i[0]*=this.amount/.55,i[1]*=this.amount/.55,i[2]="light"===this.mode||"scan"===this.mode?function(t,e,i,a){const[s,r,n,o]=i.focus,h=(t-s)*Math.max(1,a)/o,l=(e-r)*Math.max(1,1/a)/o;return"light"===i.mode?Math.exp(-3*(h*h+l*l))*n:"scan"===i.mode?(1.3*Math.exp(-h*h*110)-.3*Math.exp(-h*h*12))*Math.exp(-l*l*1.8)*n:0}(t,e,this.refraction,this.xScale/this.yScale):0}};function vt(t){return"videoWidth"in t?[t.videoWidth,t.videoHeight]:"naturalWidth"in t?[t.naturalWidth,t.naturalHeight]:[t.width,t.height]}var bt=(t=!1)=>{const e=document.createElement("canvas"),i=e.getContext("2d",{willReadFrequently:t});if(!i)throw new Error("Canvas 2D is unavailable.");return{canvas:e,ctx:i}},yt=(t,e,i)=>{t.width===e&&t.height===i||(t.width=e,t.height=i)},xt={blocks:" ░▒▓█",braille:" ⠁⠃⠇⡇⣇⣧⣷⣿",lines:" -═╪╬",cross:" ·+xX#",diagonal:" /╱╳",diamond:" ·◇◈◆",mixed:" .:+/◇#@"};function kt(t,e={},i={}){const a=t.getContext("2d");if(!a)throw new Error("Canvas is already owned by another renderer.");const s=bt(),r=bt(!0),h=bt(),l=bt(),c=bt(),d=bt(),m=bt(),u=bt(),g=bt(),p=bt();let M,w=0,v=D(e),b=0,x="",k="",S="",A=new Uint8ClampedArray(0),F=new Uint8ClampedArray(0),P=0,T=0,C=0,R=null,L="",N=new wt,O=0;const X=[0,0,0],U=[0,0,0,1],q=[0,0,0,0];let B=V(v.color),z=_(v.print);const W=new H(v.color.denoise),G=new y(v.warps,v.warpEdge),J=Math.max(64,Math.min(4096,Number.isFinite(i.maxDimension)?i.maxDimension:960)),Q=Math.max(256,Math.min(1048576,Number.isFinite(i.maxCells)?i.maxCells:12e3));let K=Q,Z=Math.max(.1,Math.min(8,i.pixelRatio??1));return{canvas:t,render:function(e,i=0,y=960,D=540,V=i*v.motion.speed){if(Number.isFinite(i)||(i=0),!Number.isFinite(y)||!Number.isFinite(D)||y<1||D<1)throw new Error("Render dimensions must be positive finite numbers.");const[H,Q]=vt(e);if(!H||!Q)return;const $=Math.min(1,J/Math.max(y,D)),_=Math.max(2,Math.round(y*$)),tt=Math.max(2,Math.round(D*$));yt(t,_,tt),yt(s.canvas,_,tt),yt(h.canvas,_,tt),yt(l.canvas,_,tt),yt(c.canvas,_,tt),O!==_/tt&&(O=_/tt,N=new wt(O)),N.configure(v.hover.effect,v.hover.strength,v.hover.radius,v.hover.edgeSafe),N.step(Math.max(0,Math.min(.05,i-C))),C=i;const at="currentTime"in e?e.getVideoPlaybackQuality?.().totalVideoFrames??e.currentTime:0,st=[b,_,tt,at].join(":"),rt="dither"===v.style,dt=Y(_,tt,v,K,Z),mt=dt.cell,ft=dt.rowHeight,ut=dt.columns,gt=dt.rows;if(x!==st||R!==e||P!==ut||T!==gt){R=e,x=st,k="",S="",P=ut,T=gt,s.ctx.clearRect(0,0,_,tt),s.ctx.save();const t=j(H,Q,_,tt,v.crop);s.ctx.translate(t.x+t.width/2,t.y+t.height/2),s.ctx.rotate(v.crop.rotation*Math.PI/180),s.ctx.drawImage(e,-H*t.scale/2,-Q*t.scale/2,H*t.scale,Q*t.scale),s.ctx.restore(),yt(r.canvas,P,T),r.ctx.clearRect(0,0,P,T),r.ctx.drawImage(s.canvas,0,0,P,T),A=r.ctx.getImageData(0,0,P,T).data,W.apply(A,P,T);const i=v.color;for(let t=0;t<A.length;t+=4){const e=.299*A[t]+.587*A[t+1]+.114*A[t+2];for(let a=0;a<3;a++){const s=e+(A[t+a]-e)*i.saturation;A[t+a]=((s*(1-i.grayscale)+e*i.grayscale)/255-.5)*i.contrast*255+127.5+255*i.brightness}}B&&function(t,e){for(let i=0;i<t.length;i+=4)t[i+3]&&(t[i]=e[t[i]],t[i+1]=e[256+t[i+1]],t[i+2]=e[512+t[i+2]])}(A,B),A=G.apply(A,P,T,_/tt)}const Mt=it(v),bt=et(v),kt=!N.active&&!Mt&&!bt,Et=[st,P,T,mt,ft,Z].join(":");if(!kt||S!==Et){h.ctx.clearRect(0,0,_,tt),h.ctx.globalAlpha=1,h.ctx.globalCompositeOperation="source-over";const t=V,e=Mt?v.motion.type:"none",a=["none","caustics","sheen","grain","trace"].includes(e);if(rt){const a=kt;if(!a||k!==st){F.length!==A.length&&(F=new Uint8ClampedArray(A.length));const s=F;if(s.set(A),N.active||"none"!==e)for(let i=0;i<T;i++)for(let a=0;a<P;a++){const r=a/P,h=i/T;let l=a,c=i,d=0,m=1,u=1;N.active&&(N.sample(r,h,X),l-=X[0]*P,c-=X[1]*T,d=X[2]/3);const g=4*(i*P+a);n(e,r,h,t,U,(.299*A[g]+.587*A[g+1]+.114*A[g+2])/255),o(U,v.motion.amount??1),l-=U[0]/960*P,c-=U[1]/960*T,m=1+U[2],u=U[3];const p=4*(i*P+a);f(A,P,T,l,c,q);for(let t=0;t<3;t++){const e=q[t]/255;let i=(["trail","contour"].includes(v.hover.effect)?pt(e,d):"etch"===v.hover.effect?Math.max(0,Math.min(1,e+.35*d)):"dissolve"===v.hover.effect?e*Math.max(0,1+d):e)*m;s[p+t]=255*i}s[p+3]=q[3]*u}!function(t,e,i,a,s=0){const{algorithm:r,amount:n,threshold:o}=a,h="blue-noise"===r,l=r.startsWith("bayer")?Number(r.slice(5)):0,c=ht.get(l),d=l-1,m="luminance"===a.colorSpace,f=("custom"===a.palette?a.colors:I[a.palette]??I.mono).map(ct),u=lt[r],g=u?new Float32Array(3*e*3):null,p="drift"===a.motion?s*a.speed*3:0,M=(a.direction??45)*Math.PI/180,w=Math.round(Math.cos(M)*p),v=Math.round(Math.sin(M)*p),b=(t,e)=>(t%e+e)%e,y=f.map(t=>.299*t[0]+.587*t[1]+.114*t[2]),x="shimmer"===a.motion?.15*Math.sin(s*a.speed*2):0;for(let a=0;a<i;a++)for(let s=0;s<e;s++){const M=4*(a*e+s),k=3*(a%3*e+s);if(0===t[M+3]){g&&(g[k]=g[k+1]=g[k+2]=0);continue}let E=0;const S=h?(nt[64*(a-v&63)+(s-w&63)]+.5)/nt.length:0;c?E=c[(a-v&d)*l+(s-w&d)]:"noise"===r?E=ot(s-w,a-v)-.5:"lines"===r?E=b(a-v,4)/3-.5:"vertical-lines"===r?E=b(s-w,4)/3-.5:"diagonal-lines"===r?E=b(s-w+a-v,4)/3-.5:"radial"===r?E=b(Math.hypot(s-e/2,a-i/2)-p,6)/6-.5:"halftone"===r&&(E=Math.hypot(b(s-w,6)-2.5,b(a-v,6)-2.5)/3.54-.5);const A=128*(E*n+x+(.5-o)),F=t[M]+A+(g?.[k]??0),P=t[M+1]+A+(g?.[k+1]??0),T=t[M+2]+A+(g?.[k+2]??0);let I=0,C=0,R=0;if(f.length){let t=1/0,e=1/0,i=0,a=0;const s=.299*F+.587*P+.114*T;for(let r=0;r<f.length;r++){const n=f[r],o=m?(s-y[r])**2:(F-n[0])**2*.299+(P-n[1])**2*.587+(T-n[2])**2*.114;o<t?(h&&(e=t,a=i,i=r),t=o,[I,C,R]=n):h&&o<e&&(e=o,a=r)}if(h&&n>0&&Number.isFinite(e)){const t=f[a],e=t[0]-I,r=t[1]-C,o=t[2]-R,h=y[a]-y[i],l=m?h*h:e*e*.299+r*r*.587+o*o*.114,c=m?(s-y[i])*h:(F-I)*e*.299+(P-C)*r*.587+(T-R)*o*.114;S<(l?Math.max(0,Math.min(1,c/l*n)):0)&&([I,C,R]=t)}}else if(h){const t=Math.max(0,Math.min(1,.5+(S-.5)*n));I=51*Math.floor(F/51+1-t),C=51*Math.floor(P/51+1-t),R=51*Math.floor(T/51+1-t)}else I=51*Math.round(F/51),C=51*Math.round(P/51),R=51*Math.round(T/51);if(t[M]=I,t[M+1]=C,t[M+2]=R,g&&u){g[k]=g[k+1]=g[k+2]=0;for(const[t,r,o]of u){const h=s+t;if(h<0||h>=e||a+r>=i)continue;const l=3*((a+r)%3*e+h);g[l]+=(F-I)*o*n,g[l+1]+=(P-C)*o*n,g[l+2]+=(T-R)*o*n}}}}(s,P,T,v.dither,i),r.ctx.putImageData(new ImageData(s,P,T),0,0),k=a?st:""}h.ctx.imageSmoothingEnabled=!1,h.ctx.drawImage(r.canvas,0,0,_,tt)}else{const i=Array.from(xt[v.style]??v.charset),s=h.ctx,r=ct(v.ink),l="ascii"===v.style||!!xt[v.style],c=E(v.style)?v.style:null,d=Math.max(3,Math.round(.92*ft)),u=Math.ceil(mt+4),g=Math.ceil(ft+4),M=[i.join(""),d,u,g,v.ink,v.colorMode].join(":");if(l&&M!==L&&(L=M,yt(m.canvas,u*i.length,g),m.ctx.clearRect(0,0,m.canvas.width,g),m.ctx.font=`${d}px monospace`,m.ctx.textBaseline="middle",m.ctx.textAlign="center",m.ctx.fillStyle="accent"===v.colorMode?v.ink:"#ffffff",i.forEach((t,e)=>m.ctx.fillText(t,e*u+u/2,g/2))),"lego"===v.style&&w!==mt){w=mt,yt(p.canvas,Math.ceil(mt),Math.ceil(ft));const t=p.ctx;t.clearRect(0,0,p.canvas.width,p.canvas.height),t.fillStyle="rgba(255,255,255,.2)",t.strokeStyle="rgba(0,0,0,.25)",t.lineWidth=Math.max(.5,.6*Z),t.beginPath(),t.arc(mt/2,ft/2,.28*mt,0,2*Math.PI),t.fill(),t.stroke()}s.font=`${d}px monospace`,s.textBaseline="middle",s.textAlign="center";for(let h=0;h<T;h++)for(let d=0;d<P;d++){let M=d,w=h,b=0;if(N.active&&(N.sample(d/P,h/T,X),M=Math.max(0,Math.min(P-1,d-X[0]*P)),w=Math.max(0,Math.min(T-1,h-X[1]*T)),b=X[2]/3),f(A,P,T,M,w,q),!q[3])continue;const y=q[0],x=q[1],k=q[2],E=(.299*y+.587*x+.114*k)/255;let S=E;if(["trail","contour"].includes(v.hover.effect)&&b)S=pt(S,b);else if("etch"===v.hover.effect)S=Math.max(0,Math.min(1,S+.35*b));else if("dissolve"===v.hover.effect){const t=Math.max(0,1+b);S=c&&z.settings.invert?1-(1-S)*t:S*t}let F=d*mt,I=h*ft,C=1;n(e,d/P,h/T,t,U,E),o(U,v.motion.amount??1),F+=U[0]*_/960,I+=U[1]*tt/960,S=Math.max(0,Math.min(1,S+U[2])),C=U[3]*q[3]/255,l||c||"accent"!==v.colorMode||"cmyk"===v.style||(C*=S),s.globalAlpha=C;const R=255*(S-E),L="source"===v.colorMode?`rgb(${y+R},${x+R},${k+R})`:"gray"===v.colorMode?`rgb(${Math.round(255*S)},${Math.round(255*S)},${Math.round(255*S)})`:v.ink;if(s.fillStyle=L,c)z.paint(s,c,d,h,F,I,mt,S,L,"gray"===v.colorMode?255*S:y+R,"gray"===v.colorMode?255*S:x+R,"gray"===v.colorMode?255*S:k+R,v.colorMode);else if(l){const t=Math.max(0,Math.min(i.length-1,Math.round(S*(i.length-1))));"accent"===v.colorMode?s.drawImage(m.canvas,t*u,0,u,g,a?Math.round(F+(mt-u)/2):F+(mt-u)/2,a?Math.round(I+(ft-g)/2):I+(ft-g)/2,u,g):s.fillText(i[t],F+mt/2,I+ft/2)}else if("dots"===v.style)s.beginPath(),s.arc(F+mt/2,I+ft/2,.48*mt*Math.sqrt(S),0,2*Math.PI),s.fill();else if("led"===v.style)s.beginPath(),s.arc(F+mt/2,I+ft/2,.39*mt,0,2*Math.PI),s.fill(),s.globalAlpha=.35*C,s.fillStyle="#ffffff",s.beginPath(),s.arc(F+.43*mt,I+.4*ft,.11*mt,0,2*Math.PI),s.fill();else if("hex"===v.style){const t=F+mt/2,e=I+ft/2;s.beginPath();for(let i=0;i<6;i++){const a=Math.PI/3*i,r=t+Math.cos(a)*mt*.49,n=e+Math.sin(a)*ft*.49;0===i?s.moveTo(r,n):s.lineTo(r,n)}s.closePath(),s.fill()}else if("cmyk"===v.style){s.fillStyle="#ffffff",s.fillRect(F,I,mt,ft);const t=(t,e)=>Math.max(0,Math.min(255,"source"===v.colorMode?t+R:"gray"===v.colorMode?255*S:e*S)),e=t(y,r[0]),i=t(x,r[1]),a=t(k,r[2]),n=1-Math.max(e,i,a)/255,o=Math.max(.001,1-n),h=[["#00ffff",(1-e/255-n)/o,.36,.36],["#ff00ff",(1-i/255-n)/o,.64,.36],["#ffff00",(1-a/255-n)/o,.5,.66],["#000000",n,.5,.5]];s.globalCompositeOperation="multiply";for(const[t,e,i,a]of h)s.fillStyle=t,s.beginPath(),s.arc(F+mt*i,I+ft*a,.48*mt*Math.sqrt(Math.max(0,e)),0,2*Math.PI),s.fill();s.globalCompositeOperation="source-over"}else if("voxel"===v.style){const t=F+mt/2,e=I+ft/2;s.beginPath(),s.moveTo(t,I),s.lineTo(F+mt,I+.25*ft),s.lineTo(t,e),s.lineTo(F,I+.25*ft),s.closePath(),s.fill(),s.globalAlpha=.72*C,s.beginPath(),s.moveTo(F,I+.25*ft),s.lineTo(t,e),s.lineTo(t,I+ft),s.lineTo(F,I+.75*ft),s.closePath(),s.fill(),s.globalAlpha=.42*C,s.beginPath(),s.moveTo(t,e),s.lineTo(F+mt,I+.25*ft),s.lineTo(F+mt,I+.75*ft),s.lineTo(t,I+ft),s.closePath(),s.fill()}else{const t="pixel"===v.style?0:Math.max(.5,.06*mt);s.fillRect(F,I,mt-t,ft-t),"lego"===v.style&&s.drawImage(p.canvas,F,I),"disco"===v.style&&(s.fillStyle=`rgba(255,255,255,${.1+.25*ot(d,h)})`,s.fillRect(F,I,mt-t,.35*ft),s.fillStyle="rgba(0,0,0,.25)",s.fillRect(F,I+.65*ft,mt-t,.35*ft-t))}}}h.ctx.globalAlpha=1,(v.color.amount||v.lights.length)&&(yt(u.canvas,_,tt),u.ctx.clearRect(0,0,_,tt),u.ctx.drawImage(h.canvas,0,0)),v.color.amount&&(h.ctx.save(),h.ctx.globalCompositeOperation=v.color.blend,h.ctx.globalAlpha=v.color.amount,h.ctx.fillStyle=v.color.tint,h.ctx.fillRect(0,0,_,tt),h.ctx.restore());for(const t of v.lights){const e=t.radius*Math.max(_,tt),i=h.ctx.createRadialGradient(t.x*_,t.y*tt,0,t.x*_,t.y*tt,e);i.addColorStop(0,t.color),i.addColorStop(1,"transparent"),h.ctx.save(),h.ctx.globalCompositeOperation="screen",h.ctx.globalAlpha=t.intensity,h.ctx.fillStyle=i,h.ctx.fillRect(0,0,_,tt),h.ctx.restore()}if((v.color.amount||v.lights.length)&&(h.ctx.globalCompositeOperation="destination-in",h.ctx.drawImage(u.canvas,0,0),h.ctx.globalCompositeOperation="source-over"),v.mask.enabled&&v.mask.shapes.length){const t=c.ctx;t.clearRect(0,0,_,tt),t.fillStyle="#fff",t.strokeStyle="#fff",t.lineCap="round",t.lineJoin="round";for(const e of v.mask.shapes){if(t.beginPath(),"ellipse"===e.kind)t.ellipse((e.x+e.width/2)*_,(e.y+e.height/2)*tt,e.width*_/2,e.height*tt/2,0,0,2*Math.PI);else{if("rectangle"!==e.kind){if(t.lineWidth=(e.size??.05)*_,1===e.points?.length){t.arc(e.points[0][0]*_,e.points[0][1]*tt,t.lineWidth/2,0,2*Math.PI),t.fill();continue}e.points?.forEach(([e,i],a)=>a?t.lineTo(e*_,i*tt):t.moveTo(e*_,i*tt)),t.stroke();continue}t.rect(e.x*_,e.y*tt,e.width*_,e.height*tt)}t.fill()}h.ctx.globalCompositeOperation=v.mask.invert?"destination-out":"destination-in",h.ctx.drawImage(c.canvas,0,0),h.ctx.globalCompositeOperation="source-over"}const M=l.ctx;M.clearRect(0,0,_,tt),M.globalAlpha=v.backdrop.opacity;const b=v.backdrop;if("solid"===b.mode&&(M.fillStyle=b.color,M.fillRect(0,0,_,tt)),"gradient"===b.mode){const t=M.createLinearGradient(0,0,_,tt);t.addColorStop(0,b.color),t.addColorStop(1,b.color2),M.fillStyle=t,M.fillRect(0,0,_,tt)}if("source"===b.mode&&M.drawImage(s.canvas,0,0),"blurred"===b.mode){const t=Math.max(1,b.blur);yt(d.canvas,Math.max(2,Math.round(_/t)),Math.max(2,Math.round(tt/t))),d.ctx.drawImage(s.canvas,0,0,d.canvas.width,d.canvas.height),M.imageSmoothingEnabled=!0,M.drawImage(d.canvas,0,0,_,tt)}M.globalAlpha=1,v.effects.characterBloom>0&&(yt(g.canvas,Math.max(2,Math.round(_/3)),Math.max(2,Math.round(tt/3))),g.ctx.clearRect(0,0,g.canvas.width,g.canvas.height),g.ctx.drawImage(h.canvas,0,0,g.canvas.width,g.canvas.height),M.save(),M.globalAlpha=.8*v.effects.characterBloom,M.globalCompositeOperation="screen",M.filter=`blur(${1+4*v.effects.characterBloom}px)`,M.drawImage(g.canvas,0,0,_,tt),M.restore()),M.drawImage(h.canvas,0,0),S=kt?Et:""}const St=Object.entries(v.effects).some(([t,e])=>!["angle","focus","blurType","characterBloom"].includes(t)&&"number"==typeof e&&e>0);a.clearRect(0,0,_,tt),St?(void 0===M&&(M=function(){const t=document.createElement("canvas"),e=t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,antialias:!1,preserveDrawingBuffer:!0});if(!e)return null;const i=[],a=(t,a)=>{const s=e.createShader(t);if(i.push(s),e.shaderSource(s,a),e.compileShader(s),!e.getShaderParameter(s,e.COMPILE_STATUS))throw new Error(e.getShaderInfoLog(s)||"Finish shader failed");return s},s=e.createProgram();if(e.attachShader(s,a(e.VERTEX_SHADER,"attribute vec2 p;varying vec2 uv;void main(){uv=(p+1.)*.5;gl_Position=vec4(p,0.,1.);}")),e.attachShader(s,a(e.FRAGMENT_SHADER,"precision mediump float;varying vec2 uv;uniform sampler2D src;uniform vec2 size;uniform float t,bloom,grain,dust,scanlines,crt,prism,vignette,glitch,pixelate,blur,blurMode,angle,focus,halftone,rgbSplit,sharpen;\n float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}\n vec4 sampleAt(vec2 p){if(min(min(p.x,p.y),min(1.-p.x,1.-p.y))<0.)return vec4(0.);return texture2D(src,vec2(p.x,1.-p.y));}\n void main(){vec2 q=uv,c=q-.5;q=c*(1.+dot(c,c)*crt*.25)+.5;\n if(glitch>0.)q.x+=(hash(vec2(floor(q.y*35.),floor(t*5.)))-.5)*.07*glitch*step(.82,hash(vec2(floor(q.y*35.),floor(t*5.)+3.)));\n if(pixelate>0.){vec2 grid=size/(1.+pixelate*20.);q=(floor(q*grid)+.5)/grid;}\n vec4 base=sampleAt(q);float edge=smoothstep(.12,.65,length(c));\n vec2 shift=vec2((prism*3.*edge+rgbSplit*8.)/size.x,prism*edge/size.y);\n if(prism>0.||rgbSplit>0.)base.rgb=vec3(sampleAt(q+shift).r,base.g,sampleAt(q-shift).b);\n vec2 dir=vec2(cos(angle),sin(angle))/size;float amount=blur;\n if(blurMode>1.5&&blurMode<2.5){dir=normalize(c+vec2(.0001))/size;amount*=length(c)*2.;}\n if(blurMode>2.5)amount*=smoothstep(.05,.5,abs(q.y-focus));\n vec4 blurred=base;\n if(amount>0.){blurred=base*.2;for(int i=1;i<=4;i++){float f=float(i)*amount*.35;vec2 off=dir*f;if(blurMode<.5)off=vec2(cos(float(i)*1.57),sin(float(i)*1.57))*amount/size;blurred+=sampleAt(q+off)*.1+sampleAt(q-off)*.1;}}\n vec3 light=vec3(0.);if(bloom>0.)for(int i=0;i<4;i++){float a=float(i)*1.5708;vec3 s=sampleAt(q+vec2(cos(a),sin(a))*6./size).rgb;light+=max(vec3(0.),s-.35)*.25;}\n vec3 col=blurred.rgb+light*bloom;\n if(sharpen>0.){vec2 px=1./size;vec3 near=sampleAt(q+vec2(px.x,0.)).rgb+sampleAt(q-vec2(px.x,0.)).rgb+sampleAt(q+vec2(0.,px.y)).rgb+sampleAt(q-vec2(0.,px.y)).rgb;col+=(base.rgb*4.-near)*sharpen*.5;}\ncol*=1.-scanlines*.4*(.5+.5*cos(q.y*size.y*3.14159));\n col*=1.-vignette*smoothstep(.15,.72,length(c));\n col+=(hash(floor(q*size)+floor(t*12.))-.5)*grain*.2;\n if(dust>0.)col+=step(1.-dust*.002,hash(floor(q*size*.25)+floor(t*2.)))*.4;\n if(halftone>0.)col*=mix(1.,smoothstep(.1,.65,length(fract(q*size/6.)-.5)),halftone);\n gl_FragColor=vec4(clamp(col,0.,1.),blurred.a);}")),e.linkProgram(s),!e.getProgramParameter(s,e.LINK_STATUS))throw new Error("Finish link failed");e.useProgram(s);const r=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,r),e.bufferData(e.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),e.STATIC_DRAW);const n=e.getAttribLocation(s,"p");e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,0,0);const o=e.createTexture();e.bindTexture(e.TEXTURE_2D,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE);const h=["t","bloom","grain","dust","scanlines","crt","prism","rgbSplit","sharpen","vignette","glitch","pixelate","blur","blurMode","angle","focus","halftone"],l=Object.fromEntries(h.map(t=>[t,e.getUniformLocation(s,t)])),c=e.getUniformLocation(s,"size");return{canvas:t,render(i,a,r,n=1){t.width===i.width&&t.height===i.height||(t.width=i.width,t.height=i.height,e.viewport(0,0,t.width,t.height)),e.useProgram(s),e.bindTexture(e.TEXTURE_2D,o),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,i),e.uniform2f(c,t.width/n,t.height/n);for(const t of h)e.uniform1f(l[t],"t"===t?r:"blurMode"===t?["gaussian","directional","radial","progressive"].indexOf(a.blurType):"angle"===t?a.angle*Math.PI/180:a[t]??0);return e.drawArrays(e.TRIANGLE_STRIP,0,4),t},destroy(){e.deleteTexture(o),e.deleteBuffer(r),e.deleteProgram(s),i.forEach(t=>e.deleteShader(t)),t.width=t.height=1,e.getExtension("WEBGL_lose_context")?.loseContext()}}}()),M?a.drawImage(M.render(l.canvas,v.effects,i,Z),0,0):a.drawImage(l.canvas,0,0),t.dataset.studioFinish=M?"gpu":"unavailable"):(a.drawImage(l.canvas,0,0),t.dataset.studioFinish="none")},setPixelRatio(t){Z=Math.max(.1,Math.min(8,Number.isFinite(t)?t:1))},get pixelRatio(){return Z},setBudget(t){K=Math.max(256,Math.min(Q,Number.isFinite(t)?Math.round(t):Q))},get maxCells(){return K},configure(t){v=D(t),B=V(v.color),z=_(v.print),W.configure(v.color.denoise),G.configure(v.warps,v.warpEdge),b++},pointer:(t,e,i)=>{N.configure(v.hover.effect,v.hover.strength,v.hover.radius,v.hover.edgeSafe),N.move(t,e,i)},leave(){N.leave()},get active(){return N.active},get settings(){return D(v)},get capabilities(){return{gpuFinish:null!==M}},invalidate(){x=""},destroy(){M?.destroy(),G.clear(),W.configure(0);for(const t of[s,r,h,l,c,d,m,u,g,p])t.canvas.width=t.canvas.height=1;R=null,A=new Uint8ClampedArray(0),F=new Uint8ClampedArray(0)}}}function Et(t,e,i){return new Promise((a,s)=>{const r=()=>{l(),a()},n=()=>{l(),s(new Error("Unable to load this media. Check its format and cross-origin permissions."))},o=()=>{l(),s(new DOMException("Cancelled","AbortError"))},h=setTimeout(n,2e4),l=()=>{clearTimeout(h),t.removeEventListener(e,r),t.removeEventListener("error",n),i?.removeEventListener("abort",o)};t.addEventListener(e,r,{once:!0}),t.addEventListener("error",n,{once:!0}),i?.addEventListener("abort",o,{once:!0}),i?.aborted&&o()})}async function St(t,e){if("string"==typeof t&&t.startsWith("blob:")){const i=await fetch(t,{signal:e}),a=await i.blob();return St(new File([a],"Imported media",{type:a.type}),e)}const i="string"!=typeof t,a=i?t.name:t;if(i?"image/gif"===t.type:/\.gif(?:[?#]|$)/i.test(a)){const a=await import("gifuct-js"),{parseGIF:s,decompressFrames:r}="function"==typeof a.parseGIF?a:a.default,n=i?await t.arrayBuffer():await fetch(t,{signal:e}).then(t=>{if(!t.ok)throw new Error("GIF download failed.");return t.arrayBuffer()});if(e?.aborted)throw new DOMException("Cancelled","AbortError");const o=s(n),h=o.lsd.width,l=o.lsd.height;if(h*l>4e6)throw new Error("GIF is too large. Use a smaller GIF or an MP4.");const c=o.frames.filter(t=>"image"in t).length;if(!c||c*h*l*4>128e6)throw new Error("GIF exceeds the decoded memory budget. Use MP4 for long animations.");const d=r(o,!0);if(d.length*h*l*4>128e6)throw new Error("GIF exceeds the 128 MB decoded budget. Use MP4 for long animations.");const m=document.createElement("canvas");m.width=h,m.height=l;const f=m.getContext("2d"),u=document.createElement("canvas"),g=u.getContext("2d"),p=d.reduce((t,e)=>t+Math.max(20,e.delay),0)/1e3;let M=-1,w=null;const v=t=>{const e=(t%p+p)%p*1e3;let i=0,a=0;for(;a<d.length-1&&(i+=Math.max(20,d[a].delay),!(e<i));a++);a<M&&(f.clearRect(0,0,h,l),M=-1,w=null);for(let t=M+1;t<=a;t++){const e=d[t-1];2===e?.disposalType&&f.clearRect(e.dims.left,e.dims.top,e.dims.width,e.dims.height),3===e?.disposalType&&w&&f.putImageData(w,0,0);const i=d[t];w=3===i.disposalType?f.getImageData(0,0,h,l):null,u.width=i.dims.width,u.height=i.dims.height,g.putImageData(new ImageData(new Uint8ClampedArray(i.patch),u.width,u.height),0,0),f.drawImage(u,i.dims.left,i.dims.top)}return M=a,m};return v(0),{source:m,width:h,height:l,duration:p,animated:!0,seek:async()=>{},frame:v,destroy(){m.width=u.width=1,d.length=0,w=null}}}const s=i?t.type.startsWith("video/"):/\.(mp4|webm|mov)(?:[?#]|$)/i.test(a),r=i?URL.createObjectURL(t):t,n=s?document.createElement("video"):new Image;n.crossOrigin="anonymous",n instanceof HTMLVideoElement&&(n.muted=!0,n.playsInline=!0,n.preload="auto");const o=()=>{n instanceof HTMLVideoElement?(n.pause(),n.removeAttribute("src"),n.load()):n.src="",i&&URL.revokeObjectURL(r)};try{const t=Et(n,s?"loadeddata":"load",e);n.src=r,await t;const i=n instanceof HTMLVideoElement?n.videoWidth:n.naturalWidth,a=n instanceof HTMLVideoElement?n.videoHeight:n.naturalHeight;return{source:n,width:i,height:a,duration:n instanceof HTMLVideoElement?n.duration:0,animated:s,async seek(t,e){if(!(n instanceof HTMLVideoElement))return;if(!Number.isFinite(n.duration)||n.duration<=0)throw new Error("Video duration is unavailable.");const i=Math.max(0,Math.min(n.duration-.001,t%n.duration));if(Math.abs(n.currentTime-i)<.001&&n.readyState>=2)return;const a=Et(n,"seeked",e);n.currentTime=i,await a},frame:()=>n,destroy:o}}catch(t){throw o(),t}}var At=t=>{if(t?.aborted)throw new DOMException("Export cancelled","AbortError")};async function Ft(t,e){const{format:i,signal:a}=e,s=Math.round(e.width),r=Math.round(e.height);if(!Number.isFinite(s)||!Number.isFinite(r)||s<2||r<2||s>4096||r>4096||s*r>16777216)throw new Error("Choose export dimensions between 2 and 4096 pixels.");if(!["png","jpeg","mp4","webm","gif"].includes(i))throw new Error("Unknown export format.");if(void 0!==e.fps&&!Number.isFinite(e.fps))throw new Error("Frames per second must be finite.");const n=Math.max(1,Math.min(60,Math.round(e.fps??24))),o=e.duration??5;if(!Number.isFinite(o)||o<=0||o>60)throw new Error("Choose a duration from 0 to 60 seconds.");const h="png"===i||"jpeg"===i,l=e.time??0;if(!Number.isFinite(l)||l<0)throw new Error("Image time must be a finite non-negative number.");if(void 0!==e.motionTime&&(!Number.isFinite(e.motionTime)||e.motionTime<0))throw new Error("Motion time must be a finite non-negative number.");if(!h&&s*r>8294400)throw new Error("Video exports support up to 3840 × 2160 pixels.");if("gif"===i&&(s*r>921600||o*n>600))throw new Error("GIF export supports up to 1280 × 720 and 600 frames. Use MP4 for larger exports.");if(void 0!==e.referenceWidth&&(!Number.isFinite(e.referenceWidth)||e.referenceWidth<1))throw new Error("Reference width must be a positive number.");if("gif"===i&&n>30)throw new Error("GIF exports support up to 30 fps. Choose MP4 or WebM for higher frame rates.");const c=document.createElement("canvas");let d;try{if(At(a),e.onProgress?.(0),h){if(await t(c,l,s,r,a,e.motionTime),"unavailable"===c.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");At(a);const n=await new Promise((t,a)=>c.toBlob(e=>e?t(e):a(new Error("Image export failed.")),"png"===i?"image/png":"image/jpeg",e.quality??.92));return At(a),e.onProgress?.(1),n}const m=Math.ceil(o*n);if("gif"===i){const i=await import("gifenc"),{GIFEncoder:h,quantize:l,applyPalette:d}="function"==typeof i.GIFEncoder?i:i.default,f=h(),u=c.getContext("2d");for(let i=0;i<m;i++){At(a);const h=i/n;if(await t(c,h,s,r,a),At(a),"unavailable"===c.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");const g=u.getImageData(0,0,s,r).data,p=l(g,256),M=d(g,p);f.writeFrame(M,s,r,{palette:p,delay:10*(Math.round(100*Math.min((i+1)/n,o))-Math.round(100*i/n)),repeat:0}),e.onProgress?.((i+1)/m*.98),await new Promise(t=>setTimeout(t,0))}return At(a),f.finish(),e.onProgress?.(1),new Blob([new Uint8Array(f.bytes())],{type:"image/gif"})}const{Output:f,Mp4OutputFormat:u,WebMOutputFormat:g,BufferTarget:p,CanvasSource:M,canEncodeVideo:w}=await import("mediabunny"),v="mp4"===i?"avc":"vp9";if(!await w(v,{width:s,height:r}))throw new Error(`${i.toUpperCase()} encoding is unavailable in this browser. Try another format or a current browser with WebCodecs.`);const b=new f({format:"mp4"===i?new u({fastStart:"in-memory"}):new g,target:new p});c.width=s,c.height=r,d=()=>b.cancel();const y=new M(c,{codec:v,bitrate:Math.max(5e5,Math.round(s*r*n*.15))});b.addVideoTrack(y,{frameRate:n}),c.width=s,c.height=r,await b.start();for(let i=0;i<m;i++){At(a);const h=i/n;if(await t(c,h,s,r,a),At(a),"unavailable"===c.dataset.studioFinish)throw new Error("Optical effects need WebGL. Disable these effects or export in a supported browser.");await y.add(h,Math.min(1/n,o-h)),e.onProgress?.((i+1)/m*.98),i%4==0&&await new Promise(t=>setTimeout(t,0))}return y.close(),At(a),await b.finalize(),At(a),d=void 0,e.onProgress?.(1),new Blob([b.target.buffer],{type:"mp4"===i?"video/mp4":"video/webm"})}catch(t){throw await(d?.().catch(()=>{})),t}finally{c.width=c.height=1}}async function Pt(t,e,i){let a;const s=D(e),r="png"!==i.format&&"jpeg"!==i.format;try{return await Ft(async(e,n,o,h,l,c)=>{a??(a=kt(e,s,{maxDimension:4096,maxCells:i.maxCells??12e3,pixelRatio:o/(i.referenceWidth??Math.min(o,960))})),r&&a.invalidate(),a.render(await t.frame(n,l),n,o,h,c)},i)}finally{a?.destroy()}}async function Tt(t,e,i={}){const a=await St(e,i.signal);try{return It(t,a,i)}catch(t){throw a.destroy(),t}}function It(t,e,i={}){let a=D(i.settings),s=i.width??e.width,n=i.height??e.height;const o=kt(t,a,i),h=new r;let l=0,c=!1,d=!0,m=!1,f=!0,u=0,g=0,p=0,M=0,w=-1,v=!1!==i.adaptive,b=0,y=0,x=0;const k=matchMedia("(prefers-reduced-motion: reduce)"),E=e.source instanceof HTMLVideoElement?e.source:null,S=()=>{c||l||!f||document.hidden||(l=requestAnimationFrame(P))},A=()=>!m&&!k.matches&&f&&!document.hidden,F=()=>{E&&(E.loop=!0,A()?E.play().catch(()=>{m=!0,d=!0,S()}):E.pause()),p=0,d=!0,S()};function P(t){if(l=0,c||!f||document.hidden)return;const r=A();r&&(u+=p?Math.min(.1,(t-p)/1e3):0),p=t;const k=at(a),F=r&&(e.animated||k),P=E?.getVideoPlaybackQuality?.().totalVideoFrames??-1,T=!E||P<0||P!==w;if(d||o.active||F&&(T||k)&&t-M>=1e3/Math.max(1,Math.min(60,i.fps??60))-.5){const r=performance.now();try{e.animated&&!E&&o.invalidate();const[t,l]=q(s,n,a);g=h.update(u,a.motion.type,a.motion.speed),o.render(e.frame(E?.currentTime??u),u,t,l,g);const c=performance.now()-r;i.onFrame?.(E?.currentTime??u,c),y=y?.9*y+.1*c:c,++b>20&&v&&(F||o.active)&&(x=y>13?x+1:0,x>=12&&o.maxCells>3e3&&(o.setBudget(Math.max(3e3,.8*o.maxCells)),i.onQualityChange?.(o.maxCells),x=0,y=0))}catch(t){m=!0,i.onError?.(t instanceof Error?t:new Error(String(t)))}d=!1,M=t,w=P}r&&(F||o.active)&&S()}const T=e=>{if(!A())return;const i=t.getBoundingClientRect();o.pointer((e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height,e.timeStamp),S()},I=()=>{o.leave(),S()},C=new IntersectionObserver(([t])=>{f=t.isIntersecting,F()});C.observe(t),t.addEventListener("pointermove",T),t.addEventListener("pointerleave",I),t.addEventListener("pointercancel",I),document.addEventListener("visibilitychange",F),k.addEventListener("change",F);const R=()=>{c||(c=!0,cancelAnimationFrame(l),C.disconnect(),t.removeEventListener("pointermove",T),t.removeEventListener("pointerleave",I),t.removeEventListener("pointercancel",I),document.removeEventListener("visibilitychange",F),k.removeEventListener("change",F),i.signal?.removeEventListener("abort",R),o.destroy(),e.destroy())};if(i.signal?.addEventListener("abort",R,{once:!0}),i.signal?.aborted)throw R(),new DOMException("Cancelled","AbortError");return F(),{canvas:t,media:e,update(t){a=B(a,t),o.configure(a),d=!0,S()},resize(t,e,i){void 0!==i&&o.setPixelRatio(i),s=Math.max(2,t),n=Math.max(2,e),d=!0,S()},pause(t=!0){m=t,F()},async seek(t){u=Math.max(0,t),await e.seek(u),o.invalidate(),d=!0,S()},redraw(){o.invalidate(),d=!0,S()},get time(){return E?.currentTime??u},get settings(){return D(a)},get motionTime(){return g},get paused(){return m||k.matches},setAdaptive(t){v=t,b=x=y=0},setBudget(t){o.setBudget(t),i.onQualityChange?.(o.maxCells),d=!0,S()},get pixelRatio(){return o.pixelRatio},get maxCells(){return o.maxCells},get capabilities(){return o.capabilities},destroy:R}}var Ct={Standard:()=>import("figlet/fonts/Standard"),Slant:()=>import("figlet/fonts/Slant"),Small:()=>import("figlet/fonts/Small"),Big:()=>import("figlet/fonts/Big"),Banner:()=>import("figlet/fonts/Banner"),Block:()=>import("figlet/fonts/Block"),Bubble:()=>import("figlet/fonts/Bubble"),Digital:()=>import("figlet/fonts/Digital"),Doom:()=>import("figlet/fonts/Doom"),Lean:()=>import("figlet/fonts/Lean"),Mini:()=>import("figlet/fonts/Mini"),Script:()=>import("figlet/fonts/Script"),Shadow:()=>import("figlet/fonts/Shadow"),Speed:()=>import("figlet/fonts/Speed"),Starwars:()=>import("figlet/fonts/Star Wars"),Stop:()=>import("figlet/fonts/Stop"),Straight:()=>import("figlet/fonts/Straight"),Thin:()=>import("figlet/fonts/Thin"),ThreeD:()=>import("figlet/fonts/3-D"),Univers:()=>import("figlet/fonts/Univers"),Wavy:()=>import("figlet/fonts/Wavy")},Rt=Object.keys(Ct);async function Lt(t,e="Standard",i="#ffffff",a="#080808"){if(!Object.prototype.hasOwnProperty.call(Ct,e))throw new Error("Unknown text font.");const{default:s}=await import("figlet/browser"),r=await Ct[e]();s.parseFont(e,r.default),s.defaults({fetchFontIfMissing:!1});const n=s.textSync(t.slice(0,120),{font:e}),o=n.split("\n"),h=Math.max(1,...o.map(t=>t.length)),l=Math.max(1,o.length),c=Math.min(1,2048/(9*h)),d=document.createElement("canvas");d.width=Math.ceil(9*h*c+32),d.height=Math.ceil(15*l*c+32);const m=d.getContext("2d");return null!==a&&(m.fillStyle=a,m.fillRect(0,0,d.width,d.height)),m.fillStyle=i,m.font=15*c+"px monospace",m.textBaseline="top",o.forEach((t,e)=>m.fillText(t,16,16+15*e*c)),{canvas:d,ascii:n}}var Nt={standard:{label:"Classic ASCII",chars:" .:-=+*#%@"},asciify:{label:"Asciify",chars:" .:-=+ASCIIFY#@"},minimal:{label:"Minimal",chars:" .:+"},detailed:{label:"Detailed",chars:" .,:;i1tfLCG08@"},letters:{label:"Letters",chars:" .ilLCFTYASMW"},technical:{label:"Technical",chars:" .:;>_/[{}]=+*#@$"},blocks:{label:"Tonal blocks",chars:" ░▒▓█"},braille:{label:"Braille",chars:" ⠁⠃⠇⡇⣇⣧⣷⣿"}},Ot=Nt,Dt=8,Xt=t=>t&&"object"==typeof t&&!Array.isArray(t)?t:{},Ut=(t,e,i,a)=>"number"==typeof t&&Number.isFinite(t)?Math.max(i,Math.min(a,t)):e,jt=(t,e)=>{if("string"!=typeof t||!/^[a-zA-Z0-9][a-zA-Z0-9:_-]{0,63}$/.test(t))throw new Error(`${e} must be 1–64 letters, numbers, colons, dashes or underscores, starting with a letter or number.`);return t};function qt(t={}){const e=Xt(t);if(void 0!==e.kind&&"asciify-project"!==e.kind||void 0!==e.version&&1!==e.version)throw new Error("Unsupported Studio project. Update asciify-engine.");if(void 0!==e.layers&&!Array.isArray(e.layers))throw new Error("Project layers must be an array.");const i=Array.isArray(e.layers)?e.layers:[];if(i.length>8)throw new Error("A project supports up to 8 layers.");const a=new Set;return{kind:"asciify-project",version:1,width:Math.round(Ut(e.width,1280,2,4096)),height:Math.round(Ut(e.height,720,2,4096)),background:null===e.background?null:"string"==typeof e.background&&/^#[a-f\d]{6}$/i.test(e.background)?e.background:"#0c1711",pointerMode:"all"===e.pointerMode?"all":"top",layers:i.map((t,e)=>{const i=Xt(t),s=Xt(i.placement),r=Xt(i.settings),n=Xt(r.backdrop),o=jt(i.id,"Layer id"),h=jt(i.source,"Source key");if(a.has(o))throw new Error(`Duplicate layer id: ${o}`);return a.add(o),{id:o,source:h,name:"string"==typeof i.name?i.name.slice(0,80):`Layer ${e+1}`,visible:!1!==i.visible,opacity:Ut(i.opacity,1,0,1),blend:T.includes(i.blend)?i.blend:"source-over",placement:{x:Ut(s.x,.5,-1,2),y:Ut(s.y,.5,-1,2),width:Ut(s.width,1,.01,2),height:Ut(s.height,1,.01,2),rotation:Ut(s.rotation,0,-180,180),flipX:!0===s.flipX,flipY:!0===s.flipY},settings:D({...r,backdrop:{mode:"transparent",...n}})}})}}function Bt(t,e,i){if(!t.layers.some(t=>t.id===e))throw new Error(`Unknown layer: ${e}`);return qt({...t,layers:t.layers.map(t=>t.id!==e?t:{...t,...i,id:e,placement:{...t.placement,...i.placement},settings:B(t.settings,i.settings??{})})})}var Yt=t=>JSON.stringify(qt(t));function zt(t){if(t.length>1e6)throw new Error("Project exceeds the 1 MB settings limit.");const e=JSON.parse(t);if("asciify-project"!==e?.kind||1!==e.version||!Array.isArray(e.layers))throw new Error("This is not an Asciify layered project.");return qt(e)}function Wt(t,e,i,a,s){const r=t.placement,n=r.rotation*Math.PI/180,o=Math.cos(n),h=Math.sin(n),l=(e-r.x)*a,c=(i-r.y)*s,d=(l*o+c*h)/(r.width*a),m=(-l*h+c*o)/(r.height*s);return[.5+d*(r.flipX?-1:1),.5+m*(r.flipY?-1:1)]}function Gt(t){return t.layers.filter(e=>{if(!e.visible||e.opacity<=0)return!1;const i=e.placement,a=i.rotation*Math.PI/180,s=Math.abs(Math.cos(a)),r=Math.abs(Math.sin(a)),n=(s*i.width*t.width+r*i.height*t.height)/2,o=(r*i.width*t.width+s*i.height*t.height)/2;return i.x*t.width+n>0&&i.x*t.width-n<t.width&&i.y*t.height+o>0&&i.y*t.height-o<t.height})}function Vt(t,e=24e3,i=4194304,a=t.width,s=t.height){const r=Gt(t),n=Math.round(Ut(e,24e3,2048,1048576)),o=Ut(i,4194304,65536,16777216),h=r.map(t=>t.placement.width*t.placement.height),l=h.reduce((t,e)=>t+e,0),c=n-256*r.length,d=r.map(t=>{const e=a*t.placement.width,i=s*t.placement.height,r=Math.min(1,4096/Math.max(e,i));return{width:Math.max(2,e*r),height:Math.max(2,i*r)}}),m=d.reduce((t,e)=>t+e.width*e.height,0);let f=0,u=0;return r.map((t,e)=>{const i=e===r.length-1?n-f:256+Math.floor(c*h[e]/l);f+=i;const a=d[e],s=e===r.length-1?o-u:4+Math.floor((o-4*r.length)*a.width*a.height/Math.max(1,m));u+=s;const g=Math.min(1,Math.sqrt(s/(a.width*a.height)));let p=Math.max(2,Math.floor(a.width*g)),M=Math.max(2,Math.floor(a.height*g));return p*M>s&&(p>=M?p=Math.max(2,Math.floor(s/M)):M=Math.max(2,Math.floor(s/p))),{id:t.id,maxCells:i,width:p,height:M}})}function Ht(t,e={},i={}){const a=t.getContext("2d");if(!a)throw new Error("Project canvas is already owned by another renderer.");let s=qt(e),r=!0,n=!1,o=new Map(s.layers.map(t=>[t.id,JSON.stringify(t.settings)]));const h=Math.max(64,Math.min(4096,Number.isFinite(i.maxDimension)?i.maxDimension:960)),l=Math.max(2048,Math.min(1048576,Number.isFinite(i.maxCells)?i.maxCells:24e3));let c=l,d=Math.max(.1,Math.min(8,Number.isFinite(i.pixelRatio)?i.pixelRatio:1)),m=[];const f=new Map,u=()=>{if(n)throw new Error("Project renderer has been destroyed.")};return{canvas:t,render(e,n=0,g=s.width,p=s.height,M={}){if(u(),!Number.isFinite(g)||!Number.isFinite(p)||g<2||p<2)throw new Error("Project dimensions must be positive finite numbers.");const w=Math.min(1,h/Math.max(g,p)),v=Math.max(2,Math.round(g*w)),b=Math.max(2,Math.round(p*w));t.width===v&&t.height===b||(t.width=v,t.height=b,r=!0);const y={...s,width:v,height:b},x=Gt(y);for(const t of x)if(!e.has(t.source))throw new Error(`Missing project source: ${t.source}`);const k=new Set(x.map(t=>t.id));for(const[t,e]of f)k.has(t)||(e.renderer.destroy(),f.delete(t),r=!0);m=Vt(y,c,i.maxRasterPixels,v,b);for(let t=0;t<x.length;t++){const i=x[t],a=m[t],s=e.get(i.source);if(!s)throw new Error(`Missing project source: ${i.source}`);let h=f.get(i.id);const c=o.get(i.id);h?h.signature!==c&&(h.renderer.configure(i.settings),h.signature=c,h.dirty=!0):(h={renderer:kt(document.createElement("canvas"),i.settings,{maxDimension:4096,maxCells:l}),signature:c,dirty:!0,geometry:""},f.set(i.id,h));const u=d*a.width/(g*i.placement.width),p=`${a.width}:${a.height}:${a.maxCells}:${u}`;h.geometry!==p&&(h.renderer.setBudget(a.maxCells),h.renderer.setPixelRatio(u),h.geometry=p,h.dirty=!0);const w="currentTime"in s?s.getVideoPlaybackQuality?.().totalVideoFrames??s.currentTime:0;if(h.dirty||h.source!==s||h.stamp!==w||h.renderer.active||at(i.settings)){const t=Object.prototype.hasOwnProperty.call(M,i.id)?M[i.id]:void 0;h.renderer.render(s,n,a.width,a.height,t),h.dirty=!1,h.source=s,h.stamp=w,r=!0}}if(!r)return!1;a.clearRect(0,0,v,b),a.globalCompositeOperation="source-over",a.globalAlpha=1,null!==s.background&&(a.fillStyle=s.background,a.fillRect(0,0,v,b));let E="none";for(const t of x){const e=f.get(t.id),i=t.placement;a.save(),a.globalAlpha=t.opacity,a.globalCompositeOperation=t.blend;try{a.translate(i.x*v,i.y*b),a.rotate(i.rotation*Math.PI/180),a.scale(i.flipX?-1:1,i.flipY?-1:1),a.drawImage(e.renderer.canvas,-i.width*v/2,-i.height*b/2,i.width*v,i.height*b)}finally{a.restore()}"unavailable"===e.renderer.canvas.dataset.studioFinish?E="unavailable":"unavailable"!==E&&"gpu"===e.renderer.canvas.dataset.studioFinish&&(E="gpu")}return a.globalAlpha=1,a.globalCompositeOperation="source-over",t.dataset.studioFinish=E,r=!1,!0},configure(t){u(),s=qt(t),o=new Map(s.layers.map(t=>[t.id,JSON.stringify(t.settings)])),(()=>{const t=new Set(Gt(s).map(t=>t.id));for(const[e,i]of f)t.has(e)||(i.renderer.destroy(),f.delete(e))})(),r=!0},pointer(e,i,a){if(n||!Number.isFinite(e)||!Number.isFinite(i))return;if(e<0||e>1||i<0||i>1){for(const t of f.values())t.renderer.leave();return}let r=!1;for(const n of Gt({...s,width:t.width,height:t.height}).reverse()){const o=f.get(n.id);if(!o)continue;const[h,l]=Wt(n,e,i,t.width,t.height);(!r||"all"===s.pointerMode)&&h>=0&&h<=1&&l>=0&&l<=1&&"none"!==n.settings.hover.effect&&n.settings.hover.strength>0?(o.renderer.pointer(h,l,a),r=!0):o.renderer.leave()}},leave(){for(const t of f.values())t.renderer.leave()},invalidate(t){u();for(const e of s.layers)if(void 0===t||t===e.source){const t=f.get(e.id);t&&(t.renderer.invalidate(),t.dirty=!0)}r=!0},setBudget(t){u(),c=Math.max(2048,Math.min(l,Number.isFinite(t)?Math.round(t):l)),r=!0},setPixelRatio(t){u(),d=Math.max(.1,Math.min(8,Number.isFinite(t)?t:1)),r=!0},get maxCells(){return c},get pixelRatio(){return d},get quality(){return m.map(t=>({...t}))},get active(){return[...f.values()].some(t=>t.renderer.active)},destroy(){if(!n){n=!0;for(const t of f.values())t.renderer.destroy();f.clear(),t.width=t.height=1}}}}function Jt(t,e){for(const i of t.layers)if(!e.has(i.source))throw new Error(`Missing project source: ${i.source}`)}async function Qt(t,e,i){const a=Object.entries(e),s=new Map;if(a.length>8)throw new Error("A project supports up to 8 media bindings.");Jt(t,new Map(a));try{for(const[t,e]of a){if(i?.aborted)throw new DOMException("Cancelled","AbortError");if("string"==typeof e||"undefined"!=typeof File&&e instanceof File)s.set(t,await St(e,i));else{if(!e||"object"!=typeof e||!("text"in e)||"string"!=typeof e.text)throw new Error(`Invalid project source: ${t}`);{const i=e,{canvas:a}=await Lt(i.text,i.font,i.ink??"#ffffff",null);s.set(t,{source:a,width:a.width,height:a.height,duration:0,animated:!1,frame:()=>a,seek:async()=>{},destroy:()=>{a.width=a.height=1}})}}}if(i?.aborted)throw new DOMException("Cancelled","AbortError");return s}catch(t){for(const t of s.values())t.destroy();throw t}}async function Kt(t,e,i,a={}){const s=qt(e),r=await Qt(s,i,a.signal);try{return Zt(t,s,r,a)}catch(t){for(const t of new Set(r.values()))t.destroy();throw t}}function Zt(t,e,i,a={}){if((i=new Map(i)).size>8)throw new Error("A project supports up to 8 media bindings.");let s=qt(e);if(Jt(s,i),a.signal?.aborted)throw new DOMException("Cancelled","AbortError");const n=Ht(t,s,a),o=matchMedia("(prefers-reduced-motion: reduce)"),h=[...new Set(i.values())],l=h.filter(t=>t.source instanceof HTMLVideoElement).map(t=>t.source),c=new Map;let d,m={},f=0,u=0,g=0,p=0,M=!0,w=!1,v=!0,b=!1,y=!1!==a.adaptive,x=0,k=0,E=0,S=s.width,A=s.height,F=0,P=!1;const T=new WeakSet,I=Math.max(1,Math.min(60,Number.isFinite(a.fps)?a.fps:60)),C=()=>!b&&!w&&!P&&!o.matches&&v&&!document.hidden,R=()=>{b||p||!v||document.hidden||(p=requestAnimationFrame(D))},L=()=>new Set(Gt({...s,width:S,height:A}).map(t=>i.get(t.source).source)),N=()=>{const t=L();for(const e of l)e.loop=!0,C()&&t.has(e)?e.paused&&!T.has(e)&&(T.add(e),e.play().then(()=>{T.delete(e),C()&&L().has(e)||e.pause()}).catch(t=>{T.delete(e),b||(w=!0,N(),a.onError?.(t instanceof Error?t:new Error(String(t))),M=!0,R())})):e.pause()},O=()=>{u=0,M=!0,N(),R()};function D(t){if(p=0,b||!v||document.hidden)return;const e=C();e&&(f+=u?Math.min(.1,(t-u)/1e3):0),u=t;const o=Gt({...s,width:S,height:A}),h=o.some(t=>i.get(t.source).animated||at(t.settings));if(M||e&&n.active||e&&h&&t-g>=1e3/I-.5){const s=performance.now();try{const t=new Map,l=new Set(o.map(t=>t.source));for(const a of l){const s=i.get(a);!s.animated||s.source instanceof HTMLVideoElement||!e||n.invalidate(a),t.set(a,s.frame(f))}m={};for(const t of o){let e=c.get(t.id);e||(e=new r,c.set(t.id,e)),m[t.id]=e.update(f,t.settings.motion.type,t.settings.motion.speed)}n.render(t,f,S,A,m);const d=performance.now()-s;a.onFrame?.(f,d),k=k?.9*k+.1*d:d,++x>20&&y&&e&&(h||n.active)&&(E=k>13?E+1:0,E>=12&&n.maxCells>2048&&(n.setBudget(Math.max(2048,.8*n.maxCells)),a.onQualityChange?.(n.maxCells),k=E=0,M=!0))}catch(t){w=!0,N(),a.onError?.(t instanceof Error?t:new Error(String(t)))}M=!1,g=t}e&&(h||n.active)&&R()}const X=e=>{if(!C())return;const i=t.getBoundingClientRect();i.width&&i.height&&(n.pointer((e.clientX-i.left)/i.width,(e.clientY-i.top)/i.height,e.timeStamp),R())},U=()=>{n.leave(),R()},j=new IntersectionObserver(([t])=>{v=t.isIntersecting,O()});j.observe(t),t.addEventListener("pointermove",X),t.addEventListener("pointerleave",U),t.addEventListener("pointercancel",U),document.addEventListener("visibilitychange",O),o.addEventListener("change",O);const q=()=>{if(!b){b=!0,F++,d?.abort(),cancelAnimationFrame(p),p=0,j.disconnect(),t.removeEventListener("pointermove",X),t.removeEventListener("pointerleave",U),t.removeEventListener("pointercancel",U),document.removeEventListener("visibilitychange",O),o.removeEventListener("change",O),a.signal?.removeEventListener("abort",q),n.destroy();for(const t of h)t.destroy();c.clear()}};a.signal?.addEventListener("abort",q,{once:!0});const B=()=>{if(b)throw new Error("Project player has been destroyed.")},Y=t=>{B();const e=qt(t);Jt(e,i),S===s.width&&A===s.height&&(S=e.width,A=e.height),s=e,n.configure(s);for(const t of c.keys())s.layers.some(e=>e.id===t)||c.delete(t);O()};return O(),{canvas:t,get project(){return qt(s)},get time(){return f},get motionTimes(){return{...m}},get paused(){return w||o.matches},get maxCells(){return n.maxCells},get pixelRatio(){return n.pixelRatio},get quality(){return n.quality},update:Y,updateLayer:(t,e)=>Y(Bt(s,t,e)),resize(t,e,i){if(B(),!Number.isFinite(t)||!Number.isFinite(e)||t<2||e<2)throw new Error("Project dimensions must be positive finite numbers.");S=t,A=e,void 0!==i&&n.setPixelRatio(i),O()},pause(t=!0){B(),w=t,O()},async seek(t){if(B(),!Number.isFinite(t)||t<0)throw new Error("Project time must be finite and non-negative.");const e=++F;d?.abort(),d=new AbortController;const i=d.signal;P=!0,N();try{if(await Promise.all(h.map(e=>e.seek(t,i))),b||e!==F)return;f=t,c.clear(),n.invalidate()}finally{b||e!==F||(P=!1,O())}},redraw(){B(),n.invalidate(),M=!0,R()},setBudget(t){B(),n.setBudget(t),a.onQualityChange?.(n.maxCells),M=!0,R()},setAdaptive(t){y=t,x=E=k=0},destroy:q}}async function $t(t,e,i){const a=qt(t),s={...i.motionTimes};if(Object.values(s).some(t=>!Number.isFinite(t)||t<0))throw new Error("Layer motion times must be finite non-negative numbers.");const r=Object.fromEntries(Object.entries(e).map(([t,e])=>[t,e&&"object"==typeof e&&"text"in e&&"string"==typeof e.text?{...e}:e]));let n,o;const h=new AbortController,l=()=>h.abort();i.signal?.aborted?l():i.signal?.addEventListener("abort",l,{once:!0});const c="png"===i.format||"jpeg"===i.format;try{return await Ft(async(t,e,h,l,d)=>{o??(o=await Qt(a,r,d)),n??(n=Ht(t,a,{maxDimension:4096,maxCells:i.maxCells??24e3,maxRasterPixels:i.maxRasterPixels,pixelRatio:h/(i.referenceWidth??Math.min(h,960))}));const m=new Set(Gt({...a,width:h,height:l}).map(t=>t.source)),f=new Map;await Promise.all([...m].map(async t=>{const i=o.get(t);await i.seek(e,d),f.set(t,i.frame(e)),i.animated&&n.invalidate(t)})),n.render(f,e,h,l,c?s:{})},{...i,signal:h.signal})}finally{if(h.abort(),i.signal?.removeEventListener("abort",l),n?.destroy(),o)for(const t of new Set(o.values()))t.destroy()}}export{T as BLEND_MODES,Nt as CHARACTER_SETS,S as DEFAULT_STUDIO_PRINT,C as DEFAULT_STUDIO_SETTINGS,P as DITHER_ALGORITHMS,Dt as MAX_STUDIO_LAYERS,p as MAX_STUDIO_WARPS,Ot as STUDIO_CHARACTER_SETS,h as STUDIO_CURVE_CHANNELS,t as STUDIO_HOVERS,z as STUDIO_LOOKS,e as STUDIO_MOTIONS,I as STUDIO_PALETTES,k as STUDIO_PRINT_STYLES,x as STUDIO_PRINT_STYLE_IDS,F as STUDIO_STYLES,Rt as STUDIO_TEXT_FONTS,g as STUDIO_WARPS,m as createStudioCurveLookup,Ht as createStudioProjectRenderer,kt as createStudioRenderer,Lt as createStudioText,Pt as exportStudio,$t as exportStudioProject,E as isStudioPrintStyle,St as loadStudioMedia,Tt as mountStudio,It as mountStudioMedia,Kt as mountStudioProject,Zt as mountStudioProjectMedia,c as normalizeStudioCurve,d as normalizeStudioCurves,A as normalizeStudioPrint,qt as normalizeStudioProject,D as normalizeStudioSettings,w as normalizeStudioWarps,zt as parseStudioProject,U as parseStudioSettings,G as restyleStudio,Yt as serializeStudioProject,X as serializeStudioSettings,j as studioCrop,q as studioDimensions,Y as studioGrid,Wt as studioLayerPoint,W as studioLook,Vt as studioProjectBudget,vt as studioSourceSize,Bt as updateStudioProjectLayer,B as updateStudioSettings,Gt as visibleStudioLayers};//# sourceMappingURL=studio.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { mountStudioProject, exportStudioProject, normalizeStudioProject, serializeStudioProject, parseStudioProject,
|
|
2
|
+
type StudioLayerPatch, type StudioProjectSources } from 'asciify-engine/studio';
|
|
3
|
+
|
|
4
|
+
/** A live local component; accessible titles and controls stay in HTML. */
|
|
5
|
+
export async function createLayeredComposition(canvas:HTMLCanvasElement,photo:File|string,signal?:AbortSignal) {
|
|
6
|
+
const sources:StudioProjectSources={photo,headline:{text:'ASCIIFY',font:'Small'}};
|
|
7
|
+
const project=normalizeStudioProject({width:1280,height:720,background:'#0c1711',layers:[
|
|
8
|
+
{id:'photo',source:'photo',name:'Photograph',settings:{ink:'#97b6a0',motion:{type:'parallax',amount:.3,speed:1},hover:{effect:'trail',radius:.45,strength:.55}}},
|
|
9
|
+
{id:'title',source:'headline',name:'Title',placement:{width:.8,height:.25},settings:{ink:'#b3ed82',cellSize:3,hover:{effect:'elastic',radius:.4,strength:.5}}},
|
|
10
|
+
]});
|
|
11
|
+
const player=await mountStudioProject(canvas,project,sources,{maxDimension:1280,maxCells:24000,maxRasterPixels:2097152,signal});
|
|
12
|
+
return {player,
|
|
13
|
+
updateLayer:(id:string,patch:StudioLayerPatch)=>player.updateLayer(id,patch),
|
|
14
|
+
save:()=>serializeStudioProject(player.project),
|
|
15
|
+
restore:(json:string)=>player.update(parseStudioProject(json)),
|
|
16
|
+
exportPng:(signal?:AbortSignal)=>exportStudioProject(player.project,sources,{format:'png',width:1280,height:720,
|
|
17
|
+
referenceWidth:canvas.width/player.pixelRatio,maxCells:player.maxCells,time:player.time,motionTimes:player.motionTimes,signal}),
|
|
18
|
+
// One moving layer has a 12-second cycle. Media, other speeds and
|
|
19
|
+
// temporal finishing can change the combined loop period.
|
|
20
|
+
exportMp4:(signal?:AbortSignal)=>exportStudioProject(player.project,sources,{format:'mp4',width:1280,height:720,duration:12,fps:24,
|
|
21
|
+
referenceWidth:canvas.width/player.pixelRatio,maxCells:player.maxCells,signal}),
|
|
22
|
+
destroy:()=>player.destroy(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createComposition } from './studio-composition.js';
|
|
2
|
+
|
|
3
|
+
/** Live image, saved controls, and independent PNG/MP4 export in one reusable component. */
|
|
4
|
+
export async function createLivingPrint(canvas: HTMLCanvasElement, source: File | string, signal?: AbortSignal) {
|
|
5
|
+
const composition = await createComposition(canvas, source, signal);
|
|
6
|
+
composition.update({
|
|
7
|
+
style: 'engraving', cellSize: 7, colorMode: 'accent', ink: '#becbbe',
|
|
8
|
+
print: { angle: -35, weight: 1.1, roughness: .3 },
|
|
9
|
+
backdrop: { color: '#101810' },
|
|
10
|
+
motion: { type: 'sheen', speed: .5, amount: .4 },
|
|
11
|
+
hover: { effect: 'water', radius: .4, strength: .5 },
|
|
12
|
+
});
|
|
13
|
+
// On unmount, call the returned destroy(). Export owns independent media.
|
|
14
|
+
return composition;
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asciify-engine",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0",
|
|
4
4
|
"description": "Framework-agnostic ASCII art engine. Convert images, videos, and GIFs into ASCII art rendered on canvas.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"LICENSE",
|
|
57
57
|
"examples/media-background.ts",
|
|
58
58
|
"examples/studio-composition.ts",
|
|
59
|
+
"examples/layered-composition.ts",
|
|
60
|
+
"examples/print-composition.ts",
|
|
59
61
|
"THIRD_PARTY.md",
|
|
60
62
|
"licenses"
|
|
61
63
|
],
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: asciify-engine
|
|
3
3
|
description: Build and tune browser ASCII images, video, GIFs, text, and interactive heroes with asciify-engine. Use for media conversion, character and color choices, hover integration, layered HTML typography, scroll-synced video, and rendering performance in apps using this package.
|
|
4
4
|
metadata:
|
|
5
|
-
tested-engine: "4.
|
|
5
|
+
tested-engine: "4.9.0"
|
|
6
6
|
updated: "2026-10-07"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Asciify Engine
|
|
10
10
|
|
|
11
|
-
Use the published `asciify-engine` npm package for browser canvas rendering. Tested against **4.
|
|
11
|
+
Use the published `asciify-engine` npm package for browser canvas rendering. Tested against **4.9.0**. Check the application's installed version and its public types before using newer options; a local checkout can contain unpublished changes.
|
|
12
12
|
|
|
13
13
|
- Agent entry: https://asciify.org/skill (redirects to this Markdown document).
|
|
14
14
|
- Playground: https://asciify.org/editor
|
|
@@ -141,7 +141,9 @@ For optional wallpaper/backdrops, alternate renderers, palettes, masks, saved lo
|
|
|
141
141
|
|
|
142
142
|
## Current catalogs
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
For multiple media/text layers in one live component, use 4.8+ `mountStudioProject` and read [layered-projects.md](references/layered-projects.md). It shares one playback loop and rendering budgets across up to eight independently styled layers. Persist source keys separately from media, and use `exportStudioProject` for independent exports. Do not create one mounted Studio instance per layer or rasterize accessible interface text.
|
|
145
|
+
|
|
146
|
+
Legacy `CHARSETS`, `ART_STYLE_PRESETS`, `CHARSET_SEQUENCES`, `LIVING_STYLE_PRESETS` and their key types are removed. Do not import them or generate old names such as Katakana, Binary, Waves or Smoke. Use the 24 `STUDIO_STYLES` for render-style selectors and `/studio` rendering. For ASCII-only character ramps use `CHARACTER_SETS` from `/core` or `STUDIO_CHARACTER_SETS` from `/studio`; custom Unicode and user-provided frame arrays remain supported. Core `artStyle` only accepts `classic`; use explicit options instead of preset shortcuts. Despite the requested 4.1.0 version number, migrating these removed APIs is a breaking change.
|
|
145
147
|
|
|
146
148
|
|
|
147
149
|
## Fine dither and creative controls (4.2)
|
|
@@ -153,3 +155,5 @@ From 4.5, `dither.algorithm: 'blue-noise'` uses a precomputed dispersed threshol
|
|
|
153
155
|
From 4.6, Studio adds `color.curves` (RGB, red, green, blue) and optional edge-preserving `color.denoise`. `player.settings` returns a detached snapshot for saving or exporting after updates. Read [channel curves and source noise](references/studio-workspace.md#channel-curves-and-source-noise-46) for point limits, update semantics and the processing budget. Do not turn noise reduction on by default or apply it again to the already-rendered characters.
|
|
154
156
|
|
|
155
157
|
From 4.7, Studio supports up to eight ordered source warps: Twirl, Pinch, Spherize, Ripple, Zigzag, Shear, Smudge, Polar and Fragment. Build controls from `STUDIO_WARPS`, retain array order, and read [source shaping](references/source-shaping.md) for bounds, alpha/edge policy and cached-map performance. These shape the source; use `motion.type` to bring a still image to life and `hover.effect` for pointer interaction. Keep them independent, with an empty warp stack by default.
|
|
158
|
+
|
|
159
|
+
From 4.9, optional Studio adds Stipple, Engraving, Crosshatch, Woodblock, Risograph and Pointillism with a shared `print` settings group. Read [print and illustration](references/print-styles.md) for exact controls, light-ink versus dark-ink polarity, still-motion integration and dense-render limits. These are genuine additional render paths; do not substitute dither presets for their IDs.
|